Create Array of Labels - vb.net

I'm really hoping to find some way to either create an Array of Label() or to create a Label variable with a constructed name using a string. Unfortunately after searching I'm afraid it won't be possible so I'm looking for alternatives as well.
I have a List of Strings, and I would like to create a Label for each one, inside of a Form using System.Windows.Forms. I am hoping to avoid having one large label holding all of the text, or needing to create a large number of predefined labels, as the number of Strings my list contains will vary from 3 or 4 to 30 or higher.
After some trial and error I have managed to get it not crashing, and the information I am setting to the Label is setting correctly, but becomes nothing outside of the For Loop.
Sub CheckResult(ByRef strList As List(Of String))
Dim LineCount As Integer = strList.Count
Dim Line As String
With CheckForm
.size = New System.Drawing.Size(340, (LineCount * 20) + 40 )
.StartPosition = FormStartPosition.CenterScreen
.MaximizeBox = False
.MinimizeBox = False
.Text = CheckType
End With
Dim CheckTextLabel(0 To LineCount - 1) As Label
Dim i As Integer = 0
For Each Line In strList
Line = strList(i)
CheckTextLabel(i) = New Label()
With CheckTextLabel(i)
.Text = Line
.Size = New System.Drawing.Size(320, 20)
.Location = New System.Drawing.Point(10, 10 + (LineCount * 20))
'.Font = MidFont
End With
CheckForm.Controls.Add(CheckTextLabel(i))
'Location 1
i += 1
Next
'Location 2
...
When I check the value of CheckTextLabel(i).Text at Location 1, I get the expected value.
If I check the value of CheckTextLabel(1) or any other value for i at Location 2, it returns a blank result.
Please let me know if there is a way to do this, and if as I fear there is not, I'll accept alternatives

Related

Created a new embed field automatically once one is full? [VB]

Private Async Function cmdList() As Task
Dim m = Context.Message
Dim u = Context.User
Dim g = Context.Guild
Dim c = Context.Client
Dim words As String = ""
Dim embed As New EmbedBuilder With {
.Title = $"Wallpaper keyword list",
.ImageUrl = "https://i.imgur.com/vc241Ku.jpeg",
.Description = "The full list of keywords in our random wallpaper list",
.Color = New Color(masterClass.randomEmbedColor),
.ThumbnailUrl = g.IconUrl,
.Timestamp = Context.Message.Timestamp,
.Footer = New EmbedFooterBuilder With {
.Text = "Keyword Data",
.IconUrl = g.IconUrl
}
}
For Each keyword As String In wall.keywords
words = words + keyword + " **|** "
Next
embed.AddField("Full list", words)
Await m.Channel.SendMessageAsync("", False, embed.Build())
End Function
This is my command to get every word from an array and put it on a field. What I want to know is how do I make it so once the field gets full it'll automatically add a new one and continue with the list. This might be a little far-fetched but just don't know how to go about this. Sorry if I can't understand any of the answers. I'm still a little new to coding on Discord.net and well vb in general.
This is a modification of you hastebin code
Dim row As Integer = 0
Dim words As String = String.Empty
For Each keyword As String In wall.keywords
'If appending the keyword to the list of words exceeds 256
'don't append, but instead add the existing words to a field.
If words.Length + keyword.length + 7 > 256 Then
row += 1
embed.AddField($"List #{row}", words) 'Add words to field
'reset words
words = String.Empty
End If
words = words + keyword + " **|** "
Next
'The add condition within the for loop is only entered when we are
'about to exceed to field length. Anything string under the max
'length would exit the loop without being added. Add it here
embed.AddField($"List #{row + 1}", words)
Await m.Channel.SendMessageAsync("", False, embed.Build())
While it does not change any of the logic, you could consider using a StringBuilder

How do I collapse white space in a list of string that was randomized

