Export DataGridView to text file keeping columns lined up - vb.net

I am working on project for school, using VB, I am working in Visual Studio 2017.
I have a DataGridView which I need to export to a Text File.
I could use some help with an export feature from VB to a Text file. Here is the code I am using:
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim numCols As Integer = dgvApplianceList.ColumnCount
Dim numRows As Integer = dgvApplianceList.RowCount - 1
Dim strDestinationFile As String = "exportappliance.txt"
Dim tw As TextWriter = New StreamWriter(strDestinationFile)
'writing the header
For count As Integer = 0 To numCols - 1
tw.Write(dgvApplianceList.Columns(count).HeaderText)
If (count <> numCols - 1) Then
tw.Write(vbTab)
End If
Next
tw.WriteLine()
For count As Integer = 0 To numRows - 1
For count2 As Integer = 0 To numCols - 1
tw.Write(dgvApplianceList.Rows(count).Cells(count2).Value)
If (count2 <> numCols) Then
tw.Write(vbTab)
End If
Next
tw.WriteLine()
Next
tw.Close()
End Sub

Since you are writing to a “text” file, one way to line up text properly can be accomplished using spaces as others have suggested. This would require that you have a “defined” column “width” for each column. Using your picture as an example, column 0 (zero) would be “Appliance Type” and we could give that column a max “width” of… say twenty five (25) characters wide. Column 2 “kwh” could be set with a maximum column width of 15 and so on for each column.
With the “column widths” established, it should be a simple matter of adding X number of spaces needed to fill the string to the columns width. Example, to make sure column 2 lines up with the next column 2, each column 1 string MUST be all the same length. By filling each column 1 string with spaces to “fill” the string to column 1’s length, will ensure column 2’s text will line up correctly. Obviously, the same logic applies to subsequent columns.
The GetBufferedString method (below) demonstrates one way to buffer the strings to a specified column width. The method takes a string originalString, an int maxLength and a justification type. The method will return a string of length maxLength such that, if the justification type is LEFT, the method will fill the given string with spaces at the end. If the justification type is RIGHT, the method will return a string of maxLength such that spaces are added to the front of the string. Finally, if the justification type is CENTER, then the method will return a string with half the spaces in front of the string and the other half at the end. If the given string’s length is greater than maxLength, then the returned string will be a maxLength truncation of the given string.
This should enable you to set each columns justification type independently. The code below simply sets each rows justification type to right.
This is an example and I hope it helps, however there is no error checking for a possible mismatch on the number of actual columns in the grid and the number of column widths.
Some global variables… an integer array columnLengths is used to hold each columns width… also an enumeration for the justification type; RIGHT, LEFT, CENTER.
Dim columnLengths(6) As Integer
Enum JustifyType
LEFT
RIGHT
CENTER
End Enum
Set each columns width…
Private Sub FillColumnLength()
columnLengths(0) = 25
columnLengths(1) = 12
columnLengths(2) = 12
columnLengths(3) = 12
columnLengths(4) = 12
columnLengths(5) = 12
End Sub
An updated save button click event to use the GetBufferedString method.
Private Sub btnSave_Click(sender As Object, e As EventArgs) Handles btnSave.Click
Dim numCols As Integer = dgvApplianceList.ColumnCount
Dim numRows As Integer = dgvApplianceList.RowCount - 1
Dim strDestinationFile As String = "D:\Test\exportappliance.txt"
Dim tw As TextWriter = New StreamWriter(strDestinationFile)
Dim textToOutput = ""
For count As Integer = 0 To numCols - 1
textToOutput = GetBufferedString(dgvApplianceList.Columns(count).HeaderText, columnLengths(count), JustifyType.CENTER)
tw.Write(textToOutput)
Next
tw.WriteLine()
For count As Integer = 0 To numRows - 1
For count2 As Integer = 0 To numCols - 1
textToOutput = GetBufferedString(dgvApplianceList.Rows(count).Cells(count2).Value, columnLengths(count2), JustifyType.RIGHT)
tw.Write(textToOutput)
Next
tw.WriteLine()
Next
tw.Close()
End Sub
Finally, the GetBufferedString method.
Private Function GetBufferedString(originalString As String, maxLength As Int16, justifyType As JustifyType) As String
If (originalString.Length < maxLength) Then
Dim bufString = Space(maxLength - originalString.Length)
Select Case justifyType
Case JustifyType.LEFT
Return originalString + bufString
Case JustifyType.RIGHT
Return bufString + originalString
Case JustifyType.CENTER
Dim halfString = bufString.Substring(bufString.Length / 2)
originalString = halfString + originalString
bufString = Space(maxLength - originalString.Length)
Return originalString + bufString
Case Else
Return ""
End Select
Else
Return originalString.Substring(0, maxLength)
End If
End Function
Hope this helps.

