How to loop through items on an other form? - vb.net

So I have a three forms with text boxes, and I'm saving them to db on the last one, one is pretty huge and iterative so I'd like to write a loop. But when I try to loop through them it doesn't seem to grab them from the other form, what am I doing wrong?
For i = 1 To 12
Dim txtbox_bem As TextBox = CType(frm_new_prot_2.Controls("frm_new_prot_2.txtbox_bem1_" & i), TextBox)
Dim txtbox_soll As TextBox = CType(frm_new_prot_2.Controls("txtbox_soll1_" & i), TextBox)
Dim txtbox_messw As TextBox = CType(frm_new_prot_2.Controls("txtbox_messw1_" & i), TextBox)
Dim txtbox_einheit As TextBox = CType(Controls("frm_new_prot_2.txtbox_einheit1_" & i), TextBox)
Dim txtbox_max As TextBox = CType(Controls("frm_new_prot_2.txtbox_max1_" & i), TextBox)
Dim txtbox_min As TextBox = CType(Controls("frm_new_prot_2.txtbox_min1_" & i), TextBox)
Dim txtbox_tol As TextBox = CType(Controls("frm_new_prot_2.txtbox_tol1_" & i), TextBox)
Dim ckbox_ok As CheckBox = CType(Controls("frm_new_prot_2.ckbox_ok1_" & i), CheckBox)
command.CommandText = "INSERT INTO tb_1_" & i & " (Auftraggeber, Protokollnr, 1_" & i & "bem, 1_" & i & "soll, 1_" & i & "messw, 1_" & i & "einheit, 1_" & i & "max, 1_" & i & "min, 1_" & i & "tol, 1_" & i & "ok) VALUES ('" & Auftraggeber & "'," & Protokollnr & ",'" & txtbox_bem.Text & "','" & txtbox_soll.Text & "','" & txtbox_messw.Text & "','" & txtbox_einheit.Text & "','" & txtbox_max.Text & "','" & txtbox_min.Text & "','" & txtbox_tol.Text & "','" & ckbox_ok.Text & "')"
command.CommandType = CommandType.Text
command.ExecuteNonQuery()
MsgBox("success row " & i)
Next
As you see I tried different combinations. The error I'm getting is:
"System.NullReferenceException: 'Object reference not set to an instance of an object.' txtbox_bem was Nothing."

The line ..
Dim txtbox_bem As TextBox = CType(frm_new_prot_2.Controls("txtbox_bem1_.txtbox_bem1_" & i), TextBox)
is searching through the controls of frm_new_prot_2 for a control called "frm_new_prot_2.txtbox_bem1_" & i.
That won't exist. In the controls collection will only contain the textbox with a name of "txtbox_bem1_" & i, so the corrected version should be
Dim txtbox_bem As TextBox = CType(frm_new_prot_2.Controls("txtbox_bem1_" & i), TextBox)
The other lines in your code probably won't work either. They should probably be ..
Dim txtbox_bem As TextBox = CType(frm_new_prot_2.Controls("txtbox_bem1_" & i), TextBox)
Dim txtbox_soll As TextBox = CType(frm_new_prot_2.Controls("txtbox_soll1_" & i), TextBox)
Dim txtbox_messw As TextBox = CType(frm_new_prot_2.Controls("txtbox_messw1_" & i), TextBox)
Dim txtbox_einheit As TextBox = CType(frm_new_prot_2.Controls("txtbox_einheit1_" & i), TextBox)
Dim txtbox_max As TextBox = CType(frm_new_prot_2.Controls("txtbox_max1_" & i), TextBox)
Dim txtbox_min As TextBox = CType(frm_new_prot_2.Controls("txtbox_min1_" & i), TextBox)
Dim txtbox_tol As TextBox = CType(frm_new_prot_2.Controls("txtbox_tol1_" & i), TextBox)
Dim ckbox_ok As CheckBox = CType(frm_new_prot_2.Controls("ckbox_ok1_" & i), CheckBox)
I think you got a bit confused about how references work. :-)
Also I suspect that the data in the textboxes is the only place where you're storing the data. This isn't terribly good programming practice. For example...
Say, the data comes from an external device and you have code that reads data from the device and stores it in the textboxes. This isn't good. anyone could accidentally overwrite data in the textbox.
It would be much better to store the data in Lists or Lists of class objects. and populate the textboxes with the data. When it comes to storing the data in your db, use the data in the lists rather than the textboxes.
The user interface should never be used to store data. Hope this helps