I have a list of strings that hold 10 answers.
Each question has a different amount of answers 2-10.
After randomizing the list, I end up with white space or empty spaces in my list depending on the number of answers.
After randomizing the list of let's say 2 answers, i would like to shift them back to position 0 and 1 in my list keeping the size of the list at 10 and of course keeping the order randomized.
I'm not sure how to programmatically solve this problem...
I've tried to sort/reverse the list after randomize, but of course, this removes the randomization.
I've tried to remove the white space with something like
answerlist.RemoveAll(Function(str) String.IsNullOrWhiteSpace(str))
but I then get an out of bounds when trying to write them back to my radiobuttons.text as there are 10 of them.
This is where writing my list of...
RadioAnswer1.Text = answerlist(0)
RadioAnswer2.Text = answerlist(1)
RadioAnswer3.Text = answerlist(2)
RadioAnswer4.Text = answerlist(3)
RadioAnswer5.Text = answerlist(4)
RadioAnswer6.Text = answerlist(5)
RadioAnswer7.Text = answerlist(6)
RadioAnswer8.Text = answerlist(7)
RadioAnswer9.Text = answerlist(8)
RadioAnswer10.Text = answerlist(9)
Ideally, I want the list randomized then however many answers there are written back into the list starting at 0 going down to 10.
I hope my question is clear.
Additional info edit
So here is how I'm loading the answers into the List Of..
Dim answerlist As New List(Of String)
WEFESQLConn.ConnectionString = connectstring
WEFESQLConn.Open()
WERESQLStatment.CommandText = "SELECT * FROM [WEFE Questions] WHERE QuestionID = " & SQLQuestionNum.ToString
WERESQLStatment.Connection = WEFESQLConn
WEFESQLRead = WERESQLStatment.ExecuteReader
If WEFESQLRead.HasRows Then
WEFESQLRead.Read()
lblQuestion.Text = WEFESQLRead.Item("Question").ToString
answerlist.Add(WEFESQLRead.Item("CorrectAnswer").ToString)
answerlist.Add(WEFESQLRead.Item("Answer2").ToString)
answerlist.Add(WEFESQLRead.Item("Answer3").ToString)
answerlist.Add(WEFESQLRead.Item("Answer4").ToString)
answerlist.Add(WEFESQLRead.Item("Answer5").ToString)
answerlist.Add(WEFESQLRead.Item("Answer6").ToString)
answerlist.Add(WEFESQLRead.Item("Answer7").ToString)
answerlist.Add(WEFESQLRead.Item("Answer8").ToString)
answerlist.Add(WEFESQLRead.Item("Answer9").ToString)
answerlist.Add(WEFESQLRead.Item("Answer10").ToString)
answerlist.RemoveAll(Function(str) String.IsNullOrWhiteSpace(str))
WEFESQLRead.Close()
WEFESQLConn.Close()
RadioAnswer1.Text = answerlist(0)
RadioAnswer2.Text = answerlist(1)
RadioAnswer3.Text = answerlist(2)
RadioAnswer4.Text = answerlist(3)
RadioAnswer5.Text = answerlist(4)
RadioAnswer6.Text = answerlist(5)
RadioAnswer7.Text = answerlist(6)
RadioAnswer8.Text = answerlist(7)
RadioAnswer9.Text = answerlist(8)
RadioAnswer10.Text = answerlist(9)
With this code I get the out of bounds as there are not enough answers to populate the answerlist.
Without
answerlist.RemoveAll(Function(str) String.IsNullOrWhiteSpace(str))
I get the spaces in my pre-drawn radio buttons.
I am all ready hiding the unused buttons - the issue there are 10 positions for the buttons and with the randomization of the list.
4 spots of 10 used image
Why don't you toggle the visibility of the controls dynamically after removing the blank entries from the list? Take a look at this example:
'Store all controls in a collection
Dim answers(9) As RadioButton = {RadioAnswer1, RadioAnswer2, RadioAnswer3, RadioAnswer4, RadioAnswer5, RadioAnswer6, RadioAnswer7, RadioAnswer8, RadioAnswer9, RadioAnswer10}
'Iterate through all answers
For index As Integer = 0 To answerlist.Count - 1
'Show the control and set the text
With answers(index)
.Text = answerlist.Item(index)
.Visible = True
End With
Next
'Loop through the rest of the answer controls
For index As Integer = answerlist.Count To answers.Length - 1
'Hide the control
answers(index).Visible = False
Next
Initial setup...
Dim radioButtons As New List(Of RadioButton)
radioButtons.Add(RadioAnswer1)
radioButtons.Add(RadioAnswer2)
...
radioButtons.Add(RadioAnswer10)
After removing blank answers from the randomized list...
For i = 0 To answerList.Count - 1
radioButtons(i).Text = answerList(i)
radioButtons(i).Visible = True
Next
For i = answerList.Count to radioButtons.Count - 1
radioButtons(i).Visible = False
Next
To close this out I ended up going with removing all the spaces from my ListOF then using a DO WHILE for each radiobutton.text entries.
example portion
answerlist = RandomizeListOrder(answerlist)
answerlist.RemoveAll(Function(str) String.IsNullOrWhiteSpace(str))
Dim ALCount As Integer = answerlist.Count
Dim ALCounter = 0
Do
If ALCounter < ALCount Then
ALCounter += 1
RadioAnswer1.Text = answerlist(0)
ElseIf ALCounter = ALCount Then
Exit Do
End If
Maybe not very clean as there are 10 of these entries, but I'll work on that later. Just trying to get the idea out.
Thanks everyone for the suggestions they got me on the right path.

