I've got a DataTable, dt2, where I'm trying to add new rows (in the else block of the code below). I cannot simply add the rows within the foreach loop (which I tried with the line dt2.Rows.Add(newRow);) because that screws up the loop counter or something and causes the following error: "Collection was modified; enumeration operation might not execute."
So I tried storing the new row values in a List and then adding the List to the table outside of the loop. This works in the sense that it compiles and it does add something; unfortunately it doesn't take the correct values or column locations but instead displays this crap: System.Collections.Generic.List`1[System.Object]
Also, the information should be displayed in the 3rd, 4th, and 5th index columns under Target_Folder, Target_File, and Target_Checksum, not under Baseline_Folder.
How do I store and display the correct values under the correct columns?
foreach (DataRow drow in dt2.Rows)
{
if (drow["BASELINE_FILE"].ToString() == filename)
{
// do stuff
}
else
{
newRow = dt2.NewRow(); // newRow is a DataRow I declared up above
newRow[3] = directory;
newRow[4] = filename;
newRow[5] = checksumList[j];
newRow[6] = "Missing";
//dt2.Rows.Add(newRow);
// can't add here because that increases the number of rows and screws up the foreach loop
// therefore need to find way to store these values and add outside of loop
newFiles.Add(newRow); // newFiles is a List
}
}
dt2.Rows.Add(newFiles); // this doesn't work properly, doesn't take correct values
I think this is what you really want to do :
DataRow[] drx = dt2.Select(string.Format("BASELINE_FILE = '{0}'" , filename));
if (drx.Length == 1)
{
// do stuff with drx[0]
}
else
{
newRow = dt2.NewRow(); // newRow is a DataRow I declared up above
newRow[3] = directory;
newRow[4] = filename;
newRow[5] = checksumList[j];
newRow[6] = "Missing";
dt2.Rows.Add(newRow);
}
This way you don't need to loop through the rows.
If you're looking to go through each row in the existing grid, this should do it for you. This way currentRows isn't being modified while loop is running as it will be a shallow copy of that list.
var currentRows = from row in dataTable.Rows select row;
foreach (var row in currentRows)
{
if(doStuffCondition){ doStuff();}
else{
DataRow newRow = dataTable.NewRow();
newRow[1] = newValue; //repeat until values are loaded
employeesDataTable.Rows.Add(newRow);
}
}
This is off the top of my head, but something along these lines should work:
DataRow dr = dt2.NewRow();
foreach (ListItem item in newFiles.Items)
{
dr[3] = item[3].ToString();
dr[4] = item[4].ToString();
etc.
}
If you need more guidance, let me know and I'll look harder at it.
Related
I want to index an Array of IEnumerable<DataRow> and print out the Data into a table. I get the below error and I'm not sure hoe to overcome it.
cannot convert type System.Data.DataRow to string
IEnumerable<DataRow> query = from result in
DtSet.Tables["Results"].AsEnumerable()
where result.Field<string
("test").Contains("50")
select result;
var queryArray = query.ToArray();`
for (int i = 0; i < queryArray.Count(); i++)
{
table.Rows[i + 1].Cells[0].Paragraphs.First().Append(queryArray[i]);
}
Consider:
var queryArray = query.ToArray();
(You also have a small problem in that you're trying to stuff a datarow into your destination paragraph; this might just append "system.data.datarow" to your paragraph)
But really you could just delete that line and:
int i = 1:
foreach(var q in query)
table.Rows[i++].Cells[0].Paragraphs.First().Append(q["your column name"].ToString());
That is to say; enumerate the IEnumerable, using a separate indexer variable to keep track of where you are in (the excel sheet?)
Side note; I put a call into extract a single column from the data row; you could alternatively make this a part of your select LINQ statement, converting the datarow to a string enuneabke instead
It looks like using a dataview rowfilter might save you some effort here, something like:
DataView dv = new DataView(DtSet.Tables["Results"]);
dv.RowFilter = "test LIKE '%50%'";
foreach (DataRowView drv in dv)
{
//do the stuff...
}
Microsoft Documentation
I have a DataTable with multiple rows. I'm using a foreach loop to loop through each item and return the name. This is returning the same (1st) value for each row. What have I done wrong?
DataTable table = new DataTable();
table.Columns.Add("tag", typeof(string));
string name = hfSelected.Value;
string[] names = name.Split(',');
for (int i = 0; i < names.Length; i++)
table.Rows.Add(new object[] { names[i] });
DataRow row = table.Rows[0];
foreach (var item in table.Rows)
{
Value = row["tag"].ToString() // this is returning the same value for both items in the table.
}
In a comment you mentioned that you get the error:
cannot apply indexing with [] to an expression of type object
when trying to access item["tag"] in the foreach loop.
You need to explicitly declare the DataRow in the foreach.
// declare DataRow here, not var
foreach (DataRow item in table.Rows)
{
// use item here
Value = item["tag"].ToString(); // use += to concatenate string
}
The reason is that the DataRowCollection implements a non-generic IEnumerable so you index an object instead of DataRow. The solution above casts to a DataRow.
I would recommend looking at the Field<T>() and AsEnumerable() methods from System.Data.DataSetExtensions. AsEnumerable() returns an IEnumerable<DataRow>. Field() provides strongly typed access to the values (ie it casts/converts the types for you).
Then you can do:
foreach (var item in table.AsEnumerable())
{
// item is a DataRow here
var myString = item.Field<string>("tag"); // gets string
// you can also do
var myInt = item.Field<int>("Id"); // gets int
var myDate = item.Field<DateTime?>("Date"); // gets nullable DateTime?
var myValue = item.Field<decimal>("Price"); // gets decimal
}
Carl is correct, this is producing the same output, because inside the iteration, you use the same row, all the time. You should use 'item', instead of 'row' there (you don't need 'row' at all).
The exception you receive is because you declared 'item' with a dynamic type, it's
foreach (var item in table.Rows)
You can try
foreach (DataRow item in table.Rows)
this way, you'll be able to get the column info.
your iteration seems to be using the same 'row' variable instead of the 'item' variable you defined in the foreach statement.
I have two DataGridView like this:
Button selected will move DataRow of DataGridView to another DataGridView.
My code like this:
public static DataRow[] GetSelectedDataRows(DataGridView grid)
{
DataRow[] dRows = new DataRow[grid.SelectedRows.Count];
for (int i = 0; i < grid.SelectedRows.Count; i++)
dRows[i] = ((DataRowView)grid.SelectedRows[i].DataBoundItem).Row;
return dRows;
}
public void MoveRows(DataTable src, DataTable dest, DataRow[] rows)
{
foreach (DataRow row in rows)
{
// add to dest
dest.Rows.Add(row.ItemArray);
// remove from src
src.Rows.Remove(row);
}
}
I use it in Event btnMoveToRight_Click().
MoveRows(dtUser, dtUserStop, GetSelectedDataRows(dgvUser));
It throws exception error like:
The given DataRow is not in the current DataRowCollection
at line:
src.Rows.Remove(row);
You can't change the Table field of a DataRow.
So you need to create a new row and also copy the data separately, maybe like this:
public void MoveRows(DataTable src, DataTable dest, DataRow[] rows)
{
foreach (DataRow row in rows)
{
// create empty row
DataRow newrow = dest.NewRow();
// copy data
newrow.ItemArray = row.ItemArray;
// add to dest
dest.Rows.Add(newrow); // (*)
// remove from src NOTE: This may or may not throw an RowNotInTableException
// to avoid it you can skip the Remove and use the loop below instead..
src.Rows.Remove(row);
}
// alternative way of removing the rows..
//foreach (DataGridViewRow item in this.dgvUser.SelectedRows)
//{
// dgvUser.Rows.RemoveAt(item.Index);
//}
}
(*) An even shorter way to clone a DataRow is using this overload of the Add method:
dest.Rows.Add(row.ItemArray);
No need for the newrow now. Note that you may want to copy the RowState from the old to the new row!? See here and here for examples of changing the RowState
If you find you need to remove the DataRows via removing the DataGridViewRows you should add the DGV to the parameters of the MoveRows function to avoid an unecessary dependence..!
Of course this assumes that the DataTables have the same structure, maybe because one is a (structural) clone of the other:
dest = src.Clone();
DataRow has a DataTable property on it (DataRow.Table).
This leads me to think that adding the row to a new table breaks the association with the old DataTable, so you don't need to call src.Rows.Remove(row).
Here is method which copy DataTable into DataGridView which is not not working, this method only able to add columns and empty rows in DataGridView. Can any one suggest me solution for this without using DataSource property of DataGridView?
public void CopyDataTableInDataGridView(DataTable table, DataGridView gdv)
{
if (gdv.Rows.Count > 0)
gdv.Rows.Clear();
if (table != null && table.Rows.Count > 0)
{
foreach (DataColumn _colm in table.Columns)
{
DataGridViewColumn _col;
if (_colm.GetType() == typeof(bool))
_col = new DataGridViewCheckBoxColumn();
else
_col = new DataGridViewTextBoxColumn();
_col.Name = _colm.ColumnName;
_col.HeaderText = string.Concat(_colm.ColumnName.Select(x => Char.IsUpper(x) ? " " + x : x.ToString())).TrimStart(' ');
gdv.Columns.Add(_col);
}
foreach (DataRow _row in table.Select())
{
//Rows getting added in dgv but not data
// By adding following line in Code my problem get solved
//object[] _items = _row.ItemArray;
gdv.Rows.Add(_row);
}
}
}
You are trying to add a DataRow to DataGridView instead of adding DataGridViewRow
Look at what visualstudio's intelisence is telling you about DataGridView.Rows.Add() methods. There are 4 of them:
Add() - adds an empty row to DataGridView
Add(DataGridViewRow) - adds new row (this is what you need)
Add(count) - adds [count] of empty rows to DataGridView
Add(object[]) adds new row and populates it with values (you can also use this)
you are currently using the last one: Add(object[]). compiler doesn't complain because it's treating DataGridViewRow you passed to it as an array of objects with only one object in it. Obviously not what you want.
here is related question: https://stackoverflow.com/a/9094325/891715
By adding following line before adding row in DataGridView my problem get solve.
object[] _items = _row.ItemArray;
I am Working in asp.net and c#.
I have a datatable in my application with one column.I want to iterate through that column values and check those values with someother value.please tell me how to do that.I tried it with foreach but its not working.
Code:
foreach (DataRow dr in dt.Rows)
{
int code = Convert.ToInt32(dt.Rows[0]["Code"]);
if (code == pcode)
{
//do something
}
else
{ }
}
Note:
dt is my datatable with column code.I want to compare all values in column code with pcode.
int code = Convert.ToInt32(dr["Code"]);
Although you might want to check for NULL also :)
Inside your loop, access dr, instead of dt.Rows[0].
You are always accessing the first row:
dt.Rows[0]["Code"] // use dr instead of dt.Rows[0]
dt is my datatable with column code.I want to compare all values in
column code with pcode.
So am i right when i assume that you want to compare all values with one variable, if all fields equal this value, a bool variable should be true, otherwise false?
You can use Linq:
var allEqual = dt.AsEnumerable()
.All(r => r.Field<int>("Code") == pcode);
Enumerable.All determines whether all elements of a sequence satisfy a condition.
foreach (DataRow dr in dt.Rows)
{
object o = dr["Code"];
if (o != DBNull.Value) // Check for null
{
int code = Convert.ToInt32(o);
if (code == pcode)
{
//do something
}
else
{ }
}
}