How to get the previous column value using datareader - sql

Hi i am trying to get the previous value of my column so I can do a simple calculation my code is like that.
ElseIf data_reader("PCT_HFO") < 0 Then
actual ROBS
Actual_ROBS = data_reader("Distance Run - NM")
+data_reader("PCT_Distance")-"Previous value of data_reader("PCT_Distance")".
New code
Previous_PCT_Distance = 0
DO while....
Actual_Distance = data_reader("Distance Run - NM") + data_reader("PCT_Distance") - Previous_PCT_Distance
Do stuff....
Previous_PCT_Distance = data_reader("PCT_Distance")
Loop
Any ideas?

Data readers are forward-only iterators. I suggest you use a Datatable, rather that data reader. But if u insist on using a data reader, you can use a new variable, say PreviousPCTDistance, that stores the copy of previous datareader value. Initialize the value of this variable to nothing or 0, for the first iteration. At the end of each loop, update this variable with the datareaders value, like :
PreviousPCTDistance = data_reader("PCT_Distance"),
So when your condition is satisfied, to get to use this previous value :
Actual_ROBS = data_reader("Distance Run - NM")+data_reader("PCT_Distance")- PreviousPCTValue

As your using a data reader you are looping though the rows so you just need a second variable previous value which is initially 0 for first record.
You then set this variable to the data reader value after you set Actual_ROBS

Related

Reference another cell in the same row having calculated the minimum value in a datatable column

