VB Avoiding text box that is occupied - vb.net

I am making an application where there is a form with a column of text boxes that are filled from two different forms with a button on each. when the button of these forms are clicked they input the results into the text boxes in the column.
the problem I am having is that say i click (form2.button 1) three times it will occupy text boxes 1,2 and 3. Now say I want to use (form1.button 1) to input data into text box 4 it will occupy text box 1.
I have each button set up for multiple clicks so I would like to understand how i can have is so say(form2.button 1) is clicked then (form1.button1) will go to 2nd click for example. there are 10 text boxes so I will need it so that they react to how many times each has been clicked.

Assuming the TextBoxes were called TextBox1 thru TextBox10, you could use a sub like this:
Public Sub AddValue(ByVal value As String)
For i As Integer = 1 To 10
Dim tbName As String = "TextBox" & i
Dim matches() As Control = Me.Controls.Find(tbName, True)
If matches.Length > 0 AndAlso TypeOf matches(0) Is TextBox Then
Dim tb As TextBox = DirectCast(matches(0), TextBox)
If tb.Text.Trim.Length = 0 Then
tb.Text = value
Exit Sub
End If
End If
Next
MessageBox.Show("All TextBoxes are already taken!")
End Sub

Why not just store a counter variable in the form that contains the textboxes, say NextTextBoxNumber that increments each time a textbox is filled in and then you know exactly which textbox to go to next based upon the value of this variable?
Also, to continue with #Oded's comment, you can easily accomplish what he meant using something along the lines of If Textbox1.Text <> "" Then ...
Does that make sense??

Related

Rename TextBoxes on Form after Copying it into a new multipage

I'm dealing with this issue. I have a userform that addapts after the user enters a value (for example, if he wants to add 3 members, the user form creates 3 different pages with the same boxes, after renaming them).
I have this right now:
After pressing "Lanzar", the userform will create more pages with "Datos Educando 2", "Datos Educando 3"... and so on, taking the value introduced on "Educandos a inscribir:"
The code is the following:
Private Sub lanzar_numero_educandos_Click()
Dim l As Double, r As Double
Dim ctl As Control
Me.MultiPage1.Pages(1).Visible = True
If Me.MultiPage1.Pages.Count > 2 Then
For a = Me.MultiPage1.Pages.Count - 1 To 2 Step -1
Me.MultiPage1.Pages.Remove a
Next a
End If
Me.MultiPage1.Pages(1).Visible = True
If educandos_a_inscribir.Value <> 1 Then
For a = 1 To educandos_a_inscribir.Value
MultiPage1.Pages.Add
MultiPage1.Pages(a).Controls.Copy
MultiPage1.Pages(a + 1).Paste
For Each ctl In MultiPage1.Pages(a).Controls
If TypeOf ctl Is MSForms.Frame Then
l = ctl.Left
r = ctl.Top
Exit For
End If
Next
For Each ctl In MultiPage1.Pages(a + 1).Controls
If TypeOf ctl Is MSForms.Frame Then
ctl.Left = l
ctl.Top = r
Exit For
End If
Next
Me.MultiPage1.Pages(a + 1).Caption = "Datos Educando " & a
Next a
Me.MultiPage1.Pages(1).Visible = False
End If
End Sub
Now, the problem I have is that the pages generated with this code have random names on each TextBox, so I'm not able to locate the information introduced from the user.
For example, this is the first page (the one that has the names I already know):
Here, the TextBox "Nombre Educando" is called "nombre_educando_1", so I can locate it easily on code:
The Textboxes created when copying the first page, have random names (like "TextBox 34", "TextBox 35"... and so on), so I'm not able to controll how are they called.
There is a way of generate the pages editing the TextBox names? Like, for example, for the second page generated, the TextBox in the example above should be "nombre_educando_2" and so on.
Thanks!
Each control on the first page has an attribute named Tag. You can value these with unique and meaningful values. When you paste the controls to the new page the Tag values will follow. Then as you loop through the controls on any page, use a Select Ctl.tag statement to identify what to do with the value of the control.

Highlight sets of matches within textbox

