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);
}