It might be easier to debug without all the casting.
Public Class Form2
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim lst As New List(Of String)
For i As Integer = 1 To 3
Dim str1 As String = Form1.Controls("TextBox" & i).Text
lst.Add(str1)
Next
For Each s As String In lst
Debug.Print(s)
Next
End Sub
End Class
I just added the List for testing purposes.

Related

Access abends after DoCmd.OpenReport

A report is called from VBA to receive returned records from an Access pass-through query. After the DoCmd completes the report's parameters are set in the report's appropriate label containers setting their .Caption property as required. Access fails intermittently during this process which leads me to believe that the report is not truly open to receive the parameters. Here's the VBA sub:
Private Sub Report_Open(Cancel As Integer)
Dim strFromDate As String
Dim strToDate As String
Dim strWC As String
Dim intShift As Integer
Dim strSQL As String
strFromDate = InputBox("Enter From Date and Time: ")
strToDate = InputBox("Enter To Date and Time: ")
strWC = InputBox("Enter Work Center: ")
intShift = InputBox("Enter Shift: ")
strSQL = "exec dbo.uspWorkCentreReport_TEST " & "'" & strFromDate & "', " & "'" & strToDate & "', " & "'" & strWC & "', " & intShift & ";"
CurrentDb.QueryDefs("ptq_uspWorkCentreReport").SQL = strSQL
DoCmd.OpenReport "rpt_qry_ptq_uspWorkCentreReport", acViewReport
Me.lblFromDate.Caption = strFromDate
Me.lblToDate.Caption = strToDate
Me.lblWC.Caption = strWC
Me.lblShift.Caption = intShift
End Sub
When the failure occurrs VBA highlights the Me.lblFromDate.Caption = strFromDate. If I press Reset in VBA or End on the Run-time error '2467': dialog, Access abends without any other outward signs. Access then re-opens to save the copied *_Backupx.accdb and opens with a fresh copy of the .accdb. The error seems to be a standars MS error:
As I said the report is intermittent and when it fails VB always highlights the same line in code. How do I capture what is happening or can I make VB wait a half of full second before it tries to write the parameters?
As I remember, captions can not be modified, when report open. Only in design mode. So this is not correct, because you have already opened report
Me.lblFromDate.Caption = strFromDate
You should use text boxes instead of captions. Also you can clear the borders, fillings and so on, that text box will appear like a caption.
Finally the correct set of code was produced. The button click creates strOpenArgs and passes it with .OpenReport. The report opens and splits the OpenArgs and populates the appropriate labels with updated Captions. Text boxes would not work! Here's the button click event:
Private Sub btnPreviewP1_Click()
If (Me.txtToDateP1 < Me.txtFromDateP1) Then
MsgBox ("The From Date must occurr before the To Date!")
End If
Dim strFromDateHMS As String
Dim strToDateHMS As String
Dim strSQLP1 As String
Dim strOpenArgs As String
strFromDateHMS = Format(Me.txtFromDateP1, "yyyy-mm-dd") & " " & Me.cboFromHourP1 & ":" & Me.cboFromMinuteP1 & ":" & Me.cboFromSecondP1
strToDateHMS = Format(Me.txtToDateP1, "yyyy-mm-dd") & " " & Me.cboToHourP1 & ":" & Me.cboToMinuteP1 & ":" & Me.cboToSecondP1
strSQLP1 = "exec dbo.uspWorkCentreReport '" & strFromDateHMS & "','" & strToDateHMS & "','" & strWCP1 & "'," & strShiftP1
strOpenArgs = Me.RecordSource & "|" & strFromDateHMS & "|" & strToDateHMS & "|" & strWCP1 & "|" & strShiftP1
' This line is all that's needed to modify the PT query
CurrentDb.QueryDefs("ptq_uspWorkCentreReport").SQL = strSQLP1
DoCmd.OpenReport "rpt_ptq_uspWorkCentreReport", acViewReport, , , , strOpenArgs
End Sub
And here's the reports _Open:
Private Sub Report_Open(Cancel As Integer)
Dim SplitOpenArgs() As String
SplitOpenArgs = Split(Me.OpenArgs, "|")
Me.lblFromDate.Caption = SplitOpenArgs(1)
Me.lblToDate.Caption = SplitOpenArgs(2)
Me.lblWC.Caption = SplitOpenArgs(3)
Me.lblShift.Caption = SplitOpenArgs(4)
End Sub
This opens the report every time with new appropriate data, so long as the report is closed before the form's button is pressed again for another refresh of the report. If the report is not closed the report stays up with the original data and does not refresh with new data... But that is another question I am about to ask. Thanks All.