Related

create 1000, 8-character random ID's, all unique and display in a text box

enter image description hereWrite a program to display 1000 8-character random user IDs in a text box after you click a button. Make sure the program verifies that none of the IDs are identical. Each userid should include a mixture of alphabetic characters and numbers.
What I have so far, which could be enough to get by as a random ID generator alone, but it does not loop 1000 times to be displayed in the label, and doesn't check for repeated ID's.
Public Class Form1
Private Sub btnGenerateRandomID_Click(sender As Object, e As EventArgs) Handles btnGenerateRandomID.Click
Dim rand As New Random
Dim char1 As String
Dim char2 As String
Dim char3 As String
Dim char4 As String
Dim char5 As String
Dim char6 As String
Dim char7 As String
Dim char8 As String
char1 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
char2 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
char3 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
char4 = ChrW(rand.Next(Asc("A"), Asc("Z") + 1))
char5 = rand.Next(0, 9)
char6 = rand.Next(0, 9)
char7 = rand.Next(0, 9)
char8 = rand.Next(0, 9)
lblRandomId.Text = char1 + char2 + char3 + char4 + char5 + char6 + char7 + char8
End Sub
End Class
Thanks.
EDIT:
Public Class Form1
'Write a program to display 1000 8-character random user IDs in a text
'box after you click a button. Make sure the program verifies that none Of the IDs are identical.
'Each userid should include a mixture Of alphabetic characters And numbers.
Private Sub btnGenerateRandomID_Click(sender As Object, e As EventArgs) Handles btnGenerateRandomID.Click
Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
Dim rand As New Random
Dim strID As String = ""
For count_ids As Integer = 0 To 999
For count_chars As Integer = 0 To 7
strID += strChar(rand.Next(0, 62))
Next count_chars
lblRandomId.Text = strID
Next
End Sub
End Class
Here is the actual question "Q. Write a program to display 1000 8-character random user IDs in a text box after you click a button. Make sure the program verifies that none of the IDs are identical. Each userid should include a mixture of alphabetic characters and numbers.
Explain your program in your essay, with screenshots. Include a paragraph on the random number generator used in Visual Basic, and answer the question: how should the random number generator be best seeded?"
First of all, Welcome to StackOverflow,
From what i understand from your post you want to generate 1000 8 Character long Unique ID's
First of all we declare our variables
Dim Characters As String = "AZERTYUIOPQSDFGHJKLMWXCVBN0123456789" 'Declare All Characters on one string
Dim IDsList As New List(Of String) With {.Capacity = 1000} 'You can limit the capacity to 1000
Dim Id As String = ""
Dim Rand As New Random
Now we begin to genearte ID's and add them to IDsList using a nested loop
For i As Integer = 0 To 999 'This is a Zero Based Index so 999 is actually 1000
For _i As Integer = 0 To 7 'This also means 7 is 8
Id += Characters(Rand.Next(0, 36))
Next
IDsList.Add(Id)
Id = ""
Next
'You can Check for duplicates by adding this piece of code or use the next one instead
Dim NoDupesIDsList As New List(Of String)
NoDupesIDsList = IDsList.Distinct.ToList
For i As Integer = 0 To 999 'This is a Zero Based Index so 999 is actually 1000
For _i As Integer = 0 To 7 'This also means 7 is 8
Id += Characters(Rand.Next(0, 36))
Next
If not IDsList.contains(Id) then
IDsList.Add(Id)
End if
Id = ""
Next
Use a Textbox with multiline and scroll bar for better experience
Feel free to ask me anything via comments
PS: I tested my method and it's working , enjoy it !
This function will return the ASCII characters between 48 an 122. That will include some characters that are not letters or numbers but this makes the ids even more unique and simplifies the code.
The For loop builds the ids with a length of 8. Then the id is checked for uniqueness with the .Contains method. Only if it is not in the list, it is added to the list and the counter is incremented.
Private Rnd As New Random
Private Function GetListOfIDs() As List(Of String)
Dim Counter As Integer
Dim lst As New List(Of String)
Dim id As String = ""
Do While Counter < 1000
id = ""
For i = 0 To 7
id &= Chr(Rnd.Next(48, 123))
Next
If Not lst.Contains(id) Then
lst.Add(id)
Counter += 1
End If
Loop
Return lst
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lst = GetListOfIDs()
TextBox1.Text = String.Join(vbCrLf, lst)
End Sub
EDIT
As per suggestion by Caius Jard in comments I have added a solution using a HashSet. Same idea only a HashSet will not accept duplicate entries. The .Add method returns a boolean telling you if the Add was successful.
Private Function GetListOfIDs() As HashSet(Of String)
Dim hs As New HashSet(Of String)
Dim id As String = ""
Do While hs.Count < 1001
id = ""
For i = 0 To 7
id &= Chr(Rnd.Next(48, 123))
Next
If hs.Add(id) Then
Counter += 1
End If
Loop
Return hs
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim hs = BuildHashSet()
TextBox1.Text = String.Join(vbCrLf, hs)
End Sub
This method is probably more efficient because a HashSet is designed for hight performance. For 1000 items I did not notice any difference in the user interface. The text box updated immediately with both methods.
This will create the names:
Function RandomName(length As Integer) As String
Shared rnd As New Random()
Shared corpus() As Char = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray()
Return New String(Enumerable.Range(0, length).Select(Function(c) corpus(rnd.Next(corpus.Length))).ToArray())
End Function
Iterator Function GetUniqueNames(length As Integer, count As Integer) As IEnumerable(Of String)
Dim names As New HashSet(Of String)
For i As Integer = 0 To count
Dim name As String = RandomName(length)
While names.Contains(name)
'Potential (but unlikely) halting problem
name = RandomName(length)
End While
names.Add(name)
Yield name
Next
End Function
Dim uniqueNames = GetUniqueNames(8, 1000)
But do you really want to display 1000 of them in a single label?
lblRandomId.Text = string.Join(vbCrLf, uniqueNames)
Let's talk about your code.
Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
This assignment will work in your loop because a String is really an array of Char. This is why you can refer to an index in the string.
Dim rand As New Random()
The .net Random class provides a seed for Random based on system time. Only rarely would you want to provide a seed.
From the docs https://learn.microsoft.com/en-us/dotnet/api/system.random?view=netcore-3.1
CONSTRUCTORS
Random() Initializes a new instance of the Random class
using a default seed value.
Random(Int32) Initializes a new instance of the Random class, using
the specified seed value.
For count_ids As Integer = 0 To 999
A For loop is not appropriate for this problem. We only want to increment the counter if we get a unique ID. The above For loop will increment on every iteration.
Do While Counter < 1000
'Code here
Loop
Notice in my code the counter is only incremented if the ID is unique.
The following loop should work fine but above this code we need to reset strID to an empty string. Otherwise we will have a very long string.
For count_chars As Integer = 0 To 7
strID += strChar(rand.Next(0, 62))
Next count_chars
You should not update the user interface (the label) on each iteration of the loop. Repainting the screen is one of the slowest operations in code. This line will overwrite the string in the label on every iteration.
lblRandomId.Text = strID
Move the update of the UI to after both loops are complete
Your code never checks for duplicates.
Now let's fix it.
We use a List(Of T) to accumulate the IDs. The T stands for Type; in our case it is String. A List is like an array only you don't have to know ahead of time how many entries there will be. No ReDim Preserve required.
Moved Dim strID As String = "" to the beginning of the inner loop so we will get a new strID on each iteration of the outer loop.
Changed strID &= strChar(rand.Next(0, 62)). &= instead of +=. In VB.net we use the ampersand to concatenate strings although the plus sign will work. The .Next method of the Random class has an overload that takes 2 Integers. It is inclusive of the first and exclusive of the second which means (0, 62) will return numbers form 0 to 61. Your string with a length of 62 has indexes of 0 to 61.
Next we check for duplicates with the .Contains method of the List class. This method does just what you would expect. We pass the new ID to the method and it returns a Boolean telling if the string is already in the list.
If it is not in the list, we add it to the list and increment the counter. The counter is only incremented if we have a successful add.
Finally we update the user interface by using a method of the String class. the .Join method takes a separator and the list to join. The TextBox must be multiline and have scroll bars.
I changed the names of the controls so I could test it in my testing program.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lst As New List(Of String)
Dim strChar As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
Dim rand As New Random()
Dim counter As Integer
Do While counter < 1000
Dim strID As String = ""
For count_chars = 0 To 7
strID &= strChar(rand.Next(0, 62))
Next
If Not lst.Contains(strID) Then
lst.Add(strID)
counter += 1
End If
Loop
TextBox1.Text = String.Join(vbCrLf, lst)
End Sub
EDIT
The official documentation for this method can be found here.
https://learn.microsoft.com/en-us/dotnet/api/system.string.join?view=netcore-3.1
I know it will be difficult to read but just take a look. Eventually you will be able to understand it and will be using these docs a lot.
String.Join(separator, List(Of String))
The separator is what to put between the strings in the list. In our case that is vbCrLf which is a vb constant for new line. Cr = Carraiage Return and Lf = Line Feed. Other types of collections that contain strings can also use this method.
The method takes each string in the list and adds the separator. After it is done with the list it returns one long string which we display in the TextBox.