How do I add to this array?

I have an object called pushOrderIncQTY. I can insert one item into the array using the I have an overload which accepts multiple items. My question is: how do I resize the array and add a record to it?
Dim pushOrderIncQTY() As infoPushOrderIncQTY
With pushOrderIncQTY
.costPrice = thisentry.Item("costPrice")
.externalTimeStamp = DateTime.Now()
.RootPLU = thisentry.Item("tagbarcode") 'set this to the barcode from the file
.sizeBit = -666
.supplierID = cfb.SupplierID
.orderReference = thisentry.Item("OrderNumber")
.orderLineReference = ""
.externalTransaction = ""
.sourceShop = cfb.SiteId 'set to the GEMINI location ID for this store (you will have to get this from your configuration file
.destinationShop = cfb.SiteId 'set this to the same as the sourceshop
.QTY = thisentry.Item("ActQty")
.whichQty = LiveSales.infoPushOrderIncQTY.Which_OrderQty.delivered 'only available option at present
End With
Edits here
Ok So i Can go with a list I tested this code and its putting int 16 records fine but how do I get it to go in batches
Dim pushOrderInQty As New List(Of infoPushOrderIncQTY)()
For Each thisentry2 In orderLineData.Rows
With pushOrderIncQTY
.costPrice = thisentry2.Item("costPrice")
.externalTimeStamp = DateTime.Now()
.RootPLU = thisentry2.Item("tagbarcode") 'set this to the barcode from the file
.sizeBit = -666
.supplierID = cfb.SupplierID
.orderReference = thisentry2.Item("OrderNumber")
.orderLineReference = ""
.externalTransaction = ""
.sourceShop = cfb.SiteId 'set to the GEMINI location ID for this store (you will have to get this from your configuration file
.destinationShop = cfb.SiteId 'set this to the same as the sourceshop
.QTY = thisentry2.Item("ActQty")
.whichQty = LiveSales.infoPushOrderIncQTY.Which_OrderQty.delivered 'only available option at present
End With
recordCount = recordCount + 1
pushOrderInQty.Add(pushOrderIncQTY)
Next
CallWebSerivce(wrpPush, request, pushOrderInQty.ToArray())
What I want is the ability to set batch size in cfb.batchsize which is a wrapper for my config file, what I want is say if their is 20 records and batch size is 5 it means the web service should be only called 4 times and not 20 individual times? and the records that get added to list is only 5 till the records set is completed?
You have asked two questions. So here is a separate answer to your second question. You simply need to count the reps within your loop. When you hit your batch size, call your web service and empty your list (to start over with a fresh batch). Like this:
Dim pushOrderInQty As New List(Of infoPushOrderIncQTY)()
For Each thisentry2 In orderLineData.Rows
With pushOrderIncQTY
.costPrice = thisentry2.Item("costPrice")
.externalTimeStamp = DateTime.Now()
'...etc
End With
recordCount = recordCount + 1
pushOrderInQty.Add(pushOrderIncQTY)
If recordCount >= cfb.BatchSize Then
CallWebSerivce(wrpPush, request, pushOrderInQty.ToArray())
pushOrderInQty.Clear()
recordCount = 0
End If
Next
'get the last, partial batch
If pushOrderInQty.Count > 0 Then
CallWebSerivce(wrpPush, request, pushOrderInQty.ToArray())
End If
You can use ReDim to resize any arry, but it wipes the contents. ReDim Preserve will retain the contents.
ReDim Preserve pushOrderIncQTY(5)
'or just make it one element larger, which is something you DO NOT want to do in a loop
Dim oldSize as integer = UBound(pushOrderIncQTY)
ReDim Preserve pushOrderIncQTY(oldSize + 1)
Btw, you could also define it as type List(of pushOrderIncQTY) and then after the list is loaded, you could use the .ToArray() method to convert it to an array.

