VB.NET nested for loops - vb.net

I am having two datasets,I have to check if plant code is 1st dataset and 2nd dataset then i have to set some value for a variable.If plant code is in 1st dataset and not in second dataset then have to set some value.I have try this with following code,but i m not getting output as i want
If Not dsCheckForBOM Is Nothing AndAlso dsCheckForBOM.Tables.Count > 0 Then
If dsCheckForBOM.Tables(0).Rows.Count > 0 Then
For count1 As Int32 = 0 To dsCheckForBOM.Tables(0).Rows.Count - 1
For count2 As Int32 = 0 To dsTmpMat.Tables(0).Rows.Count - 1
If dsTmpMat.Tables(0).Rows(count2)("PLANT_CODE").ToString() = dsCheckForBOM.Tables(0).Rows(count1)("PLANT_CODE").ToString() Then
dsTmpMat.Tables(0).Rows(count2)("BOM_IND") = 1
dsTmpMat.Tables(0).Rows(count2)("BOM_DESC") = "BOM CREATED"
If count2 < dsTmpMat.Tables(0).Rows.Count - 1 AndAlso count1 < dsCheckForBOM.Tables(0).Rows.Count - 1 Then
count2 = count2 + 1
count1 = count1 + 1
End If
Else
dsTmpMat.Tables(0).Rows(count2)("BOM_IND") = 0
dsTmpMat.Tables(0).Rows(count2)("BOM_DESC") = "BOM NOT CREATED"
If count2 < dsTmpMat.Tables(0).Rows.Count - 1 Then
count2 = count2 + 1
End If
End If
Next
Next
Else
For i As Int32 = 0 To dsTmpMat.Tables(0).Rows.Count - 1
dsTmpMat.Tables(0).Rows(i)("BOM_IND") = 0
dsTmpMat.Tables(0).Rows(i)("BOM_DESC") = "BOM NOT CREATED"
Next
End If
End If

I can't test this, but I think you need to use a different approach.
First, there is no need to have two loop nested. Use the Select method to find the rows in the temporary table.
Second, if you don't find the row in the temporary table then I think you need to create it, not to set the last row of the temporary table to zero
If Not dsCheckForBOM Is Nothing AndAlso dsCheckForBOM.Tables.Count > 0 Then
' To remove the clutter, assign the two tables
' to two local variables and work with them
Dim tempTable = dsTmpMat.Tables(0)
Dim checkTable = dsCheckForBOM.Tables(0)
If checkTable.Rows.Count > 0 Then
' Loop on the primary table
For count1 As Int32 = 0 To checkTable.Rows.Count - 1
' Get the key to search for in the temporary table
Dim plantCode = checkTable.Rows(count1)("PLANT_CODE").ToString()
' Use Select to return an array of rows that match the condition.
' I suppose that PLANT_CODE is a primary key value here, so just one
' row should be returned
Dim foundRows = tempTable.Select("PLANT_CODE = '" plantCode + "'")
if foundRows.Count > 0
foundRows(0)("BOM_IND") = 1
foundRows(0)("BOM_DESC") = "BOM CREATED"
Else
' No row found, so create a new row and add it to the temporary table
Dim newRow = tempTable.NewRow()
newRow("BOM_IND") = 0
newRow("BOM_DESC") = "BOM NOT CREATED"
tempTable.Rows.Add(newRow)
End If
Next
Else
For i As Int32 = 0 To dsTmpMat.Tables(0).Rows.Count - 1
dsTmpMat.Tables(0).Rows(i)("BOM_IND") = 0
dsTmpMat.Tables(0).Rows(i)("BOM_DESC") = "BOM NOT CREATED"
Next
End If
End If

Related

Charting Sales Order stats

I have a datatable that has the columns: Order Number, a count of Lines, and a sum of Units. I want to end up with charts shown here. 3 charts Each shows a column for 1 through 20 and then >20
The problem is looping through the datatable takes over 1.5 minutes.
Dim XAxis(21) As String
Dim LinesPO(21) As Integer 'Lines per Order
Dim UnitsPO(21) As Integer 'Units Per Order
Dim UnitsPL(21) As Integer 'Units Per Line
For Each Dr As DataRow In LivesqlDt2.Rows
For i = 0 To 21
If i < 21 Then
XAxis(i) = i.ToString
If Dr.Item("Lines") = i Then LinesPO(i) += 1
If Dr.Item("Units") = i Then UnitsPO(i) += 1
If Math.Round(Dr.Item("Units") / Dr.Item("Lines"), 0) = i Then UnitsPL(i) += 1
Else
XAxis(i) = ">20"
If Dr.Item("Lines") >= i Then LinesPO(i) += 1
If Dr.Item("Units") >= i Then UnitsPO(i) += 1
If Math.Round(Dr.Item("Units") / Dr.Item("Lines"), 0) >= i Then UnitsPL(i) += 1
End If
Next
Next
I'm looking for any good ideas to speed this up, because the salesman wants to be able to run this in front of their customer.

