Reading Numbers from Webbrowser Vb.net - vb.net

In my WebBrowser I got text like this: Remaining balance: 10$
I would like to convert it to another currency, I want just to read number from my browser, then after that I will send it to a Label or TextBox with the new converted currency. I am stuck here.
A screenshot of it
Private Sub LinkLabel2_LinkClicked(sender As Object, e As LinkLabelLinkClickedEventArgs) Handles LinkLabel2.LinkClicked
WebBrowser2.Navigate(TextBox9.Text + TextBox2.Text)
End Sub
Private Sub WebBrowser2_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser2.DocumentCompleted
Label1.Text = (WebBrowser2.Document.Body.InnerText)
End Sub

I have this suggestion (I know this is probably not the perfect solution):
First, try loading that same webpage in a normal web browser such as Google Chrome or Firefox or any browser which has the feature to "inspect elements", meaning to view their HTML code.
Find out the element which displays the price you want.
Note down the ID of the element (usually written something like id="someID")
Back to your program's code, include the following Function, which will get the text displayed and convert it to another currency:
Public Function ConvertDisplayedCurrency() As Decimal
Dim MyCurrencyElement As HtmlElement = WebBrowser2.Document.GetElementById("theIdYouGotInStep3") 'This will refer to the element you want.
Dim TheTextDisplayed As String = MyCurrencyElement.InnerText 'This will refer to the text that is displayed.
'Assuming that the text begins like "Remaining balance: ###", you need to strip off that first part, which is "Remaining balance: ".
Dim TheNumberDisplayed As String = TheTextDisplayed.Substring(19)
'The final variable TheNumberDisplayed will be resulting into a String like only the number.
Dim ParsedNumber As Decimal = 0 'A variable which will be used below.
Dim ParseSucceeded As Boolean = Decimal.TryParse(TheNumberDisplayed, ParsedNumber)
'The statement above will TRY converting the String TheNumberDisplayed to a Decimal.
'If it succeeds, the number will be set to the variable ParsedNumber and the variable
'ParseSucceeded will be True. If the conversion fails, the ParseSucceeded will be set
'to False.
If Not ParseSucceeded = True Then Return 0 : Exit Function 'This will return 0 and quit the Function if the parse was a failure.
'Now here comes your turn. Write your own statements to convert the number "ParsedNumber"
'to your new currency and finally write "Return MyFinalVariableName" in the end.
End Function
Call that Function probably when the document of the WebBrowser2 loads, that is, in the WebBrowser2_DocumentCompleted sub.
I hope it helps!

Related

Append Strings and values together to target a form control in VBA

I'm so close to getting this code working, I just need a little push please. I would like to
take the name of a combo box and then add a string to the end, But then get the value of a textbox with that string. This is to create a dynamic function instead of pasting the same code over and over.
Here's what I have so far, after you select something in the dropdown, the data is then pulled to populate the boxes next to it. I have about 8 drop downs so far so that's why I need this to work.
'Combobox after update
Call GrabData(Me, Me.ActiveControl)
Then
Private Sub GrabData(ctl As Control)
'name of ctl/combobox is "Kitchen"
data1 = (ctl.Name & "Size") '"KitchenSize"
'Here is where it all goes wrong
data1.Value = size.value
'size.value is just a textbox for example
End Sub
I can debug this with:
msgbox(data1)
'outputs "KitchenSize"
But I cannot get the value of kitchensize's textbox with data1.value
Error:
Object Required
I have also added Dim As String / Dim As Control.
I will be assigning the variable to some other stuff in this 50 line code I wrote so please don't take the above example as exactly what I intend to do, I just need help appending the ctl.name to a string, then use that to reference another control and so on.
EDIT
For anyone who wants to know, I figured it out.
Dim Ctrl As Control
Dim CtrlName As String
CtrlName = ctl.Name & "Size"
Set Ctrl = Me.Controls(CtrlName)
Ctrl.Value = 'Wherever you want to send the values to
See the edit.
You need to dim it as a string, then use Set Ctrl

Is there a way to retrieve some text from a webpage to a textbox in VB?

I'm trying to make it so I can have several text boxes in my form show pieces of information from a specific webpage. For example, would there be a way I would be able to retrieve the title of this question to a variable with the click of a button in Visual Basic?
It not hard but you have to look at the source page, and identify the elements.
In nicely formed pages, usually the div elements have a tag ID, but often they don't, so you have to grab say by a attribute name - often you can use the class name of the div in question.
So, to grab the Title, and you question text of this post?
This works:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim xDoc As New Xml.XmlDocument
Dim strURL As String = "https://stackoverflow.com/questions/55753982"
Dim xWeb As New WebBrowser
xWeb.ScriptErrorsSuppressed = True
xWeb.Navigate(strURL)
Do Until xWeb.ReadyState = WebBrowserReadyState.Complete
Application.DoEvents()
Loop
Dim HDoc As HtmlDocument = xWeb.Document
Debug.Print(HDoc.GetElementById("question-header").FirstChild.InnerText)
Debug.Print(FindClass(HDoc, "post-text"))
End Sub
Function FindClass(Hdoc As HtmlDocument, strClass As String) As String
' get all Divs, and search by class name
Dim OneElement As HtmlElement
For Each OneElement In Hdoc.GetElementsByTagName("div")
If OneElement.GetAttribute("classname") = strClass Then
Return OneElement.InnerText
End If
Next
' we get here, not found, so return a empty stirng
Return "not found"
End Function
OutPut:
(first part is title question)
Is there a way to retrieve some text from a webpage to a textbox in VB?
(second part is question text)
I'm trying to make it so I can have several text boxes in my form show pieces of
information from a specific webpage. For example, would there be a way I would be
able to retrieve the title of this question to a variable with the click of a button
in Visual Basic?