Adding two column values to listbox in vb.net

I have a table named users which has the following columns in it
User_id,user_name,user_pwd,First_Name,Middle_Name,Last_Name and user_type.
I have dataset named dst and created a table called user in the dataset. Now I want to populate listbox with user_Name, First_Name, Last_name of each and every row in the table user.
I am able to add one column value at a time but not getting how to add multiple column values of each row to listbox
Dim dt As DataTable = Dst.Tables("user")
For Each row As DataRow In dt.Rows
lstUsers.Items.Add(row("User_Name"))
Next
Above code works perfectly but I also want to add First_name as well as last_name to the list box at the same time.
Use same approach as you have, but put all values you want in one string.
Dim dt As DataTable = Dst.Tables("user")
For Each row As DataRow In dt.Rows
Dim sItemTemp as String
sItemTemp = String.Format("{0},{1},{2}", row("User_Name"), row("First_Name"), row("Last_Name"))
lstUsers.Items.Add(sItemTemp)
Next
String.Format() function will call .ToString() on all parameters.
In this case if row(ColumnName) is NULL value then .ToString() return just empty string
You have 2 choices:
Using the ListBox:
To use the ListBox, set the font to one that is fixed width like courier new (so that the columns line up), and add the items like this:
For Each row As DataRow In dt.Rows
lstUsers.Items.Add(RPAD(row("User_Name"),16) & RPAD(row("First_Name"),16) & RPAD(row("Last_Name"),16))
Next
The RPAD function is defined like this:
Function RPAD(a As Object, LENGTH As Object) As String
Dim X As Object
X = Len(a)
If (X >= LENGTH) Then
RPAD = a : Exit Function
End If
RPAD = a & Space(LENGTH - X)
End Function
Adjust the LENGTH argument as desired in your case. Add one more for at least one space. This solution is less than ideal because you have to hard-code the column widths.
Use a DataGridView control instead of a ListBox. This is really the best option, and if you need, you can even have it behave like a ListBox by setting the option to select the full row and setting CellBorderStyle to SingleHorizontal. Define the columns in the designer, but no need to set the widths - the columns can auto-size, and I set that option in the code below. if you still prefer to set the widths, comment out the AutoSizeColumnsMode line.
The code to set up the grid and add the rows goes like this:
g.Rows.Clear() ' some of the below options are also cleared, so we set them again
g.AutoSizeColumnsMode = DataGridViewAutoSizeColumnMode.AllCells
g.CellBorderStyle = DataGridViewCellBorderStyle.SingleHorizontal
g.SelectionMode = DataGridViewSelectionMode.FullRowSelect
g.AllowUserToAddRows = False
g.AllowUserToDeleteRows = False
g.AllowUserToOrderColumns = True
For Each row As DataRow In dt.Rows
g.Rows.Add(row("User_Name"), row("First_Name"), row("Last_Name"))
Next
You might solved your problem by now but other users like me might have issue with it.
Above answers given worked for me even but I found a same answer in a simple way according to what I want..
cmd = New SqlCommand("select User_Name, First_Name, Last_Name from User")
Dim dr As SqlDataReader = cmd.ExecuteReader(YourConnectionString)
If dr.HasRows Then
Do While dr.Read
lst.Items.Add(dr.Item(0).ToString & " " & dr.Item(1).ToString & " " & dr.Item(2).ToString)
Loop
End If
This worked for me, maybe wrong way but I found it simple :)
May I suggest you use a ListView control instead of Listbox?
If you make the switch, here's a sample subroutine you could use to fill it up with the data you said you want. Adapt it the way you like; there's much room for improvement but you get the general idea:
Public Sub FillUserListView(lstUsers As ListView, Dst As DataSet)
Dim columnsWanted As List(Of String) = New List(Of String)({"User_Name", "First_Name", "Last_Name"})
Dim dt As DataTable = Dst.Tables("user")
Dim columns As Integer = 0
Dim totalColumns = 0
Dim rows As Integer = dt.Rows.Count
'Set the column titles
For Each column As DataColumn In dt.Columns
If columnsWanted.Contains(column.ColumnName) Then
lstUsers.Columns.Add(column.ColumnName)
columns = columns + 1
End If
totalColumns = totalColumns + 1
Next
Dim rowObjects(columns - 1) As ListViewItem
Dim actualColumn As Integer = 0
'Load up the rows of actual data into the ListView
For row = 0 To rows - 1
For column = 0 To totalColumns - 1
If columnsWanted.Contains(dt.Columns(column).ColumnName) Then
If actualColumn = 0 Then
rowObjects(row) = New ListViewItem()
rowObjects(row).SubItems(actualColumn).Text = dt.Rows(row).Item(actualColumn)
Else
rowObjects(row).SubItems.Add(dt.Rows(row).Item(actualColumn))
End If
lstUsers.Columns.Item(actualColumn).Width = -2 'Set auto-width
actualColumn = actualColumn + 1
End If
Next
lstUsers.Items.Add(rowObjects(row))
Next
lstUsers.View = View.Details 'Causes each item to appear on a separate line arranged in columns
End Sub

