I need to iterate over a DataRow in gridview, to compare the values from the current row and previous row. Appreciate if someone could help on this issue. I'm new
I am currently iterating like this, but i dont know how to continue:
//Check if current row ACTIVITY = LOAD_A and previous row ACTIVITY = LOAD_B is true , then store the
value and do the sum calculation.
foreach (DataRow sda in dt.Rows)
{
if (sda.Field<string>("ACTIVITY") == "LOAD_A")
{
}
}
As devNull already mentioned you can use a variable to hold the value of the previous iteration of the foreach loop.
This could look like this:
DataRow previousDr = null;
foreach (DataRow sda in dt.Rows)
{
if (previousDr != null)
{
if (sda.Field<string>("ACTIVITY") == "LOAD_A" &&
previousDr.Field<string>("ACTIVITY") == "LOAD_B")
{
//Store value und do calculation.
}
}
previousDr = sda;
}
You can use for statement and indexer property of DataRow to accomplish this
DataColumn column = table.Columns["ACTIVITY"];
for (int index = 1; index < table.Rows.Count; ++index)
{
if (table.Rows[index - 1].Field<string>(column) == "LOAD_B" && // previous row
table.Rows[index].Field<string>(column) == "LOAD_A") // current row
{
// do somthing
}
}
Need an easy method to sum row values(int columns) when a string column value has duplicates in a datatable. And need to remove rows having duplicate values. Below is a datatable for example.
Below table have duplicate "AAA" values, so need to sum Int_Col3,Col4,Col5,Col6,Col7. Note that the columns with Int are integer columns.
Expected Datatable:
Here is a simple method to achieve what you want, in-place. (The same data table is converted to the expected state)
private static void CombineDuplicatesInPlace(DataTable dt)
{
Dictionary<string, DataRow> cachedRows = new Dictionary<string, DataRow>();
for (int i = 0; i < dt.Rows.Count; i++)
{
DataRow dataRow = dt.Rows[i];
string key = Convert.ToString(dataRow["String_Col1"]);
if (cachedRows.ContainsKey(key))
{
DataRow existingRow = cachedRows[key];
foreach (DataColumn dc in dt.Columns)
if (dc.DataType == typeof(int))
existingRow[dc] = (int)existingRow[dc] + (int)dataRow[dc];
dt.Rows.Remove(dataRow);
i--;
}
else { cachedRows[key] = dataRow; }
}
}
I have a problem.
I have two loops (one for row, one for column) for creating data in DataTable. I want to check if cell is empty for column named "Name" and if it is empty just don't add this row. And here is a question: How to cancel adding row?
Got some code:
for (int i = 0; i < data.Count(); i++)
{
cell = data.ElementAt(i);
DataRow row;
row = dataTable.NewRow();
foreach (string column in columns)
{
if (row["Name"] == "")
{
row = null;
}
else
{
row[column] = cell;
}
}
if (row != null)
{
dataTable.Rows.Add(row);
}
}
But after next loop is starting it throws NullException: Object reference not set to an instance of an object.
Generally I want to add Rows to DataTable only those where value of cell is not empty at column called "Name" (i mean where is "").
What is the best way or easiest way to do it right?
Change it as:
....
foreach (string column in columns)
{
if (row["Name"] == "")
{
row = null;
break; //--> Add this line
}
else
{
row[column] = cell;
}
}
....
I am trying to store the values of each of my rows in a string.
If I try to do DataGridView.Rows.ToString() I get
System.Windows.Forms.DataGridViewRowCollection
Not even close to what I need.
Any ideas?
I think you're looking for something on a per row basis. If so, I suggest the following.
private static IEnumerable<string> GetRowValues(this DataGridView dgv)
{
var list = new List<string>(dgv.Rows.Count);
foreach (DataGridViewRow row in dgv.Rows)
{
var sb = new StringBuilder();
foreach (DataGridViewCell cell in row.Cells)
{
sb.Append(cell.ToString());
}
list.Add(sb.ToString());
}
return list.AsReadOnly();
}
You need to do something like this:
StringBuilder sb = new StringBuilder();
for(int row=0; row<DataGridView.Rows.Count; row++)
{
for(int col=0; col < DataGridView.Columns.Count; col++)
{
sb.Append(DataGridView.Row[row][col].ToString());
}
}
sb.ToString(); // that will give you the string you desire
EDIT I didn't run this through to check that it runs but it should at least give you a starting point. Also, this will give you all rows. If you want just one row, change the variable row to the row number you need (keep in mind that it is zero-based).
Use the for each statement to iterate through each row in the Datagridview.
foreach (DataGridViewRow datarow in dataGridView.Rows)
{
string col1 = datarow.Cells["Col1"].Value.ToString();
string col2 = datarow.Cells["Col2"].Value.ToString();
string col3 = datarow.Cells["Col3"].Value.ToString();
}
Foreach(Var row in DataGridView.Rows)
{
Foreach(Var cell in row.Cells)
{
Var str = cell; // this is the string you want
}
}
Something like the code above. Excuse the formatting typed on iPad.
in the next example how can I know the current row index?
foreach (DataRow temprow in temptable.Rows)
{
//this.text = temprow.INDEX????
}
You have to create one yourself
var i = 0;
foreach (DataRow temprow in temptable.Rows)
{
this.text = i;
// etc
i++;
}
or you can just do a for loop instead.
I have a type in MiscUtil which can help with this - SmartEnumerable. It's a dumb name, but it works :) See the usage page for details, and if you're using C# 3 you can make it even simpler:
foreach (var item in temptable.Rows.AsSmartEnumerable())
{
int index = item.Index;
DataRow value = item.Value;
bool isFirst = item.IsFirst;
bool isLast = item.IsLast;
}
If you can use Linq, you can do it this way:
foreach (var pair in temptable.Rows.Cast<DataRow>()
.Select((r, i) => new {Row = r, Index = i}))
{
int index = pair.Index;
DataRow row = pair.Row;
}
You actually Don't. One of the beauties with foreach is that you don't have the extra set of code handling incrementing and checks on the length.
If you want to have your own Index you would have to do something like this
int rowindex = 0;
foreach (DataRow temprow in temptable.Rows)
{
//this.text = temprow.INDEX????
this.text = rowindex++;
}
int rowIndex = temptable.Rows.IndexOf(temprow);
It's not possible with a standard foreach loop. The simplest way is to use a for loop
for ( int i = 0; i < temptable.Rows.Count; i++ ) {
DataRow temprow = (DataRow)temptable.Rows[i];
...
}
Another option is to use an extension method
public static void ForEachIndex<T>(this IEnumerable<T> e, Action<T,int> del) {
var i = 0;
foreach ( var cur in e ) {
del(cur,i);
}
}
...
temptable.Rows.Cast<DataRow>.ForEachIndex((cur,index)
{
...
});
Hey there's a much faster way I think. No iteration required!
First, declare a static variable for the Friend RowID Field of the DataRow:
Private Shared RowIDFieldInfo As System.Reflection.FieldInfo = GetType(DataRow).GetField("_rowID", System.Reflection.BindingFlags.NonPublic Or System.Reflection.BindingFlags.Instance)
Then All you need to do to use it is:
RowIDFieldInfo.GetValue(MyDataRow) - 1
I have not tested this after resorting or filtering.
In my case I haven't a need to do that, so this works.
Better late than never...
foreach (DataRow temprow in temptable.Rows)
{
temptable.Rows.IndexOf(temprow);
}
Write any Cell number and get RowIndex
foreach (var item in datagridview.Rows)
{
//TextBox1.Text= item.Cells[0].RowIndex.ToString();
}
Either use a for-loop, or use an integer follow along:
int count =0;
foreach (DataRow temprow in temptable.Rows)
{
//count is the index of the row in the array temptable.Rows
//this.text = temprow.INDEX????
++count;
}
You can use the standard for loop to get the index
for(int i=0; i<temptable.Rows.Count; i++)
{
var index = i;
var row = temptable.Rows[i];
}
While LFSR's answer is right, I'm pretty sure calling .IndexOf on just about any collection/list is going to enumerate the list until it finds a the matching row. For large DataTable's this could be slow.
It might be better to for (i = 0; i < temptable.Rows.Count; i++) { ... } over the table. That way you have the index without imposing a find-the-index tax.
The alternative way to retrieve data by using index instead of using column name
foreach (DataRow temprow in temptable.Rows)
{
String col1 = temprow[0].ToString().Trim();
String col2 = temprow[1].ToString().Trim();
}
Hope it help