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] + " 汇总";
                else
                    objs[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);
        }

 

    原文作者:qq_42678477
    原文地址: https://blog.csdn.net/qq_42678477/article/details/97244106
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