2013-10-01 6 views
-1

저는 오랫동안이 문제를 해결하려고 노력해 왔습니다. 내 스택을 보여스택 공간이 부족합니다.

VBAProject.RecebeContratos.ParseHTML3 
[<The code isnt Basic>] 
VBAProject.Módulo1.TodosContratosOrgao5 
[<The code isnt Basic>] '(I don't know the exact translation for this, my excel is in portuguese) 

그런 다음 다시

Sub TodosContratosOrgao5(MacroLoop As Long, Z As Long) 
    Dim URL As String 
    Dim ultimo As Long 
    Dim ultimoorgao As Long 
    Set rng = Range("D2:D589") 
    If MacroLoop = 0 Or MacroLoop = 1 Then 
     MacroLoop = 3 
    End If 
    Do While MacroLoop <= 589 
     If Plan4.Range("E1") = Plan5.Range("E" & MacroLoop) Then 
      URL = Plan5.Range("C" & MacroLoop).Value 
      Call ParseHTML3(URL, MacroLoop, Z, "") 'Here it stops with the stack error 
     End If 
     MacroLoop = MacroLoop + 1 
    Loop 
End Sub 

어떤 생각을 루프? 이 루프가 쌓이는 것을 어떻게 막을 지 모르겠습니다.

감사합니다.

Function ParseHTML3(URL As String, MacroLoop As Long, Z As Long, Teste As String) 

    Dim htm As Object: Set htm = CreateObject("htmlfile") 
    Dim tr As Object 
    Dim td As Object 
    Dim X As Long 
    Dim i As Long 
    Dim URL2 As Long 
    Dim htmlColl As MSHTML.IHTMLElementCollection 
    Dim htmlElem As MSHTML.IHTMLElementCollection 
    Application.DisplayStatusBar = True 
    Application.StatusBar = "Recebendo Contratos... Aguarde!" 
    Dim shellWins As ShellWindows 
    Dim IE As InternetExplorer 
    Range("D1").Calculate 
    Range("E1").Calculate 
    Set shellWins = New ShellWindows 

          'Create IE 
    Set IE = New InternetExplorer 
    On Error Resume Next 
    IE.Visible = True 
    On Error GoTo 0 
    If Teste = "" Then 
     If URL = Plan4.Range("C1").Value Then 
      GoTo Termina 
     End If 
    End If 
    IE.Navigate URL 
    'Aguarda IE completar o carregamento 
    While IE.Busy Or IE.ReadyState <> READYSTATE_COMPLETE 
     DoEvents 
    Wend 


    ''''''''''''''''''''''''''''''''''Clica em "Pesquisar" 

    Set htmlColl = IE.Document.getElementsByTagName("input") 

    For Each Htmlinput In htmlColl 

     If Trim(Htmlinput.Type) = "submit" Then 
      Htmlinput.Click 
      Do While IE.Busy Or IE.ReadyState <> READYSTATE_COMPLETE 
       DoEvents 
      Loop 
      Exit For 
     End If 
    Next Htmlinput 


    '''''''''''''''''''''''''''''''''''''''''''''''''''''' 

     ''''''''''''''''''''''''''''''''' Exibe 100 resultados 

    Set htmlColl = IE.Document.getElementsByTagName("select") 

    Application.Wait Now + TimeValue("00:00:02") 
    For Each HTMLSelect In htmlColl 

     Application.Wait Now + TimeValue("00:00:01") 

     If Trim(HTMLSelect.Value) = "20" Or Trim(HTMLSelect.Value) = "50" Then 
      HTMLSelect.Value = "100" 
      HTMLSelect.onchange 

      Exit For 
     End If 
    Next HTMLSelect 
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 



