2014-01-24 51 views
4

我自由地承认,我对HTML对象库不太了解。VBA:循环中的不一致错误91 w/IE.doc参考

我有一个电子表格,包含IRS雇主识别号码,我必须将其识别为在我的数据库中。我只有基于Web的访问这个数据库,其他人已经写了HTML并管理数据库。我相信他们的方法过时了,他们的设计实践很差;但我并不是最终的数据库管理员,所以我知道什么?因此,我最终的正常做法是在搜索页面输入EIN并记录结果。

我的Excel宏是为了

  1. 登录到基于Web的数据库查询网站。

  2. 循环遍历EIN的,注意哪些EIN的发现

不过,我有以下问题:

  • A.登录部分工作得很好,但有一个怪癖:我必须将 保留为验证登录成功(或不是) 的“If Then Else”,否则登录失败。鉴于登录后发生“If Then Else” ,这是完全令人困惑的。
  • B.判断EIN是否在数据库中的唯一方法是查看 innerText,并查看EIN是否发生在由 查询得到的页面上。这是行不通的,即我只在 (在测试中)时才得到正面打击,我连续查询两次相同的EIN。 (我碰到了 第二个EIN。)
  • C.在循环中,我得到不一致的错误91(对象变量不是 集)。有时循环完成;有时会挂起,但从来没有在 的地方。

我的代码如下所示(虽然我不得不修改URL):

Option Explicit 
Sub FillFromWorkbookTest() 

On Error GoTo ErrHandler 

Const cURL = "https://www.someURL.com/LoginPage.jsp" 
Const cUsername = "myUSERNAME" 
Const cPassword = "myPASSWORD" 
Dim IE As Object 
Dim Doc As HTMLDocument 
Dim LoginForm As HTMLFormElement 
Dim UsernameInput As HTMLInputElement 
Dim PasswordInput As HTMLInputElement 
Dim LoginButton As HTMLInputButtonElement 
Dim SearchForm As HTMLFormElement 
Dim EINInput As HTMLInputElement 
Dim SearchButton As HTMLInputButtonElement 
Dim cEIN As String 
Dim BotRow As Long 
Dim EINRange As Range 
Dim c As Variant 
Dim i As Integer 
Dim EINCheck As String 
Dim EINCount As Integer 

'## Open Browser & go to Admin Module, and Login 
Set IE = CreateObject("InternetExplorer.Application") 
IE.Visible = True 
IE.Navigate cURL 

'## Wait for Adimn Module to load 
Do Until IE.ReadyState = 4 
    DoEvents 
Loop 

'## Get the HTML Document of Admin Module login page (cURL) 
Set Doc = IE.document 

'## Get Admin Module login form 
Set LoginForm = Doc.forms("f1") 

'## Get Username input field and populate it 
'## HTML: <input id=EIN type=text tabindex=3 size=9 maxlength=9 name=EIN title="Admin Code"> 
Set UsernameInput = LoginForm.elements("EIN") 
UsernameInput.Value = cUsername 

'## Get Password input field and populate it 
'## HTML: <input id=PIN type=password tabindex=4 size=8 maxlength=8 name=PIN title="PIN"> 
Set PasswordInput = LoginForm.elements("PIN") 
PasswordInput.Value = cPassword 

'## Submit LoginForm 
'## HTML: <input type=submit value=Login tabindex=5 title="Login"> (no onClick attribute; no element) 
LoginForm.submit 

Do Until IE.ReadyState = 4 
    DoEvents 
Loop 

'## Get the HTML Document of the new page 
Set Doc = IE.document 

'## Determine if login succeeded 
If InStr(Doc.body.innerText, "Invalid Login.") = 0 Then 
    MsgBox "Login successful." 
Else 
    MsgBox "Login failed." 
End If 

Debug.Print "Current URL: " & IE.LocationURL 

'## Navigate to Global Change and reset HTML Document 
IE.Navigate "https://www.someURL.com/LOGGED_IN/SomePage.jsp" 