Upon first inspection, I surmised this would be a straightforward task (maybe it still is!), yet I am having difficulty. Suppose I have a form with 1000 textboxes, where each textbox contains randomly distributed, yet in many cases matching strings. For example, the below may be found in any one if the 1000 textboxes:
AAAA-XXXX
AAAA-XXXX
BBBB-XXXX
BBBB-XXXX
CCCC-XXXX
CCCC-XXXX
...
How might I loop through the textboxes, identify all the matching examples and highlight the textbox.backcolor where the matches occur? The backcolor should be the same for the exact matches, yet different for each unique set of matches. There could be as many as 100 different sets!
Just whipped together a working test project, this is the kind of approach I'd take. It avoids comparing every textbox to every other textbox. I've commented it all up for you :)
Private Sub SetBoxColors()
'The keys are textbox texts, the values are the number of times it occurs
Dim UniqueTextsAndUsage As New Dictionary(Of String, Integer)
Dim FirstInstanceTextBoxes As New List(Of TextBox)
'The keys are textbox texts, the values are the colour for the box
Dim UniqueColors As New Dictionary(Of String, System.Drawing.Color)
'Iterate over all the text boxes
' Substitute Me for your Form instance if necessary
For Each TBox As Control In Me.Controls
'Skip things that aren't textboxes
If Not TypeOf TBox Is TextBox Then
Continue For
End If
'If we have seen this textbox text before
If UniqueTextsAndUsage.ContainsKey(TBox.Text) Then
'Increase the usage
UniqueTextsAndUsage(TBox.Text) += 1
If UniqueTextsAndUsage(TBox.Text) = 2 Then
'This is the second usage, generate a colour for this set of boxes
UniqueColors.Add(TBox.Text, GenerateColor(UniqueColors.Count + 1))
End If
'Colour this textbox
' (it won't get the first instance of each unique string)
TBox.BackColor = UniqueColors(TBox.Text)
Else
'We have NOT seen this textbox text before
'Add the first occurence of the text
UniqueTextsAndUsage.Add(TBox.Text, 1)
'Mark this textbox as one we may have to colour later
FirstInstanceTextBoxes.Add(TBox)
End If
Next
'Colour all the first instances
For Each TBox As TextBox In FirstInstanceTextBoxes
'Check there are sufficient uses of this text
If UniqueTextsAndUsage(TBox.Text) > 1 Then
TBox.BackColor = UniqueColors(TBox.Text)
End If
Next
End Sub
Private Function GenerateColor(Id As Integer) As System.Drawing.Color
'Needs more thought - often too dark
Dim KnownColourByIdNumber As System.Drawing.KnownColor = Id
Return System.Drawing.Color.FromKnownColor(KnownColourByIdNumber)
End Function
The GenerateColor function needs more thought so that it generates some nicer colours but I leave that to you.
You may also need a reset that sets every box to the DefaultControl color or whatever it's called, and run that at the top of SetBoxColors.
You can do this
Dim strText As String
For Each TextBox1 As System.Windows.Forms.TextBox In Me.Controls
strText = TextBox1.Text
For Each TextBox2 As System.Windows.Forms.TextBox In Me.Controls
If strText = TextBox2.Text AndAlso TextBox2.Name <> TextBox1.Name Then
TextBox2.BackColor = Color.Red ' or whatever you want to use
TextBox1.BackColor = Color.Red
End If
Next
Next

Is there a way to find the length of several variables at the same time?

