Check duplicate GridEX rows with Linq does'nt work - c#

I have two Janus GridEXs. When an specific button is clicked, I want to add rows of first grid to another grid; but I want to check that already these rows do'nt exist in the second grid, so I used this code block with linq:
DataTable dtSelectedRows = new DataTable();
dtSelectedRows = firstGrid.GetDataSource().Clone();
foreach (GridEXRow row in rows)
{
DataRow dr = ((DataRowView)row.DataRow).Row;
if (dtSelectedRows.AsEnumerable().Count() > 0)
{
if (dtSelectedRows.AsEnumerable().Where(t => t.Field<Int32>("myColumn") == Convert.ToInt32(dr["myColumn"])).Count() == 0)
{
dtSelectedRows.ImportRow(dr);
}
}
else
dtSelectedRows.ImportRow(dr);
}
}
secondGrid.SetDataSource(dtSelectedRows);
but unfortunately it did'nt work and dtSelectedRows is always empty. So I forced to rewrite the block as:
GridEXRow[] rows = firstGrid.GetCheckedRows();
DataTable dtSelectedRows = new DataTable();
dtSelectedRows = firstGrid.GetDataSource().Clone();
foreach (GridEXRow row in rows)
{
if (row.RowType == Janus.Windows.GridEX.RowType.Record)
{
DataRow dr = ((DataRowView)row.DataRow).Row;
bool rowExists = false;
foreach (DataRow r in dtSelectedRows.Rows)
{
if (Convert.ToInt32(r["myColumn"]) == Convert.ToInt32(dr["myColumn"]))
{
rowExists = true;
break;
}
}
if (!rowExists)
dtSelectedRows.ImportRow(dr);}
}
secondGrid.SetDataSource(dtSelectedRows);
and fortunately it just worked. So how can I correct the first code block?

try this :
dtSelectedRows = firstGrid.GetDataSource().AsEnumerable().ToList();
instead of :
dtSelectedRows = firstGrid.GetDataSource().Clone();

Related

Check empty rows in datatable in Visual Studio 2005, no LINQ

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);

How to get column header with non empty data in row?

I have a 15x15 dataGridView which on creation has empty (has no values) cells. Then, after user input the data, I want to get the column header which has non empty data in its row. I've been trying the following code:
DataTable dt = new DataTable();
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
bool empty = true;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[col.Index].Value!=null)
{
empty = false;
break;
}
}
if (empty == false)
{
dt.Columns.Add(col.HeaderText);
}
}
However, it doesn't appear to be working.
DataTable dt = new DataTable();
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
bool empty = false;
foreach (DataGridViewRow row in dataGridView1.Rows)
{
if (row.Cells[col.Index].Value.ToString() == string.Empty)
{
empty = true;
}
break;
}
if (empty == false)
{
dt.Columns.Add(col.HeaderText);
}
}

c# Need to remove and add a row in a DataTable at a specific value

I have a DataTable dt where I have a string column Salenumber.
I need to remove the row where the Salenumber is between 1 - 5999 and move that row to DataTable dt2.
Something like this, but foreach wont work when you want to remove rows.
DataTable dt2 = new DataTable();
dt2 = CreateNewDataTable.NewDataTable();
foreach (DataRow row in dt.Rows)
{
double RowDoubleValue;
if (Double.TryParse(row["Salenumber"].ToString(), out RowDoubleValue) && RowDoubleValue >= 1.0 && RowDoubleValue <= 5999.0)
{
dt2.ImportRow(row); //Copy
dt.Rows.Remove(row); //Remove
}
}
One way to circumvent the problem that you cant modify a collection during enumeration in a foreach is to use another collection where you store the items that you want to modify, so like:
List<DataRow> rowsToRemove = new List<DataRow>();
foreach (DataRow row in dt.Rows)
{
double RowDoubleValue;
if (Double.TryParse(row["Salenumber"].ToString(), out RowDoubleValue) && RowDoubleValue >= 1.0 && RowDoubleValue <= 5999.0)
{
rowsToRemove.Add(row);
}
}
foreach(DataRow row in rowsToRemove)
{
dt2.ImportRow(row); //Copy
dt.Rows.Remove(row); //Remove
}
Another more readable and shorter way is LINQ:
var rowsToImport = from row in dt.AsEnumerable()
let salesNumDouble = row.Field<string>("Salenumber").TryGetDouble()
where salesNumDouble.HasValue
&& salesNumDouble.Value >= 1.0 && salesNumDouble.Value <= 5999.0
select row;
DataTable dt2 = rowsToImport.CopyToDataTable();
I've used this extension to try-parse a string to double?:
public static Double? TryGetDouble(this string item, IFormatProvider formatProvider = null)
{
if (formatProvider == null) formatProvider = NumberFormatInfo.CurrentInfo;
Double d = 0d;
bool success = Double.TryParse(item, NumberStyles.Any, formatProvider, out d);
if (success)
return d;
else
return null;
}
You shouldn't modify collection in foreach process, you can use DataTable.Select for simple solution
DataTable dt;
DataTable dt2;
var rows = dt.Select("Salenumber >=1 and Salenumber<5999");
foreach (var row in rows)
{
dt.Rows.Remove(row);
}
dt2.Rows.Add(rows);

issues with apostrophes in dataTables in web application

I have a dataTable which has a good amount of data in it.
In certain columns, there is an apostrophe in the cell.
e.g. "Jack's Pot"
However, when I try to get this data as such:
var originalFinalShowsTable = Session["finalShowsTable"] as DataTable;
var finalShowsTable = new DataTable();
if (originalFinalShowsTable != null)
{
finalShowsTable = originalFinalShowsTable.Clone();
}
foreach (GridViewRow gvr in gvShows.Rows)
{
if (gvr.RowType == DataControlRowType.DataRow)
{
if (((CheckBox) gvr.FindControl("cbSelect")).Checked)
{
DataRow dr = finalShowsTable.NewRow();
for (int i = 0; i < gvr.Cells.Count - 1; i++)
{
dr[i] = gvr.Cells[i + 1].Text;
}
finalShowsTable.Rows.Add(dr);
}
}
}
"Jack's Pot" turns into a "Jack's Pot".
How do I go about avoiding this?
I have seen the same occurring with spaces ( ).
HttpUtility.HtmlDecode Method
see http://msdn.microsoft.com/en-us/library/system.web.httputility.htmldecode(v=vs.100).aspx

Error in datarow,Collection was modified; enumeration operation might not execute [duplicate]

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.

Categories