I am trying to write a visual basic application to retrieve xpaths from html pages. What I would like to do is have a page load in the web browser, click on any given element on the web page, and have the xpath of that element stored in a variable.
I have been searching the web for 2 days but can not find anything. How can this be done?
I have a basic understanding of VB. I'm just not sure what the code for the onclick event would be.
Use OnBeforeNavigate event and return the URL property
In Access VBA:
Assuming your WebBrowser object is called WebBrowser6
Private Sub WebBrowser6_BeforeNavigate2(ByVal pDisp As Object, URL As Variant, flags As Variant, TargetFrameName As Variant, PostData As Variant, Headers As Variant, Cancel As Boolean)
MsgBox (URL)
End Sub
Related
I have a bunch of TextBox-Button pairs on a form. When the button is clicked I want to insert the value of the text box into a database. The name TextBoxes and Buttons follow a naming standard, for example Value1Tb - Value1Cmd and Value2Tb - Value2Cmd.
My problem is that since I want to do the same for every button I would like the possibility to write a Sub like:
Private Sub AnyButton_Click(sender As CommandButton)
Dim tb As TextBox
Set tb = GetTBByName(s.Name)
PutValueToDatabase(s.Name,tb.Text)
End Sub
But I cannot find a way to point the Click-event of a Button to a different sub than the standard Name_Click().
Anybody know a way around this, that doesn't involve me writing 50 or so different Name_Click() subs?
If you are OK to use Form Controls rather that ActiveX, as it looks as though you may be at the moment, then Chris' solution seems good.
However if you need ActiveX CommandButtons then you are unable (as the VBA compiler will tell you, "Procedure declaration does not match...") to have parameters in the callback for the click event, and you are unable to raise the event from multiple objects, although you do of course know which button raised the event (since the relationship is 1 CommandButton = 1 Sub).
So... I would go with something like:
Private Sub Value1Cmd_Click()
Call TheMethod(Value1Cmd)
End Sub
Private Sub Value2Cmd_Click()
Call TheMethod(Value2Cmd)
End Sub
Private Sub TheRealMethod(sender As CommandButton)
' Do your thing '
Dim tb As TextBox
Set tb = GetTBByName(s.Name)
PutValueToDatabase(s.Name,tb.Text)
' Etcetera... '
End Sub
Requires a stub for each button, so some copying and pasting to begin with, but then easy to maintain etcetera as all _Click event callbacks are pointing at the same method...
Edit:
E.g.
Sub AutoWriteTheStubs()
Dim theStubs As String
Dim i As Long
For i = 1 To 10
theStubs = theStubs & "Private Sub Value" & CStr(i) & "Cmd_Click()" & vbCrLf _
& " Call TheMethod(Value" & CStr(i) & "Cmd)" & vbCrLf _
& "End Sub" & vbCrLf & vbCrLf
Next i
Debug.Print theStubs
End Sub
It seems that what you want is to get the name of the clicked button. If you are creating buttons like this:
(where 'i' increments in a loop)
Set btn = Sheet1.Buttons.Add( , , , ,)
With btn
.OnAction = "btnSub"
.Caption = "Upadate"
.Name = "btn" & CStr(i) & "Cmd"
End With
and then defining a generic "private sub btnSub()" for all the buttons, you could at least get the name of the button that was clicked using Application.Caller. Something like:
Private Sub btnSub()
Dim ButtonName As String
ButtonName = Application.Caller
MsgBox ("Hello:" & ButtonName)
End Sub
Hope it helps!
I decided to make this an answer because I am doing something similar and I confirmed that it works.
You can store the OLEobjects in a Collection, of arbitrary size, containing Custom Class Objects that include the OLEobjects and associations and the events that you need. Thus you can completely avoid any code stubs.
Create a Custom Class to bind the Button and TextBox pairs.
Declare the Button object WithEvents.
Include your call-back in the exposed button event handler in the Class Module.
Put a Public routine in a Standard Module to initialise a Collection of these Custom Class objects by spanning the Form Controls. You can also use this to Add the controls programmatically as a 'reBuild' option. The Collection can be inside another Class Module with all of the management routines, but it needs to be Instantiated and loaded in a Standard Module.
Put a public routine in a standard module to receive the call-backs with whatever context you need. This can also be in a Worksheet Module if it makes for better encapsulation. You can use late binding to reference the callback or CallByName.
You need to bear in mind that the Module of the Form will recompile every time you add a control, so you have to be careful where you put your code.
My application has the controls directly on the Worksheet Surface, so I can't put the the Collection Class in, or source any initialisation of the Collection from the Worksheet module. This would amount to self modifying code and it grinds excel to a halt.
I dreamed this idea up through bloody-minded idealism (not necessarily a good thing) but, of course, I was not the first one to think of it as you can see here. #Tim Williams explains it in his answer. You can also google VBA Control Array Events to see plenty of similar examples including an excellent article by #SiddharthRout. In line with the VB6 analogy, he uses an Array instead of a Collection to achieve the same result.
I'll try to post some code later. My application is a bit different so it will take a lot of work to trim it down, but the principle is the same.
The other thing to bear in mind is that VBE really struggles with this type of thing so don't worry if it is loading up you processors. After you re-start with VBE off, all will be fine.
I have this same situation, and I just have a click event for every button that is a wrapper to the function I want to call. This also allows you to pass sheet-specific parameters if you need to.
Example:
Public Sub StoreButton_Click()
' Store values for transaction sheet 3/27/09 ljr
Call StoreTransValues(ActiveSheet)
End Sub
I just published (Open Source) the Event Centralizer for MSForms.
Citation: "The Event Centralizer for MSForms is a VBA programming tool that allows all sorts of custom grouping when writing handlers for the events occurring in UserForms.
With the Event Centralizer for MSForms, it is easy for example to have all TextBoxes react the same way when the Enter event occurs, or all except one, or only those with a particular Tag value.
Thanks to its events logs system, the Event Centralizer for MSForms is a powerful learning and debugging help."
I can't explain here how it works. I tried to do it on the site.
Set the event to =FunctionName(parameter).
A bit late but this may help someone else:
If you have a function called OpenDocumentById(docID as integer), then each control calling the function would have in the event the following:
cmd1's On Click event:
=OpenDocumentById([DocID])
cmd2's On Click event:
=OpenDocumentById([DocID])
etc...
The current Code in VBA is
Option Explicit
Sub login ()
Dim i As SHDocVw.InternetExplorer
Set i =New InternetExplorer
i.Visible=True
i.navigate ("https://insertconfidentialwebsitehere")
Do while i.readystate <> READYSTATE_COMPLETE
Loop
Dim idoc As MSHTML.HTMLDocument
Set idoc=i.document
Idoc.all.USER.Value="username"
idoc.all.password.value="password"
End Sub
The website does load when I run but I get Automation error 440 and the username and password do not show up when I run the command.
I checked through the reference after inspecting element which is correct.
It is USER and PASSWORD.
I'm not sure why those values are not filled in with the given code.
I have also made VBS code for this application and VBS works great with Send Keys. If the above code has nothing wrong with it could you find a way to implement VBS send keys with the VBA and maybe that would work?
I don't know why using idoc.all is not loading my credentials.
I am currently creating an automation to fill-in field in the browser (Chrome) with VBA and selenium. Which is currently doing fine. (the site is internal)
However, I came across with this "message from web" prompt after saving / submitting the information. Sometimes, this pop-up box gives me a prompt that it was saved successfully and sometimes, if there are errors, the message box contains some text.
In order for me to handle this pop-up message box and put some validation. In this case, I would like to get the text inside this message box. (Please refer to the red arrow).
The code below is what I used in order to accept / click the "OK" button. And doesn't have any problems. However, as mentioned, I would like to get the text inside that box to put some validation.
What I tried so far:
driver.SwitchToAlert
driver.SwitchToAlert.Text <<<--- this is where I attempt to get the text however, it doesn't work.
driver.SwitchToAlert(20).accept
Also, I have check below code:
driver.switchTo().alert().getText();
However, this seems not to be working in VBA / selenium.
Try such a code (Change to suit your issue)
Dim bot As Selenium.ChromeDriver
Sub Test()
Dim dlg As Selenium.Alert
Set bot = New Selenium.ChromeDriver
With bot
.Get "http://the-internet.herokuapp.com/javascript_alerts"
.FindElementByCss("#content > div > ul > li:nth-child(2) > button").Click
Set dlg = .SwitchToAlert(Raise:=False)
Debug.Print dlg.Text
.Wait 2000
dlg.Dismiss
End With
End Sub
Im creating a very simple Windows Phone 8.1 app in Visual Studio Express. I have added a Hyperlink control, then from that I have double click to go to the relevant VB page.
As instructed by the many tutorials out there I have added the code for the button - which should navigate it to the second page I have created.
Private Sub hyperlinkButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
NavigationService.Navigate(New Uri("/SecondPage.xaml", UriKind.Relative))
End Sub
However VB keeps on giving me the error "NavigationService is not declared"
Searching the error message has given me very little joy so far.
In Windows Phone 8.1, code for navigation to another page are declared as,
this.Frame.Navigate(typeof(SecondPage));
You cannot just call the class as you will need to get it from the app (so that the system navigates within the app). This is done by accessing the PhoneApplicationFrame!
It should look something like this:
Private Sub hyperlinkButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
Uri uri = New Uri("/SecondPage.xaml", UriKind.Relative);
((PhoneApplicationFrame)Application.Current.RootVisual).Navigate(uri)
End Sub
I want to preview the current form and in the preview I can print it, how can I do this in lotus script?
You want to preview currently selected document in a view?
You could use view action that would run something like this:
Sub Click(Source As Button)
Dim w As New NotesUIWorkspace
Dim doc As NotesDocument
Set doc = GetSelectedDoc()
Call w.DialogBox(doc.form(0),True,True,True,True,False,True,"Put your title here",doc,True,True,False)
End Sub
Function GetSelectedDoc() As NotesDocument
'MbĀ¤, 04.04.2005
'The function returns currently selected document
'On Error Goto ErrHandler
Dim s As New NotesSession
Dim db As NotesDatabase
Dim c As NotesDocumentCollection
Set db = s.CurrentDatabase
Set c = db.UnprocessedDocuments
If c Is Nothing Then Exit Function
Set GetSelectedDoc = c.getFirstdocument
'add your error handling
End Function
See here for NotesUIWorkspace.DialogBox param explanation.
Or you can simply use #DialogBox formula:
#DialogBox( form ; [AUTOHORZFIT] : [AUTOVERTFIT] : [NOCANCEL] : [NONEWFIELDS] : [NOFIELDUPDATE] : [READONLY] : [SIZETOTABLE] : [NOOKCANCEL] : [OKCANCELATBOTTOM] : [NONOTE] ; title )
Notes is not really great for printing. Depending on your requirements you might be better off writing code to create a word document, which can then be printed. There are plenty of examples out there for achieving this and here is one of them to get you started: http://searchdomino.techtarget.com/tip/A-flexible-data-export-agent-for-Lotus-Notes
Hope this helps.
Create a subform with a read-only version of the form you want to print.
To preview the form - have the subform display in a Dialog box. Have dialog box set to inherit the values from main document.
On the subform display a print button that will print the read-only document. Have the print button hide when printed.
Have you tried to do a right click on the document? You might be able to print it by doing a right click. I would try the simple things first and see if this meets the user needs.
If you are talking about a workflow where you are handling documents and the process is complete and you want to preview the final document you should be able to do this via the UI Document Classes in either the java side or the NotesUI classes in LotusScript. Once you have a handle to the UIDocument you can do several things..
I would try setting the document to readonly and show it in the Preview pane if that object is in your UI design. You could then query the user if they want to print the document or not and use the UIDocument.print option.