''''''''''''''''''''''''''''''''''''''''''Pega o conteúdo da primeira página 

    If Teste = "primeira" Then 
     Z = 2 
     Teste = "segunda" 
    End If 


    Application.Wait Now + TimeValue("00:00:02") 
    With IE.Document.getElementsByTagName("tbody")(1) 


     For Each tr In .Rows 
     Dim newURL As String 
     Dim newURL2 As String 
     If tr.innerText <> "Nenhum resultado para esta consulta " Then 
      newURL = Mid(tr.innerHTML, InStr(1, tr.innerHTML, ";") + 1, InStr(1, tr.innerHTML, "&amp;idContrato") - 1 - InStr(1, tr.innerHTML, ";")) 
      newURL2 = Mid(tr.innerHTML, InStr(1, tr.innerHTML, "idContrato"), InStr(1, tr.innerHTML, "><u") - 2 - InStr(1, tr.innerHTML, ";idContrato")) 
      newURL = "http://www3.transparencia.gov.br/TransparenciaPublica/jsp/contratos/contratoExtrato.jsf?consulta=3&" & newURL & "&" & newURL2 
     End If 
      For Each td In tr.Cells 
       X = X + 1 
       With Plan6.Range("a" & Z) 
        If X = 1 Then 
         Plan6.Cells(Z, X).Value = td.innerText 
        Else 
         If Left(td.innerText, 2) = " =" Then 
          Plan6.Cells(Z, X).Value = "..." & td.innerText 
         Else 
          Plan6.Cells(Z, X).Value = td.innerText 
         End If 
        End If 
       End With 
      Next td 
     Plan6.Cells(Z, 7).Value = newURL 
     Z = Z + 1 
     X = 0 
     Next tr 
    End With 

    If i = 0 Then 
     i = 134  'Variável referente a páginas 
    End If 
    w = 136  'Variável referente ao orgão com mais de 10 paginas 
    Do 
     On Error Resume Next 
     Teste = IE.Document.Links(135).innerText 
     Teste2 = IE.Document.Links(134).innerText 
     On Error GoTo 0 
     If Teste2 = "[anterior]" Then 
      If w = 146 Then   'Volta a contagem após clicar em [posterior] 
       w = 136 
      End If 
      On Error GoTo Termina 
      IE.Document.Links(w).Click 
      On Error GoTo 0 
      u = 1 
      w = w + 1 
      On Error GoTo 0 

     ElseIf Teste = "[anterior]" Then 
      If w = 146 Then   'Volta a contagem após clicar em [posterior] 
       w = 135 

      End If 

     ElseIf Teste2 <> "[anterior]" And Teste = "[anterior]" Then  'Avança página 
      IE.Document.Links(i).Click 

     ElseIf Teste <> "[anterior]" And Teste2 = "[anterior]" And u <> 1 Then  'Avança página 
       IE.Document.Links(i).Click 
       u = 0 

     ElseIf u <> i Then 
      On Error GoTo Termina 
       IE.Document.Links(i).Click 
      On Error GoTo 0 
       u = i 

     Else 
      IE.Document.Links(w).Click 

     End If 

     Do While IE.Busy Or IE.ReadyState <> READYSTATE_COMPLETE 
      DoEvents 
     Loop 

    '''''''''''''''''''''''''''''Pega o conteúdo das demais páginas 

    On Error GoTo Termina ''''''''''''Finaliza caso não tenha (mais) páginas. 

    With IE.Document.getElementsByTagName("tbody")(1) 

     For Each tr In .Rows 
      newURL = "http://www3.transparencia.gov.br/TransparenciaPublica/jsp/contratos/contratoExtrato.jsf?consulta=3&" & Mid(tr.innerHTML, InStr(1, tr.innerHTML, ";") + 1, InStr(1, tr.innerHTML, "&amp;idContrato") - 1 - InStr(1, tr.innerHTML, ";")) & "&" & Mid(tr.innerHTML, InStr(1, tr.innerHTML, "idContrato"), InStr(1, tr.innerHTML, "><u") - 2 - InStr(1, tr.innerHTML, ";idContrato")) 
       For Each td In tr.Cells 
        X = X + 1 
        With Plan6.Range("a" & Z) 
         If X = 1 Then 
         Plan6.Cells(Z, X).Value = td.innerText 
        Else 
         If Left(td.innerText, 2) = " =" Or Left(td.innerText, 1) = "=" Then 
          Plan6.Cells(Z, X).Value = "..." & td.innerText 
         Else 
          Plan6.Cells(Z, X).Value = td.innerText 
         End If 
        End If 
        End With 
       Next td 
      Plan6.Cells(Z, 7).Value = newURL 
      Z = Z + 1 
      X = 0 
     Next tr 
    i = i + 1 
    End With 
    Loop 


'''''''''''''''''''''''''''''''''''''''''''''''''''''' 



Termina: 
    IE.Quit 
    If MacroLoop <> 0 Then 
     MacroLoop = MacroLoop + 1 
    End If 
    i = 0 
    Call TodosContratosOrgao5(MacroLoop, Z) 
    Application.StatusBar = "Pronto." 
    Exit Function 

End Function 



End Sub 

PasteHTML3 코드를 게시하지 않으려면 죄송합니다. 여기에 있습니다. (그것은 잘 실행하지만 잠시 후 정지!)

그리고 나는 ParseHTML 전에 매크로 실행 내 시트에 버튼이있어 :

Sub GetData() 
    Dim Teste As String 
    Plan6.UsedRange.ClearContents 
    Range("D1").Calculate 
    Range("E1").Calculate 
    Range("C1").Calculate 
    Teste = "primeira" 
    Call ParseHTML3(Plan4.Range("C1").Value, 0, 0, Teste) 

End Sub 
+2

무엇'ParseHTML3' 모습입니까? – Ryan

+0

'ParseHTML3'이란 무엇입니까? –

+0

주요 주제가 업데이트되었습니다. –

답변

1

귀하의 ErrorHandler (Termina)을 것 같다 스택 오버 플로우의 경우 :

먼저 (1) ParseHTML3을 호출하십시오. 문제가 발생하면 Termina-(MacroLoop+1)으로 코드 실행이 계속됩니다.

TodosContratosOrgao5에서 MacroLoop에서 589로 루프하여 (3) ParseHTML3을 호출하십시오. 첫 번째 실행에서 동일한 오류가 계속 발생한다고 가정하면 ParseHTML3은 사실 (TodosContratosOrgao5)을 다시 호출합니다. 따라서,이 같은 성장을 계속 스택 :

  1. ParseHTML3
  2. TodosContratosOrgao5
  3. ParseHTML3는
  4. TodosContratosOrgao5는
  5. ...

당신이 아마하고 싶은 것은이다 TodosContratosOrgao5 (올바른 MacroLoop 값 사용)을 먼저 호출하십시오. ParseHTML3이 오류를 일으키는 경우 th 전자 기능 - 그리고 TodosContratosOrgao5 다음 라인을 호출하자!

F8으로 코드를 계속 실행하여 ParseHTML3의 버그를 찾으십시오.

+0

나는 이것을 지금 시험해 볼 것이다! 고마워요! –

+0

완료! 너무 바보 같아서 아무 이유없이 다른 함수에서 호출하지 않으면 코드가 이전 하위로 되돌아 가지 않을 것이라고 생각했습니다! –

1

스택 공간이 부족하다는 것은 프로그램에서 너무 많은 중첩 호출이 있음을 의미합니다. 이것은 일반적으로 순환 참조에 의해 발생합니다.

이 경우 ParseHTML3에서 TodosContratosOrgao5으로 전화하고 TodosContratosOrgao5에서 ParseHTML3으로 전화하십시오. 이것은 결코 해결되지 않을 것이지만, 그들은 계속해서 서로에게 계속 전화 할 것입니다.

문제의 간단한 예는 다음과 같습니다

Sub DoFoo() 
    Call DoBar 
End Sub 

Sub DoBar() 
    Call DoFoo 
End Sub 
관련 문제