Trouble with getting value from a website - vb.net - vb.net

i'm not searching to do something complicated , i just want to retrieve certain titles from a website , the first button was just for a test ... The thing is , even the "lala" text isn't showing up which means it doesn't enter in the loop in the first place ...
Public Class Form1
Function ElementsByClass(document As HtmlDocument, classname As String)
Dim coll As New Collection
For Each elem As HtmlElement In document.All
If elem.GetAttribute("appcenter").ToLower.Split(" ").Contains(classname.ToLower) Then
coll.Add(elem)
End If
Next
Return coll
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim wb As New System.Net.WebClient
wb.Headers.Add("user-agent", "Only a test!")
Dim sourceString As String = wb.DownloadString("http://www.ign.com/games/upcoming")
RichTextBox1.Text = sourceString
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim elementss As HtmlElementCollection = WebBrowser1.Document.GetElementsByTagName("div")
For Each pElem As HtmlElement In elementss
If pElem.GetAttribute("class") = "item-title" Then
RichTextBox1.Text = "lala"
RichTextBox1.Text = pElem.InnerHtml
End If
Next
End Sub
End Class

Ok, from what I can tell you are after the titles of each new upcoming game.Something like this should do the trick for you.I would recommend that for larger web scraps that you use the HTML Agility PackHowever since you are only wanting a few strings, this solution should be ok for you.
Imports System.Net
Imports System.Text.RegularExpressions
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim websiteURL As String = "http://www.ign.com/games/upcoming"
getTiles(websiteURL) 'where you access this is up to you
End Sub
Private Sub getTiles(website As String)
ListBox1.Items.Clear() 'Clear old results or any errors
Dim tempTitles As New List(Of String)()
Dim webClient As New WebClient()
webClient.Headers.Add("user-agent", "null")
Try 'If the website happens to go offline, at least your application wont crash.
Dim content As String = webClient.DownloadString(website)
Dim pattern As String = "alt=""(?<Data>[^>]*)""/>"
For Each title As Match In (New Regex(pattern).Matches(content)) 'Since you are only pulling a few strings, I thought a regex would be better.
tempTitles.Add(title.Groups("Data").Value)
Next
Dim titles = tempTitles.Distinct().ToArray() 'remove duplicate titles
For Each title As String In titles
ListBox1.Items.Add(title) 'what you do with the values from here is up to you.
Next
If titles.Count() = 0 Then
ListBox1.Items.Add("Nothing Found")
End If
Catch ex As Exception
ListBox1.Items.Add(ex.Message)
Return
End Try
End Sub
I have written some comments to go along with the code to answer any questions you might have.If i have missed something out, feel free to leave a comment below, Happy Coding

I'm sorry but I suck at explaining these things so please analyze the regex in the site I mentioned in the comment earlier.
The site you specified lists the games like this:
<a class="product_spot " href="/browse?nav=16k-3-rime,28zu0" data-date="05/06/2017"><img src="/gs/pages/landing/upcoming-video-games/images/223x120_rime.jpg"><p>RiME<br><br><span>05/06/2017</span></p></a>
<a class="product_spot " href="/browse/games?nav=16k-3-the+surge,28zu0,13ffff2418" data-date="05/16/2017"><img src="/gs/pages/landing/upcoming-video-games/images/223x120_thesurge.jpg"><p>The Surge<br><br><span>05/16/2017</span></p></a>
So this regex will match that.
<a class=.product_spot\s.\shref=.(?:.+?)\sdata-date=.(?:.+?)><img\ssrc=(?:.+?)><p>(.+?)<br><br><span>(?:.+?)<\/span><\/p><\/a>
Imports System.Net
Imports System.Text.RegularExpressions
Module Module1
Sub Main()
Dim wc As New WebClient
Dim input As String = wc.DownloadString("http://www.gamestop.com/collection/upcoming-video-games")
Dim games As New List(Of String)
Dim matchCollection As MatchCollection = Regex.Matches(input, "<a class=.product_spot\s.\shref=.(?:.+?)\sdata-date=.(?:.+?)><img\ssrc=(?:.+?)><p>(.+?)<br><br><span>(.+?)<\/span><\/p><\/a>")
For Each item As Match In matchCollection
games.Add(item.Groups(1).Value.ToString)
Next
For Each item As String In games
Console.WriteLine(item)
Next
Console.ReadLine()
End Sub
End Module
Output:
Dead Island 2
Final Fantasy XV
De-Formers
Injustice 2
...
Killing Floor 2
Tales of Berseria
Nintendo Switch
Mass Effect Andromeda
MLB The Show 17
Has-Been Heroes
Ride 2
...
..
.

