Visual Basic 2008 - Me.Controls - Textboxes - NULL - - vb.net

Self taught(in progress) Visual Basic guy here.
I've searched for a clear answer on this, but so far have come up empty handed.
The problem...
I have two comboboxes. The first combobox has 10 options, second combobox has 2 options
I have 10 textboxes, with a name that includes one of the 10 options.
ex 1st textbox name - "txb_Option1Type"
2nd textbox name - "txb_Option2Type" and so on.
I have 2 tabs, with the first 5 text boxes on the 1st tab and last 5 on the 2nd tab.
I thought the following bit of code, upon a button click, would transfer the text of the chosen option in the 2nd combobox to the corresponding textbox...
`
Public Sub TransferTruckToDoorText()
Dim str_ErrorButton As String = cbx_DoorNumber.Text
Dim str_ReplaceSpacesButton As String = str_ErrorButton.Replace(" ", "")
Dim str_Button As String = str_ReplaceSpacesButton
' Null reference error on below line of code
Me.Controls("txb_" & str_Button & "Type").Text = cbx_TruckType.Text
End Sub
`
As noted in the above code, I'm getting a null reference and for the life of me cannot figure out why. I've stepped through the code, and I'm not able to find a NULL or Nothing value that could be making this catch.
Any and all help would be appreciated.
edited for clarity

The Me.Controls collection does not automatically search the child panels.
Try using the Controls.Find method for that, which includes a parameter to search the child control's control collection, too. It returns an array:
Dim c As Control() = Me.Controls.Find("txb_" & str_Button & "Type", True)
If c.Length = 1 Then
c(0).Text = cbx_TruckType.Text
End If

Me.Controls.Item("txb_" & str_Button & "Type")

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

DataGridView properties not being set when called from Form Load

I'm having a really strange issue with the DataGridView control in a VS2008 / .NET 3.5 winforms project. I have a simple form with a grid. In the form constructor I call a function to bind the grind to a DataTable, and then loop through the rows setting the background colour of the last cell to LightGrey and the cell itself to read-only if the column value is true. After the form finishes loading the code didn't work i.e. the cells are not set to LightGrey and are not read-only (even though when I step through the code I can see the properties being set). I then call the function again from a button, but this time the colour is changed to LightGrey and the cell is made read-only i.e. the code works.
CODE:
Dim dgr As DataGridViewRow
For i_DsRow As Integer = 0 To ds.Tables(0).Rows.Count - 1
dr = ds.Tables(0).Rows(i_DsRow)
For i_row As Integer = 0 To DgSearch.Rows.Count - 1
dgr = DgSearch.Rows(i_row)
If dr("DsColoumn1").ToString.ToUpper = dgr.Cells("DgColoumn1").Value.ToString.ToUpper Then
If Val(dr("Coloumn2").ToString) = 3 Then
dgr.Cells("SomeColomname").Value = dr("SomeColoumName2").ToString
If dgr.Cells("SomeColomname3").Value.ToString <> "" Then dgr.Cells("SomeColomname3").Value &= ", "
dgr.Cells("SomeColomname3").Value &= dr("SomeColoumName2").ToString
SetCellColor(dgr.Cells("SomeColomname"), dgr.Cells("SomeColomname3"))
End If
Exit For
End If
Next
Next
Private Sub SetCellColor(ByVal resultCell As DataGridViewCell, ByVal ColorCell As DataGridViewCell)
If resultCell.Value.ToString().ToUpper = "A".ToUpper Or resultCell.Value.ToString().ToUpper = "B".ToUpper Then
ColorCell.Style.BackColor = Color.FromName("Red")
ElseIf resultCell.Value.ToString().ToUpper = "C".ToUpper Or resultCell.Value.ToString().ToUpper = "D".ToUpper Then
ColorCell.Style.BackColor = Color.FromName("MediumSeaGreen")
Else
ColorCell.Style.BackColor = Color.FromName("Yellow")
End If
End Sub
Thanks for adding the code. I would suggest putting all formatting in the CellFormatting event of the DataGridView.
There are a couple of gotchas that you have to watch, which looking at your code shouldn't be a problem but to be aware of:
This runs for each cell in the grid. Therefore Database lookups are a really bad idea.
You do best to get values where possible from the eventargs parameter of the method
If you need a code sample, I believe there are some good c# examples (possibly vb to) this one for example.

Can not update List Box Selected Collection in code

I have a list box on a form being populated from a query, with items selected on basis of matching a delimited list. So sSystemString equals something like "A;B;C"
Then I load records A,B,C,D,E,F from the SQL Server DB and only A,B,C should be selected.
Is there a native way to do this in MS Access (2010). I'm using an ADP in this case.
I'm doing it via code but I can't the selected property does not reflect my changes, nor does the form.
Here's my code:
Dim rs As New ADODB.Recordset
Dim sSystemString As String
If Not IsNull(Me.OpenArgs) Then sSystemString = Me.OpenArgs
' Load this list box with SRC Systems
Call rs.Open("SELECT DISTINCT System FROM dbo.System WHERE System IS NOT NULL", _
CurrentProject.Connection, adOpenForwardOnly, adLockReadOnly)
Do Until rs.EOF
lstSrcSystems.AddItem (rs.Fields(0))
If InStr(sSystemString, rs.Fields(0)) > 0 Then
lstSrcSystems.Selected(lstSrcSystems.ListCount - 1) = True
End If
rs.MoveNext
Loop
My code definitely hits the lstSrcSystems.Selected(lstSrcSystems.ListCount - 1) = True line.
After running this line, inspecting the property in the immediate window still returns 0 (it doesn't change). On the form, the item is also not selected.
UPDATE: I just checked my code again and now it is being updated, but the next AddItem apparently unselects it again.
I suspect I have some weird combination of properties that make this read only, but I can select items interactively, and indeed when I extract the selected items back off in code, the Selected property works as expected - i.e. I select an item on the form and it reflected in this property.
The form is unbound and is called from a button on another form with this code:
DoCmd.OpenForm "fSiteList", acNormal, , , acFormEdit, acDialog, Me.SRCSystems
The problem was actually that lstSrcSystems.AddItem (rs.Fields(0)) was resetting the Selected state. I can't find any mention of this behaviour or how to turn it off. I altered my form as follows:
Form / Data properties all blank (unbound)
List Control / Data / Control Source: blank
List Control / Data / Row Source: SELECT statement populating my list
This has the effect of populating the list but not binding the list or form to anything. (I found that binding it stopped me interactively editing data on it)
Form_Load code behind the form was changed to select already existing items:
Private Sub Form_Load()
Dim sSystemString As String
Dim iIndex As Integer
' List is bound to site list (from connections)
' Highlight those that are listed
If Not IsNull(Me.OpenArgs) Then sSystemString = Me.OpenArgs
iIndex = lstSrcSystems.ListCount
Do While iIndex > 0
If InStr(sSystemString, lstSrcSystems.ItemData(iIndex)) > 0 Then
lstSrcSystems.Selected(iIndex) = True
End If
iIndex = iIndex - 1
Loop
End Sub
I'm still curious to know whether there is a more 'built in' way to achieve this: edit a delimited string field.