Code to show a DataGridView works only if I run another sub before

I wrote a code to show/hide content of a certain DataTable into a DataGridView.
DataGridView appears and disappears when I click a button.
I don't get errors but nothing is shown.
But if I click another button (who shows another form) and then go back to the main form, the code works. (??!!??)
I wasn't able to understand what (in the 2nd code) makes the first code to work: it seems there aren't connections between two codes.
EDIT
I made some tests and I can add more informations:
I added a button to show (in a msgbox) the DataGridView properties.
The control was correctly added and all properties are correct.
The property "Visible" is set "True" but the DataGridView is still "invisible".
I added a button that sets DGV_Tbl.Visible = False and DGV_Tbl.Visible = True
And when I click it the DataGridView appears.
But if I click Btn_ShowHideTbl again (to remove DGV) and again (to re-add DGV) DataGridView is still "invisible".
This doesn't happens when I click the button to open the second form and then I close it to go back to the first form.
In this case all works correctly.
I could solve adding DGV_Tbl.Visible = False and DGV_Tbl.Visible = True to the first code but I don't think it's a good idea.
I would like to understand the problem and solve it without "strange instructions".
EDIT 2
I noticed that also the code .AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells) doesn't work without opening the 2nd form.
On this istruction DGV_Tbl.Visible = False and DGV_Tbl.Visible = True haven't effect.
EDIT 3
I've done as in the accepted answer, but I posted another question here hoping to understand what's wrong in my code.
This is my code to show/hide DataGridView:
Private Sub Btn_ShowHideTbl_Click(sender As Object, e As EventArgs) Handles Btn_ShowHideTbl.Click
ShowHideTbl()
End Sub
Private Sub ShowHideTbl()
'Look for DGV
Dim DGV_Tbl As DataGridView = Nothing
Try
DGV_Tbl = CType(Me.Controls("DGV_Tbl"), DataGridView)
Catch ex As Exception
MsgBox(ex.ToString)
End Try
Try
'If not found I need to show data
If DGV_Tbl Is Nothing Then
If Me.CBox_ProcType.Text = "Select a Procedure" Then
MsgBox("You need To select a Procedure", vbInformation, "Unable to show table")
Exit Sub
End If
DGV_Tbl = New DataGridView
'It needs to copy data to another DataTable to show Double as Currency
Using DTemp As DataTable = New DataTable
Dim TblName As String = Me.CBox_ProcType.Text
For C As Integer = 0 To DS_All.Tables(TblName).Columns.Count - 1
DTemp.Columns.Add(DS_All.Tables(TblName).Columns(C).ColumnName, Type.GetType("System.String"))
Next
Dim Arr(DS_All.Tables(TblName).Columns.Count - 1) As String
For R As Integer = 0 To DS_All.Tables(TblName).Rows.Count - 1
For C As Integer = 0 To DS_All.Tables(TblName).Columns.Count - 1
If C = 0 Then
Arr(C) = DS_All.Tables(TblName).Rows(R)(C).ToString
Else
Arr(C) = FormatCurrency(DS_All.Tables(TblName).Rows(R)(C).ToString, 2)
End If
Next
DTemp.Rows.Add(Arr)
Next
'Working on created DataGridView
With DGV_Tbl
.Name = "DGV_Tbl"
'Add control to the Form
Me.Controls.Add(DGV_Tbl)
.DataSource = DTemp
.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells)
.RowHeadersVisible = False
.AllowUserToAddRows = False
.AllowUserToDeleteRows = False
End With
'Dispose the copied DataTable
End Using
'Resizing Form to include new DataGridView
Dim DGV_H As Integer = 0
Dim DGV_W As Integer = 0
For Each R As DataGridViewRow In DGV_Tbl.Rows
DGV_H += R.Height
Next
DGV_H += DGV_Tbl.ColumnHeadersHeight
'Add more space to include spaces between cells
DGV_H += CInt(DGV_Tbl.Rows.Count * 0.45)
For Each C As DataGridViewColumn In DGV_Tbl.Columns
DGV_W += C.Width
Next
'Add more space to include spaces between cells
DGV_W += CInt(DGV_Tbl.Columns.Count * 0.45)
DGV_Tbl.Height = DGV_H
DGV_Tbl.Width = DGV_W
'Resize the Form
Me.Height += DGV_H + 30
Me.Controls("DGV_Tbl").Location = New Point(15, Me.Height - DGV_H - 30)
'Align for currency
For x As Integer = 1 To DGV_Tbl.Columns.Count - 1
DGV_Tbl.Columns(x).DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleRight
Next
Else
'If DGV exists I need to remove it and resize the form
Dim DGV_H As Integer = DGV_Tbl.Height
DGV_Tbl.Dispose()
Me.Height -= (DGV_H + 30)
End If
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
This is the code in the button who shows another form (and the code to close the form and go back):
Private Sub Btn_ShowSummary_Click(sender As Object, e As EventArgs) Handles Btn_ShowSummary.Click
Try
If Me.CBox_ProcType.Text = "Select a Procedure" OrElse Me.CBox_ProcValue.Text = "Select a Value" Then
MsgBox("It needs to select a Procedure and a Value",
vbInformation, "Unable to show table")
Exit Sub
End If
Summary = "...Here Some text..." & vbCrLf & Split(Me.CBox_ProcType.Text, ".")(1).Trim & vbCrLf & vbCrLf
Summary &= "...Here Some text..." & Me.CBox_ProcValue.Text & vbCrLf & vbCrLf
Dim C1Wdt% = -50
Dim C2Wdt% = TBox_TotAll.Text.Length
For R As Integer = 1 To 4
Dim CBox_Phase As CheckBox = CType(Me.TLP_Phases.Controls("CBox_Phase" & R.ToString), CheckBox)
Dim TBox_ValPh As TextBox = CType(Me.TLP_Phases.Controls("TBox_ValPh" & R.ToString), TextBox)
If CBox_Phase.Checked Then
Summary &= String.Format("{0," & C1Wdt.ToString & "} {1," & C2Wdt.ToString & "}",
CBox_Phase.Text, TBox_ValPh.Text) & vbCrLf
Dim TBox_SelVarPh As TextBox = CType(Me.TLP_Phases.Controls("TBox_SelVarPh" & R.ToString), TextBox)
If TBox_SelVarPh.Text = "" OrElse TBox_SelVarPh.Text = "€ 0,00" Then
Summary &= "...Here Some text..." & vbCrLf
Else
Dim SelVarTxt$ = If(Val(TBox_SelVarPh.Text) > 0,
"...Here Some text..." & TBox_SelVarPh.Text,
"...Here Some text..." & TBox_SelVarPh.Text.Substring(1)) & vbCrLf
Summary &= SelVarTxt
End If
End If
Next
Summary &= String.Format("{0," & C1Wdt.ToString & "} {1," & C2Wdt.ToString & "}", "", New String(CChar("_"), C2Wdt)) & vbCrLf
Summary &= String.Format("{0," & C1Wdt.ToString & "} {1," & C2Wdt.ToString & "}",
"...Here Some text...",
Me.TBox_TotPhases.Text) & vbCrLf
If Me.TBox_PrtAdg.Text <> "€ 0,00" Then
Summary &= String.Format("{0," & C1Wdt.ToString & "} {1," & C2Wdt.ToString & "}",
"...Here Some text...",
Me.TBox_PrtAdg.Text) & vbCrLf
Summary &= "...Here Some text..." & TBox_PrtRapp.Text & "...Here Some text..." & TBox_CPrt.Text & "...Here Some text..." & vbCrLf
End If
Summary &= String.Format("{0," & C1Wdt.ToString & "} {1," & C2Wdt.ToString & "}",
"...Here Some text..." & TBox_ForfPercent.Text,
Me.TBox_ForfImp.Text) & vbCrLf
Summary &= "...Here Some text..." & TBox_TotPhases.Text & ")" & vbCrLf
Summary &= String.Format("{0," & C1Wdt.ToString & "} {1," & C2Wdt.ToString & "}", "", New String(CChar("_"), C2Wdt)) & vbCrLf
Summary &= String.Format("{0," & C1Wdt.ToString & "} {1," & C2Wdt.ToString & "}",
"...Here Some text...",
Me.TBox_TotAll.Text) & vbCrLf
Me.Hide()
Me.ShowInTaskbar = False
Frm_Summary.Show()
Catch ex As Exception
MsgBox(ex.ToString)
End Try
End Sub
Here the code of the back button:
Private Sub Btn_CloseNBack_Click(sender As Object, e As EventArgs) Handles Btn_CloseNBack.Click
Frm_Base.ShowInTaskbar = True
Frm_Base.Show()
Me.Close()
End Sub
I don't see any connetion between the codes (but it seems I'm wrong) please show me what I'm missing.
May I suggest another approach for your problem ?
If i were you, i would think about using a drawn datagridview, put datatable content into it before hand.
Then in the show/hide button, just switch the visibility of that datagridview along with recalculating the form size.
As for the currency column, instead of making another table, you can just populate the datatable into your datagridview, then set the format of that column into currency:
DGV_Tbl.Columns("CurrencyColumn").DefaultCellStyle.Format = "c"
More information about datagridview column formatting can be found here