Related

VB.NET Program is always reading last created textfile

Trying to create a login form,
My coding is currently:
Imports System
Imports System.IO
Public Class frmLogin
Dim username As String
Dim password As String
Dim fileReader As String
Dim folderpath As String
Dim files As Integer
Dim filepath As String
Public Structure info
Dim U As String
Dim P As String
End Structure
Dim details As info
Private Sub btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
If txtusername.Text = details.U And txtpassword.Text = details.P Then
MessageBox.Show("Correct!")
frmmenu.Show()
Me.Hide()
Else
MessageBox.Show("wrong")
txtusername.Clear()
txtpassword.Clear()
End If
End Sub
Private Sub btncreate_Click(sender As Object, e As EventArgs) Handles btncreate.Click
frmcreate.Show()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
files = files + 1
filepath = "C:\Users\TheGlove\Desktop\Alex's Program\loginfile" & files & ".txt"
Dim di As DirectoryInfo = New DirectoryInfo("C:\Users\TheGlove\Desktop\Alex's Program")
folderpath = "C:\Users\TheGlove\Desktop\Alex's Program"
files = System.IO.Directory.GetFiles(folderpath, "*.txt").Count
For Each fi In di.GetFiles()
MsgBox(fi.Name)
Dim FILE = System.IO.File.ReadAllLines("C:\Users\TheGlove\Desktop\Alex's Program\loginfile" & files & ".txt")
Dim myArray As String() = FILE
details.U = myArray(0)
details.P = myArray(1)
Next
End Sub
End Class
Button 1 will be merged with btnlogin when i get it working and for now is currently just a seperate button to read each textfile.
When each button is pressed (Button 1 -> btnlogin), only the last created textfile is correct.
By the looks of things, your code does read all the text files, but keeps overwriting details.u and details.p with the value retrieved from each file. So, when the loop gets to the last file, those values are what ends up in the details object.
I'm assuming that you want to read all the usernames and passwords into a list and check the details in the TextBoxes against that list, so .. Your code should probably be something like the code below (see the code comments for an explanation of some of the differences.
Before we get to the code, can give you a couple of pointers.
Firstly, always try to use names that are meaningful. Defining your structure as Info is not as meaningful as it could be. For example, you would be better calling it UserInfo and rather than use P and U, you would be better using Password and UserName. It may not matter so much right now, but when you start writing larger more complex programs, and have to come back to them in 6 months time to update them, info.P or details.P aren't as informative as the suggested names.
Secondly, as #ajd mentioned. Don't use magic strings. Create one definition at the beginning of your code which can be used throughout. Again it makes maintenance much easier if you only have to change a string once instead of multiple times, and reduces the chance of mistakes.
Finally, several of the variables you have defined aren't used in your code at all. Again, at this level, it isn't a major issue, but with large programs, you could end up with a bigger memory footprint than you want.
Dim username As String
Dim password As String
Dim fileReader As String
Dim folderpath As String = "C:\Users\TheGlove\Desktop\Alex's Program"
Dim files As Integer
Dim filepath As String
Public Structure UserInfo
Dim Name As String
Dim Password As String
End Structure
'Change details to a list of info instead of a single instance
Dim userList As New List(Of UserInfo)
Private Sub Btnlogin_Click(sender As Object, e As EventArgs) Handles btnlogin.Click
'Iterate through the list of details, checking each instance against the textboxes
For Each tempUserInfo As UserInfo In userList
If txtusername.Text = tempUserInfo.Name And txtpassword.Text = tempUserInfo.Password Then
MessageBox.Show("Correct!")
frmmenu.Show()
Me.Hide()
'This is here, because after your form has opened an closed, the loop
'that checks usernames and passwords will continue. The line below exits the loop safely
Exit For
Else
MessageBox.Show("wrong")
txtusername.Clear()
txtpassword.Clear()
End If
Next
End Sub
Private Sub Btncreate_Click(sender As Object, e As EventArgs) Handles btncreate.Click
frmcreate.Show()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
'clear the list of user details otherwise, if the files are loaded a second time,
'you'll get the same details added again
userList.Clear()
'This line replaces several lines in your code that searches the folder for files
'marching the search pattern
Dim fileList() As FileInfo = New DirectoryInfo(folderpath).GetFiles("loginfile*.txt")
For Each fi As FileInfo In fileList
MsgBox(fi.Name)
Dim userDetails() As String = System.IO.File.ReadAllLines(fi.FullName)
Dim tempInfo As New UserInfo With {.Name = userDetails(0), .Password = userDetails(1)}
'An expanded version of the above line is
'Dim tempInfo As New info
'tempInfo.U = userDetails(0)
'tempInfo.P = userDetails(1)
userList.Add(tempInfo)
Next
files = fileList.Count
End Sub