How to change my code to work a certain number of times?

My code gets a list of words from a txt file and chooses the words randomly. However, the same word can appear more than once and i need to know how to stop this from happening?
Here is the code:
Dim aryName As String() = Nothing
aryName = File.ReadAllLines(Application.StartupPath & "\Random\fnames.txt")
Dim randomWords As New List(Of String)
For i = 0 To aryName.Length - 1
If randomWords.Contains(aryName(i)) = False Then
randomWords.Add(aryName(i))
End If
Next
Dim random As New Random
Label2.Text = (randomWords(random.Next(0, randomWords.Count - 1)).ToString)
Maybe this might work, although it's in english and not code :(
if label1.text is changed then
Get label1.text
if label.text becomes this word again then
run the random code
end if
end if
This should prevent immediate repeats:
Dim random As New Random
'Just create a temporary holder for comparison
Dim word As String = Label2.Text
'Run a while loop that works as long as there
'is no change to the word. This should prevent
'back to back repeats.
While word = Label2.Text
word = (randomWords(random.Next(0, randomWords.Count - 1)).ToString)
End While
Label2.Text = word
If you don't want it to repeat ever again, you should probably remove the used word from the randomWords List.
Dim random As New Random
Label2.Text = (randomWords(random.Next(0, randomWords.Count - 1)).ToString)
randomWords.Remove(Label2.Text)
You can a) remove the selected word from the list, or b) you can random sort the list first.
Option a) is already addressed in another answer
Option b) lets you retain all the words in memory. Here is the code:
Dim randomWords As New List(Of String)(File.ReadAllLines(Application.StartupPath & "\Random\fnames.txt"))
Dim random As New Random
randomWords.Sort(Function(s1 As String, s2 As String) random.Next(-1, 1))
For index As Integer = 0 To randomWords.Count - 1
Label2.Text = randomWords(index)
Next
Modify your For loop to prevent dupes in aryName from getting into randomWords:
For i = 0 To aryName.Length - 1
If randomWords.Contains(aryName(i)) = False Then
randomWords.Add(aryName(i))
End If
Next