Last line of a datatable asp.net - asp.net

I have a problem when I'm trying to a loop in a DataTable that a dataset contains.
I'm doing a loop like this:
for(int i = 0; i<ds.Tables[0].Rows.Count - 1 ; i++)
The problem is that I can't get the value of the last line with this one, but if I try to get rid of the "-1" and do a loop on the whole table, I'll have an out of range exception.
This out of range exception is because I have to check if the value of a line "i" is equal to the value of a line "i+1", like this:
if (ds.Tables[0].Rows[i]["Release_No"] != ds.Tables[0].Rows[i + 1]["Release_No"])
So if I do it in a loop, when the index is on the last line it will check if the last line is equal to i+1, and it's out of the table.
So I was trying to check if the index is on the last line, then just get the value of the last line, but it seems like it doesn't work.
if(ds.Tables[0].Rows.IndexOf(ds.Tables[0].Rows[i]) == ds.Tables[0].Rows.Count)
If anyone has an idea, let me know, and of course if it is not clear enough let me know, I'll give more information and more code.
Thanks for your help and your time!

Check if it's the last record, first.
I like to refactor code to read as close to sentence form as possible, explaining what you want it to do using named variables and methods, and that often gets me unlocked.
Try to make each line of code do one thing, and one thing only, like check if it is the last row:
var data = ds.Tables[0].Rows;
var lastRow = data.Count - 1;
for(int i = 0; i < lastRow ; i++)
{
if (i == lastRow){
// This is the last row. Handle the last row here.
}
else
{
// Handle all other rows here
var currentRecord = data[i];
var nextRecord = data[i + 1];
if (currentRecord["Release_No"] != nextRecord["Release_No"])
{
// Handle unique Releases...
}
}
}

Use less than or equal to like this
for(int i = 0; i<=ds.Tables[0].Rows.Count - 1 ; i++)
I hope this may get what you want.

Something like this is better ?
var lastRow = data.Count - 1;
var data = ds.Tables[0].Rows;
for(int i = 0; i< lastRow; i++)
{
testFirstCum = Convert.ToInt32(ds.Tables[0].Rows[i]["EDI_Accum_Quantity"]);
if ( i == lastRow)
{
if (DBNull.Value.Equals(data[i]))
{
quantity = 0;
}
else
{
quantity = Convert.ToInt32(data[i]);
testFirstCum = testFirstCum + quantity;
System.Diagnostics.Debug.WriteLine(quantity);
System.Diagnostics.Debug.WriteLine(testFirstCum);
}
}
else
{
var col = ds.Tables[0].Columns;
var currentRecord = data[i];
var nextRecord = data[i + 1];
if(currentRecord["Release_No"] != nextRecord["Release_No"])
{
for (int j = col[2].Ordinal; j < col.Count; j++)
{
if (DBNull.Value.Equals(data[i][j]))
{
quantity = 0;
}
else
{
quantity = Convert.ToInt32(data[i][j]);
testFirstCum = testFirstCum + quantity;
System.Diagnostics.Debug.WriteLine(quantity);
System.Diagnostics.Debug.WriteLine(testFirstCum);
}
}
}
}
}

Related

