Object reference not set to an instance of an object - vb.net - html

I'm trying to get the InnerHtml of a child of a child of an element. Here is what I have:
If doc.GetElementById("ctl00_cphBanner_MenuRedesign_BannerAlertsAndOptionsLoginView_BannerAlertsAndOptions_Authenticated_FriendsBubble") IsNot Nothing Then
Dim el As HtmlElement = doc.GetElementById("ctl00_cphBanner_MenuRedesign_BannerAlertsAndOptionsLoginView_BannerAlertsAndOptions_Authenticated_FriendsBubble")
inboxTxt.Text = el.Children(1).Children(0).InnerHtml.ToString
End If
And this is the error I'm receiving:
"Object reference not set to an instance of an object."
How do I fix this?
Edit: When I removed the "Try" function, the error was shown here:
If doc.GetElementById("ctl00_cphBanner_MenuRedesign_BannerAlertsAndOptionsLoginView_BannerAlertsAndOptions_Authenticated_FriendsBubble") IsNot Nothing Then

You are making the assumption that your doc object has a value. Try checking if it is nothing also, before you check for child elements.
If Not IsNothing(doc) Then
If Not IsNothing(doc.GetElementById("ctl00_cphBanner_MenuRedesign_BannerAlertsAndOptionsLoginView_BannerAlertsAndOptions_Authenticated_FriendsBubble")) Then
Dim el As HtmlElement = doc.GetElementById("ctl00_cphBanner_MenuRedesign_BannerAlertsAndOptionsLoginView_BannerAlertsAndOptions_Authenticated_FriendsBubble")
inboxTxt.Text = el.Children(1).Children(0).InnerHtml.ToString
End If
End If
Updated Code. This Works but does not return your HtmlElement
Public Class Form1
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
wb.Navigate("http://www.roblox.com/user.aspx?id=3659905")
End Sub
Private Sub Form1_MouseClick(sender As Object, e As System.Windows.Forms.MouseEventArgs) Handles Me.MouseClick
Dim doc As HtmlDocument = wb.Document
If Not IsNothing(doc) Then
Dim el As HtmlElement = doc.GetElementById("ctl00_cphBanner_MenuRedesign_BannerAlertsAndOptionsLoginView_BannerAlertsAndOptions_Authenticated_FriendsBubble")
If el IsNot Nothing Then
inboxTxt.Text = el.Children(1).Children(0).InnerHtml.ToString
Else
inboxTxt.Text = "No Data"
End If
End If
End Sub
End Class

Most likely, at least one of the expressions el.Children(1), el.Children(1).Children(0), or el.Children(1).Children(0).InnerHtml results in null/Nothing. Check each of those, in order, to make sure you actually have a value.

Related

ArgumentOutOfRangeException was unhandled - Index was out of range. Must be non-negative and less than the size of the collection

Here's the link for the error
Public Class frmMenu
Private Sub UserMaintenanceToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles UserMaintenanceToolStripMenuItem.Click
frmUser.Show()
End Sub
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Me.StatusStrip1.Items(0).Text = strUser
Me.StatusStrip1.Items(1).Text = Today()
Me.StatusStrip1.Items(2).Text = TimeOfDay()
End Sub
End Class
After I log in an existing user the error appears.
The Items array of the StatusStrip1 element has no items. You need to make sure to fill it before you try to acces it.

What is wrong with this attempt to get a JSON value?

I'm trying to get the Json value and put it in a label, the syntax seems to be correct, but there sure is something wrong with the code, the value simply doesn't display on the Label. What can it be?
NOTE: I have already added the Newstonsoft JSON reference and the timer is 5 seconds and is activated after the form is loaded.
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
Dim json = New IO.StreamReader(DirectCast(DirectCast(Net.WebRequest.Create("https://www.bitstamp.net/api/ticker/"), Net.HttpWebRequest).GetResponse, Net.HttpWebResponse).GetResponseStream)
Dim rq As Newtonsoft.Json.Linq.JToken = Newtonsoft.Json.Linq.JObject.Parse(json.ReadToEnd)
BitCoinPrice = $"{rq.SelectToken("last")}"
Label1.Text = BitCoinPrice
End Sub
I was inattentive but realized that I put the code to activate the Timer1 in the wrong place, instead of putting it when the form loads, it was in when WebBrowser1 loads.
Wrong
Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
Timer1.Enabled = True 'Wrong Place
End Sub
Correct
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Timer1.Enabled = True 'Correct Place
End Sub
Sorry for the inconvenience and thanks for the help.