Advanced Replacement Freeze

Basically I'm creating a tool which while is looking through lines of "file.txt" to replace a word from a textbox's content with that line if the line is containing that word.
Basically if the line is: pizza-cheese-potatoes, all the words containing "pizza" or "cheese" or "potatoes" to be replaced with "pizza-cheese-potatoes"
Here is what I have until now. But it freeze and I don't really know why. Please help me. :)
Dim PATH As String = "C:\test.txt"
Sub Repl(x As String)
For Each line As String In File.ReadLines(PATH)
Dim myList = New List(Of String)(line.Split("|"c))
For Each item As String In myList
If x Is item Then
TextBox1.Text.Replace(x, line)
End If
Next
Next
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For Each word As String In TextBox1.Text.Split(" "c)
Repl(word)
Next
End Sub
Thank you in advance!
Try doing it like this instead.
Public Sub DoWork()
Dim lines = IO.File.ReadAllLines(PATH)
For Each line In lines
Dim myList = New List(Of String)(line.Split("-"c))
For Each item In myList
If TextBox1.Text.Contains(item) Then
TextBox1.Text = TextBox1.Text.Replace(item, line)
End If
Next
Next
End Sub
Your reader reads the file multiple times which is massively inefficient. This code reads it once, then we just loop over each line with no need to worry about exit conditions etc.
However it's not really doing anything useful as you're not pausing after each line so you'll only be able to review the final one.
There is also no need to test if the textbox contains the text, just simply do a replace then you only search the text once.
For Each item In myList
TextBox1.Text = TextBox1.Text.Replace(item, line)
Next
-------- edit --------
To fix the issue with replacing the word you've already replaced you could try using a replacement placeholder.
For Each item In myList
TextBox1.Text = TextBox1.Text.Replace(item, "#")
Next
TextBox1.Text = TextBox1.Text.Replace("#", line)
---------- edit 2 ------------------
You want to try and build up a new string, word by word, instead of replacing the text in the textbox. This is so that words you've substituted already don't get converted.
Function ReplaceWord(word As String, lines As String())
For Each line As String In File.ReadLines(PATH)
Dim myList = New List(Of String)(line.Split("|"c))
For Each item As String In myList
If word = item Then
Return line
End If
Next
Next
Return word
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim result As New System.Text.StringBuilder
Dim lines = File.ReadLines(PATH)
For Each word As String In TextBox1.Text
result.Append(ReplaceWord(word, lines)).Append(" ")
Next
Textbox1.Text = result.ToString()
End Sub

