Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Datatable - Sum Each Cell In a Row

Tags:

c#

datatable

There are lots of examples of how to get the sum of each cell in a column. I have not been able to find an example of how to sum each cell in a row and add that total into the new column called "Total" for example.

C# DataTable has the DataTable1.Compute("SUM(["Column Name"])", "")

Example of What I would like to do below. However I would also like to be able to exclude specific columns as they may not contain numbers.

enter image description here

Edit The table is dynamic and the number of columns may change.

like image 466
Matt Avatar asked Sep 27 '13 14:09

Matt


3 Answers

You can use this loop:

table.Columns.Add("Total", typeof(decimal));
foreach (DataRow row in table.Rows)
{
    decimal rowSum = 0;
    foreach (DataColumn col in table.Columns)
    {
        if(!row.IsNull(col))
        {
            string stringValue = row[col].ToString();
            decimal d;
            if(decimal.TryParse(stringValue, out d))
                rowSum += d;
        }
    }
    row.SetField("Total", rowSum);
}

This should work with any column type.

like image 66
Tim Schmelter Avatar answered Oct 16 '22 06:10

Tim Schmelter


DataTable has capability to create calculated columns. In your case you can create "Total" column as

DataTable1.Columns.Add("Total", typeof(Double));
DataTable1.Columns["Total"].Expression = "C1+C2+C3";
like image 3
Yuriy Galanter Avatar answered Oct 16 '22 04:10

Yuriy Galanter


Example code for Yuriy's answer:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;

namespace DynamicColumns
{
    class MainClass
    {
        public static void Main (string[] args)
        {
            Console.WriteLine ("Total all quantity columns");

            var dt = new DataTable ();
            dt.Columns.Add ("ProductName", typeof(string));
            dt.Columns.Add ("Qty1", typeof(int));
            dt.Columns.Add ("Qty2", typeof(int));
            dt.Columns.Add ("Qty3", typeof(int));

            {
                var dr = dt.NewRow ();
                dr ["ProductName"] = "Keyboard";
                dr ["Qty1"] = 2;
                dr ["Qty2"] = 5;
                dr ["Qty3"] = 6;
                dt.Rows.Add (dr);
            }

            {
                var dr = dt.NewRow ();
                dr ["ProductName"] = "Mouse";
                dr ["Qty1"] = 5;
                dr ["Qty2"] = 1;
                dr ["Qty3"] = 2;
                dt.Rows.Add (dr);
            }




            string expression = 

                string.Join (" + ", 
                    dt.Columns.OfType<DataColumn>()
                        .Where(x => x.DataType == typeof(int))
                        .Select(x => x.ColumnName)
                         .ToArray() );

            dt.Columns.Add("Total", typeof(int)).Expression = expression;


            Console.WriteLine ("Expression: {0}",expression);

            Console.WriteLine ("\nProduct and totals");
            foreach (var r in dt.Rows.OfType<DataRow>()) {
                Console.WriteLine ("{0} {1}", r["ProductName"], r["Total"]);
            }


        }
    }
}

Output:

Expression: Qty1 + Qty2 + Qty3

Product and totals
Keyboard 13
Mouse 8

I would hazard a guess this (.Expression) is the most performant solution compared to lambda-ing our way to each row to each column, and even compared to looping each row and each column

like image 1
Michael Buen Avatar answered Oct 16 '22 04:10

Michael Buen