Report's textbox function call from ControlSource not firing

Firstly, here's a pic on my report in design mode:
The underlying query for the report returns values like so:
Allen Nelli 3:A,5:B,7:A,8:A, etc.
Breton Micheline 1:A,3:A,5:B,7:A, etc
Caporale Jody 1:A,3:A,5:B,7:A, etc
I had to use a subquery to get the third field which concatenates the number : letter combinations. These values actually represent day of month and designation to a particular shift in a schedule. So basically, for a given month, each individual works the designated shift indicated by the day value.
The intention is to call a user defined public function named PopulateTextboxes(Value as String) to be called from the first textbox in the report from the textbox's ControlSource property. The third field in the query is actually named Expr1 and that is being passed as a parameter to the function. The function is designed to populate all the textboxes with the appropriate letter designation: A or B or C or D, etc. The function itself is not being fired when I run the report.
The function is as follows:
Public Function PopulateTextboxes(Expr As String) As String
'Each element of Expr should be a number followed by a colon followed by a letter: 10:A,12:B,15:C, etc.
Dim shiftData() As String
Dim Data As Variant
Dim i As Integer
Dim j As Integer
Dim temp() As String
Dim txt As TextBox
Dim rpt As Report
Dim strCtrl As String
If Expr = "" Then Exit Function
If IsNull(Expr) Then Exit Function
shiftData = Split(Expr, ",")
If UBound(shiftData) > 0 Then
'Make a 2D array
ReDim Data(UBound(shiftData), 2)
'Load up 2D array
For i = 0 To UBound(shiftData) - 1
If shiftData(i) <> "" Then
temp = SplitElement(shiftData(i), ":")
Data(i, 0) = temp(0)
Data(i, 1) = temp(1)
End If
Next i
Set rpt = Reports.item("Multi_Locations_Part_1")
If UBound(days) = 0 Then
MsgBox "days array not populated"
Exit Function
End If
'Populate each Textbox in the Multi_Locations_Part_1 Report
For i = 1 To UBound(days)
strCtrl = "txtDesig_" & CStr(i)
Set txt = rpt.Controls.item(strCtrl)
For j = 0 To UBound(Data) - 1
If Data(j, 0) = days(i) Then
txt.Value = Data(j, 1) 'A,B,C,etc.
Exit For
End If
Next j
Next i
End If
PopulateTextboxes = Expr
End Function
Private Function SplitElement(Value As String, Delim As String) As String()
Dim result() As String
result = Split(Value, Delim)
SplitElement = result
End Function
Please advise.
The best way is to call your function from the Format event of the Detail section, so it will be called for each record.
Private Sub Detail_Format(Cancel As Integer, FormatCount As Integer)
Call PopulateTextboxes(Me.Expr1)
End Sub
If PopulateTextboxes is in a separate module, I suggest to pass Me as additional parameter for the report, so you don't have to hardcode the report name.
Also note that you need the Set keyword when assigning object variables, e.g.
Set txt = rpt.Controls.item("txtDesig_" & CStr(i))