Remove duplicates from DataGridView but keep the count?

I have a datagridview with data I pull from an SQL Server. It comes back with some data that are duplicates. I want to remove all the duplicates but keep count of how many there are of each unique items. Here is an example of what the data looks like...
For intI = DataGridView1.Rows.Count - 1 To 0 Step -1
For intJ = intI - 1 To 0 Step -1
If DataGridView1.Rows(intI).Cells(1).Value =
DataGridView1.Rows(intJ).Cells(1).Value AndAlso
DataGridView1.Rows(intI).Cells(3).Value =
DataGridView1.Rows(intJ).Cells(3).Value Then
DataGridView1.Rows.RemoveAt(intI)
Exit For
End If
Next
Next
So I can remove all the duplicates, but I want to be able to have a count of all the items in the end, including the duplicates. For example, There are 5 CA, I want to remove 4 leaving just 1 unique one, but I want to show that there are 5 CA in my datagridview next to California.
So in the end, I want the datagridview to have something like :
State | Short
California | 5
Here is my Query:
DECLARE #StartDate DATETIME
DECLARE #EndDate DATETIME
SELECT
States , Shorts
FROM
DAT.States
INNER JOIN
DATR.[Shorts]
WHERE #StartDate IS NULL
Thank you for your help!
EDIT:
I came up with a method of counting the GridView1 into GridView2 but I'm not exactly sure on the code. Maybe I could get some help with this part instead?
For i As Integer = DataGridView1.RowCount - 1 To 1 Step -1
For j As Integer = DataGridView2.RowCount - 1 To 1 Step -1
'If Grid2.Row(j).Cells(1).Value = Grid1.Rows(i).Cells(1).Value Then
' Grid2 already has that value, +1 to Column 2 of Cell(j)
' Delete row(i)
'Else
'Value does not exist, add row(i) into Grid2, and in the 2nd column of Grid2, the count is 1
'End If
Next
Next
The end result for GridView2 would be something like :
Here is my code I came up with to try and count the States in Column 1 and then delete it and add it to the Grid2, but it's not working...
Dim Counts As Integer = 0
Dim State As String = ""
Dim CurLoop As Integer = 0
Do Until CurLoop > DataGridView1.RowCount - 1
State = DataGridView1.Rows(CurLoop).Cells(0).Value
For i As Integer = DataGridView1.RowCount - 1 To 1 Step -1
If DataGridView1.Rows(i).Cells(0).Value = State Then
Counts += 1
DataGridView1.Rows.RemoveAt(i)
End If
Next
DataGridView2.Rows.Add(State, Counts)
State = ""
Counts = 0
CurLoop += 1
Loop
I have figured out the answer to my own question. It's not the prettiest solution but it works. If anyone else is in need of something like this, here is what I did...
Dim Counts As Integer = 0
Dim State As String = ""
Dim CurLoop As Integer = 0
Do Until CurLoop > DataGridView1.RowCount - 1
State = DataGridView1.Rows(CurLoop).Cells(0).Value
For i As Integer = DataGridView1.RowCount - 1 To 1 Step -1
If DataGridView1.Rows(i).Cells(0).Value = State Then
Counts += 1
DataGridView1.Rows.RemoveAt(i)
End If
Next
DataGridView2.Rows.Add(State, Counts)
State = ""
Counts = 0
CurLoop += 1
Loop
Counts = DataGridView2.Rows(0).Cells(1).Value
Counts += 1
DataGridView2.Rows(0).Cells(1).Value = Counts
For some reason, whatever in the first row of Grid1 is, it's always 1 lower than what it's supposed to be, so I add 1 to it in the end.

Updating A DataGridView Cell Incrementally