Identify HtmlElement under cursor in WebBrowser

I'm trying to set up a small extension of WebBrowser control as an HtmlTextBox, with limited formatting possibilities. It works for basic formatting (bold, italic, underline). But I also wanted to allow indentation in one single level, and ideally call this in a "toggle" fashion.
I noticed that when I run Document.ExecCommand("Indent", False, Nothing) it converts the <p> element into a <blockquote> element, which is exactly what I need. But a second call to the same command just adds to the indent margin, but I want to make it so that, if cursor is already inside a <blockquote> element, it will perform an "outdent" instead.
For that, I tried to query Document.ActiveElement before performing my action, but this returns always the whole <body> element, and not the specific block element in which cursor rests at that moment.
How could I accomplish that?
This is my code:
Public Class HtmlTextBox
Inherits WebBrowser
Public Sub New()
WebBrowserShortcutsEnabled = False
IsWebBrowserContextMenuEnabled = False
DocumentText = "<html><body></body></html>"
If Document IsNot Nothing Then
Dim doc = Document.DomDocument
If doc IsNot Nothing Then
doc.designMode = "On"
If Me.ContextMenuStrip Is Nothing Then
AddHandler Document.ContextMenuShowing, Sub(sender As Object, e As HtmlElementEventArgs) Application.DoEvents()
End If
End If
End If
End Sub
Private Sub HtmlTextBox_PreviewKeyDown(sender As Object, e As PreviewKeyDownEventArgs) Handles Me.PreviewKeyDown
If e.Control Then
If e.KeyData.HasFlag(Keys.B) OrElse e.KeyData.HasFlag(Keys.N) Then BoldToggle()
If e.KeyData.HasFlag(Keys.I) Then ItalicToggle()
If e.KeyData.HasFlag(Keys.S) OrElse e.KeyData.HasFlag(Keys.U) Then UnderlineToggle()
If e.KeyData.HasFlag(Keys.M) Then BlockQuoteToggle()
End If
End Sub
Public Sub BoldToggle()
Document.ExecCommand("Bold", False, Nothing)
End Sub
Public Sub ItalicToggle()
Document.ExecCommand("Italic", False, Nothing)
End Sub
Public Sub UnderlineToggle()
Document.ExecCommand("Underline", False, Nothing)
End Sub
Public Sub BlockQuoteToggle()
If Document.ActiveElement.TagName.ToLower = "blockquote" Then
Document.ExecCommand("Outdent", False, Nothing)
Else
Document.ExecCommand("Indent", False, Nothing)
End If
End Sub
End Class
The method ElementAtSelectionStart is designed to return the element containing the start of the current selection. This code is for a WebBrowser control in edit mode. Hopefully it will work for your needs.
Public Class mshtmlUtilities
Public Enum C_Bool
[False] = 0
[True] = 1
End Enum
Public Shared Function ElementAtSelectionStart(ByVal wb As System.Windows.Forms.WebBrowser) As System.Windows.Forms.HtmlElement
Dim el As System.Windows.Forms.HtmlElement = Nothing
If wb IsNot Nothing AndAlso _
wb.Document IsNot Nothing AndAlso _
DirectCast(wb.Document.DomDocument, mshtml.IHTMLDocument2).designMode.Equals("on", StringComparison.InvariantCultureIgnoreCase) Then
Dim doc As mshtml.IHTMLDocument2 = DirectCast(wb.Document.DomDocument, mshtml.IHTMLDocument2)
Dim sel As mshtml.IHTMLSelectionObject = DirectCast(doc.selection, mshtml.IHTMLSelectionObject)
Select Case sel.type.ToLowerInvariant
Case "text"
Dim rng As mshtml.IHTMLTxtRange = DirectCast(sel.createRange(), mshtml.IHTMLTxtRange)
rng.collapse(True)
el = MakeWinFormHTMLElement(rng.parentElement, wb)
Case "control"
Dim rng As mshtml.IHTMLControlRange = DirectCast(sel.createRange(), mshtml.IHTMLControlRange)
el = MakeWinFormHTMLElement(rng.item(0).parentElement, wb)
Case "none"
Dim ds As mshtml.IDisplayServices = DirectCast(doc, mshtml.IDisplayServices)
Dim caret As mshtml.IHTMLCaret = Nothing
ds.GetCaret(caret)
Dim pt As mshtml.tagPOINT
caret.GetLocation(pt, C_Bool.False)
el = wb.Document.GetElementFromPoint(New Point(pt.x, pt.y))
End Select
End If
Return el
End Function
Private Shared Function MakeWinFormHTMLElement(ByVal el As mshtml.IHTMLElement, ByVal wb As System.Windows.Forms.WebBrowser) As System.Windows.Forms.HtmlElement
Dim shimInfo As Reflection.PropertyInfo = wb.GetType.GetProperty("ShimManager", Reflection.BindingFlags.NonPublic Or Reflection.BindingFlags.Instance)
Dim shimManager As Object = shimInfo.GetValue(wb, Nothing)
Dim ciElement As Reflection.ConstructorInfo() _
= wb.Document.Body.GetType().GetConstructors(Reflection.BindingFlags.Instance Or Reflection.BindingFlags.NonPublic)
Return CType(ciElement(0).Invoke(New Object() {shimManager, el}), HtmlElement)
End Function
End Class