Firebase (....ContinueWith(task => ...) in a For-Loop

First, this is the code:
for (int j = 1; j <= count; j++)
{
db.Child("Some Child").GetValueAsync().ContinueWith(task =>
{
Debug.Log("j: " + j); // Here the Debug will show me that j = count
if (task.IsFaulted)
{
// ERROR HANDLER
}
else if (task.IsCompleted)
{
// Some Code Here
}
});
}
Ok, so my problem is that after the "....ContinueWith(task => ..." ' j ' will become directly equal to the count variable. Why this happens and how to solve it? Or is there another method to do that?
Ok, so my problem is that after the "....ContinueWith(task => ..." ' j
' will become directly equal to the count variable. Why this happens
and how to solve it?
That's because you used <= instead of <. With <=, j must be equals to count for the loop condition to be met and finish. If you want j to be less than count then use count-1 or simply use <.
So, that should be
for (int j = 1; i <= count-1; j++)
Or
for (int j = 1; i < count; j++)
Note that array starts from 0 not 1 so int j = 1; should be int j = 0; but I have a feeling that's what you wanted to do and you are starting the loop from 1 on purpose.
Finally, another problem is your variable being captured in a loop because you are using lambda in the ContinueWith function. See this post for more information. To use the j variable inside the ContinueWith lambda function, make a copy of it then use that copy instead of the j variable.
db.Child("Some Child").GetValueAsync().ContinueWith(task =>
{
//MAKE A COPY OF IT
int jCopy = j;
Debug.Log("j: " + jCopy); // Here the Debug will show me that j = count
}
Complete fixed code:
for (int j = 1; i < count; j++)
{
db.Child("Some Child").GetValueAsync().ContinueWith(task =>
{
//MAKE A COPY OF IT
int jCopy = j;
Debug.Log("j: " + jCopy);
if (task.IsFaulted)
{
// ERROR HANDLER
}
else if (task.IsCompleted)
{
// Some Code Here
}
});
}

On the Foreach Loop Get Previous Value

How can I implement the below statement using a foreach loop
for(int i = 0; i<=dt.Rows.Count -1; i++)
{
var quote = Convert.ToDouble(dt.Rows[i]["Data"]) - Convert.ToDouble(dt.Rows[i-1]["Data"])
}
when I use a foreach loop:
foreach (DataRow row in dt.Rows)
{
// how can i write this statement like the loop above.
}
You can store the previous value on each iteration of the loop to use in the next iteration.
var prev = 0;
foreach (DataRow row in dt.Rows)
{
var quote = Convert.ToDouble(row["Data"]) - Convert.ToDouble(prev);
prev = row["Data"];
}
How to set quote with an initial value of 0:
double quote = 0.0;
var prev = 0;
foreach (DataRow row in dt.Rows)
{
quote = Convert.ToDouble(row["Data"]) - Convert.ToDouble(prev);
prev = row["Data"];
}
Another way to set quote to 0 on the first iteration of the loop:
var prev = 0;
var i = 0;
foreach (DataRow row in dt.Rows)
{
double quote;
if(i == 0)
{
quote = 0.0;
}
else
{
quote = Convert.ToDouble(row["Data"]) - Convert.ToDouble(prev);
}
prev = row["Data"];
i++;
}
NOTE: this last example, based on OP's comments to my answer, is really just a stab in the dark because the OP has given no clear definition of what is needed. These add-on examples are really beyond the scope of the original question.
If you use a foreach-loop you don't have an index but only the current item. So if you want to access the previous DataRow you should use a for-loop as in your first approach. But you could write it more readable and efficient:
for(int i = 1; i < dt.Rows.Count -1; i+=2)
{
double thisData = dt.Rows[i].Field<double>("Data");
double prevData = dt.Rows[i-1].Field<double>("Data");
double quote = thisData - prevData;
}

Trying to compare multiple consecutive elements of a 2D array of Lables

I have a 2d array of Labels, each label contains a String version of an int. I'm attempting to traverse my array and check to see if each element contains the same int. Am I going about this the wrong way?
public boolean isPattern(Label[][] matirx) {
boolean pattern = false;
for (int rPos = 0; rPos < rows; rPos++) {
for (int cPos = 0; cPos < columns - 3; cPos++) {
if (matrix[cPos][rPos].equals(matrix[cPos + 1][rPos])
&& matrix[cPos][rPos].equals(matrix[cPos + 2][rPos])
&& matrix[cPos][rPos].equals(matrix[cPos + 3][rPos])) {
pattern = true;
}
}
}
When I print my boolean to the output window, I get false no matter what. So I guess my real question is. Am I comparing the contents of each Label or the value at each index, thus causing the variable never to be true?
So I ended up using this solution:
for (int rPos = 0; rPos < rows - 3; rPos++) {
for (int cPos = 0; cPos < columns; cPos++) {
if (matrix[cPos][rPos].getText().equals(matrix[cPos][rPos + 1].getText())
&& matrix[cPos][rPos].getText().equals(matrix[cPos][rPos + 2].getText())
&& matrix[cPos][rPos].getText().equals(matrix[cPos][rPos + 3].getText())) {
pattern = true;
Works as needed. If anyone comes across this and knows a better way, please do share.

Changing Data Structure in Data Table

I want to change the structure of my DataTable. My datatable shows data in following format:-
I pivoted my datatable, using following code.
public DataTable PivotTable(DataTable source)
{
DataTable dest = new DataTable("Pivoted" + source.TableName);
dest.Columns.Add(" ");
foreach (DataRow r in source.Rows)
dest.Columns.Add(r[0].ToString());
for (int i = 0; i < source.Columns.Count - 1; i++)
{
dest.Rows.Add(dest.NewRow());
}
for (int r = 0; r < dest.Rows.Count; r++)
{
for (int c = 0; c < dest.Columns.Count; c++)
{
if (c == 0)
dest.Rows[r][0] = source.Columns[r + 1].ColumnName;
else
dest.Rows[r][c] = source.Rows[c - 1][r + 1];
}
}
dest.AcceptChanges();
return dest;
}
After pivoting my Datatable shows record in following format:-
But I need result in following format:-
That is if there are 1 Sector it should show till 1 stop, if there are 3 Sector then it should show till 3 stop. It should increase or decrease automatically.
Please help me with the code.
Thanks

Avoiding comma separator for the last value

I am generating an output on a webpage in a format like this
({"1":"Jeff","2":"Tom","3":"Michael",})
For this, basically this is the code I am using
Response.Write("(" + "{");
//
for (Int32 i = 0; i < k.Length; i++)
{
Response.Write(Convert.ToString(k.GetValue(i)) + ",");
}
//
Response.Write("}" + ")");
Notice my output, after Michael" there is a comma which I do not want since this is the last vaue but this is appearing since , is in the for loop. How to prevent this/remove this last comma from appearing?
My output should be ({"1":"Jeff","2":"Tom","3":"Michael"}) (There's no comma after last value here)
Assuming k is an array of strings
List<string> tokens = k.ToList<string>();
Response.Write("({" + String.join<string>(",", tokens) + "})");
Simplified and VB.Net, but i think you will get it:
Dim values As New List(Of String)(New String() {"1:Jeff", "2:Tom", "3:Michael"})
Dim result As String = "({" & String.Join(",", values.ToArray) & "})"
If k is a Collection like Array,List etc.
Depending on the number of iterations and how often this happens use StringBuilder instead.
StringBuilder sb = new StringBuilder();
for (Int32 i = 0; i < k.Length; i++)
{
sb.Append(",");
sb.Append(Convert.ToString(k.GetValue(i)));
}
if (sb.Length > 0) {
sb.Remove(0,1);
}
Response.Write(String.Format("({{{0}}})", sb.ToString()));
Another way is: However, it has to check every iteration.
StringBuilder sb = new StringBuilder();
for (Int32 i = 0; i < k.Length; i++)
{
if (sb.Length > 0) {
sb.Append(",");
}
sb.Append(Convert.ToString(k.GetValue(i)));
}
Response.Write(String.Format("({{{0}}})", sb.ToString()));
you can decrease your loop instead increase... like
for (Int32 i = k.Length; i > 0; i--)
and put: if (i == 1) removeComa;
Response.Write("(" + "{");
//
for (Int32 i = 0; i < k.Length; i++)
{
Response.Write(Convert.ToString(k.GetValue(i)) + (i == k.Length - 1 ? "" : ","));
}
//
Response.Write("}" + ")");
One of my favorite fixes for this is to use a prepend instead and only set comma as the seperator value after the first item (sorry for the VB):
Dim seperator As String = ""
For i As Integer = 0 To k.Length
Response.Write(seperator + Convert.ToString(k.GetValue(i)))
seperator = ","
Next
In your loop, simply use insert a "break" when the count reaches the last digit and that has been processed?
If you change how you output to write the first object in the collection then everyone after preceded by a comma it should work fine.
Response.Write("(" + "{");
//
Response.Write(Convert.ToString(k.GetValue(0)));
for (Int32 i = 1; i < k.Length; i++)
{
Response.Write("," + Convert.ToString(k.GetValue(i)));
}
//
Response.Write("}" + ")");
An alternative would be writing to a stringbuilder and outputting all but the last character

Resources