I'm currently having a slight issue duplicating a row and incrementing the sequence number.
So based on a button click, this is how I'm duplicating row 0, duplicated only one time per click.
Dim dr As DataRow
For n As Integer = 0 To 0 ' how many dupes you want
dr = tbl.NewRow
For c As Integer = 0 To tbl.Columns.Count - 1 ' copy data from 0 to NewRow
dr.Item(c) = tbl.Rows(0).Item(c)
Next
tbl.Rows.Add(dr) ' add NewRow to datatable
Next n
Here's how I'm creating the sequence number, pads with leading zeros, which seems to increment, but only after I click the duplicate button, so essentially the last row added, it the duplicated row 0, but doesn't represent the new sequence number needed.
'UPDATE SEQUENCE NUMBER
i += 1
Dim value As Integer = i
Dim r As Integer
Dim decimalLength1 As Integer = value.ToString("D").Length + 7
Dim decimalLength2 As Integer = value.ToString("D").Length + 6
Dim decimalLength3 As Integer = value.ToString("D").Length + 5
Dim decimalLength4 As Integer = value.ToString("D").Length + 4
If i >= 0 And i <= 9 Then
'1 TO 9 FORMAT
DataGridView1.CurrentCell = DataGridView1.CurrentRow.Cells("sequence")
DataGridView1.Item(73, r).Value = value.ToString("D" + decimalLength1.ToString())
'Debug.Print(value.ToString("D" + decimalLength1.ToString()))
ElseIf i >= 10 And i <= 99 Then
'10 TO 99 FORMAT
DataGridView1.CurrentCell = DataGridView1.CurrentRow.Cells("sequence")
DataGridView1.Item(73, r).Value = value.ToString("D" + decimalLength2.ToString())
'Debug.Print(value.ToString("D" + decimalLength1.ToString()))
ElseIf i >= 100 And i <= 999 Then
'100 TO 999 FORMAT
DataGridView1.CurrentCell = DataGridView1.CurrentRow.Cells("sequence")
DataGridView1.Item(73, r).Value = value.ToString("D" + decimalLength3.ToString())
'Debug.Print(value.ToString("D" + decimalLength1.ToString()))
ElseIf i >= 1000 And i <= 9999 Then
'1000 TO 9999 FORMAT
DataGridView1.CurrentCell = DataGridView1.CurrentRow.Cells("sequence")
DataGridView1.Item(73, r).Value = value.ToString("D" + decimalLength4.ToString())
'Debug.Print(value.ToString("D" + decimalLength1.ToString()))
End If
Row 0 will always have a sequence number of 1, so in theory I need to start incrementing at 2.
Suggestions? Is there a better/cleaner way of doing this?
UPDATE 2
Dim startSeq As Integer = Convert.ToInt32(tbl.Rows(0).Item(73))
MsgBox("startSeq = " & startSeq)
For n As Integer = 0 To NumericUpDown1.Value - 1
MsgBox("n = " & n)
dr = tbl.NewRow
For c As Integer = 0 To tbl.Columns.Count - 1
dr.Item(c) = tbl.Rows(0).Item(c)
If c = "73" Then ' if this is the SEQ column,
' add the current seq val to the seq column
dr.Item(c) = (startSeq + n).ToString("00000000")
End If
Next c
tbl.Rows.Add(dr)
Next n
It seems like you should be able to add the sequencer as you create the duplicates. Perhaps make it a method and pass the index of the column which has the sequence string. Something like:
Private Sub DuplicateRows(ColIndx As Integer,
Dupes As Integer)
' start value is Row(0) + 1
Dim startSeq As Integer = Convert.ToInt32(tbl.Rows(0).Item(ColIndx )) + 1
For n As Integer = 0 to Dupes -1
dr = tbl.NewRow
For c As Integer = 0 To tbl.Columns.Count - 1
If c = ColIndx Then ' if this is the SEQ column,
' add the current seq val to the seq column
dr.Item(c) = (startSeq + n).ToString("00000000")
Else
' otherwise copy the data from Row(0)
dr.Item(c) = tbl.Rows(0).Item(c)
End If
Next c
tbl.Rows.Add(dr)
Next n
End Sub
This should initialize each new row with an incremented counter. Is there a better/cleaner way of doing this
a) you should be adding to the DataTable, not the DGV if it is bound
b) (startSeq + n).ToString("00000000") should work to do the padding etc instead of that ugly block of code.
c) Use Option Strict On. If c = "73" ... is nonsense which makes the compiler guess at your intentions. Its is bug food.
d) Hardcoding "73" may work this time, but previously you said it could be anywhere. The code below finds the sequence column based on the name so it can appear anywhere. Rather than a form level var, you could find it just before you make the dupes or even in the Dupes procedure.
e) Dim startSeq As Integer = Convert.ToInt32(tbl.Rows(0).Item(73)) if you examine the answer above, this should be ... + 1 to increment the first value.
Usage:
Private tbl As DataTable ' table loaded from flat file
Private SeqColIndex As Integer ' assigned somewhere to
' point to the "sequence" column
' method to load data
Dim connstr = "Provider=Microsoft.ACE.OLEDB.12.0;..."
Using cn As New OleDbConnection(connstr)
...
End Using
' FIND the sequence column for this session
For n = 0 To tbl.Columns.Count - 1
If tbl.Columns(n).ColumnName.ToLowerInvariant = "sequence" Then
SeqColIndex = n
Exit For
End If
Next
' later to add some rows
Private Sub ButtonAddRow_Click(...
DuplicateRows(SeqColIndex, NumericUpDown1.Value)
End Sub

How to copy whole column from one datagridview to another?

There are two datagridview (dgvReport and dgvReport2). dgvReport shows data from server after choosing the fields (which is working fine).
The checkboxes are the name of columns in dgvReport. If a user selects "Email" for example the column and its row data of "Email" should be added to dgvReport2.
My problem is when I select more than one checkbox the output of row is shown only at first column of dgvReport2 not under the appropriate column. For example, in the screenshot the column "fname" data is showing under email column of dgvReport2.
How can I bring the row data under appropriate column?
Below is my coding:
'Add dynamic column
Dim newCol As Integer = 0
If chkEmail.Checked = True Then
Dim column As New DataGridViewTextBoxColumn
dgvReport2.Columns.Insert(newCol, column)
With column
.HeaderText = "email"
.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
.ReadOnly = True
End With
For rows As Integer = 0 To dgvReport.Rows.Count - 1
For colcnt As Integer = 0 To dgvReport.Columns.Count - 17
dgvReport2.Rows.Add(dgvReport.Rows(rows).Cells(0).Value)
Next
Next
newCol += 1
End If
If chkFname.Checked = True Then
Dim column As New DataGridViewTextBoxColumn
dgvReport2.Columns.Insert(newCol, column)
With column
.HeaderText = "fname"
.AutoSizeMode = DataGridViewAutoSizeColumnMode.AllCells
.ReadOnly = True
End With
For rows As Integer = 0 To dgvReport.Rows.Count - 1
For colcnt As Integer = 0 To dgvReport.Columns.Count - 17
dgvReport2.Rows.Add(dgvReport.Rows(rows).Cells(1).Value)
Next
Next
newCol += 1
End If
I find out the answer of my own question. Hope fully it will help others who are looking for same issue:
replace
For rows As Integer = 0 To dgvReport.Rows.Count - 1
For colcnt As Integer = 0 To dgvReport.Columns.Count - 17
dgvReport2.Rows.Add(dgvReport.Rows(rows).Cells(0).Value)
Next
Next
with the following:
If dgvReport2.Rows.Count > 0 Then
For rows As Integer = 0 To dgvReport.Rows.Count - 1
dgvReport2.Rows(rows).Cells(newCol).Value =
dgvReport.Rows(rows).Cells(1).Value
Next
Else
For rows As Integer = 0 To dgvReport.Rows.Count - 1
dgvReport2.Rows.Add(dgvReport.Rows(rows).Cells(1).Value)
Next
End If

InvalidArgument=Value of '2' is not valid for 'index'

Dim group11_0_count = 0
Dim group11_1_count = 0
Dim group11_2_count = 0
Dim m As Integer = 0
Dim n As Integer = 0
Dim increment2 As Integer
For m = 0 To machings2.Items.Count - 1
For n = 0 To 3
If machings2.Items(m).ToString.Chars(n) = "1" Then
increment2 = increment2 + 1
End If
Next
If (increment2 = 0) Then
group11_0_count = group11_0_count + 1
group11_1_0.Items.Add(machings2.Items(m))
End If
If (increment2 = 1) Then
group11_1_count = group1_1_count + 1
group11_1_1.Items.Add(machings2.Items(m))
End If
If (increment2 = 2) Then
group11_2_count = group1_2_count + 1
group11_1_2.Items.Add(machings2.Items(m))
End If
increment2 = 0
Next
If (group11_0_count > 0 AndAlso group11_1_count > 0) Then
Dim result = ""
Dim index As Integer = 0
Dim gg As Integer = 0
Dim hh As Integer = 0
Dim i As Integer = 0
For hh = 0 To group11_1_count - 1
For gg = 0 To group11_0_count - 1
result = ""
index = 0
For i = 0 To 3
If group11_1_0.Items(gg).ToString.Chars(i) <> group11_1_1.Items(hh).ToString.Chars(i) Then
result &= "-"
index = index + 1
Else
result &= group11_1_0.Items(gg).ToString.Chars(i)
End If
Next
If (index = 1) Then
machings3.Items.Add(result)
End If
Next
Next
End If
I am comparing the items of two combobox items like that
combobox1 items
0000
combobox items
0001
0010
the result will be like that in machings3 combobox
000-
00-0
Here the differnce between two items indicated by - sign
But i am getting InvalidArgument=Value of '2' is not valid for 'index'.
I Can't make sense out of your source and where the IndexOutOfRangeException occurs. But you know that you need 3 Items in a Combobox to access Item with Index 2?! Every collection starts with 0.