BackgroundWorker not Running when it's needed

I am writing a program which lets users upload a large file, compare it to another large file uploaded before and return a list of new entries and discontinued entries.
This requires the program to run a few queries, so it takes a while for the program to complete the task.
Of course, this means that until the program is done with the task, the user cannot do anything else. To prevent that from happening I have included a BackgroundWorker to the project.
The problem is, the BackgroundWorker doesn't start, giving me the same problem.
Can you please help me with this problem? Thanks!
Code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim opendialog As New OpenFileDialog
Dim filepath As String = ""
Dim cellvalue(20) As String
opendialog.Title = "Elija el archivo que quiere importar"
opendialog.Filter = "CSV (*.csv)|*.csv"
If opendialog.ShowDialog() = DialogResult.Cancel Then
Exit Sub
End If
filepath = Replace(opendialog.FileName, "\", "\\")
Label1.Visible = True 'This is supposed to appear first, but it doesn't appear until the end of the method.
'Reading CSV file content
Cmd.CommandText = "SELECT COUNT(*) AS cuenta FROM libros WHERE 1"
rs = Cmd.Execute
If rs("cuenta").Value = 0 Then
BackgroundWorker1.RunWorkerAsync()
'MySQL queries, some of which takes a long time due to the large file being processed
Beep()
MsgBox("Archivo exportado con éxito",, "Exito")
BackgroundWorker1.CancelAsync()
Else
BackgroundWorker1.RunWorkerAsync()
'MySQL queries, some of which takes a long time due to the large file being processed
Beep()
MsgBox("Archivo exportado con éxito",, "Exito")
BackgroundWorker1.CancelAsync()
End If
End Sub
Private Sub BackgroundWoker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
' Update the progress bar
Me.ProgressBar1.Value = e.ProgressPercentage
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If e.Cancelled Then
Label1.Text = "Cancelled"
Else
Label2.Text = "Completed"
End If
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object,
ByVal e As System.ComponentModel.DoWorkEventArgs) _
Handles BackgroundWorker1.DoWork
' Do some time-consuming work on this thread.
System.Threading.Thread.Sleep(5)
End Sub
RunWorkerAsync is, as the name implies, an async method call. This means that the only work done here is to start the DoWork event handler and return immediately. Thus your code now has two paths of execution, the one in the DoWork event handler (that has just started its work and it has probably done nothing) and the code that follows the call to RunWorkerAsync (the code in the ButtonClick).
This last code shows a messagebox and then call CancelAsync, and you could imagine what this call do to your DoWork thread of execution.
So you just need to wait before displaying anything and the Completed event is exactly what you need to use to wait the completition of your DoWork event handler
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
.....
BackgroundWorker1.RunWorkerAsync()
' Remove these lines....
' Beep()
' MsgBox("Archivo exportado con éxito",, "Exito")
' BackgroundWorker1.CancelAsync()
End Sub
Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted
If e.Cancelled Then
Label1.Text = "Cancelled"
Else
Label2.Text = "Completed"
' Add the message here....'
Beep()
MsgBox("Archivo exportado con éxito",, "Exito")
' Of course at this point you don't need to cancel anything....'
End If
End Sub
Private Sub BackgroundWoker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
Me.ProgressBar1.Value = e.ProgressPercentage
End Sub
Private Sub BackgroundWorker1_DoWork(ByVal sender As System.Object,
ByVal e As System.ComponentModel.DoWorkEventArgs) _
Handles BackgroundWorker1.DoWork
' Now suppose that your work here could be divided in 5 methods'
ExecuteMethod1()
backgroundWorker1.ReportProgress(20)
ExecuteMethod2)
backgroundWorker1.ReportProgress(40
ExecuteMethod3
backgroundWorker1.ReportProgress(60)
ExecuteMethod4
backgroundWorker1.ReportProgress(80)
ExecuteMethod5
backgroundWorker1.ReportProgress(100)
End Sub

VB Error : "'mAuto1' is not declared. It may be inaccessible due to its protection level". Need solution

I am new to programming in c# and visual basic. I am using visual studio 2010 and I am trying to retrieve some data from a mysql database. Installed using wamp.
I have already set connection to the database by going to 'Project', 'Application Properties', 'Settings'.
I have this error "'mAuto1' is not declared. It may be inaccessible due to its protection level" and I cant seem to solve it.
The code below is for a simple retrieve:
Public Class Form1
Private procAuto As CALCOM.Auto
Private Function Connect_To_Database() As Boolean
Dim mErrorNumQuery As Long
Dim mReturn As Boolean
procAuto = New CALCOM.Auto
procAuto.Connect(mErrorNumQuery)
If mErrorNumQuery = 0 Then
mReturn = True
Else
mReturn = False
End If
Connect_To_Database = mReturn
End Function
Private Function Get_Weight_By_TicketNumber(ByVal mTicketNumber As String, ByRef mAuto1 As Long, ByRef mAuto2 As Long, ByRef mTotalWeight As Long) As Boolean
Dim mErrorNumQuery As Long
Dim mXtr As New CALCOM.xTr
Dim mRec As ADODB.Recordset
Dim mReturn As Boolean
mRec = mXtr.GetList("Select Auto1,Auto2,TotalWeight From txticket Where TicketCode = '" & mTicketNumber & "'", , , mErrorNumQuery)
If mErrorNumQuery = 0 Then
mReturn = True
If mRec.RecordCount <> 0 Then
mRec.MoveFirst()
mRec.MoveFirst()
mAuto1 = mRec.Fields("Auto1").Value
mAuto2 = mRec.Fields("Auto2").Value
mTotalWeight = mRec.Fields("TotalWeight").Value
End If
Else
mReturn = False
End If
Get_Weight_By_TicketNumber = mReturn
End Function
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Label1.Text = mAuto1 <--------------------problem here
End Sub
End Class
This program was just a test to see if I can display results of a mysql query on a form label. I wanted to display results on the click of a button
How do I fix the error? Any help appreciated.
The mAuto1 variant is a local one at Get_Weight_By_TicketNumber function, you can't use it outside the function. If you want, declare a class-level variant and set it to the value of mAuto1.