Generate unique serial number incrementally

I am writing a vb.net program to generate a three digit serial number I will use in printing a barcode.
The requirements are the counter must count:
001 - 999, A00 - A99, B00 - B99, ..., Z00 - Z99
I cannot use the letters O and I
This code simply increments the value I pass to it by 1. I first check if the value is <=998 and if so return the value in 3 digits. I had to put this in a Try statement because passing the value 'A00' caused an error.
The code is still breaking once I hit Z99.
Problem: If the next serial number = Z90 and the user wants to print 35 barcodes I need to stop the operation before it begins and warn the user there are only 10 avail serial numbers remaining
Also, I am also hoping for advice on how I could have accomplished this in a better manner, any advice would be greatly appreciated
Public Shared Function NextSerial(ByVal value As String) As String
Try
If value <= 998 Then
value += 1
Return ZeroPad(value, 3)
End If
Catch ex As Exception
End Try
Const chars As String = "ABCDEFGHJKLMNPQRSTUVWXYZ"
Dim threenumber As String = ZeroPad(value, 3) 'ensure value is 3 digits.
Dim alpha As String = threenumber.Substring(0, 1).ToUpper() ' 1st digit
Dim beta As String = threenumber.Substring(1, 2) 'remaining two digits
Dim newNumber As String
Dim nextletter As String
If beta = "99" Then
beta = "00"
nextletter = chars.Substring((chars.IndexOf(alpha, System.StringComparison.Ordinal) + 1), 1)
newNumber = nextletter + beta
Return newNumber
Else
beta += 1
newNumber = alpha + ZeroPad(beta, 2)
Return newNumber
End If
End Function
Private Shared Function ZeroPad(ByVal number As String, ByVal toLength As Integer) As String
ZeroPad = number
'add the necessary leading zeroes to build it up to the desired length.
Do Until Len(ZeroPad) >= toLength
ZeroPad = "0" & ZeroPad
Loop
End Function
I think you can do this by assuming your first character is the 'hundreds' and converting to a number and incrementing:
Private Function NextSerial(value As String) As String
Const chars As String = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"
Dim numericValue As Integer = 100 * (chars.IndexOf(value.Substring(0, 1))) + Integer.Parse(value.Substring(1, 2))
numericValue += 1
Return chars.Substring(numericValue \ 100, 1) + (numericValue Mod 100).ToString.PadLeft(2, "0")
End Function
You should of course perform some error checking at the start of the function to make sure a valid serial number has been handed into the function. I would also put this function into a class and add functions such as isValid, SerialsRemaining and perhaps a function to retrieve a list of multiple serials.
I created constant strings that represent every available character in each digit position. I then used indexing to lookup the positions of the current serial number & moved one number forward to get the next serial. This will always provide the next serial until you run out of numbers.
Note: this code can easily be made more compact, but I left it as-is thinking it might be clearer.
Const charString1 As String = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ"
Const charString2 As String = "0123456789"
Const charString3 As String = "0123456789"
Public Function NextSerial(ByVal value As String) As String
' ensures the input is three chars long
Dim threenumber As String = Right("000" & value, 3)
Dim char1 As String = threenumber.Substring(0, 1)
Dim char2 As String = threenumber.Substring(1, 1)
Dim char3 As String = threenumber.Substring(2, 1)
Dim char1Pos As Integer = charString1.IndexOf(char1)
Dim char2Pos As Integer = charString2.IndexOf(char2)
Dim char3Pos As Integer = charString3.IndexOf(char3)
If char1Pos = -1 Or char2Pos = -1 Or char3Pos = -1 Then Throw New Exception("Invalid serial number format")
' move to next serial number
char3Pos += 1
If char3Pos > charString3.Length() - 1 Then
char3Pos = 0
char2Pos += 1
End If
If char2Pos > charString2.Length() - 1 Then
char2Pos = 0
char1Pos += 1
End If
If char1Pos > charString1.Length() - 1 Then Throw New Exception("Out of serial numbers!")
Return charString1.Substring(char1Pos, 1) & charString2.Substring(char2Pos, 1) & charString3.Substring(char3Pos, 1)
End Function
I suggest you use integer for all your check and calculation and only convert to serial number for display. It'll be a lot easier to know how many serial number are remaining.
Your serial number is similar to integer except everything over 100 is a letter instead of a number.
Note: It's very important to add error checking, this assumes that all input are valid.
Module Module1
Sub Main()
Console.WriteLine(SerialNumber.ConvertSerialNumberToInteger("D22"))
Console.WriteLine(SerialNumber.ConvertIntegerToSerialNumber(322))
Console.WriteLine(SerialNumber.GetAvailableSerialNumber("Z90"))
For Each sn As String In SerialNumber.GetNextSerialNumber("X97", 5)
Console.WriteLine(sn)
Next
Console.ReadLine()
End Sub
End Module
Class SerialNumber
Private Const _firstPart As String = "ABCDEFGHJKLMNPQRSTUVWXYZ"
Public Shared Function ConvertSerialNumberToInteger(ByVal serialNumber As String) As Integer
Return (_firstPart.IndexOf(serialNumber(0)) * 100) + Integer.Parse(serialNumber.Substring(1, 2))
End Function
Public Shared Function ConvertIntegerToSerialNumber(ByVal value As Integer) As String
Return _firstPart(value \ 100) & (value Mod 100).ToString("00")
End Function
Public Shared Function GetAvailableSerialNumber(ByVal serialNumber As String)
Dim currentPosition As Integer
Dim lastPosition As Integer
currentPosition = ConvertSerialNumberToInteger(serialNumber)
lastPosition = ConvertSerialNumberToInteger("Z99")
Return lastPosition - currentPosition
End Function
Public Shared Function GetNextSerialNumber(ByVal serialNumber As String, ByVal amount As Integer) As List(Of String)
Dim newSerialNumbers As New List(Of String)
Dim currentPosition As Integer
currentPosition = ConvertSerialNumberToInteger(serialNumber)
For i As Integer = 1 To amount
newSerialNumbers.Add(ConvertIntegerToSerialNumber(currentPosition + i))
Next
Return newSerialNumbers
End Function
End Class