Checked listview for duplicates

Hi Can you please help me to solve this i want to find the duplicates in listview. This is my code
For Up As Integer = lvCart.Items.Count - 1 To 1 Step -1
For down As Integer = 0 To Up - 1 Step 1
If lvCart.Items(Up).SubItems(0).Text <> lvCart.Items(down).SubItems(0).Text Then
ExecuteQry("INSERT INTO tblPurchaseOrder VALUES ('" & lvCart.Items(Up).SubItems(0).Text & "','" & dateCreated & "','" & txtTcost.Text & "','" & lblUserid.Text & "')")
ExecuteQry("INSERT INTO tblPurchaseOrder VALUES ('" & lvCart.Items(down).SubItems(0).Text & "','" & dateCreated & "','" & txtTcost.Text & "','" & lblUserid.Text & "')")
Exit For
Else
End If
Next
Next
if the nested loop found the same PONumber(lvCart.Items().SubItems(0).Text) in the listview it will be save as one transaction my code is working, it saves in the database but it show an error for duplicates
To find duplicates in your list view you can use a Dictionary to help with that. The itemDict will have no duplicates, and the duplicateItems list will contain duplicate items if you need them for some reason.
Private Sub FindListViewDups()
Dim lvCart As New ListView
lvCart.Items.Add("hi")
lvCart.Items.Add("bye")
lvCart.Items.Add("hi")
Dim itemDict As New Dictionary(Of String, String)
Dim duplicateItems As New List(Of String)
For i As Integer = 0 To lvCart.Items.Count - 1
If Not itemDict.ContainsKey(lvCart.Items(i).Text) Then
itemDict.Add(lvCart.Items(i).Text, "")
'Other non-duplicated logic goes here....
Else
duplicateItems.Add(lvCart.Items(i).Text)
End If
Next
End Sub

