I tried to loop through my dataGridView1 and remove rows which don't satisfy the condition as following:
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (!(Convert.ToDateTime(row.Cells[7].Value) - DateTime.Today).Days <= 0)
{
dataGridView1.Rows.Remove(row); //error: Uncommitted new row cannot be deleted.
}
}
But I got this error:
Uncommitted new row cannot be deleted.
I can manage if the code also VB.NET.
Don't use foreach in this case, the looped collection may be modified and leads to unpredicted result, sometimes throws exception like collection was modified (encountered mainly in LINQ), use for instead:
for(int i = dataGridView1.RowCount-1; i >= 0; i--){
var row = dataGridView1.Rows[i];
if (!row.IsNewRow&&!(Convert.ToDateTime(row.Cells[7].Value) - DateTime.Today).Days <= 0){
dataGridView1.Rows.Remove(row);
}
}
Note that we have to loop from the largest index to 0.
Try
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (!(row.Cells.OfType<DataGridViewCell>().All(c=>c.Value == null))
{
if (!(Convert.ToDateTime(row.Cells[7].Value) - DateTime.Today).Days <= 0)
{
dataGridView1.Rows.Remove(row);
}
}
}
try with putting following condition:
foreach(DataGridViewRow row in dataGridView1.Rows)
{
if(!row.IsNewRow)
{
if (!(Convert.ToDateTime(row.Cells[7].Value) - DateTime.Today).Days <= 0)
{
dataGridView1.Rows.Remove(row);
}
}
}
Related
I've uploaded data to a datatable from a excel file. Whats the best way to check empty rows in datatable. NB: Need solution for Visual Studio 2005. Cant use linq.
foreach (DataRow row in result.Rows)
{
//check if row is empty
//if not continue processing data
//else remove the row from datatable
}
Currently the solution in my mind is inside foreach loop, put another foreach loop and check each column. If all columns are null, remove the row from datatable.
Is there any other best method. Does the above method takes more time to execute as there is another for each loop. There will be lots of rows in the datatable.
Edited:
I've got one code:
private bool checkIfRowEmpty(DataRow row)
{
var r = (DataRow)row;
int emptyCount = 0;
int itemArrayCount = r.ItemArray.Length;
foreach (var i in r.ItemArray) if (string.IsNullOrWhiteSpace(i.ToString())) emptyCount++;
if (emptyCount == itemArrayCount) return false;
else return true;
}
Is this okay? Or should I use any solution from below? Which one is good?
Here is one approach - to iterate through all rows and all columns
DataTable table = new DataTable();
List<int> rowsToRemove = new List<int>();
for (int i = 0; i < table.Rows.Count; i++)
{
DataRow row = table.Rows[i];
foreach (DataColumn col in row.Table.Columns)
{
bool skip = false;
if (row[col] != null)
{
//this column is not null, so mark skip flag as true
skip = true;
}
if (skip)
//this row should be skipped because it has at least one column that isn't null
break;
else
rowsToRemove.Add(i);
//mark this row's index for deletion
}
}
//loop through list in reverse order and remove rows by their index
for (int i = rowsToRemove.Count; i > 0; i--)
table.Rows.RemoveAt(i);
Best solution I can think of is the following one:
public bool IsRowEmpty(DataRow row)
{
if (row == null)
return true;
foreach(var value in row.ItemArray)
{
if (value != null)
return false;
}
return true;
}
Then from your main code:
foreach (DataRow row in result.Rows)
{
if(!IsRowEmpty(row))
{
// Row is not empty.
}
}
Hello,
You can simply achive this using DataView : like this -
DataView dv = yourTable.DefaultView;
dv.Sort = "column_1,column_2";
DataTable dtNew = dv.ToTable(true, "column_1", "column_2",...,"column_n"); // please mention all columns here
dtNew.Rows.RemoveAt(0);
I have the following code:
foreach (DataGridViewRow row in form1.dataGridView1.SelectedRows)
{
int index = dataGridView2.Rows.Add(row.Clone() as DataGridViewRow);
foreach (DataGridViewCell cell in row.Cells)
{
dataGridView2.Rows[index].Cells[cell.ColumnIndex].Value = cell.Value;
}
So I copy rows which were selected in a GridView to another Gridview. Now I want him to check if a row is already added to the second one and open a messagebox. How to do that? I haven't found solutions which fit in my case.
foreach (DataGridViewRow row in form1.dataGridView1.SelectedRows)
{
bool isnotexist = true;
foreach (DataGridViewRow rowgrid2 in dataGridView2.Rows)
{
if (rowgrid2.Cells[0].Value.ToString() == row.Cells[0].Value.ToString())
{
isnotexist = false;
break;
}
}
if (isnotexist)
{
int index = dataGridView2.Rows.Add(row.Clone() as DataGridViewRow);
foreach (DataGridViewCell cell in row.Cells)
{
dataGridView2.Rows[index].Cells[cell.ColumnIndex].Value = cell.Value;
}
}
}
Hope this code help...
This question already has answers here:
How do I loop through items in a list box and then remove those item?
(8 answers)
Closed 9 years ago.
I have for-each loop in which the data row is updated so the exception ,Collection was modified; enumeration operation might not execute is generated. any way to fix it? i have seen To-List function but it is not working with data row , here is my code:
foreach (DataRow row in dataTable.Rows) {
temp = row[0].ToString();
foreach (DataRow rows in dataTable.Rows) {
if (temp == rows[0].ToString()) {
tempdatatable.Rows.Add(row[0],row[1]);
dataTable.Rows.Remove(rows);
//Update happens here
}
tempdatatable.DefaultView.Sort = "gscitations DESC";
dataGridView1.DataSource = tempdatatable;
}
}
You cannot modify collection while enumerating it using Enumerator, which is happening behind the scene of the foreach statement (MDSN link).
One possible way to solve this problem is to collect rows to be deleted in the first enumeration and than remove them in the separate loop like this:
var rowsToDelete = new List<DataRow>();
foreach (DataRow row in dataTable.Rows)
{
temp = row[0].ToString();
foreach (DataRow rows in dataTable.Rows)
{
if (temp == rows[0].ToString())
{
tempdatatable.Rows.Add(row[0],row[1]);
rowsToDelete.Add(rows);
}
tempdatatable.DefaultView.Sort = "gscitations DESC";
dataGridView1.DataSource = tempdatatable;
}
}
rowsToDelete.ForEach( x => dataTable.Rows.Remove(x) );
You can also replace foreach loop with for, but you need to do extra work properly handling the current index while deleting the elements.
Try this :
for (int i = 0; i < dataTable.Rows.Count; i++)
{
var tempRow = dataTable.Rows[i];
var temp = dataTable.Rows[i][0];
for (int j = 0; j < dataTable.Rows.Count; j++)
{
DataRow rows = dataTable.Rows[j];
if (temp == rows[0].ToString())
{
tempdatatable.Rows.Add(tempRow[0], tempRow[1]);
dataTable.Rows.Remove(rows); //Update happen here
}
tempdatatable.DefaultView.Sort = "gscitations DESC";
dataGridView1.DataSource = tempdatatable;
}
}
I would say that you should make a separate table of entries, and instead of calling datatable.Rows.Remove(rows), add the row "rows" to this other table. Then, whenever row or rows iterates, you run an if statement to check if its been "deleted", i.e., in the list of deleted rows. After the enumeration is over, you can then delete those rows permanently from the table.
EDIT:
Here's the code implementation:
DataTable duplicates = dataTable;
duplicates.Rows.Clear(); /* Produces an empty duplicate of the
dataTable table to put the duplicates in */
foreach (DataRow row in dataTable.Rows)
{
if (!duplicates.Rows.Contains(row))
{
temp = row[0].ToString();
foreach (DataRow rows in dataTable.Rows)
{
if (temp == rows[0].ToString()&&!duplicates.Rows.Contains(rows)) //need unique key
{
tempdatatable.Rows.Add(row[0],row[1]);
}
tempdatatable.DefaultView.Sort = "gscitations DESC";
dataGridView1.DataSource = tempdatatable;
}
}
}
foreach (DataRow row in duplicates.Rows)
{
dataTable.Rows.Remove(row);
}
if you don't have a unique key, you can try switching !duplicates.Rows.Contains(/*specific row*/) for duplicates.Rows.IndexOf(/*specific row*/)>0. That should provide an adequate substitute.
hi guys im new here =)
i would need your help in a minimal troubble case, to save time for me =)
The problem is about that, i want to have datagridview Cells Values and
save the values to an array.
Up to now it works fine, but it just reads the first row cell and after
that process it just tells that the index is out of bound, but i dont understand why.
foreach (DataGridViewRow row in dataGridView1.Rows) //wo soll er sich aufhalten -> zeilen
{
**if (row.Cells[i].Value == null)**
{
MessageBox.Show("This row is empty");
break;
}
if (row.Cells[i].Value != null)
{
UnsortArray[i] = row.Cells[i].Value.ToString();
MessageBox.Show(UnsortArray[i]);
++i;
}
}
foreach (DataGridViewRow row in dataGridView1.Rows)
{
for (int i=0; i<= dataGridView1.Columns.Count; i++)
{
**if (row.Cells[i].Value == null)**
{
MessageBox.Show("This row is empty");
}
if (row.Cells[i].Value != null)
{
UnsortArray[i] = row.Cells[i].Value.ToString();
MessageBox.Show(UnsortArray[i]);
}
}
}
also, I don't understand why would you want to do messageBox.show inside a loop. It should be out side the loop.
foreach (DataGridViewRow row in dataGridView1.Rows) //wo soll er sich aufhalten -> zeilen
{
if (row.Cells[i].Value == null)
MessageBox.Show("This row is empty")
else
{
UnsortArray[i] = row.Cells[i].Value.ToString();
MessageBox.Show(UnsortArray[i]);
// ++i; dont need to increment if you want to read only specific column
}
}
Try something like following code>>
for(int i=0;i<dataGridView1.Rows.Count;i++)
{
if (dataGridView1.Rows[i].cells[i].Value==null)**
{
MessageBox.Show("This row is empty");
break;
}
else
{
UnsortArray[i] = dataGridView1.Rows[i].cells[i].Value.ToString();
MessageBox.Show(UnsortArray[i]);
}
}
Use different Index variable for UnSortArray (let say j). i is a index of cell which value you want to store in UnSortArray
CODE
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[i].Value == null)
{
MessageBox.Show("This row is empty")
}
else
{
UnsortArray[j] = row.Cells[i].Value.ToString();
MessageBox.Show(UnsortArray[j]);
++j;
}
}
what is the best way to identify first row in the following code?
foreach(DataRow row in myrows)
{
if (first row )
{
...do this...
}
else
{
....process other than first rows..
}
}
You can use a boolean flag for this:
bool isFirst = true;
foreach(DataRow row in myrows)
{
if (isFirst)
{
isFirst = false;
...do this...
}
else
{
....process other than first rows..
}
}
you could just use a for loop instead
for(int i = 0; i < myrows.Count; i++)
{
DataRow row = myrows[i];
if (i == 0) { }
else { }
{
Maybe something like this?
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Index == 0)
{
//...
}
else
{
//...
}
}
Use a int to loop through the collection.
for (int i =0; i < myDataTable.Rows.Count;i++)
{
if (i ==0)
{
//first row code here
}
else
{
//other rows here
}
}
First convert the DataRow to DataRowView:
How Can Convert DataRow to DataRowView in c#
and after that:
foreach (DataRowView rowview in DataView)
{
if (DataRowView.Table.Rows.IndexOf(rowview.Row) == 0)
{
// bla, bla, bla...
}
}