How to write a List(of) to a text file and retrieve it (vb.net)

Title. I need to write my ListOf, which just contains values such as Zero, Zero, One, One, Two, etc to a text file, and then load back up again. Any help appreciated!
Hello & Welcome to Stack Overflow!. In the future please show some effort when asking a question and at least google or even bing your question first, there are a stack of tutorials regarding your question.With that being said, I am going to give you a lifeline.From what I can tell, you want to write your list to a text file and then read from that text file.
Module Module1
Dim mylist As List(Of String) = New List(Of String)
Dim desktopPath As String = Environment.GetFolderPath(Environment.SpecialFolder.Desktop)
Dim newfile As String = "myTextFile.txt"
Dim newPath As String = System.IO.Path.Combine(desktopPath, newfile)
Sub Main()
mylist.Add("Zero")
mylist.Add("One")
mylist.Add("Two")
mylist.Add("Three")
writer()
End Sub
Sub writer()
Using sw As New System.IO.StreamWriter(newPath)
For Each item As String In mylist
sw.WriteLine(item)
Next
sw.Flush() ''yeap I'm the sort of person that flushes it then closes it
sw.Close()
End Using
reader()
End Sub
Sub reader()
Using sr As New System.IO.StreamReader(newPath)
Console.WriteLine(sr.ReadToEnd)
sr.Close()
End Using
Console.ReadKey()
End Sub
End Module
I didn't put too much effort into this, I will leave the rest up to you, however this should get your well and truly on your way.This was done with a Console applicationAlso if you have any problems or even a question or two regarding my answer, leave a comment and I will do my best to answer you and help you out as I know learning something for the first time can be difficult and you will have lots of questions.EDIT: If you need to load each value separately eg skip the first 4 lines and only read the 5th line, you should look into learning how to do a loop.
EDIT - Here is what I think you are trying to achieve just from reading your comments.
''Reads whatever is in the newPath Textfile and addes the words to a listbox or wherever is needed.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
ListBox1.Items.Clear() ''This is stop double ups.
Dim myTextFile = System.IO.File.ReadAllLines(newPath)
For Each word As String In myTextFile
ListBox1.Items.Add(word) '' change this to mylist if need be
''mylist.Add(word)
Next
End Sub
This should fix your problem, although you may need to clear the mylist first or even create another array.
Here's some sandbox code:
Imports System.Xml.Serialization
Imports System.IO
Public Class frmTest
Dim l1 As New List(Of String)
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
l1.AddRange({"1", "b", "7"})
Dim mySerializer As XmlSerializer = New XmlSerializer(GetType(List(Of String)))
' To write to a file, create a StreamWriter object.
Dim myWriter As StreamWriter = New StreamWriter("C:\temp\list.xml")
mySerializer.Serialize(myWriter, l1)
myWriter.Close()
End Sub
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim myFileStream As FileStream = New FileStream("C:\temp\list.xml", FileMode.Open)
Dim mySerializer As XmlSerializer = New XmlSerializer(GetType(List(Of String)))
' Call the Deserialize method and cast to the object type.
l1 = New List(Of String) ' refresh for test
l1 = CType(mySerializer.Deserialize(myFileStream), List(Of String))
Stop ' l1 is populated
End Sub
End Class

HI, New to programming with textfiles loops and much more