Check String for identical Digits

I'm asking my users to enter a 4 - 6 digit numberic PIN. And I'd like to make sure users can't enter 0000 or 11111 or 333333. How can I check a string for 4 consecutive identical digits? I'm using vb.net.
See code snippet below:
Sub Main()
Dim a As String = "001111"
Dim b As String = "1123134"
Dim c As String = "1111"
Console.WriteLine(CheckConsecutiveChars(a, 4)) 'True => Invalid Pin
Console.WriteLine(CheckConsecutiveChars(b, 4)) 'False => Valid Pin
Console.WriteLine(CheckConsecutiveChars(c, 4)) 'True => Invalid Pin
Console.ReadLine()
End Sub
'maxnumber = maximum number of identical consecutive characters in a string
Public Function CheckConsecutiveChars(ByVal j As String, ByVal maxNumber As Integer) As Boolean
Dim index As Integer = 0
While ((index + maxNumber) <= j.Length)
If (j.Substring(index, maxNumber).Distinct.Count = 1) Then
Return True
End If
index = index + 1
End While
Return False
End Function
The method String.Distinct.Count() counts the number of distinct characters in a string. You cast your digit to a String and test for the number of different characters. If the result is 1 then the user has entered the same number.
Note: If you're using the Substring, you must check the length of the string first (is it long enough) to avoid exceptions.
This answer is similar to the accepted answer, but does not create lots of temporary strings in memory.
'maxnumber = maximum number of identical consecutive characters in a string
Public Function HasConsecutiveChars(ByVal j As String, ByVal maxNumber As Integer) As Boolean
Dim result As Boolean = False
Dim consecutiveChars As Integer = 1
Dim prevChar As Char = "x"c
For Each c in j
If c = prevChar Then
consecutiveChars += 1
If consecutiveChars >= maxNumber Then
result = True
Exit For
End If
Else
consecutiveChars = 1
End If
prevChar = c
Next
Return result
End Function

How to get each value in an array and show it in a listbox

Hi I am new to VB and I have problems with using array. My code is like that.
This is class FindFactorsObject.vb
Public Sub FindFactors()
count = 0
temp = Convert.ToInt32(Math.Sqrt(_x))
For i As Integer = 1 To temp
If _x Mod i = 0 Then
ReDim array(count)
array(count) = i
count += 1
End If
Next
So I created an array and stored the results. Now I want to display each value in my array in Form.vb and if it is possible can somebody teach me how to make delay for each of the displayed value. Thanks very much
Always declare your variables, if possible to their exact types, you think they will take care of. When you say 'Now I want to display each value in my array in Form.vb' I understood literally: in the Form so, we will print them on your form
Public Sub FindFactors(_x As Integer)
Dim temp As Integer = Convert.ToInt32(Math.Sqrt(_x))
Dim l As New List(Of Integer)
For i As Integer = 1 To temp
If _x Mod i = 0 Then
l.add(i)
End If
Next
Dim pf As New PointF(20, 20)
For Each i As Integer In l
creategraphics.drawstring(i.ToString, New font(font.fontFamily, 24), brushes.cadetblue, pf)
pf = New PointF(pf.X, pf.Y + 30)
Next
End Sub