VB Using variable name to access control properties - vb.net

I am trying to set the Text property of a dynamically created text box using a variable name, but when I use the Me.Controls(variable name).Text, I'm getting an error saying I need to set it up as "New". The name property of the text box, using a variable, was set when it was created but I don't seem to be able to retrieve using the same name.
Private Sub Example(panposition As Integer)
Dim tbfile = New TextBox()
Dim lineExample As Integer = 2
' creating a text box with a variable name
Controls.Add(tbfile) ' create the new textbox to hold the file name
tbfile.Name = "tbfile" + panposition.ToString
tbfile.Location = New Point(85, tvposition)
tbfile.Size = New Size(155, 20)
tbfile.Text = "file name"
tbfile.TextAlign = HorizontalAlignment.Left
tbfile.HideSelection = False
tbfile.TabStop = False
tbfile.AllowDrop = False
tbfile.Visible = True
' trying to update the text in the text box using file name and text retrieved from an array
Me.Controls.(arrTextVals(1, lineExample)).Text = arrTextVals(2, lineExample)
End Sub

I think the problem is in line:
Me.Controls.(arrTextVals(1, lineExample)).Text = arrTextVals(2, lineExample)
The correct way to address a control in this way is to make a reference like this
Me.Controls(i).Text = arrTextVals(2, lineExample)
where i is an integer or using the name of the desired control which in your case could be
Me.Controls(arrTextVals(1, lineExample)).Text = arrTextVals(2, lineExample)
Of course i suppose as you mentioned before that arrTextVals is a string array
Edit:
You have a dot after Me.Controls.( <- never put a . before a bracket.

Related

VB.Net | Is there a way to reference a dynamic amount of variables as arguments to function/sub?

I'm trying to pass a dynamic amount of variables to a Sub by using ByRef;
Essentially I'm trying to create a module that I can easily import into my projects and make handling the file saving/loading process automated.
The Sub/Function would take a number of variables as references and then loop through them changing each one's value.
I realize I'm missing a crucial point in how visual basic's syntax works but I haven't been able to figure out what I need to do.
The code I've written for this is:
Public Sub LoadSaveToVars(ByRef KeyNamesAndVars() As Object, ByVal FileLoc As String = "")
If isEven(KeyNamesAndVars.Length) Then
Dim Contents As String = My.Computer.FileSystem.ReadAllText(FileLoc)
Dim isOnName As Boolean = True
Dim CurrentVal As String = ""
For i = 0 To KeyNamesAndVars.Length - 1
If isOnName Then
CurrentVal = GetStringValue(KeyNamesAndVars(i), Contents) 'Get the value of the key with the key name in the array
isOnName = False
Else
KeyNamesAndVars(i) = CurrentVal 'Set the variable referenced in the array to the value
isOnName = True
End If
Next
Else
Throw New ArgumentOutOfRangeException("The key names and variables supplied are not even.", "Error loading to variables!")
End If
End Sub
And here's how I try to use this function:
Dim TestVar1 As String = ""
Dim TestVar2 As String = ""
LoadSaveToVars({"key1", TestVar1, "key2", TestVar2})
To keep this question clean I did not include the other functions, but I did make a poor attempt at drawing what I want to happen: https://gyazo.com/eee34b8dff766401f73772bb0fef981a
In the end, I want TestVar1 to be equal to "val1" and TestVar2 to be equal to "val2" and to be able to extend this to a dynamic number of variables. Is this possible?

Dynamically calling another variable name with another variable

Currently I have the following lines of code:
Dim ta = frmControllerScreen.Controls.Find("txtResponseA", True)
If ta.Count > 0 Then
Dim txt As TextBox = ta.First
txtResponseA = txt.Text
End If
Dim tb = frmControllerScreen.Controls.Find("txtResponseB", True)
If tb.Count > 0 Then
Dim txt As TextBox = tb.First
txtResponseB = txt.Text
End If
Dim tc = frmControllerScreen.Controls.Find("txtResponseC", True)
If tc.Count > 0 Then
Dim txt As TextBox = ta.First
txtResponseC = txt.Text
End If
Dim td = frmControllerScreen.Controls.Find("txtResponseD", True)
If td.Count > 0 Then
Dim txt As TextBox = ta.First
txtResponseD = txt.Text
End If
So it's clear that I'm assigning a string to an A, B, C, D version of a variable. The goal is that I will be able to go ahead and call one of these values up and assign it to a textbox/label.
I'm trying to use the following code:
lblAutoChoice1.Text = ("txtResponse" & chrAvailableAnswers.Item(0).ToString.Trim)
But It's not exactly working. I attempted to use .ToString method on it but I'm only greeted with a System.ToString[] response during run time.
This would be easy to do in other languages, like PHP $Somevariable$correctAnswer for example to pull up $SomevariableA but I've yet to see an example of a variable variables in VB.
How do you create a variable variables (I believe is the proper name) in Visual Basic?
Taking a cue from Idle_Mind's answer listed here:
How to use a string like a variable in Visual Basic
lblAutoChoice1.Text = Me.GetType.GetField("txtResponse" & chrAvailableAnswers.Item(0).ToString, _
BindingFlags.Instance Or BindingFlags.NonPublic).GetValue(Me).ToString
This directly calls for Imports System.Reflection on being used as the top line, above the declaration of the Class of the form.

Storing datagridview name in a variable

I am working on user rights. I want to load the grid items checked using following code.
Dim l As Integer = 0, vrGridName As New DataGridView, vrGridItemIndex As Integer
taSaveTemplates.Connection.ConnectionString += ";password=" & vrSAPWD
Me.taSaveTemplates.Fill(Me.DsSaveTemplates.tblTemplates, lstTemplateID.Text)
'Load Grids according to data saved
Do While DsSaveTemplates.tblTemplates.Rows.Count > l
vrGridName.Name = DsSaveTemplates.tblTemplates.Rows(l).Item("GridName")
vrGridItemIndex = DsSaveTemplates.tblTemplates.Rows(l).Item("GridItemIndex")
vrGridName.Item(0, vrGridItemIndex).Value = True
l = l + 1
Loop
vrGridName stores the name of grid selected from DB and vrGridItemIndex stores the item that needs to be checked.
The problem is, when I run the code, it says Index is our of range.
I have checked, the vrGridName does not store the name of grid but stores
System.windows.datagridview
Please advise.
Thanks
Your code is treating a control reference as if it were a name (string variable), so you get the Type name (System.windows.datagridview) rather than the name of the control. Since the template DGV happarently has the name, use it:
Dim myGridName As String ' name is a String, not DGV
Dim myGridItemIndex As Integer
Dim myDGV As DataGridView ' no NEW - not creating a new one
' just a reference var
'...
' this is now a For/Each loop
For Each row As DataGridViewRow in DsSaveTemplates.tblTemplates.Rows
myGridName = row.Cell("GridName")
myGridItemIndex = row.Cell("GridItemIndex")
' assuming this code is in a Form:
' get a reference to the control
myDGV = CType(Me.Controls(myGridName), DataGridView)
' talk to it like a DGV:
myDGV.Item(0, myGridItemIndex).Value = True
Next
Note: Option Strict would likely require some conversions for the name and index
If the DGV(s) reside in container controls like Panels or Tabs, you have to "find" the control because they will be in that control's collection, not the Form's. Instead of myDGV = CType(Me.Controls(myGridName), DataGridView):
' have the form search for the ctl by name
' the TRUE param tells it to search child controls like panels
Dim tmpArry = Me.Controls.Find(myGridName, True)
' test for a return
If tmpArry.Length > 0 Then
' tmpArry will be Type Control, so cast it
myDGV = CType(tmpArry(0), DataGridView)
End If
This is usually better from the start so you do not have to remember how the form is laid out when coding.

Access a form's control by name

not sure whether the title of this post is accurate.
I'm trying to access windows form controls and their properties by "composing" their name within a loop, but I can't seem to find the related documentation. Using VB.net. Basically, say I have the following:
Dim myDt As New DataTable
Dim row As DataRow = myDt.NewRow()
row.Item("col01") = Me.label01.Text
row.Item("col02") = Me.label02.Text
'...
row.Item("colN") = Me.labelN.Text
I'd like to write a for loop instead of N separate instructions.
While it's simple enough to express the left-hand side of the assignments, I'm stumped when it comes to the right-hand side:
For i As Integer = 1 to N
row.Item(String.format("col{0:00}", i)) = ???
' ??? <- write "label" & i (zero-padded, like col) and use that string to access Me's control that has such name
Next
As an extra, I'd like to be able to pass the final ".Text" property as a string as well, for in some cases I need the value of the "Text" property, in other cases the value of the "Value" property; generally speaking, the property I'm interested in might be a function of i.
Cheers.
You could use the ControlsCollection.Find method with the searchAllChildren option set to true
For i As Integer = 1 to N
Dim ctrl = Me.Controls.Find(string.Format("label{0:00}", i), True)
if ctrl IsNot Nothing AndAlso ctrl.Length > 0 Then
row.Item(String.format("col{0:00}", i)) = ctrl(0).Text
End If
Next
An example on how to approach the problem using reflection to set a property that you identify using a string
Dim myLabel As Label = new Label()
Dim prop as PropertyInfo = myLabel.GetType().GetProperty("Text")
prop.SetValue(myLabel, "A Label.Text set with Reflection classes", Nothing)
Dim newText = prop.GetValue(myLabel)
Console.WriteLine(newText)

How to print Data to Word 2013 template using vb.net

I have a problem to print data to Word document template in 2013 , Actually i can able to print data in word 2010(Using XSD file) using vb.net , but 2013 doesn't accept xmlnodes(i know they remove xml nodes in 2013).How can i print the data in word2013 .
My scenario is :
I create template with different font styles and Header colors with three tables .
I need to dynamically add the rows based on my data ( in all my tables ).
Please guide how can i move....
This is not quite an answer for xsd files. But by request i put this forward.
Opening the docx as a memory stream and in this example I have a table with a caption.
That is in the word document there is a table and when you select it and right click->properties->Alternative Text -> title.
This title is the thing that I search for in the word document to know where to add my stuff. There are probably much better ways of doing this. But this makes the document editable for administrators and as long as they dont delete the table they can edit it as they see fit.
dim mem As MemoryStream
dim doc = WordprocessingDocument.Open(mem, true)
Dim tableProperties = doc.MainDocumentPart.Document.Body.Descendants(Of TableProperties)().Where(Function(tp) tp.TableCaption IsNot Nothing)
For Each tProp As TableProperties In tableProperties
If tProp.TableCaption.Val.ToString() = "DatatableTitle" Then
Dim tbl = DirectCast(tProp.Parent, Table)
InsertTableRows(tbl, myListOfThings)
End If
Next
Private Function CreateTableCellText(myText As String) As TableCell
Dim run = New Run()
Dim runProperties = New RunProperties()
runProperties.Append(New RunFonts() With { .Ascii = "Times New Roman" })
runProperties.Append(New FontSize() With { .Val = "16" })
run.PrependChild(runProperties)
run.Append(New Text(myText))
Dim p = New Paragraph()
p.Append(run)
Dim td = New TableCell()
td.Append(p)
Return td
End Function
Private Sub InsertTableRows(tbl As Table, patients As List(Of MyTableList))
'var refRow = tbl.Elements<TableRow>().ElementAt(1); // the first is the header.
tbl.Elements(Of TableRow)().ElementAt(1).Remove()
For Each patient As MyTableList In patients
Dim tr = New TableRow()
tr.Append(CreateTableCellText(patient.DepartmentName))
tr.Append(CreateTableCellText(patient.PatientLastName))
tbl.Append(tr)
Next
End Sub
End Class
Public Class MyTableList
Public Property DepartmentName() As String
Get
Return m_DepartmentName
End Get
Set
m_DepartmentName = Value
End Set
End Property
Private m_DepartmentName As String
Public Property PatientLastName() As String
Get
Return m_PatientLastName
End Get
Set
m_PatientLastName = Value
End Set
End Property
Private m_PatientLastName As String
End Class
And adding checkboxes and such is no problem, just create them in word, open the word document in a texteditor and copy the xml from the document and add it as new paragraph and then use firstChild.InnerXml and copy the xml into the text. and then append it