Adding a column to a Farpoint Spread grid

I've never really used Farpoint Spread before, but I have an existing VB.NET application in which I need to add a column to a Spread grid. There is currently some code like:
For Each dr As DataRow In g_AdoRS.Rows
vaSpreadSum.SetText(1, x, dr(0)) 'pol_ser
...
vaSpreadSum.SetText(20, x, dr(19)) 'renew_pay_cd
vaSpreadSum.SetFloat(21, x, dr(20)) 'renew_tot_prem
vaSpreadSum.SetFloat(22, x, dr(21)) 'renew_pol_limit
vaSpreadSum.SetFloat(23, x, dr(22)) 'renew_ded_amt
vaSpreadSum.Col = 28
x = x + 1
Next dr
These SetFloat() and SetText() calls go from 0 to 28. So in order to add another column I added this line of code:
vaSpreadSum.SetText(28, x, dr(27)) 'agent name
and changed the vaSpreadSum.Col to 29
vaSpreadSum.Col = 29
But I am not seeing another column in my grid. Any idea why? There is no error thrown or anything like that, just no changes on the screen. I know there is probably more information needed to solve this, but even if anyone know the basics of adding a column to a Farpoint Spread grid that would be much appreciated. I found this but it doesn't seem that my application is adding columns that way, I couldn't find any calls to the AddColumns() method anywhere.
Thanks for any help!
I believe this is my Form_Load method
Private Sub FrmDetailRPC_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load
Cursor.Current = Cursors.WaitCursor
FormInit()
QryLocation()
Cursor.Current = Cursors.Default
End Sub
I'll also include FormInit() because that sounds like it might have to do with what I'm looking for
Sub FormInit()
txtBusUnit.Text = svBusUnit
stmtMktSeg()
txtProduct.Text = svProduct
txtSource.Text = svSource
txtSystem.Text = svSystem
txtCustSeg.Text = svCustSeg
stmtProduct()
txtLocation.Text = svLocation
If svLocationLabel = "Region" Then
lblLocation.Text = "Territory"
Else
lblLocation.Text = svLocationLabel
End If
lblLocation.TextAlign = ContentAlignment.TopRight
stmtLocation()
'txtPayType.Text = svPayType
txtTimePer.Text = TimeName
stmtTimePer()
End Sub
And QryLocation()
Sub QryLocation()
Dim producerID As String
'SetProductSelection()
stmtLocation()
stmtGetProductType()
stmtGetTimePeriodType()
stmtGetTimePeriod()
stmtGetProducerID()
stmtGetProducerType()
If stmtProducerType = "No Preference" Then
producerID = "NULL"
Else
producerID = "'" & stmtProducerID & "'"
End If
g_strSQL = "pc_mis_rpc_getdata_detail " & _
"'" & stmtLocationType & "'," & _
"'" & Trim(svLocation) & "'," & _
"'" & svBusUnit & "'," & _
"'" & stmtProductType & "'," & _
"'" & Trim(stmtProductDtl) & "'," & _
"'" & stmtTimePeriod & "'," & _
"'" & stmtTimePeriodType & "'," & _
"'" & stmtProducerType & "'," & _
producerID & "," & _
"'Retention'" _
& FilterQry & "," & _
"'" & Trim(txtCustSeg.Text) & "'," & _
"'" & Trim(txtSource.Text) & "'," & _
"'" & Trim(txtSystem.Text) & "'"
ProcQry()
End Sub
In your Form_Init() you will need to adjust the number of columns in spread control.
It should look something like this:
Sub FormInit()
' Add a column to the spreadsheet control
vaSpreadSum.ActiveSheet.AddColumns(29, 1)
' Code cut for brevity
End Sub
--or--
Sub FormInit()
' Add a column to the spreadsheet control
vaSpreadSum.ActiveSheet.Columns.Count = 29
' Code cut for brevity
End Sub
Another method for achieving the same thing is to open the form designer, select the spread control, display the properties window (press F4 if it isn't already open), and increase the Cols property to 29.
You increase the column as follows:
vaSpreadSum.MaxCols = 29

Getting Textboxes to Clear after use

I have an access form where I input data into them to be inserted into a table for storage, the code I use is
Private Sub cmd_go_Click()
Dim insertstring As String
insertstring = "INSERT INTO KWTable (KW, Source, Code) VALUES('" & text_key.Value & "','" & combo_source.Value & "','" & txt_code.Value & "');"
DoCmd.RunSQL insertstring
End Sub
And I was wondering if there was a code I could add to this so that once the data has been inserted the text box and the combo box would automatically clear?
Use the properties of the controls. Specifically, try setting the .Text or .Value properties to "":
txtTextBox.Text = ""
Or:
txtTextBox.Value = ""