Visual Basic Autotyper, Outputting listbox items - vb.net

I'm trying to make a simple auto typer in Visual Basic. I want it to take the ListBox items and output at the user's choice of interval.
The problem is I don't know how to make the Timer's Tick event send each line and restart at the top of the list and continue to loop this way.
Form Design:
I have not listed much code because there really isn't much to list yet.
Private Sub intervalTimer_Tick(sender As Object, e As EventArgs) Handles intervalTimer.Tick
End Sub

Here is a code, but you need to replaced the ListBox with a ListView, it is the same look, this is just for the code to work.
This code is going to take each line from the ListView and output it using MsgBox using a timer that has an interval of user's choice, just remove the message box and output the result where ever you need, and you're all good :
First define this variable in your public class :
Dim ListedItems As String
Here is when you press the set button to set the interval :
Try
intervalTimer.Interval = intervalTextBox1.Text * 1000
Catch
MsgBox("The interval must be in purly seconds only!")
End Try
Here is when you press the start button :
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
For Each LVI As ListViewItem In ListView1.Items
If ListedItems = "" Then
ListedItems = LVI.Text
Else
ListedItems &= vbLf & LVI.Text
End If
Next
Timer1.Start()
End Sub
Here is when the timer tick event :
Private Sub intervalTimer_Tick(sender As Object, e As EventArgs) Handles intervalTimer.Tick
intervalTimer.Stop()
Dim SeprateLine As String
Dim Separator As Integer
If ListedItems.Contains(vbLf) Then
Separator = ListedItems.IndexOf(vbLf)
SeprateLine = ListedItems.Remove(Separator)
ListedItems = ListedItems.Substring(Separator + 1)
Else
SeprateLine = ListedItems
ListedItems = ""
End If
MsgBox(SeprateLine)
If ListedItems <> "" Then
intervalTimer.Start()
End If
End Sub
Finally i hope that this will help you with what you need :)

Related

Loop through each item in Listbox and load a webpage

I'm trying to load a new webpage through the control webview2 in .net6+ windows forms, and I'm using a listbox to extract any single item and add it to the url to load on webview.
For example in listbox I have:
11
22
33
44
55
I would like at the press of a button that a loop starts to load one by one,each of these items like
WebView21.Source = New Uri("https://google.it" & ListBox1.Items.first & "rest of the url")
and after the webpage is loaded, it s supposed to extract it's html to check if a certain string is present with
Dim html As String
html = Await WebView21.ExecuteScriptAsync("document.documentElement.outerHTML;")
If html.Contains("Not found") Then
MsgBox("In Vacanza")
Else
MsgBox("Attivo")
End If
End Sub
after that, it goes back to the second listbox item, load the webview, check the html and so on.
My question is how can I loop the WebView in order to pick each of the items one by one and to proceed to do these little things in the while?
p.s. Once the loop arrives to the last listbox item, would it be possible to start it again from the first item?
Much thanks
edit1:
I'm trying with
Private ReadOnly resetEvent As New ManualResetEvent(False)
Async Sub scanWeb()
For Each listBoxElem As String In ListBox1.Items
resetEvent.Reset()
AddHandler WebView2.CoreWebView2.NavigationCompleted, AddressOf OnNavigationCompleted
WebView2.Source = New Uri("https://ikalogs.ru/tools/map/?page=1&server=22&world=10&state=active&search=city&allies%5B1%5D=&allies%5B2%5D=&allies%5B3%5D=&allies%5B4%5D=&nick=" & listBoxElem & "&ally=&island=&city=&x=&y=")
Await Task.Run(Sub() resetEvent.WaitOne())
RemoveHandler WebView2.CoreWebView2.NavigationCompleted, AddressOf OnNavigationCompleted
Dim html As String
html = Await WebView2.ExecuteScriptAsync("document.documentElement.outerHTML;")
If html.Contains("Not found") Then
DataGridView1.Rows.Add(listBoxElem, "IN vacanza")
Else
DataGridView1.Rows.Add(listBoxElem, "Attivo")
End If
Next
End Sub
Private Sub OnNavigationCompleted(sender As Object, e As CoreWebView2NavigationCompletedEventArgs)
resetEvent.Set()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
WebView2 = New WebView2()
WebView2.EnsureCoreWebView2Async()
End Sub
but it seems the loop doesn't wait for the process to end and it goes straight to the next listbox item...
best way is to enumerate listBox items in a for-each loop : (I added an escape way -simple mouse clic on form - to quit loop)
Dim wStop As Boolean
sub scanWeb()
Do
For Each listBoxElem As String In ListBox1.Items
WebView21.Source = New Uri("https://google.it" & listBoxElem & "rest of the url")
'etc....
Next
Loop Until wStop = True
wStop = False
end sub
'way to stop scan
Private Sub form_clic(sender As Object, e As MouseEventArgs) Handles MyBase.MouseClick
wStop = True
End Sub
*** Update *****
The webview2 control is rather made to display data, and I have no experience on it.
Also I suggest you use a simpler method, based on System.Net.WebClient() and associated with threading.
Here is a start of code that works:
Dim wStop As Boolean
Dim i As Integer = 0
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim BackProcess = New Thread(Sub() Me.scanWeb())
BackProcess.Priority = ThreadPriority.Normal
BackProcess.Start()
end sub
Sub scanWeb()
Do While Not wStop
Dim WC As New System.Net.WebClient()
'change url for your need
Dim url As String = "https://www.google.fr/search?q=" & ListBox1.Items(i)
Dim s As System.IO.Stream = WC.OpenRead(url)
Dim sr As New System.IO.StreamReader(s)
Dim html As String = sr.ReadToEnd()
If html.Contains("Not found") Then 'beginInvoke allows the back task to communicate with UI
Me.BeginInvoke(Sub() DataGridView1.Rows.Add(ListBox1.Items(i), "In vacanza"))
Else
Me.BeginInvoke(Sub() DataGridView1.Rows.Add(ListBox1.Items(i), "Attivo"))
End If
i += 1
If i > ListBox1.Items.Count - 1 Then i = 0
Loop
End Sub
'button event to stop scanning
Private Sub stopScan_Click(sender As Object, e As EventArgs) Handles stopScan.Click
wStop = True
End Sub

