I have a VBA code which allows me to read/place string in HTML objects (like input boxes).
This is the example of code:
Sub ReadCheck()
Dim objlement As Object
Dim i As Integer
Dim isNothing As Boolean
'
Dim shellWins As ShellWindows
Dim ie As InternetExplorer
'Set shellWins = New ShellWindows
Set shellWins = New ShellWindows
i = shellWins.Count
'On Error Resume Next
For i = 0 To i - 1
If shellWins.Item(i).Parent = "Internet Explorer" Then
If shellWins.Item(i).Document.URL = "https://intservices.mybebpage" Then
Set ie = shellWins.Item(i)
Exit For
End If
End If
Next i
On Error GoTo 0
isNothing = ie Is Nothing
Debug.Print Format(Now, "HH:MM:SS") & " IE is nothing: " & isNothing
If isNothing Then Exit Sub
'combo box
Set objlement = ie.Document.getelementsbyname("txtboxx")
objlement (0).Value = "Some text to place"
End Sub
Due to my testing, this code works fine with 99% of cases, but sometimes it returns error 91 (Object variable or With block variable not set), in the last line.
I'm pretty sure, that I can get correct object for objelement, but it looks like there were no .Value property for it.
This is wierd, becouse I know that this code works.
In my opinion the most possible reason for this is that I should use some different properties than .Value for this.
Do you have any comments for this?
Related
I am automating web scraping and i'm getting an object error 438 object doesn't support this property or method. in vba when i get to last line of code. If i run it on the internet explorer console, i get the value but i get error in vba. Any help?
Dim shellWins As ShellWindows
Dim IE As Object
Set shellWins = New ShellWindows
If shellWins.Count > 0 Then
' Get IE
Set IE = shellWins.Item(0)
Else
' Create IE
Exit Sub
End If
IE.Navigate "https://mywebpage.com"
While IE.Busy
DoEvents
Wend
Do Until IE.ReadyState = 4
DoEvents
Loop
Dim rtn As String
rtn = IE.getElementById("myID").getAttribute("value") << I get ERROR here
I saw your question in this comment,
is there a way to set an object to an already existing instance of IE ?
so here's what you can do to grab an already-existing IE browser:
Dim IE As Object
Set IE = GetIE("https://mywebpage.com")
Function GetIE(sLocation As String) As Object
Dim objShell As Object, objShellWindows As Object, o As Object
Dim sURL As String
Dim RetVal As Object
Set objShell = CreateObject("shell.application")
Set objShellWindows = objShell.Windows
For Each o In objShellWindows
sURL = ""
On Error Resume Next
sURL = o.document.Location
On Error GoTo 0
If sURL Like "*" & sLocation & "*" Then
Set RetVal = o
Exit For
End If
Next o
Set GetIE = RetVal
End Function
Now to the actual question. It's impossible to help you precisely without seeing HTML code or the website itself.
However, you can try either of these properties to see if they'd work (Try in the order listed here):
Dim rtn As String
rtn = IE.Document.getElementById("myID").Value
Dim rtn As String
rtn = IE.Document.getElementById("myID").innerText
Dim rtn As String
rtn = IE.Document.getElementById("myID").outerText
The method is a property of .document (HTMLDocument) object not the IE object
IE.document.getElementById("myID")
To create an IE instance:
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
Going to agree with some of the above answers. Get off IE unless its a constraint.
You're not creating an IE object at all. So you're trying to use a non-existent object.
Dim IE As Object
Set IE = CreateObject("InternetExplorer.Application")
First of all: Don't use IE. Firefox and Chrome are much more viable and are actually HTML comformant.
In case this doesn't fix it: Furthermore, if your script runs on startup and is declared before the HTML, it wil try search the current buffer and wont find the object since it hasn't been loaded yet. Try placing the script after the HTML declaration.
I'm sorry if I misunderstood the Code above since I don't actually speak VB ^^'
I am trying to figure out how to get VBA code to continue after being interrupted by a popup inquiring if I want to convert. I think I can figure out how to handle the first and subsequent popups that appear via the Windows API. However, I can't figure out how to put focus on my code when the popup appears so I can't run the line "MsgBox FindWindow(vbNullString, "Convert macro: " & m.Name)." Is there away for the code to continue running? I know that I will have to add a loop to check for the popup with the title "Convert macro: " & m.Name. Below is the code I have so far.
Sub ConvertMacrosToVBA()
Dim strDB As String
Dim appAccess As Access.Application
Dim m As Object
strDB = "C:\Users\Me\Desktop\testme.accdb"
Set appAccess = New Access.Application
appAccess.OpenCurrentDatabase strDB
For Each m In appAccess.CurrentProject.AllMacros
appAccess.DoCmd.SelectObject acMacro, m.Name, True
appAccess.DoCmd.RunCommand acCmdConvertMacrosToVisualBasic
MsgBox FindWindow(vbNullString, "Convert macro: " & m.Name)
Next
Set appAccess = Nothing
End Sub
I have been researching this for some time and I have come up with the following code. However, I keep getting an error. See below.
The intent of this code is to produce an HTML document. Then it opens and prints the document from a printer. I have gotten the file to save successfully and even open it in an IE window. Then I get the error.
Function generateResults()
Dim resultsBrowser As SHDocVw.InternetExplorer
Set resultsBrowser = New SHDocVw.InternetExplorer
Dim resultsPath As String
Dim resultsFile As String
resultsPath = ThisWorkbook.Path & "\As-Run Test Results"
If Len(Dir(resultsPath, vbDirectory)) = 0 Then
MkDir resultsPath
End If
resultsFile = resultsPath & "\As-Run " & Format(Now, "mm-dd-yyyy hmmss") & ".html"
Open resultsFile For Output As #1
Print #1, "<html><title>Test</title><body>Hello World</body></html>"
Close #1
resultsBrowser.Navigate resultsFile
Do While resultsBrowser.ReadyState = READYSTATE_COMPLETE
Loop
resultsBrowser.Stop
resultsBrowser.ExecWB 7, 1
resultsBrowser.Quit
Set resultsBrowser = Nothing
End Function
Here is the error message.
When I go to debug, the VBA debugger points to the following line:
resultsBrowser.ExecWB 7, 1
What am I doing wrong? My research shows that this works for others, but it does not seem to work for me. Another oddity is that if I navigate to about:blank instead of the HTML file and comment out the ReadyState check loop, a blank Print Preview comes up successfully.
You need to use InternetExplorerMedium instead of InternetExplorer, as in this post: https://stackoverflow.com/a/19221313/6201755
(As a note, to make this clear for future users, the SHDocVw object is contained in the Microsoft Internet Controls reference library, make sure to add this reference in the VBE.)
Also as the comment above, this Do While resultsBrowser.ReadyState = READYSTATE_COMPLETE line makes it loop infinitely, so you need to change it to <>.
Here is the working code:
Private Sub test()
Dim resultsBrowser As SHDocVw.InternetExplorerMedium
Set resultsBrowser = New SHDocVw.InternetExplorerMedium
Dim resultsPath As String
Dim resultsFile As String
resultsPath = ThisWorkbook.Path & "\As-Run Test Results"
If Len(Dir(resultsPath, vbDirectory)) = 0 Then
MkDir resultsPath
End If
resultsFile = resultsPath & "\As-Run " & Format(Now, "mm-dd-yyyy hmmss") & ".html"
Open resultsFile For Output As #1
Print #1, "<html><title>Test</title><body>Hello World</body></html>"
Close #1
resultsBrowser.Navigate resultsFile
Do While resultsBrowser.ReadyState <> READYSTATE_COMPLETE
Loop
resultsBrowser.Stop
resultsBrowser.ExecWB 7, 1
resultsBrowser.Quit
Set resultsBrowser = Nothing
End Sub
I read through a pretty thorough response in the link How to search through VBA code files and it works just fine for the current project. However, I'm just feeling slow in opening up other projects and looking through their code.
The response mentioned using OpenDatabase but I'm not seeing examples about the association between the database and the Application.VBE.ActiveVBProject. I've not been lazy about this, but 4 days of searching the web has exhausted my options.
Any help would be really appreciated.
My apologies. Found other way to make this work.
Public Sub FindWordInOtherModules(ByVal pSearchWord As String, sApplicationFilePath As String)
Dim objComponent As VBComponent
' VBComponent requires reference to Microsoft Visual Basic
' for Applications Extensibility; use late binding instead:
Dim lStartLine As Long
Dim lEndLine As Long
Dim lStartColumn As Long
Dim lEndColumn As Long
Dim accApp As Access.Application
Set accApp = New Access.Application
With accApp
.Visible = True
.OpenCurrentDatabase (sApplicationFilePath)
.UserControl = True
'MsgBox .VBE.ActiveVBProject.VBComponents.Count
'MsgBox .CurrentDb.Name
For Each objComponent In .VBE.ActiveVBProject.VBComponents
If objComponent.CodeModule.Find(pSearchWord, lStartLine, lStartColumn, lEndLine, lEndColumn, _
FindWholeWord, MatchCase, PatternSearch) = True Then
MsgBox "Found text " & StringToFind & vbCrLf _
& "Start line: " & lStartLine & vbCrLf _
& "Line text: " & objComponent.CodeModule.Lines(lStartLine, lEndLine - lStartLine + 1), vbOKOnly, objComponent.CodeModule.Name
End If
Next objComponent
End With
accApp.CloseCurrentDatabase
Set accApp = Nothing
End Sub
You should probably add accApp.Quit:
accApp.CloseCurrentDatabase
accApp.Quit
Set accApp = Nothing
before Set accApp = Nothing to speed up closing the application and close it during execution of this code (Public Sub FindWordInOtherModules), on the line accApp.Quit, not later. On my computer mouse is still inactive several seconds after execution such kind of Sub if accApp.Quit is not added.
But there is no need to open another database, because the current database can be only "linked' to it by creating temporary reference:
Private Sub FindWordInOtherModules2()
Dim objComponent As VBComponent
...
...
Dim lEndColumn As Long
Dim ref As Reference
Dim RefName As String
Const FileName = "C:\Users\....mdb"
With Application 'instead of accApp
.References.AddFromFile FileName
'.References.Count because the new one is supposed be the last one (?)
RefName = .References(.References.Count).Name
Dim VBProj As VBProject
For Each VBProj In .VBE.VBProjects
If VBProj.FileName <> .CurrentDb.Name Then Exit For
Next
For Each objComponent In VBProj.VBComponents
'Debug.Print objComponent.Name
...
...
Next
Set objComponent = Nothing '?
Set VBProj = Nothing '?
Set ref = .References(RefName)
.References.Remove ref
Set ref = Nothing '??
End With
End Sub
This seems be faster then opening another database file, but VBA can't be updated.
References.Remove ref removes reference, but VBA folders are still visible in the left panel and all the code works, what is a little disturbing ...
Application.VBE.VBProjects.Remove VBProj doesn't work. It may have something to do with "Trust access to the VBA project object model" option in Trust Center - Macro Settings, which is not available in Access.
But the project is not visible after closing and opening the database.
I'm using VBA in access to open up a protected word template, fill in the data, and then re-protect it.... this way, if the database system goes down, the word template can still be used manually in its protected state.
I have just started using VBA and in this line:
If ActiveDocument.ProtectionType <> wdNoProtection Then
ActiveDocument.Unprotect Password:=""
End If
I'm concerned that whilst running the code in access, that if the user opens up another word document and makes it the focus, that it will occidentally get protected instead of the other. How do I keep active focus on the document I'm writing to... or do I need to reference my document somehow using WordApp.protect (or something similar that works)
Private Sub Command0_Click()
Dim WordApp As Word.Application
Dim strDatabasePath As String
Dim strTemplatePath As String
Dim strTemplate As String
Dim strJobTitle As String
Dim strFile As String
strFile1 = "testcoc.dotx"
strFile2 = "testcoc-private.dotx"
strDatabasePath = CurrentProject.Path & "\"
strTemplatePath = "\templates\"
strTemplate = strDatabasePath & strTemplatePath & strFile2
On Error Resume Next
Set WordApp = GetObject(, "Word.Application")
If Err.Number <> 0 Then
Set WordApp = CreateObject("Word.Application")
End If
On Error GoTo ErrHandler
WordApp.Visible = True
WordApp.WindowState = wdWindowStateMaximize
WordApp.Documents.Add Template:=strTemplate, NewTemplate:=True
'strJobTitle = DLookup("JobTitle", "Job", "JobNum = " & [JobType])
strJobTitle = DLookup("JobTitle", "Job", "JobNum = 'J0456'")
With WordApp.Selection
'Unprotect the file
If ActiveDocument.ProtectionType <> wdNoProtection Then
ActiveDocument.Unprotect Password:=""
End If
.Goto what:=wdGoToBookmark, Name:="bm_0_4"
.TypeText strJobTitle
End With
'Reprotect the document.
'If ActiveDocument.ProtectionType = wdNoProtection Then
'ActiveDocument.Protect _
'Type:=wdAllowOnlyFormFields, NoReset:=True, Password:=""
'End If
DoEvents
WordApp.Activate
Set WordApp = Nothing
Exit Sub
ErrHandler:
Set WordApp = Nothing
End Sub
Thank You
I haven't tried this but WordApp.Documents.Add Template:=strTemplate, NewTemplate:=True does return the new document. So I would do something like
Dim doc as Word.Document
Set doc = WordApp.Documents.Add(Template:=strTemplate, NewTemplate:=True)
and reference doc throughout my code instead of ActiveDocument. It seems like doing that should get help you avoid the particular situation you're concerned about.