Array copy will not work in a if statement or by button click sub - vb.net

I am trying to make a small log ( string array of 10 ) of time stamps that on a event will move the newest event towards the first string in the array.
Here is a few attempts that I have tried. The only time the array will change is when it is in a timer.
What Iam looking to do is
on a bit change to copy arrayA(1) to array(0). witch will move the string from (1) to (0),(2) to (1),(3) to (2) and the rest of the array. So when the event happens it cascades the strings to make a list of last events (0) would be the 10th event that happened and the (9) would be the first or latest event
Attempt 1
Private Sub RcvTmr_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RcvTmr.Tick
dim SrvUpTimeStgArray(9) as string
If BtnBit = False And OneShot(5) = True Then
OneShot(5) = False
SrvUpTimeStgArray(9) = LAtimeSvrUp.TimeString
For I = 0 To 8
SrvUpTimeStgArray(I) = SrvUpTimeStgArray(I + 1)
Next
LAtimeSvrUp.StopTimer()
End If
ListBox1.DataSource = SrvUpTimeStgArray
End Sub
Then this code to
Private Sub RcvTmr_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RcvTmr.Tick
Dim StringArrayA(9) as string : Dim StringArrayB(9) as string
If OneShot(10) = False Then
OneShot(10) = True
StringArrayA(3) = "testst 33333"
StringArrayA(2) = "testst 22222"
StringArrayA(1) = "testst 11111"
StringArrayA(0) = "testst 00000"
End If
StringArrayA(0) = StringArrayA(1)
If Btn1TestBit Then
counter1 = counter1 + 1
BtnTest3.Text = "worked"
'Call ArrayCopy()
Btn1TestBit = False
StringArrayA(0) = StringArrayA(1)
' The below was alternated with the above line ans also did not work
' Array.Copy(StringArrayA, 1, StringArrayB, 0, 4)
End If
ListBox1.DataSource = StringArrayA
ListBox2.DataSource = StringArrayB
Lacount3.Text = counter1
End Sub
I am missing something so thanks..
Update but It has duplicate strings to the array
This is using the AddLog Sub
If ClientConnBit = False And OneShot(5) = True Then
OneShot(5) = False
AddLog(SrvUpTimeStgArray, "Stopped # " & DateTime.Now.ToString() & "* Up Time " & LAtimeSvrUp.TimeString)
LAtimeSvrUp.StopTimer()
For Each entry As String In SrvUpTimeStgArray
If Not String.IsNullOrEmpty(entry) Then
LBSvrUptimeLog.Items.Add(entry)
End If
Next
'LBSvrUptimeLog.DataSource = SrvUpTimeStgArray
My.Settings.UpTimeString.AddRange(SrvUpTimeStgArray)
My.Settings.Save()
End If

You need to copy the values backward, if you do it forward you'll end up copying the same value everywhere. I suggest you load how to use break point and watch.
This is how it would look like
Sub AddLog(ByVal logAsArray() As String, ByVal newEntry As String)
For index As Integer = logAsArray.Length - 1 To 1 Step -1
logAsArray(index) = logAsArray(index - 1)
Next
logAsArray(0) = newEntry
End Sub
You can also use list instead
Sub AddLog(ByVal logAsList As List(Of String), ByVal newEntry As String)
If logAsList.Count = logAsList.Capacity Then
logAsList.RemoveAt(logAsList.Capacity - 1)
End If
logAsList.Insert(0, newEntry)
End Sub
Here's an example on how to use these functions.
Sub Main()
Dim logAsArray(2) As String
AddLog(logAsArray, "a")
AddLog(logAsArray, "b")
AddLog(logAsArray, "c")
AddLog(logAsArray, DateTime.Now.ToString())
For Each entry As String In logAsArray
Console.WriteLine(entry)
Next
Dim logAsList As New List(Of String)(3)
AddLog(logAsList, "a")
AddLog(logAsList, "b")
AddLog(logAsList, "c")
AddLog(logAsList, DateTime.Now.ToString())
For Each entry As String In logAsList
Console.WriteLine(entry)
Next
Console.ReadLine()
End Sub

Related

Highlight specific text while user is typing

