using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;using System.Data;namespace CpmBigDataImportService
{/// <summary>/// 内存表分类汇总/// </summary>public class SumDataTable{/// <summary>/// 内存表分类汇总/// </summary>/// <param name="dt">需要分类汇总的内存表</param>/// <param name="group">分类字段,逗号分隔字符串</param>/// <param name="sum">汇总字段,逗号分隔字符串</param>public SumDataTable(DataTable dt, string group, string sum){if (null == dt || string.IsNullOrEmpty(group) || string.IsNullOrEmpty(sum))throw new Exception("参数错误");this.dt = dt;this.groupFields = group.Split(',');this.groupIndexs = new int[groupFields.Length];for (int i = 0; i < groupFields.Length; i++){for (int j = 0; j < dt.Columns.Count; j++){if (groupFields[i].Equals(dt.Columns[j].ColumnName)){this.groupIndexs[i] = j;break;}}}this.sumFields = sum.Split(',');this.sumIndexs = new int[sumFields.Length];for (int i = 0; i < sumFields.Length; i++){for (int j = 0; j < dt.Columns.Count; j++){if (sumFields[i].Equals(dt.Columns[j].ColumnName)){this.sumIndexs[i] = j;break;}}}}#region 属性/// <summary>/// 需要分类汇总内存表/// </summary>private DataTable dt;/// <summary>/// 分组字段/// </summary>private string[] groupFields;/// <summary>/// 汇总字段/// </summary>private string[] sumFields;/// <summary>/// 分组字段索引/// </summary>int[] groupIndexs;/// <summary>/// 汇总字段索引/// </summary>int[] sumIndexs;#endregion/// <summary>/// 检查是否表为空、没有分类及汇总字段/// </summary>private void Check(){if (null == dt || null == groupFields || null == sumFields || groupFields.Length == 0 || sumFields.Length == 0){throw new Exception("表汇总参数错误!");}}/// <summary>/// 返回分类汇总后新内存表/// </summary>/// <returns></returns>public DataTable Sum(){Check();if (0 == dt.Rows.Count)return dt;dt.DefaultView.Sort = string.Join(",", groupFields);DataTable dtSource = dt.DefaultView.ToTable();bool first = true;List<string> flagList = new List<string>();List<string> currFlagList = new List<string>();List<double> subTotals = InitListDouble(sumFields.Length);List<double> totals = InitListDouble(sumFields.Length);DataTable dtNew = dt.Clone();DataRow drSource = null, drNew = null;object[] sourceObjs;object[] objs;for (int i = 0; i < dtSource.Rows.Count; i++){if (0 == i)first = true;else{first = false;flagList = new List<string>();for (int j = 0; j < currFlagList.Count; j++)flagList.Add(currFlagList[j]);}drSource = dtSource.Rows[i];sourceObjs = drSource.ItemArray;//当前分组标记currFlagList = new List<string>();foreach (var item in groupFields)currFlagList.Add(drSource[item].ToString());//与上一条记录字段不一致 打印出小计行 初始化小计行if (!first && !FlagEqual(currFlagList, flagList)){objs = new object[dtNew.Columns.Count];AddSubTotal(dtNew, objs, flagList, subTotals.ToArray());subTotals = InitListDouble(sumFields.Length);}//小计及总计汇总for (int j = 0; j < sumFields.Length; j++){totals[j] += double.Parse(drSource[sumIndexs[j]].ToString());subTotals[j] += double.Parse(drSource[sumIndexs[j]].ToString());}drNew = dtNew.NewRow();drNew.ItemArray = sourceObjs;dtNew.Rows.Add(drNew);}objs = new object[dtNew.Columns.Count];AddSubTotal(dtNew, objs, currFlagList, subTotals.ToArray());objs = new object[dtNew.Columns.Count];AddTotal(dtNew, objs, totals.ToArray());return dtNew;}/// <summary>/// 辅助方法:上个分组标记与当前行分组标记是否一致/// </summary>/// <param name="l1"></param>/// <param name="l2"></param>/// <returns></returns>private bool FlagEqual(List<string> l1, List<string> l2){if (l1.Count != l2.Count)return false;for (int i = 0; i < l1.Count; i++){if (!l1[i].Equals(l2[i]))return false;}return true;}/// <summary>/// 添加小计行/// </summary>/// <param name="dtSubTotal"></param>/// <param name="objs"></param>/// <param name="ls"></param>/// <param name="ds"></param>private void AddSubTotal(DataTable dtSubTotal, object[] objs, List<string> ls, double[] ds){DataRow dr = dtSubTotal.NewRow();for (int i = ls.Count - 1; i >= 0; i--){if ((ls.Count - 1) == i)objs[groupIndexs[ls.Count - 1]] = ls[ls.Count - 1] + " 汇总";elseobjs[groupIndexs[ls.Count - 1]] = ls[ls.Count - 1];}for (int i = 0; i < ds.Length; i++)objs[sumIndexs[i]] = ds[i];dr.ItemArray = objs;dtSubTotal.Rows.Add(dr);}/// <summary>/// 添加总计行/// </summary>/// <param name="dtTotal"></param>/// <param name="objs"></param>/// <param name="ds"></param>private void AddTotal(DataTable dtTotal, object[] objs, double[] ds){DataRow dr = dtTotal.NewRow();objs[groupIndexs[0]] = "汇总";for (int i = 0; i < ds.Length; i++)objs[sumIndexs[i]] = ds[i];dr.ItemArray = objs;dtTotal.Rows.Add(dr);}/// <summary>/// 初始化汇总容器/// </summary>/// <param name="length"></param>/// <returns></returns>private List<double> InitListDouble(int length){List<double> dl = new List<double>();for (int i = 0; i < length; i++)dl.Add(0D);return dl;}}
}

