String to Object as Expression - vb.net

I have multiple TextBox controls Monday that will hold a value. I want to be able to add up all of the Monday textboxes and store that value as monTotal. I am getting an error message that says string cannot be converted to integer.
For i As Integer = 1 To rowCount Step 1
Dim var As Object
var = "txtMonday" & i & ".Text"
monTotal = monTotal + CInt(var)
Next

The way you are attempting to obtain a reference to the text boxes is not idiomatic of VisualBasic .NET.
var = "txtMonday" & i & ".Text" ' this is not a way to obtain a reference to the text box's text
While it would be possible to accomplish something like that using reflection, you'd be much better off refactoring your code to use an array of text boxes.
Since you are probably using Windows Forms you could perhaps implement logic to find the text box control you are interested in on the form using something like this:
' assuming container is the control that contains the text boxes
For Each ctrl In container.Controls
If (ctrl.GetType() Is GetType(TextBox)) Then
If ctrl.Name.StartsWith("txtMonday") Then
Dim txt As TextBox = CType(ctrl, TextBox)
monTotal = monTotal + CInt(txt.Text)
End If
End If
Next
The example above assumes that all the txtMonday.. text boxes are placed inside a control named container. That could be the form itself, or some other panel or table.

If all the textboxes live on the form and there are none being used for other text work you could use this. You could place all the textboxes that contain values your looking for in a separate container and get them like below, but use that control collection.
Dim amount As Double = 0
For Each tb As Textbox In Me.Controls.OfType(Of Textbox)()
amount += Convert.ToDouble(tb.Text)
Next

Dim monTotal as double=0
For Each ctrl As Control In Me.Controls
If TypeOf ctrl Is TextBox AndAlso ctrl.Name.StartsWith("txtMonday") Then
monTotal = monTotal + val(ctrl.Text)
End If
Next

Related

Append Strings and values together to target a form control in VBA

I'm so close to getting this code working, I just need a little push please. I would like to
take the name of a combo box and then add a string to the end, But then get the value of a textbox with that string. This is to create a dynamic function instead of pasting the same code over and over.
Here's what I have so far, after you select something in the dropdown, the data is then pulled to populate the boxes next to it. I have about 8 drop downs so far so that's why I need this to work.
'Combobox after update
Call GrabData(Me, Me.ActiveControl)
Then
Private Sub GrabData(ctl As Control)
'name of ctl/combobox is "Kitchen"
data1 = (ctl.Name & "Size") '"KitchenSize"
'Here is where it all goes wrong
data1.Value = size.value
'size.value is just a textbox for example
End Sub
I can debug this with:
msgbox(data1)
'outputs "KitchenSize"
But I cannot get the value of kitchensize's textbox with data1.value
Error:
Object Required
I have also added Dim As String / Dim As Control.
I will be assigning the variable to some other stuff in this 50 line code I wrote so please don't take the above example as exactly what I intend to do, I just need help appending the ctl.name to a string, then use that to reference another control and so on.
EDIT
For anyone who wants to know, I figured it out.
Dim Ctrl As Control
Dim CtrlName As String
CtrlName = ctl.Name & "Size"
Set Ctrl = Me.Controls(CtrlName)
Ctrl.Value = 'Wherever you want to send the values to
See the edit.
You need to dim it as a string, then use Set Ctrl

Select Textbox using For Loop