Making an auto typer from list view

I currently have everything working as it should except for one thing, right now I have the user type into a textbox, press the Add button and it inserts the text into the list view, when the autotyper starts it starts a timer tick with 6000 intervals and types the list but does not go back to the beginning of the list it repeats the last known phrase.
EX:
How can I make it start back over from the beginning if there is nothing left to be typed?
My code for the timer tick
intervalTimer_Tick.Start()
Dim SeprateLine As String
Dim Separator As Integer
If ListedItems.Contains(vbLf) Then
Separator = ListedItems.IndexOf(vbLf)
SeprateLine = ListedItems.Remove(Separator)
ListedItems = ListedItems.Substring(Separator + 1)
Else
SeprateLine = ListedItems
End If
SendKeys.Send(SeprateLine)
SendKeys.Send("{ENTER}")
If ListedItems <> "" Then
End If
End Sub
My code for button
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
For Each LVI As ListViewItem In ListView1.Items
If ListedItems = "" Then
ListedItems = LVI.Text
Else
ListedItems &= vbLf & LVI.Text
End If
Next
intervalTimer_Tick.Start()
End Sub
I think it's great you've started coding in VB.NET. You are almost there, but I want to give you a suggestion. Don't store your values on your user interface - store them in code off the UI thread. Using plain old objects to keep data makes it easier to write and read. Consider a List(Of string) to hold the items, and using a ListBox and DataSource to present the data. This allows for definite separation between what is UI and what is data.
Private ReadOnly items As New List(Of String)()
Private ReadOnly timer As New System.Threading.Timer(AddressOf autoType, Nothing, -1, -1)
Private Sub AddButton_Click(sender As Object, e As EventArgs) Handles AddButton.Click
Dim s = InputBox("Add item", "Add", Nothing)
If s IsNot Nothing Then items.Add(s)
ListBox1.DataSource = Nothing
ListBox1.DataSource = items
End Sub
Private Sub RemoveButton_Click(sender As Object, e As EventArgs) Handles RemoveButton.Click
Dim si = ListBox1.SelectedIndex
If si >= 0 Then
items.RemoveAt(si)
ListBox1.DataSource = Nothing
ListBox1.DataSource = items
End If
End Sub
Private Sub StartButton_Click(sender As Object, e As EventArgs) Handles StartButton.Click
' different buttons / handlers for different intervals
timer.Change(5000, 6000) ' 5s delay before first tick, 6s between subsequent ticks
End Sub
Private Sub autoType(state As Object)
' this ticks off the UI thread, so must Control.Invoke to run on the UI
Me.Invoke(Sub() SendKeys.Send(String.Join(vbLf, items)))
End Sub
To stop it, just change the timer again
timer.Change(-1, -1)

