Tenho seguido este tutorial para extrair dados de uma URL, pois ele corresponde bem de perto à minha necessidade (3 div's de profundidade). Infelizmente, onde o StackOverflow não suporta mais o IE, não posso testar o código do tutorial para ver se ele funciona como está. No meu caso, não posso usar o plugin do Chrome e tenho que autenticar no site antes de navegar para a URL. Também tentei as soluções na pergunta 15191847 - especificamente a solução do gembird - ela me deu o mesmo erro.
Quando executo o abaixo, recebo um "Erro de tempo de execução '91'. Imprimi o ie.document em um arquivo de texto e verifiquei que os IDs de div que estou pesquisando estão corretos e que estão sendo capturados. O erro aparece em Set Questions = QuestionList.Children
. Alguma ideia sobre o motivo pelo qual ele pode estar me mostrando o erro?
Dim ie As InternetExplorer
Dim html As HTMLDocument
Dim QuestionList As IHTMLElement, QuestionField As IHTMLElement
Dim Questions As IHTMLElementCollection, QuestionFieldLinks As IHTMLElementCollection, QuestionFields As IHTMLElementCollection
Dim Question As IHTMLElement
Dim RowNumber As Long
Dim votes As String, url As String, views As String, QuestionId As String
url = "<<my url>>"
'open Internet Explorer in memory, and go to website
Set ie = New InternetExplorer
ie.Visible = True
ie.navigate url
'Wait until IE is done loading page
Do While ie.READYSTATE <> READYSTATE_COMPLETE
Application.StatusBar = "Trying to go to " & url
DoEvents
Loop
Cells.Clear
'show text of HTML document returned
Set html = ie.Document
'close down IE and reset status bar
Set ie = Nothing
Application.StatusBar = ""
'put heading across the top of row 3
Range("A3").Value = "Field"
Range("B3").Value = "Values"
Set QuestionList = html.getElementByID("fieldgroup ")
Set Questions = QuestionList.Children
RowNumber = 4
For Each Question In Questions
If Question.className = "fieldrow _text-field" Then
'get a list of all of the parts of this question, and loop over them
Set QuestionFields = Question.all
For Each QuestionField In QuestionFields
'if this is the question's votes, store it (get rid of any surrounding text)
If QuestionField.className = "fieldlabel" Then
Cells(RowNumber, 1).Value = Trim(QuestionField.innerText)
End If
'likewise for views (getting rid of any text)
If QuestionField.className = "fieldvalue" Then
Cells(RowNumber, 2).Value = Trim(QuestionField.innerText)
End If
Next QuestionField
'go on to next row of worksheet
RowNumber = RowNumber + 1
End If
Next
Set html = Nothing
A saída HTML se parece com isso.
<div class="fieldgroup " style="" group-title="">
<div class="fieldrow _text-field">
<div class="fieldlabel">Reporting</div>
<div class="fieldvalue">Yes</div>
</div>
<div class="fieldrow _text-field">
<div class="fieldlabel">Annotate ''Yes''</div>
<div class="fieldvalue">Yes</div>
</div>
...
Você está misturando
id
eclass
quais são coisas diferentes, veja por exemplo Qual é a diferença entre um id e uma classe? .Seus elementos têm atributos de classe , não IDs. Para procurar elementos com atributos de classe específicos, use a função
getElementsByClassName
. Observe que esta é uma função "plural", ela retornará todos os elementos que têm aquele atributo de classe específico. Mesmo que encontre apenas um elemento, ela retorna uma estrutura de dados que pode conter qualquer número de elementos e você precisa usar um índice para acessar um dos elementos. Até onde me lembro, no VBA é uma matriz baseada em 0.Se você tiver certeza de que sempre um elemento será encontrado, use
ou (mas neste caso você precisa de uma definição diferente para QuestionList):
Omiti a verificação de erros, então se o HTML não contiver nenhum elemento com esse nome de classe, você ainda receberá um erro de tempo de execução. Para escrever código robusto, você deve adicionar essa verificação.