Sorry this is weird and silly question but I need a solution of this...
I have 30 textboxes named as Txt1,Txt2,Txt3,...,Txt30
I have to fill textbox as Txt1.text = 0 on button click..
Is there any way like On Button Click
Dim i as Integer
For i = 1 to 30 '----- Possible in string but don't know if possible in textboxes
Txt(i).text = 0
Next
Or I have to write all 30 lines like
Txt1.text = 0
...
Txt30.text = 0
I don't know how this question asked, maybe Question improper.
Thanx in Advance...
If the textboxes are all contained in Controls collection of the Form, then it is really easy to loop over them
For Each(t in Me.Controls.OfType(Of TextBox)())
t.Text = "0"
Of course the advantage of this approach is that you don't have to worry if you add other textboxes to your form. They will be found using the foreach loop without having a fixed top limit.
And, if not all of your textboxes should be included in the loop, then you can simply use the Tag property of the textboxes that you want to use. For example, if you set the Tag property to the string "Y", then you can change the foreach loop to find only the controls with the matching Tag property
For Each t in Me.Controls.OfType(Of TextBox)() _
.Where(Function(x) x.Tag = "Y")
t.Text = "0"
The two solutions above works well if all your textboxes are contained in the same container (Form, GroupBox or Panel), instead, if these textboxes are dispersed in different containers (some in a groupbox, others in a panel etc) then you can build a List(Of TextBox) variable filling it with the textboxes instances and use it when the need arise
Dim myTexts = New List(Of TextBox)() From { Txt1, Txt2, Txt3, ....}
And loop over this variable
You can do as Steve said, but if you have other textboxes that you don't want to edit then there is another way:
For i = 1 to 30
dim found = Me.Controls.Find("Txt" & i, True) '<- the True argument is for recursive search
If Not IsNothing(found) AndAlso found.Length > 0 Then
found(0).Text = "0"
End If
Next
If your textboxes are all in the same control, for example GroupBox, you can do GroupBox.Controls.Find saving CPU resources

Getting .value property when using a string and variable

I am creating a form in Access which will be used as an order sheet for classroom materials. I have the available resources listed and a text box next to the resource where the user inputs the quantity they desire.
My VBA code checks to see if any entries have been made by using the following. (I am using Nz() to allow for Null results):
QuantCheck = Nz(Box1.Value, 0) + Nz(Box2.Value, 0) + Nz(Box3.Value, 0)
Where "QuantCheck" is the variable I am using in the IF statement which begins the workflow:
If QuantCheck > 0 Then
I would like to clean this up by using some kind of loop statement, however I am not able to extract the .value from a string. I would love something like the following which I could incorporate into a loop:
"Box"&VariableNumber.Value
From what I can tell, I am not able to use a string (concatenated or otherwise) as the base for the .value call.
It is interesting that there is a way to accomplish this when using a SQL statement. I have this elsewhere in the code which works nicely:
SQLStr = "INSERT INTO OrderRequests VALUES (cbSchool, txtName, Title" & x & ".caption, Box" & x & ")"
Here I have a variable "x" which increases with each loop to change the Title line, and the Box line.
Any help is appreciated.
I suggest you use the Tag property of the controls. Put "QuantCheck" in the Tag property of any control you want to include. Then
Function QuantitiesExist(frm As Form) As Boolean
Dim Ctrl As Control
Const sQUANTCHK As String = "QuantCheck"
For Each Ctrl In frm.Controls
If Ctrl.Tag = sQUANTCHK Then
If Nz(Ctrl.Value) > 0 Then
QuantitiesExist = True
Exit For
End If
End If
Next Ctrl
End Function
Now you get self documenting code
If QuantitiesExist(Me) Then
And when you add/delete/change controls, you don't have to edit your code. Just set up new controls with the proper tags.
You could loop through the control on the for checking the names and then if it is the one you wanted take an action on it, is this what you was thinking of?
Dim Ctrl As Control
For Each Ctrl In Me.Controls
If Ctrl.Name = "TxtPath" Then ' "Box" & VariableNumber Then
MsgBox Ctrl.Value
End If
Next

Access a dynamically created textbox text from another sub. And I also want to be user-configurable and access the user-configured text

Textbox.text I want to access. And I want it user-configurable before I want to access the altered text.
Dim qbox As New TextBox
qbox.Size = New Size(20, 20)
qbox.Location = New Point(90, 10)
qbox.Parent = addtocart
qbox.Name = "quarts"
qbox.Text = "ss"**
how I dynamically add it inside a series of other dynamic controls:
tile.Controls.Add(addtocart)
flpp.Controls.Add(tile)
tile.Controls.Add(plabel)
tile.Controls.Add(nlabel)
addtocart.Controls.Add(qbox)
How I tried to access it:
qb.Text = CType(Me.Controls("flpp").Controls("tile").Controls("addtocart").Controls("qbox"), TextBox).Text
I generated to textbox at runtime. Of course it's dynamic. I'm new to VB and I'm just experimenting a school project. I wanted the textbox text to be configurable and then access that configured value. I've been brain-cracking for days about this. when I run the thing, I "getObject reference not set to an instance of an object." under NullReferenceException was unhandled" something like this. I don't get it.
WinForms? If yes, and you want to find that control "by name", then use the Controls.Find() function:
Dim ctlName As String = "quarts"
Dim matches() As Control = Me.Controls.Find(ctlName, True)
If matches.Length > 0 AndAlso TypeOf matches(0) Is TextBox Then
Dim tb As TextBox = DirectCast(matches(0), TextBox)
' ... use "tb" somehow ...
Dim value As String = tb.Text
MessageBox.Show(value)
End If