Using VB, I've used the following line to successfully find the minimum value in a specific column (say column 5, where the values are all of double) in a datatable:
Dim test as double
test = datatable.Compute("min(sourcecolumn)", "")
I would now like to refer to the values in other columns (let's say column 2) along the row containing that minimum column value.
Any help would be much appreciated as I can't get my head round it!
Thanks
You can use the DataTable.Select() method to get the row(s) that contain the minimum value. DataTable.Select() returns a DataRow(). In the code below, I assumed only one column contains the minimum value hence Data(0).
Dim test as double
test = datatable.Compute("min(sourcecolumn)", "")
Dim Data() As DataRow = datatable.Select("sourcecolumn = " & test.ToString())
Dim column2 = Data(0)(1)
All you have is a value but you currently have no idea what row(s) contain that value. You can use the table's Select method to get the row(s) that contain that value in that column. Once you have the row(s), you can do whatever you want with it/them:
Dim minValue = CDbl(myDataTable.Compute("MIN(MyColumn)", Nothing))
Dim rows = myDataTable.Select($"MyColumn = {minValue}")
For Each row In rows
'Use row here.
Next
Select always returns an array, even if there is only one row, so the loop will always work. If you know that there will never be more than one match, you can just get the first element directly.

Remove elements in an arraylist that exist in another arraylist

i have 2 array list, dateListDead and dateListNotMinggu. Both is DateTime List of Array. This is the ilustration of the date value in list of array
The arrayList value
its supposed to remove specific element that exist in other array list.
so far i tried, this code it's not working.
Dim d, x As Integer
For x = 0 To dateListDead.Count - 1
For d = 0 To dateListNotMinggu.Count - 1
If dateListNotMinggu(d) = dateListDead(x) Then
dateListNotMinggu.RemoveAt(d)
End If
Next
Next
the error is : index out of range. how could it be ? i define the parameter of end looping base on arraylist.count -1
The main is that you are using a For loop from the first index to the last index but you don't account for the change of index when you remove a value. If there might be multiple values then you should start and the end rather than the beginning. In that case, removing an item won't affect the indexes of the items you are yet to test. If there can only be one match then you should be exiting the loop when you find one.
Either way, while you don't have to, I would suggest using a For Each loop on the outside. If you want to perform an action for each item in a list then that's exactly what a For Each loop is for. Only use a For loop if you need to use the loop counter for something other than accessing each item in turn.
For multiple matches:
For Each dateDead As Date In dateListDead
For i = dateListNotMinggu.Count - 1 To 0 Step -1
If CDate(dateListNotMinggu(i)) = dateDead Then
dateListNotMinggu.RemoveAt(i)
End If
Next
Next
For a single match:
For Each dateDead As Date In dateListDead
For i = 0 To dateListNotMinggu.Count - 1
If CDate(dateListNotMinggu(i)) = dateDead Then
dateListNotMinggu.RemoveAt(i)
Exit For
End If
Next
Next
Note that I have also cast the Date values as that type for comparison, which is required with Option Strict On. Option Strict is Off by default but you should always turn it On because it will help you write better code by focusing on data types.
Also, the code above would work with a List(Of Date) as well as an ArrayList but the casts would not be required with a List(Of Date). That's one of the advantages of using a generic List(Of T) over an ArrayList, which paces no restrictions on what it can contain.
If you really must use a For loop because that's what your homework assignment says then it would look like this:
For i = 0 To dateListDead.Count - 1
For j = dateListNotMinggu.Count - 1 To 0 Step -1
If CDate(dateListNotMinggu(j)) = CDate(dateListDead(i)) Then
dateListNotMinggu.RemoveAt(j)
End If
Next
Next
and this:
For i = 0 To dateListDead.Count - 1
For j = 0 To dateListNotMinggu.Count - 1
If CDate(dateListNotMinggu(j)) = CDate(dateListDead(i)) Then
dateListNotMinggu.RemoveAt(j)
Exit For
End If
Next
Next
Note that it is convention to use i as a first option for a loop counter, then j for the first nested loop, then k for the second nested loop. You should only use something else if you have good reason to do so. Remember that the loop counter doesn't represent the value in the list but rather its index. That's why you use i for index and not d for date or the like.
EDIT:
As per Jimi's comment below, the way this would usually be tackled is with a simple LINQ query. If you were using LINQ then you definitely wouldn't be using an ArrayList but rather a List(Of Date). In that case, the code would look like this:
dateListNotMinggu = dateListNotMinggu.Except(dateListDead).ToList()
If you were completely insane and wanted to use LINQ and ArrayLists then this would work:
dateListNotMinggu = New ArrayList(dateListNotMinggu.Cast(Of Date)().
Except(dateListDead.Cast(Of Date)()).
ToArray())
Take note that, as I replied in the comments, using LINQ will generate a new list, rather than changing the existing one.

The do while loop structure

In the do while loop structure usually there's a part where you declare a variable equal to a number (in this case i) and then in a second part you make a increment (i+1). I've made this example in vba, but the structure could be repeated in several different programming languages like the for in php when you're getting data from a database. Now, what I would like to understand better is the relation between the previous mentioned declarations, that is i = some number and i = i + 1 . Wouldn't this generate a problem of interpretation since you're declaring a variable to something and then assigning a different value right after it? Is the second declaration of the variable value, i = i + 1, a new variable calling the previous one or both i's are the same? This is the general orientation I intend with this question. I think explaining the scoop of both variables would help understanding. Thanks!
Sub DoWhile()
Dim x, i, sum
x = 10
i = 1
sum = 0
Do While i < x
sum = sum + i
i = i + 1
Loop
MsgBox “Sum = ” & sum
End Sub
A variable is really just a location in memory. That location can have any value. By setting i=i+1, you're really saying "take the value at position i, add 1 to it, and store it at position i". No new variable is created. There's no problem with the computer interpreting this- what it cares about is the location of i, which isn't changing. It still knows where to find i, regardless of how many times you change the value there.
Since you have created the variable i as a global variable, any reference or modification to i in the sub will be on the same variable. That being said:
Dim i as int
i = 1
Do while i < 11
MsgBox("The value of i is: " & i)
i = i + 1
Loop
would display 10 messageboxes showing the value of i being between 1 and 10.
When the program encounters i = i + 1, the computer 'sees' this as take the value of i, add one to it, and store the result in the variable i.
Hope that helps.

Function does not read last value

I am developing a program for a chain of restaurants, they should normally be able to calculate their guestcount and sales through a vb.net application with a connection to dbf files.
My dataset gets filled in correctly as is my datatable (checked by filling in datarowview = right data)
But then I get a problem, in all my functions using my datatable, the datatable skips the final value, in this case it is all values from a month so it either skips 31 or day 30.
Tried while, Tried for each, debugged alot (how i found it was the last value). But now I have no idea why the last value isn't used by the function
Public Function Getgctakeout(ByVal i_table As DataTable)
table = i_table
i = 0
gctakeout = 0
For Each row As DataRow In i_table.Rows
gctakeout = gctakeout + Convert.ToDouble(row(4))
Next row
'MessageBox.Show(gctakeout)
Return gctakeout
End Function
This function does not use the value of the last row to calculate gctakeout
what in the name of the lord is wrong :)
Assuming that your DataTable is really filled correctly, you have two other options to get the sum.
Use the old DataTable.Compute method which works also with .NET < 2.0
Use Linq-To-DatSet and it's Enumerable.Sum
1)
Dim Sum = CType(table.Compute("Sum(ColumnName)", Nothing), Double)
2)
Dim Sum = table.AsEnumerable().
Sum(Function(row)row.Field(Of Double)("ColumnName"))

How can I update a row in a DataTable in VB.NET?

I have the following code:
Dim i As Integer = dtResult.Rows.Count
For i = 0 To dtResult.Rows.Count Step 1
strVerse = blHelper.Highlight(dtResult.Rows(i).ToString, s)
' syntax error here
dtResult.Rows(i) = strVerse
Next
I want to add a strVerse to the current row.
What am I doing wrong?
The problem you're running into is that you're trying to replace an entire row object. That is not allowed by the DataTable API. Instead you have to update the values in the columns of a row object. Or add a new row to the collection.
To update the column of a particular row you can access it by name or index. For instance you could write the following code to update the column "Foo" to be the value strVerse
dtResult.Rows(i)("Foo") = strVerse
You can access columns by index, by name and some other ways:
dtResult.Rows(i)("columnName") = strVerse
You should probably make sure your DataTable has some columns first...
Dim myRow() As Data.DataRow
myRow = dt.Select("MyColumnName = 'SomeColumnTitle'")
myRow(0)("SomeOtherColumnTitle") = strValue
Code above instantiates a DataRow. Where "dt" is a DataTable, you get a row by selecting any column (I know, sounds backwards). Then you can then set the value of whatever row you want (I chose the first row, or "myRow(0)"), for whatever column you want.