调用示例

        private void button6_Click(object sender, EventArgs e){DataTable dt = MyCommon.GetDtFromSerializer("e:\\temp.dat");SumDataTable sdt = new SumDataTable(dt, "小组", "待提交,审批中,失败,未处理,超时未处理,总计");DataTable dtDest = sdt.Sum();MyCommon.FillDtToWorksheetBatched(dtDest);}
        /// <summary>/// 反序列化内存表/// </summary>/// <param name="filename"></param>/// <returns></returns>public static DataTable GetDtFromSerializer(string filename){XmlSerializer serializer = new XmlSerializer(typeof(DataTable));FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.None);return serializer.Deserialize(fs) as DataTable;}

原型:

        private void DealDt(DataTable dt){DataTable dtNew = dt.Clone();DataRow drNew = null;bool first = true; string xz = "", currentXz = "";double je1 = 0.0, je2 = 0.0, je3 = 0.0, je4 = 0.0, je5 = 0.0;double sum1 = 0.0, sum2 = 0.0, sum3 = 0.0, sum4 = 0.0, sum5 = 0.0;double ssum1 = 0.0, ssum2 = 0.0, ssum3 = 0.0, ssum4 = 0.0, ssum5 = 0.0;for (int i = 0; i < dt.Rows.Count; i++){xz = dt.Rows[i]["小组"].ToString();je1 = double.Parse(dt.Rows[i]["待提交"].ToString());je2 = double.Parse(dt.Rows[i]["审批中"].ToString());je3 = double.Parse(dt.Rows[i]["失败"].ToString());je4 = double.Parse(dt.Rows[i]["未处理"].ToString());je5 = double.Parse(dt.Rows[i]["总计"].ToString());ssum1 += je1; ssum2 += je2; ssum3 += je3; ssum4 += je4; ssum5 += je5;if (first){drNew = dtNew.NewRow();drNew.ItemArray = new object[] {dt.Rows[i]["小组"], dt.Rows[i]["财务"], dt.Rows[i]["待提交"] , dt.Rows[i]["审批中"] , dt.Rows[i]["失败"] , dt.Rows[i]["未处理"] , dt.Rows[i]["总计"] };dtNew.Rows.Add(drNew);currentXz = xz;sum1 += je1; sum2 += je2; sum3 += je3; sum4 += je4; sum5 += je5;first = false;}else{if (currentXz.Equals(xz)){sum1 += je1; sum2 += je2; sum3 += je3; sum4 += je4; sum5 += je5;}else{drNew = dtNew.NewRow();drNew.ItemArray = new object[] { currentXz + " 汇总", "", sum1, sum2, sum3, sum4, sum5 };dtNew.Rows.Add(drNew);currentXz = xz;sum1 = je1; sum2 = je2; sum3 = je3; sum4 = je4; sum5 = je5;}drNew = dtNew.NewRow();drNew.ItemArray = new object[] {dt.Rows[i]["小组"], dt.Rows[i]["财务"], dt.Rows[i]["待提交"] , dt.Rows[i]["审批中"] , dt.Rows[i]["失败"] , dt.Rows[i]["未处理"] , dt.Rows[i]["总计"] };dtNew.Rows.Add(drNew);}}if (!first){drNew = dtNew.NewRow();drNew.ItemArray = new object[] { currentXz + " 汇总", "", sum1, sum2, sum3, sum4, sum5 };dtNew.Rows.Add(drNew);drNew = dtNew.NewRow();drNew.ItemArray = new object[] { "总计", "", ssum1, ssum2, ssum3, ssum4, ssum5 };dtNew.Rows.Add(drNew);}//DataTable dtNew = new SumDataTable(dt, "小组", "待提交,审批中,失败,未处理,超时未处理,总计").Sum(); dt.Clear();dt.Merge(dtNew);}

c# datatable分类汇总相关推荐

  1. 总线控制内部eep_【上周回顾】小白如何自学单片机;电子专业的十个神总结;摩尔定律54年;电子工程师常弄混的总线分类汇总;他做成了半导体害怕他做的事...

    往期动态: 1.他60岁回国,做成了半导体行业都害怕他做成的事... 2.教你4招,小白如何自学单片机,绝对管用! 3.电子工程师常弄混的总线分类汇总,你中招了吗? 4.摩尔定律54年:他是如何在实验 ...

  2. csvtk:表格处理神器-美化、统计、头表、合并、转置、筛选、取样、去冗余 、分列、分类汇总和简单绘图...

    写在前面 CSV/TSV作为数据科学和组学分析的基本格式,其实本质上均为txt格式的表格,CSV是按逗号分隔,TSV是以制表符分隔的表格.这两种格式数据格式应用非常广泛.比较常用的处理软件包括: Ex ...

  3. excel按季度分类汇总_Excel数据透视不会,分类汇总来帮忙,强的不是一点,学会它,错不了...

    Excel数据透视不会,分类汇总来帮忙,强的不是一点,学会它,错不了 大家办公经常要用到Excel处理数据,想要对成千上万条数据做分类汇总,则需要做数据透视表和分类汇总功能:在数据量适中即小于万条时, ...

  4. Android开源项目分类汇总-转载

    太长了,还是转载吧... 今天在看博客的时候,无意中发现了@Trinea在GitHub上的一个项目Android开源项目分类汇总,由于类容太多了,我没有一个个完整地看完,但是里面介绍的开源项目都非常有 ...

  5. Android开源项目分类汇总[转]

    Android开源项目分类汇总 如果你也对开源实现库的实现原理感兴趣,欢迎 Star 和 Fork Android优秀开源项目实现原理解析 欢迎加入 QQ 交流群:383537512(入群理由需要填写 ...

  6. 2018年视觉所有干货博文的分类汇总

    原文:转载自 我爱计算机视觉 https://mp.weixin.qq.com/s?__biz=MzIwMTE1NjQxMQ==&mid=2247485040&idx=1&sn ...

  7. sql 分类汇总 列_分类汇总哪家强?R、Python、SAS、SQL?

    Excel数据透视表(Pivot Table)可以快速汇总大量数据,能够分类汇总和聚合数值数据,按类别和子类别汇总数据,功能十分强大,并且提供了展开.折叠.行列交换等交互式方法,对使用者来说十分的友好 ...

  8. 计算机三级分类汇总,计算机三级网络考试机试100道分类汇总-整数各位数字运算排序统计.doc...

    计算机三级网络考试机试100道分类汇总-整数各位数字运算排序统计.doc (7页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.90 积分 ☆ 题目2 ...

  9. excel如何分类汇总_Excel教程:一个排序后分类汇总他弄了一天 Excel神技能!

    助力春季就业,越努力越幸运 特推超级会员限时疯狂抢购 点击了解 支持微信公众号+小程序+APP+PC网站多平台学习 很多小伙伴都认为Excel排序功能非常简单,自己都掌握了. 我们来看看下面的小伙伴的 ...

最新文章

  1. R语言基于glmnet构建Logistic回归模型使用L1正则化并可视化系数及最佳lambda值
  2. python笔记3(numpy数组)
  3. PostCss 从0开始
  4. Codeforces Round #732 (Div. 2) D. AquaMoon and Chess 组合数学 + 找规律
  5. 大数据解密之你的同事都跳槽到了哪些公司
  6. Android开发常用命令
  7. php获取当前页面select的值,关于JS获取select的值
  8. opencv 指定分辨率_更改OpenCV视频文件的分辨率
  9. Jmeter使用函数助手生成随机数,处理同一个随机数多处使用
  10. 一串代码远程控制电脑关机
  11. FOFA常用搜索语法
  12. ps如何把自己的图与样机结合_Ps如何套用样机图?
  13. 蜂窝物联网通信技术的演进,有人竟然用“谈恋爱”的过程给讲明白了
  14. 前端javascript常见问题总结
  15. 单点登录CAS学习(一):初识单点登录
  16. noj 1860 保研(01背包 概率dp)
  17. windows下protobuf下载、安装、使用
  18. kali渗透实验二 网络嗅探与身份认证
  19. SpringBoot - spring.factories
  20. 51单片机开发实例 基于51单片机的光控灯

热门文章

  1. 模电摸索日记之《整流与滤波电路》
  2. 网贷平台老板跑路,程序员这波操作很溜
  3. 从一个BUG聊微信朋友圈设计
  4. 5C.炫酷迷宫(C++)
  5. 电信手机信号测试软件,移动、联通、电信手机信号辐射实测~有图有真相
  6. 决议要素_2006年决议-准备
  7. dijkstra算法和A*算法
  8. Day2 B - Stones
  9. SPSS Modeler18.0数据挖掘软件教程(四):分类分析-决策树
  10. 墨迹天气总显示内部服务器更新,墨迹天气常见问题之无法更新版本的解决