Looping through Controls in VB.NET

I am creating a chess program. And it is composed of sixty four picture boxes with alternating black and white background colours.
I have named them pba1, pba2, pbb1, pbb2, pbc1 and so on.
Now, I want to loop through only the black ones, for example, I want to loop through only, pba1, pbb2, pbc3 and so on.
How do I create a loop for this in VB.NET?
I know of the way to loop through similarly named controls, but I am not able to adapt that method for my problem. Can you tell me a solution?
EDIT: In pba1, pb stands for picture box, and a1 stands for the square. Just in case, you wonder why such a name.
EDIT: Check out this answer
Loop through the PictureBox's in your ControlCollection and test for BackColor. I used the Form's ControlCollection, if they are in some other type of container control use that.
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is PictureBox Then
If cntrl.BackColor = Color.Black Then
'Do Something
End If
End If
Next
Base on the additional information that you gave in your answer, the reason your example is not working is that the Controls Name is a String and you are comparing it to the PictureBox Control not the Name of the Control.
You can try using the Tag Property instead of the Name of the Control, it will be cleaner and easier to read. I just put a 1 in the PictureBox's Tag Property for Black and a 0 for White.
Private Sub OriginalColour()
For Each cntrl As Control In Me.Controls
Dim result As Integer
If TypeOf cntrl Is PictureBox Then
If Integer.TryParse(cntrl.Tag.ToString, result) Then
If result = 1 Then
cntrl.BackColor = Color.Gray
Else
cntrl.BackColor = Color.White
End If
End If
End If
Next
End Sub
Generating controls at design time via the Forms Designer only makes sense for layouts which benefit from the forms designer.
In your case, you just have 64 uniform boxes in 8 rows of 8. Don’t use the Forms Designer for this, create the controls at runtime, and don’t give them names like pba1, just put them into an appropriate data structure (such as an 8x8 array):
Private chessFields As PictureBox(8, 8)
' In Form_Load:
For i = 0 To 7
For j = 0 To 7
chessFields(i, j) = New PictureBox
' Set size, position … then, finally,
Controls.Add(chessFields(i, j))
Next
Next
That way, you can access the fields in an orderly fashion without having to go via the Form.Controls collection.
Put all the pictureboxes in an 8x8 tableLayoutPanel (also useful for scaling etc). Then
For Each pb As PictureBox In TableLayoutPanel1.Controls
Dim col As Integer = TableLayoutPanel1.GetCellPosition(pb).Column
Dim row As Integer = TableLayoutPanel1.GetCellPosition(pb).Row
If col Mod 2 = 0 Xor row Mod 2 = 0 Then
pb.BackColor = Color.Black
Else
pb.BackColor = Color.White
End If
Next
Of course you could also use an array of the squares if you have that available.
This will not affect the events (pba1.click etc).
This is fairly simple and it may be resource heavy, but it works. I have a form with 36 CheckBoxes. This takes advantage of the fact that when you copy a checkbox it just increases the number of the name. I ended up with 36 checkboxes named CheckBox1 thru Checkbox36. The Function returns a checkbox, which may be used to set or read any property.
Private Function GetCheckBox(ByVal Index As Integer) As CheckBox
Dim CKBox As checkbox
For Each cntrl As Control In Me.Controls
If TypeOf cntrl Is CheckBox Then
CKBox = cntrl
If CKBox.Name = "CheckBox" & Index Then
Exit For
End If
End If
Next
Return ckbox
End Function