Looping through only columns containing values for specific row in dataTable - vb.net

I am developing an application using Visual Basic 2010 for hydraulic calculations of a pipe network.
This application uses a lot of iterations and loops, depending on the user input and size of network. Most of the results have to be saved temporarily to be used for the next step of calculations.
Firstly, I used a DataGridView to save the results but as the number of iterations increased, the application became very slow.
Now I am trying to create a DataTable, then populate it with some initial results (this part was successful). The obtained DataTable has some columns that are not populated like so:
22 24 10
3 16 22 9 15
16 12 24 13
14 21 10 23 12 1
24 18 23 2 1
Other calculations are performed and a certain value (X) is obtained.
Now I am trying to loop through the columns of a specific row to check if the calculated value (X) equals to one of the values in those columns.
My question is: How can I loop through only the columns that have values (avoiding the columns containing NULL values) for a specific row?
I am a beginner in VB.net. I hope my question is clear as I didn't provide any code.
Thanks in advance for you help.
This is the initial code I used:
Results.DGVInitial.Rows.Clear()
Results.DGVFinal.Rows.Clear()
For m As Integer = 0 To NetworkLayout.DGVNetworkLayout.Rows.Count - 1
Results.DGVInitial.Rows.Add()
Next
Dim I As Integer = NetworkLayout.DGVNetworkLayout.Rows.Count - 1
Dim Sec(I), Ini(I) As Integer
Dim Hyd(I), Dia(I), Len(I) As Single
Dim Qsec(I), Qini(I), Vsec(I) As Single
Dim U(I), Y(I) As Single
Do
I = I - 1
Sec(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(0).Value
Ini(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(1).Value
Hyd(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(6).Value
Dia(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(4).Value
Len(I) = NetworkLayout.DGVNetworkLayout.Rows(I).Cells(3).Value
Dim V As Integer
V = Results.DGVRandomGen.Rows(TotalNum_Runs - 1).Cells(I).Value
Qsec(I) = 0
Dim q As Single = 0
For n As Integer = 0 To Results.DGVInitial.Rows.Count - 1
If Results.DGVInitial.Rows(n).Cells(1).Value = Sec(I) Then
q = Results.DGVInitial.Rows(n).Cells(0).Value
Qsec(I) = Qsec(I) + q
Else
Qsec(I) = Qsec(I)
End If
Next
If V = 1 Then ' if the hydrant is open
Qini(I) = Hyd(I) + Qsec(I)
Else ' if the hydrant is close
Qini(I) = Qsec(I)
End If
Results.DGVInitial.Rows(I).Cells(0).Value = Qini(I)
Results.DGVInitial.Rows(I).Cells(1).Value = Ini(I)
Results.DGVSectionDischarges.Rows(TotalNum_Runs - 1).Cells(I).Value = ini(I).ToString("F2")
Now instead of using
V = Results.DGVRandomGen.Rows(TotalNum_Runs - 1).Cells(I).Value
I would like to replace the "DGVRandomGen" with a DataTable called "DT_Random"
Like I said I am a beginner so I am not sure how to code it but it will be something like this:
For DT_Random.Rows (TotalNum_Runs - 1)
For Each col As DataColumn In DT_Random.Columns
If DT_Random.Rows(TotalNum_Runs - 1).Item(col) = I Then
Qini(I) = Hyd(I) + Qsec(I)
Else
Qini(I) = Qsec(I)
End If
Next
But I want to avoid Null values as not all columns are populated
Thanks

Maybe this will help you:
Dim myXvalue = 24
Dim myDataTable As New DataTable
myDataTable.Columns.Add("Col1")
myDataTable.Columns.Add("Col2")
myDataTable.Columns.Add("Col3")
myDataTable.Columns.Add("Col4")
myDataTable.Rows.Add(22, 24, 10, DBNull.Value)
myDataTable.Rows.Add(3, 16, 22, DBNull.Value)
myDataTable.Rows.Add(24, 18, DBNull.Value, 24)
For Each column As DataColumn In myDataTable.Columns
If IsDBNull(myDataTable.Rows(0).Item(column)) Then
MsgBox("DB Null Found At: " & column.ColumnName)
Continue For
End If
If myDataTable.Rows(0).Item(column) = myXvalue Then
MsgBox("Match: " & myDataTable.Rows(0).Item(column) & " found at " & column.ColumnName)
End If
Next column
Just a quick example, you may need to restructure it a bit, but at least it shows you how to access the values in your datatable by columns. I would do a function that passes a row index as a parameter and returns a boolean. Create two booleans inside the sub, one for dbnull existing in the row, and one for finding a matching value. If dbnull bool is false, and match value is true, then return true. Just make sure you loop all the columns and dont exit early.
If you need me to elaborate let me know.

Related

For on a dataset, get column value

I am updating some old software in VB, and fixed this, but I'd like to know how to make the second option work.
The problem is in the second For loop in the code below. I'm not sure how to get a column of a specific row.
I have not worked much with VB and not used it for 10 years or so, so bare the question.
Dim i As Integer = 0
Dim dsSettings As New DataSet
dsSettings.Locale = System.Globalization.CultureInfo.InvariantCulture
If System.IO.File.Exists("QuaData\Settings.xml") Then
dsSettings.ReadXml("QuaData\Settings.xml")
ReDim Preserve IdPrefixes(dsSettings.Tables(0).Rows.Count - 1)
For Each Row As DataRow In dsSettings.Tables(0).Rows
For Each Coll As DataColumn In dsSettings.Tables(0).Columns
IdPrefixes(i) = Row("IdPrefix").ToString()
Next
i = i + 1
Next
' Here I cannot see how I can get a column of a row -
' like Rows(1)
' I cannot select Rows(index)(column name)
For i = 0 To dsSettings.Tables(0).Rows.Count - 1
IdPrefixes(i) = dsSettings.Tables(0).Rows(i)("IdPrefix").ToString()
Next
End If

Fill combobox with time values

I want fill my combobox with time values like (08:00, 08:10, 08:20 until 09:50) step=10 minutes but the result is like (8:00, 8:10, 8:20, 8:30, 9:-20,9:-10, 9:00, 9:10, 9:20).
My code doesn't show the value like 8:40, 8:50 and he also show negative value like 9:-20, 9:-10).
So please how can I resolve this problem?
Heure_rdv.Items.Clear()
Dim nbr_minute2 As String
For i = 480 To 590 Step 10
Dim nbr_heure As Integer = cint(i / 60)
Dim nbr_minute As Integer = (i - (nbr_heure * 60))
nbr_minute2 = CStr(nbr_minute) + "0"
If ((i - (nbr_heure * 60)) = 0) Then
Heure_rdv.Items.Add(CStr(nbr_heure) + ":" + nbr_minute2)
Else
Heure_rdv.Items.Add(CStr(nbr_heure) + ":" + CStr(nbr_minute))
End If
Next
This is how I should do try it in VBA.
Should be similar in VB.NET
DIM i As Integer 'Counter 1
Dim ii As Integer 'Counter 2
' make 1st loop for hours
for i = 8 To 9
' mkae 2nd loop for minutes
for ii = 0 To 50 Step 10
'
Heure_rdv.Items.Add(i & ":" & ii)
next
next
This could be done with fewer lines of code using linq
Dim steps = Enumerable.Range(0,6)
Dim items as List(Of String) = new List(Of String)()
items.AddRange(steps.Select(Function(x) "08:" & (x * 10).ToString("D2")))
items.AddRange(steps.Select(Function(x) "09:" & (x * 10).ToString("D2")))
Heure_rdv.DataSource = items
First we create a list of integers from 0 to 5 (6 elements), then using these elements we create the strings required multiplying each element of the integer list by ten and converting the result to a two digit string. We do this one time for the 8 hour and one time for the 9. Finally we could set the combo datasource to the resulting list of strings.

Excel VBA-Getting a blank message box with data derrived from an array

I am getting a blank message box for an array which should automatically have and display the following values:
00:00:00
01:00:00
02:00:00
and so on...
Here is my code
Dim i As Integer
i = 0
Dim sampleArr(0 To 24) As Variant
Dim a As Integer
a = 0
Do Until i > 23
sampleArr(a) = i & ":00:00"
a = a + 1
i = i + 1
MsgBox sampleArr(a)
Loop
Please tell me what's wrong with this code
You update the value of sampleArr(a), then increment a. So to get the just-updated value you need to use the pre-incremented value: a-1.
MsgBox sampleArr(a-1)
Put the Msgbox first before you increment a and i.
MsgBox sampleArr(a)
a = a + 1
i = i + 1
It's not entirely clear what you're trying to achieve here, (especially with a and i being identical. Presumably the msgbox is only actually in there to prove you've created the array correctly and will be removed later?
That said, as everyone is pointing out, you're incrementing your pointer before displaying the entry. The simplest way to fix that is to put the display line in immediately after creating the element.
I've also formatted i in order to produce the exact output you've requested.
Also, I suspect your array only needs to go 0 To 23 if this is some kind of time selector?
So, fixing your issue looks like:
Dim i As Integer
i = 0
Dim sampleArr(0 To 23) As Variant
Dim a As Integer
a = 0
Do Until i > 23
sampleArr(a) = Format(i, "00") & ":00:00"
MsgBox sampleArr(a)
a = a + 1
i = i + 1
Loop
However, you could just do the following:
Dim i As Integer
Dim sampleArr(0 To 23) As Variant
For i = 0 To 23
sampleArr(a) = Format(i, "00") & ":00:00"
MsgBox sampleArr(a)
Next
Beyond this, if you want to store the values in the array as TIME rather than a text representation of the time (useful for calculations etc.) then replace the sampleArr line with
sampleArr(a) = TimeSerial(i, 0, 0)

Find Common Values From Datagridview

I Have about 10 (DatagridView Count may varies As per User Selected Files From 2 to 10) Datagridview ,So How can i find common value from all Datagridviews ??
Comment If you need more brief details
Below is mine but It find common from 2 -2 datagridviews
For i As Integer = 1 To dgvCont
For j As Integer = 0 To Main.DGVM(i).Rows.Count - 1
For Each Val As DataGridViewRow In Main.DGVM(i + 1).Rows
If Val.Cells(0).Value = Main.DGVM(i).Rows.Item(j).Cells(0).Value Then
Dim cm As String = Val.Cells(0).Value
If cm = "" Then
Else
Analysis.lvCmn.Items.Add(Val.Cells(0).Value)
End If
End If
Next
Next
Next
I understand that you want to set two nested loops accounting for an undetermined number of elements (items in an array of DataGridView, I presume), performing the checks you want:
For count1 As Integer = 1 To dgvCont 'Assuming indices from 1 to dgvCont
For row1 As Integer = 0 To Main.DGVM(count1).Rows.Count - 1
If (Main.DGVM(count1).Rows(row1).Cells(0).Value Is Nothing) Then Continue For
Dim val1 As String = Main.DGVM(count1).Rows(row1).Cells(0).Value
Dim found As Boolean = False
For count2 As Integer = 1 To dgvCont 'Assuming indices from 1 to dgvCont
If (count2 = count1) Then Continue For
For row2 As Integer = 0 To Main.DGVM(count2).Rows.Count - 1
If (Main.DGVM(count2).Rows(row2).Cells(0).Value Is Nothing) Then Continue For
Dim val2 As String = Main.DGVM(count2).Rows(row2).Cells(0).Value.ToString()
If val1 = val2 Then
Dim cm As String = val1
If cm = "" Then
Else
Analysis.lvCmn.Items.Add(val1)
End If
found = True
Exit For 'By assuming that you want to stop searching after finding a match
End If
Next
If (found) Then Exit For 'By assuming that you want to stop searching after finding a match
Next
Next
Next
Your code is not too clear (neither what you want); but this should give you a good enough start to carry out the implementation you are looking for. Bear in mind that this code (like yours) only considers one column (first one); in case of wanting to iterate through all the columns, you would have to add further nested loops accounting for that.

Get row index if some column value is equal to something

In this datatable there are no duplicates, I need the row index where column x value equals 2. I would do it like this:
Dim rowIndex As Integer = 0
For i = 0 To mtable.Rows.Count - 1
If mtable.Rows(i)("x") = 2 Then
rowIndex = i
Exit For
End If
Next
I will be calling this process multiple times per second. Is there a faster way to do this in .NET?
DataTable select could work, i think it should be faster than iterating over the collection of rows.
var index = mtable.Rows.IndexOf(mtable.Select("x = 2").FirstOrDefault());
Multiple times per second is a bit vague - tens or thousands?
You could create a hash table mapping the value of "x" to the row number:
Dim nLookups = mtable.Rows.Count - 1
Dim lookupHash As New Hashtable(nLookups)
For i = 0 To nLookups
lookupHash.Add(CInt(mtable.Rows(i)("x")), i)
Next
then
Dim rowSought As Integer = -1
If lookupHash.ContainsKey(2) Then
rowSought = lookupHash(2)
End If
Or if the range of possible values of "x" is suitable, you could use an array to map the value to the row number.