I am trying to detect empty text boxes when a button is pressed. To do so I am using an if statement for each variable like so:
If Len(variable.Text) = 0 Then
Messagebox.Show("please fill in all fields.")
End If
Is there a more efficient way where I can detect if the lengths of the strings within all the text boxes are equal to zero at the same time? Or if anyone wants to suggest a better method that would also be appreciated. Thanks.
This would do, assuming the textboxes are in the same form as of the validation button
Dim ctrl As Control
For Each ctrl In Me.Controls ' panelname.controls etc
If (ctrl.GetType() Is GetType(TextBox)) Then
If Trim(ctrl.Text) = "" Then
MessageBox.Show("please fill in all fields.")
Exit Sub
End If
End If
Next
OR
Dim ctrl As Control
Dim count As Integer
count = 0
For Each ctrl In Me.Controls ' panelname.controls etc
If (ctrl.GetType() Is GetType(TextBox)) Then
If Trim(ctrl.Text) = "" Then count += 1
'you can add exceptions by textbox name also by getting ctrl.Name
End If
Next
If count > 0 Then
MessageBox.Show("please fill in all fields.")
End If
That's the way to go. (:
If you want to check if all textboxes are empty (or in other words: is it possible to leave some textboxes empty or not) you could use something like this:
'if some textboxes can be empty
IF a="" AND b="" AND c="" Then Messagebox.Show("please fill in all fields.")
'if no textbox can be empty
IF a="" OR b="" OR c="" Then Messagebox.Show("please fill in all fields.")

Delete multiple textboxes from list of controls

I have a list of controls created dynamically in a control list. The user has options to add textboxes in the control list and to delete them as well.
I have created the textboxes using the following code:
Dim tb As New TextBox
tb.Name = "Textbox" & counter.ToString
tb.Left = 55
tb.Top = fields
Me.Controls.Add(tb)
MyControls.Add(tb)
counter = counter + 1
So, the textbox names when created are Textbox1, Textbox2 and so on maximum up to Textbox10.
The user can delete textboxes by button clicks one by one. If the user wants to delete these textboxes, counter will run backward and will delete Textbox10 first and then Textbox9 and so on (This is the same as First in First Out).
So, for deleting I tried the following code, but it didn't execute, giving an error. The code is written under Button's Click event of the delete button.
For Each CType(Me.Controls("Textbox" & counter), TextBox) As Control In MyControls
Me.Controls.Remove(...) 'The textbox's name to be deleted in place of dots
'The textbox name to be deleted here with .Dispose()
Next
The error is: "Expression is a value and therefore cannot be the target of an assignment" in the first line of the above code.
How to delete a series of textboxes dynamically?
This line is causing the problem:
For Each CType(Me.Controls("Textbox" & counter), TextBox) As Control In MyControls
CType(Me.Controls("Textbox" & counter), TextBox) resolves to a value, so it cannot be a loop increment variable.
To delete based on a loop, you would need to know how many controls you want to delete. Here is one way:
For i As Integer = 1 To Math.Min(NumberOfControlsToDelete, 10) ' Cap deleting at 10.
' Make sure we don't go below 1.
If counter < 1 Then Continue
' Expected that the control will exist.
Me.Controls.Remove(Controls.Find("TextBox" & counter, True)(0))
' Decrement counter.
counter -= 1
Next
It looks like you're already keeping track of those dynamic buttons by adding them to a List? in this line (your 6th line of code):
MyControls.Add(tb)
As such, simply grab the last entry and remove it, no need to go searching for the control by name:
If MyControls.Count > 0 Then
Dim TB As TextBox = MyControls(MyControls.Count - 1)
MyControls.Remove(TB)
TB.Dispose()
End If
If you want to delete all of them at the same time:
For Each TB As TextBox In MyControls
TB.Dispose()
Next
MyControls.Clear()
Is this what you're looking for? I'm not sure I'm reading your question correctly.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Me.Controls.Remove(Me.Controls.Find(""Textbox" & counter"))
End Sub

ms access vba dynamic array -- why won't this work?

I have an access form with a textbox named txtInput and a button name btnAdd.
The following is the sub procedure for the button's click event; each time a user enters some text into the text box and clicks the button it should be adding the text string to the dynamic array.
Public Sub btnAdd_Click()
Dim equipArray() As String
Dim ctr As Integer
ctr = 0
Do While txtInput <> "stop"
ReDim Preserve equipArray(x)
equipArray(x) = txtInput
ctr = ctr + 1
Loop
End Sub
But it's not working, can anyone help please?
It's recreating the array every time you click the button. You're not preserving it until after you're recreating it. The best thing to do would be to put a hidden textbox on the form and write the values to that textbox, and then on some event (form close? whatever you want) you can write the value from that textbox to your table.