Add a completely different line with every button click

Complete noob to vb.net (and programming in general) here, all I really want is every time I click a button, the number in the textbox is added by 1 but the new number shows up on the next line. Tried to google this a hundred times but nothing really helped.
I don't want to use loops as I don't want all numbers to show up at once, only for the added number to show up after clicking a specific button (on a new line).
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim txtoutput As String = ""
Dim a As Integer = 1
txtoutput &= "the value of a =" & a & Environment.NewLine
a = a + 1
TextBox1.Text = txtoutput
End Sub
You are replacing the Text, you want to append a new line, so you need to do:
Private a As Int32 = 0
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
a += 1
Dim newLine = $"the value of a = {a}"
TextBox1.Text = TextBox1.Text & Environment.NewLine & newLine
End Sub
You also have to use a field and not a local variable if you want to retain the old value and increment it. Otherwise it is reset always to it's inital value.
Please try to change dim a to static a
Public Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim txtoutput As String = ""
Static a As Integer = 1
txtoutput &= "the value of a =" & a & Environment.NewLine
a = a + 1
TextBox1.Text = txtoutput
End Sub

how to show animated loading gif when the button is clicked vb.net using backgroundworker

everyone, I updated my question, I am just a newbie in Visual Basic.Net and Oracle stored procedure.
I have this set of codes where I found on the internet. It works but, how can I convert this importing CSV file from fetching rows from the database using Oracle stored procedure.
Dim strRow As String() 'String array to read all fields in a row
Dim dblAmount As Double 'Variable for total amount
Dim blnReported As Boolean = True 'Flag to check progress report completed or not
'Create TextFieldParser class to parse the stock.csv file in the current location
Dim txtFile As FileIO.TextFieldParser
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
'Allow background operation to be cancelled
bgWorker.WorkerSupportsCancellation = True
'Allow background operation to report progress
bgWorker.WorkerReportsProgress = True
'Disable Stop Button. It is enabled only after start
'button is pressed
btnStop.Enabled = False
'set status message
lblStatus.Text = "Press Start to import data from csv."
'Add columns to the grid
dgvCSVData.Columns.Add("colNo", "No")
dgvCSVData.Columns("colNo").Width = 30
dgvCSVData.Columns.Add("colDate", "Date")
dgvCSVData.Columns("colDate").Width = 60
dgvCSVData.Columns.Add("colItem", "Item")
dgvCSVData.Columns("colItem").Width = 120
dgvCSVData.Columns.Add("colQty", "Quantity")
dgvCSVData.Columns("colQty").Width = 50
dgvCSVData.Columns.Add("colUnit", "Unit")
dgvCSVData.Columns("colUnit").Width = 30
dgvCSVData.Columns.Add("colAmt", "Amt")
dgvCSVData.Columns("colAmt").Width = 60
End Sub
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles btnStart.Click
'Disable Start button and Enable Stop
btnStart.Enabled = False
btnStop.Enabled = True
'set status message
lblStatus.Text = "Importing data from CSV file."
'Start time-consuming operation in background
Call bgWorker.RunWorkerAsync()
End Sub
Private Sub btnStop_Click(sender As Object, e As EventArgs) Handles btnStop.Click
'Enable Start button and disable Stop
btnStart.Enabled = True
btnStop.Enabled = False
'Stop background operation
bgWorker.CancelAsync()
'set status message
lblStatus.Text = "Import cancelled. Press Start again."
End Sub
Private Sub bgWorker_DoWork(sender As Object, e As System.ComponentModel.DoWorkEventArgs) Handles bgWorker.DoWork
Dim intCount As Int16 = 0
txtFile = New FileIO.TextFieldParser("stock.csv")
'Specify structure of the file
txtFile.TextFieldType = FileIO.FieldType.Delimited
txtFile.SetDelimiters(",")
'Skip header row
txtFile.ReadFields()
'Start reading data from file
While Not txtFile.EndOfData
If bgWorker.CancellationPending Then
e.Cancel = True
Exit Sub
Else
'Wait for Progress Report to finish
While Not blnReported
Application.DoEvents()
End While
'Read all field in a row into a string array
strRow = txtFile.ReadFields()
'Do some calculations and assign value to data grid
dblAmount = CDbl(strRow(3)) * CDbl(strRow(4))
'Add some sleep to simulate a long running operation
System.Threading.Thread.Sleep(500)
'Progress report pending
blnReported = False
'increment counter
intCount += 1
'Report the progress
bgWorker.ReportProgress(10, intCount)
End If
End While
End Sub
Private Sub bgWorker_ProgressChanged(sender As Object, e As System.ComponentModel.ProgressChangedEventArgs) Handles bgWorker.ProgressChanged
'Copy values to data grid
dgvCSVData.Rows.Add(strRow)
dgvCSVData.Rows(dgvCSVData.CurrentRow.Index - 1).Cells("colAmt").Value = dblAmount
pgbCopyProgress.Value = e.UserState
'Progress report finished
blnReported = True
End Sub
Private Sub bgWorker_RunWorkerCompleted(sender As Object, e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles bgWorker.RunWorkerCompleted
If e.Cancelled Or Not IsNothing(e.Error) Then
'Clear the data grid
dgvCSVData.Rows.Clear()
Else
'Progress completed
pgbCopyProgress.Value = 100
'Release txtfile
txtFile.Dispose()
btnStop.Enabled = False
btnStart.Enabled = True
End If
End Sub
Here's my code in calling the rows in the database
Public Function RESA_Checker(ByVal stores As String, ByVal bus_date As String, ByVal warehouse As String)
dt = New DataTable
bg.GetProcDataTable(connStr, "SALES_CHECKER.procedure_checker")
cmd.Parameters.Add(New OracleParameter("stores", OracleDbType.Varchar2)).Value = stores
cmd.Parameters.Add(New OracleParameter("bus_date", OracleDbType.Varchar2)).Value = bus_date
cmd.Parameters.Add(New OracleParameter("warehouse", OracleDbType.Varchar2)).Value = warehouse
cmd.Parameters.Add(New OracleParameter("O_OUTPUT", OracleDbType.RefCursor)).Direction = ParameterDirection.Output
adap_or.SelectCommand = cmd
adap_or.Fill(dt)
Return dt
ora_conn.Close()
End Function
My purpose is that the user will be informed through a dialog box with progress bar or animated gif, that the form is loading and still fetching records from the database says "Please wait"/"Searching", and prevent confusion to the user, of having thought that the form is crashed.
P.s. It would be helpful if give the links of the video tutorials.
I do hope you could help me , Thanks.
Note: You've changed your question (you should've created a new Question instead of changing your old one) and I'm not familiar with Oracle, so this information may now be irrelevant.
Like you, I'm a noobie too, but we can figure this out. There's many ways to do this, so I'll list a few. If none scratch your itch, hopefully they will have pointed you in the right direction. I also see you know what backgroundworker is, so I'll assume you know how it works or can find the resources to figure it out yourself (if not I'll link some resources to it below).
ProgressBar:
You can increment a progressbar throughout your button's process to indicate that the process is not over.
Below, when the button is pressed it searches a list for the string "Snow White". If the current string it's checking within the list is not "Snow White" the ProgressBar1 increments to show that a move title has been checked. This will loop until the "Snow White" string comes around. Then our loop will display a completed ProgressBar1 and display "Found it!"
Example Code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim moviesList As New List(Of String) From {"Cinderella", "Snow White", "Rapunzel"}
ProgressBar1.Maximum = moviesList.Count()
For Each movie In moviesList
If movie = "Snow White" Then
ProgressBar1.Value = ProgressBar1.Maximum
Label1.Text = "Found it!"
Else
ProgressBar1.Value += 1
End If
Next
End Sub
Label:
You can display a label telling the user that the button's process is still processing until it finishes.
Below, when the button is pressed it searches a list for the string "Snow White" and sets Label1 to "Loading...". If the current string it's checking within the list is not "Snow White" it continues like normal, if it is "Snow White" it will update Label1 to say "Found it!". By displaying this the user can see whether the program is loading or not.
Example Code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim moviesList As New List(Of String) From {"Cinderella", "Snow White", "Rapunzel"}
Label1.Text = "Loading..."
For Each movie In moviesList
If movie = "Snow White" Then
Label1.Text = "Found it!"
End If
Next
End Sub
Animated Gif:
You can display an animated gif while the button's process processes.
Below, when the button is pressed it searches a list for the string "Snow White" and sets PictureBox1's Visible property to True. If you have added a gif to PictureBox1 (if you don't know how I linked it in resources) you can see the PictureBox1's loading gif. When the loop finds the "Snow White" string within the moviesList it will display "Found it!" in Label1 and set PictureBox1's Visible property to False.
Example Code:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim moviesList As New List(Of String) From {"Cinderella", "Snow White", "Rapunzel"}
PictureBox1.Visible = True
For Each movie In moviesList
If movie = "Snow White" Then
PictureBox1.Visible = False
Label1.Text = "Found it!"
End If
Next
End Sub
Resources:
For additional information you can use these to achieve what you want.
Animate a PictureBox:
https://www.youtube.com/watch?v=Zsvi0p9YUE4
Put a Gif in a PictureBox:
https://www.youtube.com/watch?v=igSsB_61BR8
Create a loading screen:
https://www.youtube.com/watch?v=w8mtv9zJBD0
BackgroundWorker Information:
BackgroundWorker Documentation