I am writing a code that highlight the duplicate words in a text. The code is working well when I add a button and the user have to press on the button to check for duplicates.
But I want to make an auto-checking code. I set my code in a subroutine that Handles RichTextBox.TextChanged. The problem is the code selects the target word and highlight it but the selection remains so when a new letter is typed, it clear what has been highlighted.
Here is my code:
Private Sub RichTextBox_TextChanged(sender As Object, e As EventArgs) Handles RichTextBox.TextChanged
Try
Call duplicate_check()
Catch ex As Exception
MessageBox.Show("error in RichTextBox.TextChanged")
End Try
End Sub
duplicate check function:
Private Sub duplicate_check()
Try
' read line by line and get input
Dim LineByLineInput() As String = RichTextBox.Lines
Dim selectionStart, selectionLength As Integer
Dim i, j As Integer
For lineNumber = 0 To UBound(LineByLineInput)
selectionStart = 0
selectionLength = 0
'get index of first char index in the current line
Dim count As Integer = lineNumber
While count <> 0
selectionStart += RichTextBox.Lines(count - 1).Length + 1
count -= 1
End While
' get line as string
Dim line As String = RichTextBox.Lines(lineNumber)
' split line into array of strings
Dim input() As String = line.Split(" ")
'check for duplicates
i = 0
For j = i + 1 To UBound(input)
If input(i) = input(j) Then 'compare each 2 consecutive words if they are the same
selectionStart += input(i).Length + 1
selectionLength = input(i).Length
RichTextBox.SelectionStart = selectionStart
RichTextBox.SelectionLength = selectionLength
RichTextBox.SelectionBackColor = Color.Yellow
Else
selectionStart += input(i).Length + 1
End If
i += 1
Next
Next
Catch ex As Exception
MessageBox.Show("error duplicate_check()")
End Try
End Sub
After your duplicate_check call, have you tried to set the selection of the RichTextBox back to the old position ?
See below :
Private Sub RichTextBox1_TextChanged(sender As Object, e As System.EventArgs) Handles RichTextBox1.TextChanged
Try
' Get current position
Dim cur_pos As Integer = Me.RichTextBox.SelectionStart
Call duplicate_check()
' Set back to old position
Me.RichTextBox.SelectionStart = cur_pos
' Unselect what your sub duplicate_check has selected
Me.RichTextBox1.SelectionLength = 0
Catch ex As Exception
MessageBox.Show("error in RichTextBox.TextChanged")
End Try
End Sub
If this solution is good for you, you should change your duplicate_check Sub to make this change and not in the RichTextBox1_TextChanged Sub

