Akjell
Akjell

Reputation: 109

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
            }

        }

Upvotes: 1

Views: 942

Answers (2)

Tim Schmelter
Tim Schmelter

Reputation: 460370

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

Upvotes: 1

Ilia Maskov
Ilia Maskov

Reputation: 1898

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

Upvotes: 0

Related Questions