Vb.net how can I set Search level as user input string

Intro... I've got a counter in my project that counts files in specified paths. Now all this depends on the users input as concerned would go into settings and set which extensions (tbExt1.text) that should be searched for as well as path (tbpath.text). The paths are listed in lbchannel1 listbox. Now this wont matter too much to my question, but I filled it in so my example below is more understandable.
Here comes the question: The users should be able to address if its going to count TopLevelOnly (FileIO.SearchOption.SearchTopLevelOnly) or TopAndSub (FileIO.SearchOption.SearchAllSubDirectories).
So I made a combobox that they can select from either of those two options. When they select one of them, FileIO.SearchOption.SearchTopLevelOnly or FileIO.SearchOption.SearchAllSubDirectories will become the text in a textbox tbTopOrSub1.text
That brings me to the next part. Instead of for example FileIO.SearchOption.SearchAllSubDirectories in my counter, I now added tbTopOrSub1.text as I hoped this would work the same way, but now be a user depended option. Have a look:
Dim TopOrSub1 As String
TopOrSub1 = tbTopOrSub1.Text
Dim fileTotal As Integer
For Each item As String In lbChannel1.Items
fileTotal += My.Computer.FileSystem.GetFiles(item.ToString, TopOrSub1, (tbExt1.Text)).Count
Next
I thought this would work like a charm, but it doesn't seem to work. I get this error The converting from string FileIO.SearchOption.SearchTopLev to type Integer is not valid (could be bad translation since the error was in Norwegian) and I notice how it sais TopLev. I suppose its too long? I can't figure out how to get around this.
First of all put Option Strict On for your VB project. This helps alot to avoid runtime errors.
The error occurs since you try to convert a string into an enumeration (=integer).
The good thing about comboboxes is that they have a DataSource property which can hold a collection of objects of any type. Additionally they have the following Properties:
DisplayMember: Name of a (public) property of the object set
in DataSource. The value of it will be displayed in the UI as "friendly" text.
ValueMember: Name of a property of the object set in DataSource. This value will not be shown in UI but you can accesss it in your code.
See my below exmaple how to use all these:
The object which holds the display text (Name) and the Value for your File Search Option:
Class FileSearchOption
Public Property Name As String
Public Property Value As FileIO.SearchOption
End Class
Fill your combobox and set its DataSource, DisplayMember and ValueMember:
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim searchOptions As New List(Of FileSearchOption)
searchOptions.Add(New FileSearchOption() With {.Name = "TopLevelOnly", .Value = FileIO.SearchOption.SearchTopLevelOnly})
searchOptions.Add(New FileSearchOption() With {.Name = "TopAndSub", .Value = FileIO.SearchOption.SearchAllSubDirectories})
ComboBox1.DataSource = searchOptions
ComboBox1.DisplayMember = "Name"
ComboBox1.ValueMember = "Value"
End Sub
Handle the action when the user has chosen a search option. Remark that it is necessary to DirectCast the SelectedValue since it is of type Object.
Private Sub ComboBox1_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox1.SelectedIndexChanged
Dim fileTotal As Integer
For Each item As String In {"G:\"}
fileTotal += My.Computer.FileSystem.GetFiles(item.ToString, DirectCast(ComboBox1.SelectedValue, FileIO.SearchOption), (tbExt1.Text)).Count
Next
End Sub

WP use string as name of control

Please, can anyone help me with this problem:
I have a name(s) of control(s) in string format (str) and I want to set property (in code) of that controls using that string-name.
I try something like this but it doesn't work. Actually, I have a problem with expression. When I put exactly the name it works but when i use variable in string format it doesn't.
Dim str as String
str="k3"
Dim g As Image = CType(str, Image)
g.Source = New BitmapImage(New Uri("/APP;component/Icons/hero.png", UriKind.Relative))
This works:
Dim g As Image = CType(k3, Image)
While this does not:
Dim g As Image = CType(str, Image)
I think I understand what you are trying to do, to declare an object by a string...
Essentially for this to work you will need a custom function that returns the Object Type that you are seeking...
You will need to loop through each control and check the name of the control as a comparison, e.g. If oControl.Name.ToString = sString then Return oControl
Example
' A function to return a Control by the Control's name...
Public Function GetControlByName(ByVal oForm As Form, ByVal sName As String) As Control
Dim cReturn As New Control
Dim ctrl As Control
For Each ctrl In oForm.Controls
cReturn = ctrl
If ctrl.Name.ToString = sName Then
Return ctrl ' this is what we want!
End If
Next
Return cReturn
End Function
' Example Usage
Dim oButton As Button = GetControlByName(Me, "Button44")
If oButton.Name.ToString = "Button44" Then
MessageBox.Show("I have found your Button!")
Else
MessageBox.Show("Your button was NOT Found!")
End If
Obviously there is room for error with this function, because if sName is NOT found, then it will return the last ctrl found, therefore, you will need to ensure that the control you seek is indeed found, via the If statement as provided in the example above...
Furthermore, it may not loop through controls inside of containers, menus, etc, but I'm not sure on that, so you will need to check to ensure it's not having that problem...
(The Me in the statement will most likely be used more often than not, though Me could be the name of the form you are searching if you are running the code outside of the form you are searching the form with the function.)
FINALLY, to answer your question, you will need to change Control to Image, and Set CReturn as a New Image, and then use Return ctrl.BackgroundImage (etc) to return the image..

Overwrite Visual Basic label text

I am reading a temperature value from a transceiver into the serial port and I want this value to change the value of a label in my Visual Basic Form. This value changes every few seconds. I am using the code below:
Me.dataReceived.Text &= [text]
where dataReceived is the label I am using and [text] is the data I am reading from the serial port. This results in the data being displayed but instead of overwriting the label, it writes the value after each other. (The data is appended). I tried to remove the & before the = but this did not work as nothing showed up. Any ideas on what I can do?
The code I am using is the following:
'To receive data into the text field
Private Sub SerialPort1_DataReceived(ByVal sender As Object, ByVal e As System.IO.Ports.SerialDataReceivedEventArgs) Handles SerialPort1.DataReceived
While (SerialPort1.IsOpen)
ReceivedText(SerialPort1.ReadExisting()) 'This is called automatically every time data is received at the Serial Port
End While
End Sub
Private Sub ReceivedText(ByVal [text] As String)
Dim temperature As String
'This function compares the creating Thread's ID with the calling Thread's ID
If Me.dataReceived.InvokeRequired Then
Dim x As New SetTextCallback(AddressOf ReceivedText)
Me.Invoke(x, New Object() {(text)})
Else
'To output to the text box:
Me.dataReceived.Text = text
'To output to the label
temperature = text
Me.temp.Text = text
hmd.Text = temperature
End If
End Sub
If you want to overwrite the old value, you should not use &= but just = to assign the new value:
Me.dataReceived.Text = newText
&= is the same as Me.dataReceived.Text = Me.dataReceived.Text & newText
From MSDN:
The &= operator concatenates the String expression on its right to
the String variable or property on its left, and assigns the result to
the variable or property on its left.
Try this:
If (text IsNot Nothing) AndAlso (text.Trim().Length <> 0) Then
Me.dataReceived.Text = text
End If
I'm not that familiar with the SerialPort class, but I'll do my best to explain what's going on. The serial port raises the data received event when new data comes in through the serial port. Your code then reads all the existing data that has been received. When you call the ReadExisting method, it only returns what has been received up to that point. It does not wait for all the data to come in before it returns. It then calls the ReceivedText method which sets the value of some controls to the text that was received. The InvokeRequired and Invoke calls are only there to get you back on the UI thread. Apparently the SerialPort's DataReceived event may be raised on a separate thread, so you need to get back to the UI thread before you can do anything to any of the controls on the form. The change I suggested simply checked to make sure that the text recieved was not null or empty before you changed the value of the text box. The odd thing about the code is that it continues to read from the serial port until it is no longer open. I wouldn't think you'd want to do that. Rather, I would think that in each DataReceived event, you would just call ReadExisting once and then just expect it to be raised again the next time more data is received. By continuously calling ReadExisting in a loop, it must either return a null string or an empty string if there is no more data to read, which was why the text box was being blanked out.
&= is concatinating your text. use = to over write lable.
Me.dataReceived.Text = text
I'm not sure what is happening, but its likely that text does not have a value when setting the dataReceived.Text. Try this,
Private Sub ReceivedText(ByVal datatext As String)
Me.Invoke(Sub()
'To output to the text box:
Me.dataReceived.Text = datatext
Me.temp.Text = datatext
hmd.Text = datatext
End Sub)
End If
End Sub
I changed text to datatext since text could be confused with the forms local text property. I also moved the setting of the text properties of the labels/textboxes to an invoke using a lambda (note this syntax is new and only will work in VB 2010). I feel like somehow your invoke statement might not have been passing the string value properly. Also I removed the check for InvokeRequired, since the doing an invoke will work in both situations and it looks like you might just be doing threaded calls each time anyways.
If that compiles for you, it should work. If not, its likely that RecievedText is never being called. Set some breakpoints and step through the code to see that datatext has a value and that ReceivedText actually gets called.