VB Thread Timer Update UI

I made a small program that allows for individual timer countdowns for each button clicked. (e.g. clicking on button 1 will start a countdown for button 1 whilst updating the text on the button itself to reflect the time remaining.)
My worry now is that I'm not sure how well my program would work in the long run. Here's a snippet of the code.
Private Sub depBtn_Clicked(sender As Button, e As EventArgs)
If sender.BackColor = Color.Green Then
Dim depRow() As Data.DataRow
Dim id As String = sender.Name
depRow = DepartmentDataSet.Departments.Select("ID Like '" & id & "'")
sender.BackColor = Color.Red
Dim timerBtn As New DepartmentTimer(sender, depRow(0)("Duration"), depRow(0)("ID"))
Dim TimerDelegate As New System.Threading.TimerCallback(AddressOf TimerTask)
Dim TimerItem As New System.Threading.Timer(TimerDelegate, timerBtn, 0, 1000)
timerBtn.timerRef = TimerItem
End If
End Sub
Private Delegate Sub TimerTaskDelegate(ByVal obj As Object)
Private Sub TimerTask(ByVal obj As Object)
If Me.InvokeRequired() Then
Me.Invoke(New TimerTaskDelegate(AddressOf TimerTask), obj)
Else
Dim depTimer As DepartmentTimer = DirectCast(obj, DepartmentTimer)
depTimer.countDown()
If depTimer.duration = -1 Then
depTimer.finish()
depTimer.timerRef.Dispose()
End If
End If
End Sub
I have read and also experienced that if I were to update on the UI thread directly from the timer callback the whole program would crash. So I ended up using a delegate in accordance to here http://tech.xster.net/tips/invoke-ui-changes-across-threads-on-vb-net/.
Is this a proper way of doing it or am I doing anything redundant/inefficient?
Also when I dispose of the Timer object. How would I go about cleaning up the DepartmentTimer class instance (timerBtn)? The button can be activated again once the timer runs out so I'm afraid that the instances would build up if I don't take care of them properly.
Thanks in advance for any help.
Since you're not actually doing anything with the Timer except immediately Invoking back to the main UI thread, you might as well just use one System.Windows.Forms.Timer and update them all in the same handler.
Something like:
Public Class Form1
Private timers As New List(Of DepartmentTimer)
Private WithEvents Tmr As New System.Windows.Forms.Timer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
Tmr.Interval = 1000
Tmr.Start()
End Sub
Private Sub depBtn_Clicked(sender As Button, e As EventArgs)
If sender.BackColor = Color.Green Then
Dim depRow() As Data.DataRow
Dim id As String = sender.Name
depRow = DepartmentDataSet.Departments.Select("ID Like '" & id & "'")
sender.BackColor = Color.Red
timers.Add(New DepartmentTimer(sender, depRow(0)("Duration"), depRow(0)("ID")))
End If
End Sub
Private Sub Tmr_Tick(sender As Object, e As EventArgs) Handles Tmr.Tick
For i As Integer = timers.Count - 1 To 0 Step -1
Dim depTimer As DepartmentTimer = timers(i)
depTimer.countDown()
If depTimer.duration = -1 Then
depTimer.finish()
timers.RemoveAt(i)
End If
Next
End Sub
End Class