Xaisoft
Xaisoft

Reputation: 46651

How to check if a DataTable row(s) has changed when using foreach?

I have the following code:

int sequence = 1; //This is incremented every time the Account changes
int numberOfItems; //This is reset after the Account changes
decimal totalAmount = 0m; //This is reset after the Account changes
string prevRow; //not sure how to handle this

foreach(DataRow row in dt.Rows)
{
  //I am stuck here
  if(row["Account"]) == prevRow)
  {
  numberOfItems++;
  totalAmount += Convert.ToDecimal(row["TotalAmount"]);
  }
  else
  {
     //reset everything and increase sequence
     numberOfItems = 0;
     totalAmount = 0m;
     sequence++
  }

}

My initial table may contain the data:

abc, 50.0
abc, 50.0
def, 60.0
ghi, 70.0

When looping through using for, the numberOfItems for abc should = 2, 1 for def, and 1 for ghi. The totalAmount for abc should be 100.0, 60.0 for def and 70.0 for ghi. The sequence should be 1 for abc, 2 for def, and 3 for ghi.

First thing I noticed when running the for loop is that it is skipping a bunch of rows in the first table, so when I create a second table in the else, numberOfItems and totalAmount are still 0. The second table should be something like:

abc, 100, 2, 1
def, 60, 1, 2
ghi, 70, 1, 3

where the last number in the csv values is the sequence and the number right before that is the numberOfItems per account.

for (int i = 0; i < dt.Rows.Count; i++ )
            {
                DataRow row = dt.Rows[i];
                DataRow prevRow = i > 0 ? dt.Rows[i - 1] : null;

                if (prevRow != null && row[1] == prevRow[1])
                {
                    numberOfItems++;
                    totalAmount += Convert.ToDecimal(row[2]);
                    row[3] = "D";
                    row[4] = c;
                    row[5] = sequence;

                }
                else
                {
                    dt2.Rows.Add("N",
                        c,
                        row[1],
                        row[2],
                        row[3],
                        numberOfItems,
                        totalAmount,
                        sequence);

                    numberOfItems = 0;
                    totalAmount = 0m;
                    sequence++;
                }
            }

Upvotes: 0

Views: 11084

Answers (4)

Tim Schmelter
Tim Schmelter

Reputation: 460258

A foreach row doesn't know it's previous row. So why don't you simply use a for-loop?

for(int i = 0; i < dt.Rows.Count; i++)
{
    DataRow row = dt.Rows[ i ];
    DataRow prevRow = i > 0 ? dt.Rows[ i - 1 ] : null;

    if(prevRow != null && row["Account"] == prevRow["Account"])
    {
        // ...
    }
} 

Now that you have updated your question i would suggest to use Linq-To-DataSet:

var groups = dt.AsEnumerable()
    .GroupBy(r => r.Field<String>("Account"))
    .Select((g, i) => new { 
        Account = g.Key,
        TotalAmount = g.Sum(r => r.Field<double>("TotalAmount")),
        Count = g.Count(),
        Id = i + 1,
    });

foreach (var grp in groups)
    Console.WriteLine("{0},{1},{2},{3}"
        ,grp.Account, grp.TotalAmount, grp.Count, grp.Id);

Note that you need to add using System.Linq.

Upvotes: 0

Lajos Arpad
Lajos Arpad

Reputation: 76988

int sequence = 1; //This is incremented every time the Account changes
int numberOfItems; //This is reset after the Account changes
decimal totalAmount = 0m; //This is reset after the Account changes
string prevRow = null; //not sure how to handle this

foreach(DataRow row in dt.Rows)
{
  //I am stuck here
  if((row["Account"]) == prevRow)
  {
  numberOfItems++;
  totalAmount += Convert.ToDecimal(row["TotalAmount"]);
  }
  else
  {
     //reset everything and increase sequence
     numberOfItems = 0;
     totalAmount = 0m;
     sequence++;
  }
  prevRow = row["Account"];

}

Note that I've put a ; after the incrementation of sequence.

Upvotes: 0

Gavin Coates
Gavin Coates

Reputation: 1425

int sequence = 1; //This is incremented every time the Account changes
int numberOfItems; //This is reset after the Account changes
decimal totalAmount = 0m; //This is reset after the Account changes
String prevAccount == ""; //not sure how to handle this

foreach(DataRow row in dt.Rows)
{
   //I am stuck here
   if(row["Account"] == prevAccount)
   {
      numberOfItems++;
      totalAmount += Convert.ToDecimal(row["TotalAmount"]);
   }
   else
   {
       //reset everything and increase sequence
       numberOfItems = 0;
       totalAmount = 0m;
       sequence++;
    }
    prevAccount = row["Account"];
}

Upvotes: 0

Aghilas Yakoub
Aghilas Yakoub

Reputation: 29000

You can use DataTable.GetChanges

Link : http://msdn.microsoft.com/en-us/library/k2552649.aspx

var changeTable = table.GetChanges();
foreach(var item in changeTable.Rows)
{
 .....

}

For modified rows you can use argument DataRowState.Modified

table.GetChanges(DataRowState.Modified);

Upvotes: 1

Related Questions