Sorted List in Array Visual Basic [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 7 years ago.
I have a program that creates a list of 25 random numbers from 0 to 1,000. I have to buttons the first button will load a list box with the random numbers and the second button will sort the list of numbers from the smallest to largest which is where I implemented bubble sort code. Now the other list box that is supposed to hold the sorted numbers doesn't work properly it only shows one number instead of all of them.
Here is my code:
Option Strict On
Public Class Form1
Dim rn As Random = New Random
Dim Clicked As Long = 0
Dim numbers, sort As Long
Private Sub GenerateBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GenerateBtn.Click
Clicked += 1
For x = 0 To 25
numbers = rn.Next(0, 1000)
RandomBox.Items.Add(numbers)
If Clicked >= 2 Then
RandomBox.Items.Clear()
Clicked = 1
End If
Next
End Sub
Private Sub SortBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SortBtn.Click
Dim Sorted() As Long = {numbers}
Dim Swapped As Boolean
Dim endOfArray As Integer = Sorted.Length - 1
Dim Tmp As Byte
While (Swapped)
Swapped = False
For I = 0 To endOfArray - 1
If Sorted(I) > Sorted(I + 1) Then
Tmp = CByte(Sorted(I))
Sorted(I) = Sorted(I + 1)
Sorted(I + 1) = Tmp
Swapped = True
End If
endOfArray = endOfArray - 1
Next
End While
SortBox.Items.Clear()
For I = 0 To Sorted.Count - 1
SortBox.Items.Add(Sorted(I))
Next
End Sub
End Class
Change your:
Dim Sorted() As Long = {numbers}
to
Sorted(x) = numbers
edit: Since you changed your code. You need to put back in the line that loads the Sorted Array.
For x = 0 To 25
numbers = rn.Next(0, 1000)
RandomBox.Items.Add(numbers)
Sorted(x) = numbers
If Clicked >= 2 Then
RandomBox.Items.Clear()
Clicked = 1
End If
Next
and remove the:
Dim Sorted() As Long = {numbers}
from the second part and put this declaration back in the beginning like you had:
Dim Sorted(26) as Long
The way you have will only show the latest random number. It is not any array but a single entity. Therefore only the latest will be add into the array. You need to load each number into the array as you create each one. Thus the (x) which loads it into position x.
You didn't use any arrays at all in your project...you're using the ListBox as your storage medium and that's a really bad practice.
I recommend you set it up like this instead:
Public Class Form1
Private rn As New Random
Private numbers(24) As Integer ' 0 to 24 = 25 length
Private Sub GenerateBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles GenerateBtn.Click
For x As Integer = 0 To numbers.Length - 1
numbers(x) = rn.Next(0, 1000)
Next
' reset the listbox datasource to view the random numbers
RandomBox.DataSource = Nothing
RandomBox.DataSource = numbers
' empty out the sorted listbox
SortBox.DataSource = Nothing
End Sub
Private Sub SortBtn_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SortBtn.Click
' make a COPY of the original array that we will sort:
Dim sorted(numbers.Length - 1) As Integer
Array.Copy(numbers, sorted, numbers.Length)
Dim Swapped As Boolean = True
Dim endOfArray As Integer = Sorted.Length - 1
Dim Tmp As Integer
While (Swapped)
Swapped = False
For I As Integer = 0 To endOfArray - 1
If sorted(I) > sorted(I + 1) Then
Tmp = sorted(I)
sorted(I) = sorted(I + 1)
sorted(I + 1) = Tmp
Swapped = True
End If
Next
endOfArray = endOfArray - 1
End While
' reset the listbox datasource to view the sorted numbers
SortBox.DataSource = Nothing
SortBox.DataSource = sorted
End Sub
End Class
Also, note that you were decrementing endOfArray inside your for loop. You should only decrement it after each pass; so outside the for loop, but inside the while loop.
Additionally, you were using a Tmp variable of type Byte, but generating numbers between 0 and 999 (inclusive). The Byte type can only hold values between 0 and 255 (inclusive).
Your Bubble Sort implementation was very close to correct!

Is it possible to do this code with less redundancy?

I have the following code:
If moves.Contains("1") Then
lblOnes.Visible = True
End If
If moves.Contains("2") Then
lblTwos.Visible = True
End If
If moves.Contains("3") Then
lblThrees.Visible = True
End If
If moves.Contains("4") Then
lblFours.Visible = True
End If
If moves.Contains("5") Then
lblFives.Visible = True
End If
If moves.Contains("6") Then
lblSixes.Visible = True
End If
I just feel like it is redundant, is there any way to do this without repeating the same statement over and over?
You could e.g. use a look up using a Dictionary:
Dim map = new Dictionary(Of String, Label) From
{
{"2", lblTwos},
{"3", lblThrees},
{"4", lblFours},
{"5", lblFives},
{"6", lblSixes}
}
For Each kvp In map
If moves.Contains(kvp.Key) Then
kvp.value.Visible = True
End If
Next
Other possible ways:
use the Tag property of the controls
name your controls lbl_1, lbl_2 etc. and loop over all elements in moves to find the right control by its name.
Another example:
Dim lbls() As Label = {lblOnes, lblTwos, lblThrees, lblFours, lblFives, lblSixes}
For i As Integer = 0 To lbls.Length - 1
If moves.Contains((i + 1).ToString) Then
lbls(i).Visible = True
Else
' ... possibly do something in here? ...
End If
Next
If you have the luxury of renaming your Labels from lblOnes, lblTwos etc. to lbl1s, lbl2s, then it would simply be:
For i = 1 To 6
Me.Controls("lbl" & i & "s").Visible = moves.Contains(i.ToString())
Next
I propose following idea:
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim moves As String
moves = "1"
Dim controlName As String
controlName = "lbl" + moves
CType(Me.Controls("controlName"), Label).Visible = True
End Sub

Background Worker and SaveDialog

I am very new with Background worker control. I have an existing project that builds file but throughout my project while building files I get the deadlock error.
I am trying to solve it by creating another project that will only consist out of the background worker. I will then merge them.
My problem is I don't know where it will be more effective for my background worker to be implemented and also the main problem is how can I use the SaveDialog with my background worker? I need to send a parameter to my background worker project telling it when my file is being build en when it is done.
This is where my file is being build:
srOutputFile = New System.IO.StreamWriter(strFile, False) 'Create File
For iSeqNo = 0 To iPrintSeqNo
' Loop through al the record types
For Each oRecord As stFileRecord In pFileFormat
If dsFile.Tables.Contains(oRecord.strRecordName) Then
' Loop through al the records
For Each row As DataRow In dsFile.Tables(oRecord.strRecordName).Rows
' Check record id
If oRecord.strRecordId.Length = 0 Then
bMatched = True
Else
bMatched = (CInt(oRecord.strRecordId) = CInt(row.Item(1)))
End If
' Match records
If iSeqNo = CInt(row.Item(0)) And bMatched Then
strRecord = ""
' Loop through al the fields
For iLoop = 0 To UBound(oRecord.stField)
' Format field
If oRecord.stField(iLoop).iFieldLength = -1 Then
If strRecord.Length = 0 Then
strTmp = row.Item(iLoop + 1).ToString
Else
strTmp = strDelimiter & row.Item(iLoop + 1).ToString
End If
ElseIf oRecord.stField(iLoop).eFieldType = enumFieldType.TYPE_VALUE Or _
oRecord.stField(iLoop).eFieldType = enumFieldType.TYPE_AMOUNT_CENT Then
strTmp = row.Item(iLoop + 1).ToString.Replace(".", "").PadLeft(oRecord.stField(iLoop).iFieldLength, "0")
strTmp = strTmp.Substring(strTmp.Length - oRecord.stField(iLoop).iFieldLength)
Else
strTmp = row.Item(iLoop + 1).ToString.PadRight(oRecord.stField(iLoop).iFieldLength, " ").Substring(0, oRecord.stField(iLoop).iFieldLength)
End If
If oRecord.stField(iLoop).iFieldLength > -1 And (bForceDelimiter) And strRecord.Length > 0 Then
strTmp = strDelimiter & strTmp
End If
strRecord = strRecord & strTmp
Next
' Final delimiter
If (bForceDelimiter) Then
strRecord = strRecord & strDelimiter
End If
srOutputFile.WriteLine(strRecord)
End If
Next
End If
Next
Next
You could try this:
Private locker1 As ManualResetEvent = New System.Threading.ManualResetEvent(False)
Private locker2 As ManualResetEvent = New System.Threading.ManualResetEvent(False)
Dim bOpenFileOK As Boolean
Dim myOpenFile As OpenFileDialog = New OpenFileDialog()
Private Sub FileOpener()
While Not bTerminado
If myOpenFile.ShowDialog() = System.Windows.Forms.DialogResult.OK Then
bOpenFileOK = True
Else
bOpenFileOK = False
End If
locker2.Set()
locker1.WaitOne()
End While
End Sub
' Detonator of the action
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim tFileOp As Thread = New Thread(AddressOf FileOpener)
tFileOp.SetApartmentState(ApartmentState.STA)
tFileOp.Start()
' Start BackgroundWorker
BW1.RunWorkerAsync()
End Sub
Private Sub AsyncFunctionForBW(ByVal args As ArrayList)
'[...]
'Change options dinamically for the OpenFileDialog
myOpenFile.Filter = ""
myOpenFile.MultiSelect = True
'Calling the FileDialog
locker1.Set()
locker2.WaitOne()
locker1.Reset()
locker2.Reset()
If bOpenFileOK Then
myStream = myOpenFile.OpenFile()
'[...]
End If
End Sub
It's a little bit complicated but it works.
ManualResetEvents interrupt the execution of code (if they are told to stop) when reached until you use .Set(). If you use .WaitOne() you set it in stop mode, so it will stop again when reached.
This code defines two ManualResetEvents. When you click the Button1 starts the function FileOpener() in a new Thread, and then starts the BackgroundWorker. The FileOpener() function shows a FileOpenDialog and waits in the locker1 so when you use locker1.Set() the function shows the file dialog.
As the myOpenFile is a "global" variable (as well as bOpenFileOK), once the user select the file (or not) you could detect the dialog result (bOpenFileOK) and the selected file.

Bubble Sort logical error VB.NET

This program suppose to sort records(in arySort) in ascending order by last name(index 1 in aryTemp and aryTemp2) and place the result in the list box over the old, preloaded, unsorted records.
It sorts them strangely, I have to click multiple times the Ascending button to get the actual sort result that I suppose to get from clicking the button once.
Why doesn't it sort items with a single mouse click?
The source:
Public Class Form1
Dim FILE_NAME As String = "Students.txt"
Dim numberOfRecords As Integer 'total number of records
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
If System.IO.File.Exists(FILE_NAME) = True Then
Dim objReader As New System.IO.StreamReader(FILE_NAME)
Do While objReader.Peek() <> -1
lstBox.Items.Add(objReader.ReadLine)
numberOfRecords += 1
Loop
objReader.Close()
End If
End Sub
Private Sub btnAscending_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAscending.Click
'load all students into array
Dim arySort(numberOfRecords - 1) As String
Dim aryTemp() As String 'holds first record's last name
Dim aryTemp2() As String 'holds second record's last name
For i = 0 To numberOfRecords - 1
arySort(i) = lstBox.Items(i)
Next
Dim temp As String 'holds temporary record
Dim k As Integer
For i = 0 To arySort.Length - 2
aryTemp = Split(arySort(i), " ")
For k = i + 1 To arySort.Length - 1
aryTemp2 = Split(arySort(k), " ")
If aryTemp(1) < aryTemp2(1) Then
temp = arySort(k)
arySort(k) = arySort(i)
arySort(i) = temp
End If
Next
Next
lstBox.Items.Clear()
numberOfRecords = 0
For i = 0 To arySort.Length - 1
lstBox.Items.Add(arySort(i))
numberOfRecords += 1
Next
End Sub
End Class
If you just need to sort your list (as you say in the comment), don't implement your own sort mechanism but use the one of .NET:
' Define how we want to compare items '
Function compareByLastName(ByVal item1 As String, ByVal item2 As String) As Integer
Return String.Compare(item1.Split(" ")(1), item2.Split(" ")(1))
End Function
Private Sub btnAscending_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAscending.Click
' load all students into array '
Dim arySort(numberOfRecords - 1) As String
For i = 0 To numberOfRecords - 1
arySort(i) = lstBox.Items(i)
Next
' Use built-in .NET magic '
Array.Sort(arySort, AddressOf compareByLastName)
' Write the values back into your list box '
lstBox.Items.Clear()
numberOfRecords = 0
For i = 0 To arySort.Length - 1
lstBox.Items.Add(arySort(i))
numberOfRecords += 1
Next
End Sub
This uses the built-in quicksort algorithm of the .NET class library. Here's the documentation of the method we are using: Array.Sort(T(), Comparison(Of T)).
compare with my working bubble sort:
Public Sub BubbleSort(ByVal arr() As Integer)
Dim flag As Boolean = False
For i As Integer = 0 To arr.Length - 1
For j As Integer = 0 To arr.Length - 2 - i
If arr(j + 1) < arr(j) Then
flag = True
Dim temp As Integer = arr(j)
arr(j) = arr(j + 1)
arr(j + 1) = temp
End If
Next
If flag = False Then Return ' no swaps =>already sorted
Next
End Sub
I see a two major issues with your algorithm:
It's not bubble sort. Bubble sort swaps adjacent elements, i.e., it swaps i with i+1. You, on the other hand, swap some element i with the first j > i where name(i) < name(j). Maybe you should show us, in pseudo code, which algorithm you are actually trying to implement?
aryTemp contains element i and aryTemp2 contains some element j > i. Why do you swap the elements if aryTemp(1) < aryTemp2(1)? Isn't that already the correct order if you want your elements to be sorted ascending?