VBA-Explorer drop down menu selecting - excel

I am a rookie to programming and am pretty sure that I am way over my head, but here is my problem. I work at a manufacturing facility that has a server that I do not have (and cannot have) access to. In order to retrieve and analyze data I have to go onto our Quality Management website which presents multiple drop down menus to select from. The first one is "Manufacturing date", then time, then machine ID, and then run the search. This then opens a new window that contains the data I need to insert into a previously written macro to organize. My buddy from work found this program:
Sub GoogleSearch()
Set objIE = CreateObject("InternetExplorer.Application")
WebSite = "http://mant6websrv1.thermatru.com/QMS/QualityReporting/Reports/LDMasterQueryReport.asp"
With objIE
.Visible = True
.navigate WebSite
Do While .Busy Or .readystate <> 4
DoEvents
Loop
Set Element = .document.getElementsByName("q")
Element.Item(0).Value = "Hello world"
.document.forms(0).submit
'.quit
End With
End Sub
It was originally a google search program that opens google in explorer and then searches the phrase "hello world". By simply replacing the website with our Quality Management address we have been able to get it to open the correct site, but I have no idea how to get it to select the options I want. I tinkered around a bit with the webdeveloper for explorer and even found the ID names for the boxes I need to fill out...but have no idea how to get the program to select them, and then insert the dates I want and run the search. Any ideas??
p.s. when I say I am a rookie I mean that this is my third day writing macros with vba so please be as simplistic and clear as possible with any answers. I am starting to really enjoy this stuff and want to learn as much as possible. Thanks everyone.

Try using the web macro recorder in Open Twebst. Record the actions you want to take and put the code in Excel's VB editor. In your case you can use VBScript, which can for the most part also be used with VBA. You might not get perfect result immediately with a recording, but it's a good tool to help you get on the right track, even if you may need to tinker with the code a bit and look through the HTML of the site to get perfect control.
Note however that it has its own framework for web automation, it's not recording using the standard Microsoft web libraries for it.

Related

Excel VBA - programmatically list available event procedures for controls on a userform