Do Until IE.ReadyState = 4 
    DoEvents 
Loop 

Set Doc = IE.document 

'## Find last row in spreadsheet 
BotRow = Worksheets("Sheet1").Range("A1").End(xlDown).Row 
Set EINRange = Range("A1:A" & BotRow) 

'## Set loop counter variable 
i = 0 

'## Cycle through IRS-identified EINs 
For Each c In EINRange.Cells 

    cEIN = c.Value 
    i = i + 1 

'## Get Admin Module login form 
    Set SearchForm = Doc.forms(0) 

'## Get EIN input field and populate it 
'## HTML: <input type="text" id=EIN name=EIN title="Enter charity EIN" maxlength=9 size=9 tabindex=11 > 
    Set EINInput = SearchForm.elements("EIN") 
    EINInput.Value = cEIN 

'## Submit SearchForm 
'## HTML: <input type="submit" value="Search" tabindex=15 title="Click here to search charity application" class="black_bold" 
'##  onclick="if (btn_OnClick(EIN,CODE)) {document.f1.action='SomeOther.jsp'; document.f1.submit(); return true;} else return false;" > 
'##  (has onClick attribute) 

    Set SearchButton = Doc.body.getElementsByTagName("table")(2). _ 
     getElementsByTagName("tr")(0). _ 
     getElementsByTagName("td")(0). _ 
     getElementsByTagName("input")(2) 
    SearchButton.Click 

    Do Until IE.ReadyState = 4 
     DoEvents 
    Loop 

'## Get the HTML Document of the new page 
    Set Doc = IE.document 

'## Find EIN string on resulting page; Some number if found; Null if not 
    EINCheck = Doc.body.getElementsByTagName("table")(3).innerText 
    EINCount = InStr(1, EINCheck, cEIN, 1) 
    MsgBox EINCount 

'## Determine which EINs are CFC charities 
    If InStr(1, EINCheck, cEIN, 1) = 0 Then 
     Worksheets("Sheet1").Range("F" & i).Value = "NO" 
    Else 
     Worksheets("Sheet1").Range("F" & i).Value = "YES" 
    End If 

Next c 

ErrHandler: 
'## Cleanup 
MsgBox "Error" & Err.Number & ": " & Err.Description 
Set IE = Nothing 
Set Doc = Nothing 
Set LoginForm = Nothing 
Set UsernameInput = Nothing 
Set PasswordInput = Nothing 
Set LoginButton = Nothing 
Set SearchForm = Nothing 
Set EINInput = Nothing 
Set SearchButton = Nothing 

End Sub 

有什么建议?

回答

9

我发现使用下面的“等待,直到IE就绪”

Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) 
Public Function IEWait(p_ieExp As InternetExplorer) 

    'this should go from ready-busy-ready 
    Dim initialReadyState As Integer 
    initialReadyState = p_ieExp.ReadyState 

    'wait 250 ms until it's done 
    Do While p_ieExp.Busy Or p_ieExp.ReadyState <> READYSTATE_COMPLETE 
     Sleep 250 
    Loop 

End Function 

你会这样称呼它

IEWait IE 'your internet explorer is named "IE" 

我也陷入了太多的古怪更好的成功仅使用“就绪”条件之一的错误。在修改我的“准备好”检查方法后,这几乎完全消失了。有时就绪状态不能准确反映状态。

关于你的第一个问题,使用上面提到的Sleep方法,试着在你的每个命令前加上Sleep 1000来验证问题出在你的逻辑上,而不是IE加载太慢。或者缓慢地逐步调试。

你所描述的声音听起来非常类似于我在IE部分加载和我的代码会继续执行时遇到的一些问题。

+1

恩德兰:你是一个美丽的人。这是frickin'真棒!像魅力一样工作。这清除了我遇到的所有问题。谢谢! – user3232254

+0

@ user3232254很乐意帮忙! – enderland

+1

仅供参考 - 我必须添加对“Microsoft Internet控件”的引用才能使用。 –