如何对dataTable中的列进行求和?

15

我如何对datatable中的所有列求和? 假设我有以下表格。 如何计算“total”行?将总行添加到datatable应该很容易。

         Columns    hits     uniques    sigups, etc...
Rows                  
1                      12         1         23
2                       1         0          5
3                       6         2          9


total                  19          3        37

更新

最终我得到了这个结果。这是我唯一能够使其工作的方法。

 For Each col As DataColumn In TotalsTable.Columns    
    If col.DataType.Name = "DateTime" Then
            count = count + 1
                Continue For
        End If

        Dim colTotal As Double = 0
        Dim value As Double

        For Each row As DataRow In TotalsTable.Rows
            If Double.TryParse(row(col), value) Then
                    colTotal += Double.Parse(row(col))
                    End If
        Next

    totalRow(count) = colTotal
        count = count + 1

  Next
6个回答

43

还有一种不使用循环的方法,可以使用DataTable.Compute Method。以下示例来自该页面。您可以看到所使用的代码非常简单:

private void ComputeBySalesSalesID(DataSet dataSet)
{
    // Presumes a DataTable named "Orders" that has a column named "Total."
    DataTable table;
    table = dataSet.Tables["Orders"];

    // Declare an object variable. 
    object sumObject;
    sumObject = table.Compute("Sum(Total)", "EmpID = 5");
}

我必须补充一点,如果您不需要过滤结果,您可以始终传递一个空字符串:

sumObject = table.Compute("Sum(Total)", "")

1
+1 这应该是正确的答案。这正是框架实际上所询问的功能。 - toddmo

8

试试这个:

            DataTable dt = new DataTable();
            int sum = 0;
            foreach (DataRow dr in dt.Rows)
            {
                foreach (DataColumn dc in dt.Columns)
                {
                    sum += (int)dr[dc];
                }
            } 

最后我从你那里得到了我想要的答案。非常感谢。 - shafi7468

5

我觉得这可能不是你想要的,但是你的问题有点含糊不清

Dim totalCount As Int32 = DataTable1.Columns.Count * DataTable1.Rows.Count

如果您的所有列都是数值列,您可能需要这样做:
您可以使用 DataTable.Compute 来对列中的所有值进行 Sum 操作。
 Dim totalCount As Double
 For Each col As DataColumn In DataTable1.Columns
     totalCount += Double.Parse(DataTable1.Compute(String.Format("SUM({0})", col.ColumnName), Nothing).ToString)
 Next

在您编辑了问题并添加更多信息后,这应该可以工作:

 Dim totalRow = DataTable1.NewRow
 For Each col As DataColumn In DataTable1.Columns
     totalRow(col.ColumnName) = Double.Parse(DataTable1.Compute("SUM(" & col.ColumnName & ")", Nothing).ToString)
 Next
 DataTable1.Rows.Add(totalRow)

抱歉,我想要将dataTable中的所有列求和。 - chobo
@chobo:添加了另一种方法来求解所有列的所有行的和。 - Tim Schmelter
嗨,Tim,抱歉回复晚了。我刚试了一下你的解决方案,但它没有使用列值,只有标题。 - chobo
@chobo:最后一个代码示例将“SUM all”给定DataColumn的所有值,并且我会迭代所有列。至少在我的情况下是这样,如果不是,请向我们展示您尝试的方法。 - Tim Schmelter
+1 我忘记了 DataTable.Compute。谢谢你提醒我。 - Jay Riggs
显示剩余3条评论

3
您可以遍历 DataTable 中的 DataColumn 和 DataRow 集合:
// Sum rows.
foreach (DataRow row in dt.Rows) {
    int rowTotal = 0;
    foreach (DataColumn col in row.Table.Columns) {
        Console.WriteLine(row[col]);
        rowTotal += Int32.Parse(row[col].ToString());
    }
    Console.WriteLine("row total: {0}", rowTotal);
}
// Sum columns.
foreach (DataColumn col in dt.Columns) {
    int colTotal = 0;
    foreach (DataRow row in col.Table.Rows) {
        Console.WriteLine(row[col]);
        colTotal += Int32.Parse(row[col].ToString());
    }
    Console.WriteLine("column total: {0}", colTotal);
}

注意:上面的代码在将对象转换为int之前没有进行任何检查。

编辑:添加显示列总和的DataRow

尝试使用以下代码创建新行以显示您的列总和:

DataRow totalsRow = dt.NewRow();
foreach (DataColumn col in dt.Columns) {
    int colTotal = 0;
    foreach (DataRow row in col.Table.Rows) {
        colTotal += Int32.Parse(row[col].ToString());
    }
    totalsRow[col.ColumnName] = colTotal;
}
dt.Rows.Add(totalsRow);

如果您的DataTable的DataRows的数据类型是非数值型的,或者您想要在求和时检查每个单元格的值,那么这种方法是可行的。否则,我认为@Tim使用DataTable.Compute的响应更好。

有没有一种简单的方法将该数据表的总计分配给一个新行? - chobo
@chobo 我更新了代码,展示了如何添加一个DataRow来显示你的列求和。 - Jay Riggs

2
很遗憾如果你使用.NET而不使用集合和Lambda来节省时间和代码行数,这将是一件令人遗憾的事情。以下是一个示例说明: 将你的DataTable转换为Enumerable,如果需要可以根据“FILTER_ROWS_FIELD”列进行筛选,如果需要,可以按照“A_GROUP_BY_FIELD”分组数据。然后获取计数、总和或任何你想要的内容。 如果你只想要计数和总和而不需要分组,请不要对数据进行分组。
var groupedData = from b in yourDataTable.AsEnumerable().Where(r=>r.Field<int>("FILTER_ROWS_FIELD").Equals(9999))
                          group b by b.Field<string>("A_GROUP_BY_FIELD") into g
                          select new
                          {
                              tag = g.Key,
                              count = g.Count(),
                              sum = g.Sum(c => c.Field<double>("rvMoney"))
                          };

1
我同意。虽然我仍在审查这篇文章,但我很惊讶没有立即看到一个lambda解决方案。 - Ross Brasseaux

1
 for (int i=0;i<=dtB.Columns.Count-1;i++)
 {
   array(0, i) = dtB.Compute("SUM([" & dtB.Columns(i).ColumnName & "])", "")                   
 }

在你的解决方案开头加上一个简短的说明是个好主意。 - ughai

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接