Hi! I searched google already but found only 1 page mentioning how to do it in MS Access but not in MS Excel, here:
List an MS Access form's controls with their events.
I know how to list the controls on a userform. What I want to know is how to get to the list of events available to a control in the code editor (just clarifying).
Is there a way to programmatically list all available event procedures for a control on a userform like a command button, so that I can add that list of events to an array/collection/dictionary for other uses.
I can't find the control.properties as mentioned the referred link above since I am working in Excel, where this property is not exposed, I guess.
I wish I could go through a collection of properties/events like "for each oneEvent in oneControl.Events" and I know that it is not possible.
I think there must be an internal list/collection like that because we can go through Object Browser in VBA Editor or write event handler code in the VBA Editor.
Is there a way to access that list/collection (may be through VBIDE.VBProject)?
Many thanks in advance.
Hurrah!
I finally found the answer myself! Well, with a little help from #Tim Williams.
It took me 5 days to research the topic of TLI.
Even when my country, Myanmar, was under siege by an unlawful and awful military coup (on 01FEB2021), I couldn't stop thinking about this TLI issue I am facing, despite having to live through anguish, anger, pain, uncertainty and the feeling of being violated.
Now, I got it solved.
That said, I still don't really understand how the whole TLI thing works.
I think it would take me several years of reading on the subject matter to fully understand its declarations, mechanism, functions and methods.
Anyway, I will share what I found out through reading a lot of webpages and finally getting to the answer using a simple watch window to figure out how to get to the list of event procedure names that are available to a given userform control in VBA.
The following sub was taken from another stackoverflow page about listing the properties of userform object, I got stuck with it because I don't fully understand how the structure of the return data is formatted but that was overcome by looking at the structure using the Watch window in VBA Editor.
Requirement: Reference to TypeLib Information library at C:\Windows\SysWow64\TLBINF32.DLL
Sub listControlEventNames(ByVal o As Object)
Dim t As TLI.TLIApplication
Set t = New TLI.TLIApplication
Dim ti As TLI.TypeInfo
Set ti = t.ClassInfoFromObject(o)
Dim i As Integer
Dim mi As TLI.MemberInfo
For Each mi In ti.DefaultEventInterface.Members
i = i + 1
ActiveSheet.Cells(i, 1).value = mi.Name
Next
End Sub
This sub should be called with a userform control name like:
call listControlEventNames(UserForm1.ToggleButton1)
or
listControlEventNames Userform1.ToggleButton1
Finally, I can swear to God (but I'm a Free Thinker) that I can't really find how to list UserForm Control Events anywhere on the web, let alone a user manual on this library. The many many example code snippets, explanations and discussions that I found on TLI, were, for listing properties of UserForm Controls only.
Anyway, enjoy!

Minimizable message box in VB

I need a Visual Basic form that will allow the user to scroll through an Excel sheet while the form is running so that they can locate the information they need to enter into the form. Currently, the user must look up all the information before running the macro, which is obviously not very user friendly.
In other words, as the program is now, if the user tries to scroll through the Excel sheet (or do anything at all outside of the form), they are not allowed to without first canceling the form.
Is there a way to do this? Seems like this should be a simple thing to resolve, but I'm having trouble finding good VB documentation online.
Message boxes always pause the execution of the program. You'll need to find an alternative, for example by using the status bar instead, which is probably the easiest option. You can use the status bar in excel like this:
Application.StatusBar = "Hello world"
and
Application.StatusBar = variableName & " pounds."
and clear it using:
Application.StatusBar = False

Error with VBA Web Scrape

I spent several hours researching this, couldn't find a solution.
I'm trying to do a relatively simple VBA web scrape on google. I'm currently hung up on inputting text into google's search box. There are three different routes I have seen, all of which cause errors.
One route is the following code
Dim aEXPLORER as InternetExplorer
Set aEXPLORER = New InternetExplorer
Do While aEXPLORER.readyState <> READYSTATE_COMPLETE
Application.StatusBar = "Loading google..."
DoEvents
Loop
At this point, the first route goes like this:
aEXPLORER.Document.Getelementbyid("idhere").value
The problem is after .document my intellisense stops working. If I continue to write the code anyway it errors out.
Route two - add at the top dim aHTML as HTMLDocument
Set aHTML = aEXPLORER.document
aHTML.getElementById("idhere").value
This is marginally more successful as I get to the getelementbyID tag but my intellisense doesn't find a .value anywhere. I have a lot of other options like innertext, etc. But no .value like several people use in tutorials online.
I looked in my object libraries and I don't see a .value in my HTMLDocument library or my InternetExplorer library or my Excel library.
The problem has to be something with declaring a variable or an object or something of that nature. Why don't I ever get to a .value? This first method worked online for three different people showing tutorials, why isn't it working when I do it? How are they getting a Getelementbyid tag without setting up an HTML document at the top? For reference, this popular tutorial uses method one, "http://analystcave.com/web-scraping-tutorial/" about 75% of the way through the tutorial.
Thank you so much for being such helpful people. I'm at the end of my currently very limited rope.
Answer credit goes to Berco!
Problem 1: I was using the wrong ID identifier. Solution 1: Copy and Paste HTML code for each interaction point into VBA, comment it out, and copy/paste the identifier directly from that. This has several other benefits as well.
Problem 2: I was concerned with losing intellisense at .value. Solution 2: Not having intellisense does not mean the code won't work. It just means the code isn't set up with a dim/set. To solve for this one, you have to dim that item as an HTMLInput, which requires the Microsoft HTML Object Library reference to be checked. However, you may still use the .value etc even without intellisense as long as the HTML Object Library reference is checked.
The ID of the googles searchbar is (id="lst-ib"). Try something like:
dim searchbar as object
set searchbar = aEXPLORER.Document.Getelementbyid("lst-ib")
searchbar.value = "I wanna google this"
Answer credit goes to Berco!
Problem 1:
I was using the wrong ID identifier.
Solution 1:
Copy and Paste HTML code for each interaction point into VBA, comment it out, and copy/paste the identifier directly from that. This has several other benefits as well.
Problem 2:
I was concerned with losing intellisense at .value.
Solution 2:
Not having intellisense does not mean the code won't work. It just means the code isn't set up with a dim/set. To solve for this one, you have to dim that item as an HTMLInput, which requires the Microsoft HTML Object Library reference to be checked. However, you may still use the .value etc even without intellisense as long as the HTML Object Library reference is checked.

Pulling data into Excel from multiple pages

I’m currently trying to pull data from an internal website. However, a few challenges stand in my way. For clarity, I’ve attached a screenshot of the interface I’m working with. I’ve removed all of the text and added my own references for confidentiality purposes.
The data I need to pull is in Tab1 > TabD. I then apply a filter to it (not sure if that’s relevant here). In this example, there are 16 pages and it is these 16 pages of data (headers 1 to 5) that I need to pull into an excel sheet.
There’s no API for this and the page number doesn’t change in the URL so it can’t be used (to my knowledge).
With all these conditions, is this even feasible with VBA?
Thank you all for your time.
I WOULD just comment on this. But I don't have enough reputation to do so. Come on StackOverflow, I want to help people! I'll leave an answer instead, though I may need more information.
I am assuming this is done in Internet Explorer. In which case if you press Ctrl+U you can bring up the source for a page. Bring up the source to the page shown in your screenshot. You'll need to look for a javascript button that changes the page, which is the tricky part. The syntax for such a button in javascript looks like this:
<button onclick="functionToRun()">Button Text</button>
The button in the example above runs the function "functionToRun." Once you find the function that changes the page, insert it into the VBA line below, once you have IE properly initialized in your script:
Call IE.document.parentWindow.execScript("functionToRun()", "JavaScript")
The line above runs the JavaScript function in IE, effectively changing the page.

VBA Code breaks when looping

I have a small problem, I need to loop through excel rows
However, the code broke. If I am just running it step by step by cliking F8, it is ok. but if I want to run it just by F5, it breaks...
I guess it is not to fast to connect to external source, but how can I solve such problem?
lDate = ws.Cells(i, 2).Value
With appIE
.Navigate "www.thisisjusttheexampleweb.com"
'it usually breaks here or below
End With
Do While appIE.Busy
DoEvents
Loop
'or it breaks here on setting allRowOfData
Set allRowOfData = appIE.document.getElementById("Table")
Set InterestingFields = allRowOfData.Children
Thanks for all the help
P.
Edit: I found other solution without parsing any web, what is more it is better to use some API to get the data for free, and very often the web's owners don't allow to parse/scrape any info from the web.
As for the problem you're asking about in your question, the problem is that the browser changes its "Busy" status before the page is completely loaded. This might happen, so the statement:
Do While appIE.Busy
DoEvents
Loop
gets out of the loop before the page is really loaded. What happens then? Well, when you try to set your statement:
Set allRowOfData = appIE.document.getElementById("historicalRateTb1")
...it fails because such element with the ID you look for is not in the document of your IE application yet. A "not very nice" way to solve this, but that should answer your question, usually consits of let the Excel application waiting some time before to run the rest of the code, so that the browser will have the material time to load the full page:
Application.Wait TimeSerial(Hour(Now()), Minute(Now()), Second(Now())+5) 'this waits 5 seconds before the code run is restored
However, now that you seem to be a bit more acquainted with IE automation, my suggestion is to start learning the use of the so-called XMLHTTP Request object. Find more info about it here. I aware you in advance that:
The good aspect of this object is the speed, since it queries the data in XML and is way faster than the human robotization of the browser to get the same HTML body where your data lie;
The "bad" aspect, apart for the fact that the website might not provide this service, is that usually the object uses the cache to avoid the call; in other words, if you queried the data at 19:52, when you will query at 19:53 it will rather take the cached data of your browser at 19:52 and not the new data at 19:53. There should be a property into the object to avoid this, or you might just append a random number to the website string (that will not be read in the URL but will force the new query to the website).

Resources