i have a textfile which is in this format
and i am trying to use a stream reader to help me loop each word into a text box, i am new to programming and really need help because all other examples are too complicated for me to understand,
this is what i am trying to do :
Dim objectreader As New StreamReader("filepath")
Dim linereader(1) As String
linereader = Split(objectreader.ReadLine, ",")
For i As Integer = 0 To UBound(linereader)
Spelling_Test.txtSpelling1.Text = linereader(0)
Spelling_Test.txtSpelling2.Text = linereader(0)
Next
but only get the first line of the text file in to a textbox, i need it to loop to the next line so i can write the next line in!
your help would be much appreciated, and if possible then can you show it practically , if you dont understand what i am trying to do then please ask
It is a little confusing on what you are trying to do, it looks like your text file consists of a word and a hint, you only have one set of textbox's and 3 lines of information in your file.
This example show you how to incrementally read your Stream.
Public Class Form1
Dim objectreader As StreamReader
Dim linereader() As String
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
If IsNothing(objectreader) Then
objectreader = New StreamReader("C:\Temp\data.txt")
End If
linereader = Split(objectreader.ReadLine, ",")
If String.IsNullOrEmpty(linereader(0)) Then
objectreader.Close()
objectreader = Nothing
Else
txtSpelling1.Text = linereader(0) 'Word
txtSpelling2.Text = linereader(1) 'Hint
End If
End Sub
End Class
But in your case, I would probably just use the File.ReadAllLines Method
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
Dim result As String() = File.ReadAllLines("C:\Temp\data.txt")
For x = 0 To UBound(result)
Dim c As Control = Controls.Find("txtSpelling" + (x + 1).ToString, True)(0)
If Not IsNothing(c) Then
c.Text = Split(result(x), ",")(0)
End If
Next
End Sub

WinNT giving to much information. I need to narrow down to just Machine Names

Dim de As New System.DirectoryServices.DirectoryEntry()
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
de.Path = "WinNT://*****".Replace("*****", ActiveDirectory.Domain.GetCurrentDomain.Name)
Dim Mystream As Object
MsgBox("Please choose the place you want the file")
If savefileDialog1.ShowDialog() = DialogResult.OK Then Mystream = savefileDialog1.FileName
Dim UserFile As String = savefileDialog1.FileName & ".txt"
Dim fileExists As Boolean = File.Exists(UserFile)
Using sw As New StreamWriter(File.Open(UserFile, FileMode.OpenOrCreate))
For Each d As DirectoryEntry In de.Children()
sw.WriteLine(d.Name)
Next
End Using
End Sub
I am getting a large number of entries written out to the text file. The bottom half of the file is all that I really need. The bottom half seems to be the list of all machine names on the domain and the first half is filled with names or printers, and other names that i cannot "pushd \" into.
I am unable to figure out what will cut down this user list and give me only the machine names.
You might find something here...look at "Enumerate Objects in an OU"
Public Function EnumerateOU(OuDn As String) As ArrayList
Dim alObjects As New ArrayList()
Try
Dim directoryObject As New DirectoryEntry("LDAP://" + OuDn)
For Each child As DirectoryEntry In directoryObject.Children
Dim childPath As String = child.Path.ToString()
alObjects.Add(childPath.Remove(0, 7))
'remove the LDAP prefix from the path
child.Close()
child.Dispose()
Next
directoryObject.Close()
directoryObject.Dispose()
Catch e As DirectoryServicesCOMException
Console.WriteLine("An Error Occurred: " + e.Message.ToString())
End Try
Return alObjects
End Function
I'm not sure if there is much difference in our active directory setups, but I ran the following code in a console application and it only output the AD Names (as expected):
Module Module1
Sub Main()
Using de As New System.DirectoryServices.DirectoryEntry
de.Path = "WinNT://*****".Replace("*****", System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain.Name)
For Each d As System.DirectoryServices.DirectoryEntry In de.Children()
If d.SchemaEntry.Name = "User" Then
Console.WriteLine(d.Name)
End If
Next
Console.ReadKey()
End Using
End Sub
End Module
EDIT:
Code change to only output members with the SchemaType of "User"