c# datatable分类汇总
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分类汇总相关推荐
- 总线控制内部eep_【上周回顾】小白如何自学单片机;电子专业的十个神总结;摩尔定律54年;电子工程师常弄混的总线分类汇总;他做成了半导体害怕他做的事...
往期动态: 1.他60岁回国,做成了半导体行业都害怕他做成的事... 2.教你4招,小白如何自学单片机,绝对管用! 3.电子工程师常弄混的总线分类汇总,你中招了吗? 4.摩尔定律54年:他是如何在实验 ...
- csvtk:表格处理神器-美化、统计、头表、合并、转置、筛选、取样、去冗余 、分列、分类汇总和简单绘图...
写在前面 CSV/TSV作为数据科学和组学分析的基本格式,其实本质上均为txt格式的表格,CSV是按逗号分隔,TSV是以制表符分隔的表格.这两种格式数据格式应用非常广泛.比较常用的处理软件包括: Ex ...
- excel按季度分类汇总_Excel数据透视不会,分类汇总来帮忙,强的不是一点,学会它,错不了...
Excel数据透视不会,分类汇总来帮忙,强的不是一点,学会它,错不了 大家办公经常要用到Excel处理数据,想要对成千上万条数据做分类汇总,则需要做数据透视表和分类汇总功能:在数据量适中即小于万条时, ...
- Android开源项目分类汇总-转载
太长了,还是转载吧... 今天在看博客的时候,无意中发现了@Trinea在GitHub上的一个项目Android开源项目分类汇总,由于类容太多了,我没有一个个完整地看完,但是里面介绍的开源项目都非常有 ...
- Android开源项目分类汇总[转]
Android开源项目分类汇总 如果你也对开源实现库的实现原理感兴趣,欢迎 Star 和 Fork Android优秀开源项目实现原理解析 欢迎加入 QQ 交流群:383537512(入群理由需要填写 ...
- 2018年视觉所有干货博文的分类汇总
原文:转载自 我爱计算机视觉 https://mp.weixin.qq.com/s?__biz=MzIwMTE1NjQxMQ==&mid=2247485040&idx=1&sn ...
- sql 分类汇总 列_分类汇总哪家强?R、Python、SAS、SQL?
Excel数据透视表(Pivot Table)可以快速汇总大量数据,能够分类汇总和聚合数值数据,按类别和子类别汇总数据,功能十分强大,并且提供了展开.折叠.行列交换等交互式方法,对使用者来说十分的友好 ...
- 计算机三级分类汇总,计算机三级网络考试机试100道分类汇总-整数各位数字运算排序统计.doc...
计算机三级网络考试机试100道分类汇总-整数各位数字运算排序统计.doc (7页) 本资源提供全文预览,点击全文预览即可全文预览,如果喜欢文档就下载吧,查找使用更方便哦! 9.90 积分 ☆ 题目2 ...
- excel如何分类汇总_Excel教程:一个排序后分类汇总他弄了一天 Excel神技能!
助力春季就业,越努力越幸运 特推超级会员限时疯狂抢购 点击了解 支持微信公众号+小程序+APP+PC网站多平台学习 很多小伙伴都认为Excel排序功能非常简单,自己都掌握了. 我们来看看下面的小伙伴的 ...
最新文章
- R语言基于glmnet构建Logistic回归模型使用L1正则化并可视化系数及最佳lambda值
- python笔记3(numpy数组)
- PostCss 从0开始
- Codeforces Round #732 (Div. 2) D. AquaMoon and Chess 组合数学 + 找规律
- 大数据解密之你的同事都跳槽到了哪些公司
- Android开发常用命令
- php获取当前页面select的值,关于JS获取select的值
- opencv 指定分辨率_更改OpenCV视频文件的分辨率
- Jmeter使用函数助手生成随机数,处理同一个随机数多处使用
- 一串代码远程控制电脑关机
- FOFA常用搜索语法
- ps如何把自己的图与样机结合_Ps如何套用样机图?
- 蜂窝物联网通信技术的演进,有人竟然用“谈恋爱”的过程给讲明白了
- 前端javascript常见问题总结
- 单点登录CAS学习(一):初识单点登录
- noj 1860 保研(01背包 概率dp)
- windows下protobuf下载、安装、使用
- kali渗透实验二 网络嗅探与身份认证
- SpringBoot - spring.factories
- 51单片机开发实例 基于51单片机的光控灯