我们在使用PivotGridControl进行数据统计的时候,用时候需要在不同的行使用不同的汇总公式的情况,本文就是为了说明怎么实现此功能,如下图说明
数据源:
注意:此时数据列指定的SummaryType设置的是Sum;并且数据列指定了为double类型
SummaryType指定的几种聚合函数,Max、Min、Count适用于所有类型,只有数字类型可以适配所有聚合函数
以上示例很明显的错误:在GrandTotal列,成功数和总数直接使用求和的公式没有问题,但是成功率也使用求和的公式就出现了问题。
根据这样的场景在成功率这一行,必须使用的是总成功数/总总数的公式。这就需要在指定的行实现自定义的公式。
那么怎么实现这样的功能呢?
- 将数据字段的SummaryType设置为Custom
2.创建CustomSummary事件(这个事件是在创建每一个单元格的时候会调用的事件,此时可以直接修改计算的公式和显示的值)
3.实现CustomSummary事件
为了减少逻辑复杂度,此处设置数据类型、数据、日期三个字段不可拖动;班次可以拖动,但是只能作为FilterArea或者RowArea
在这样的情况下,原始数据可以不用计算成功率,改为在CustomSummary事件中计算
CustomSummary实现代码如下所示
private void pivotGridControl1_CustomSummary(object sender, DevExpress.XtraPivotGrid.PivotGridCustomSummaryEventArgs e)
{
if (e.DataField != pivotGridField2)
{
//因为需要计算的是数据字段,所以如果此时的DataField不是数据字段时,则直接返回,不执行任何操作
return;
}
//只有行数据为成功率%的时候,需要计算自定义显示的数据
if (e.RowField != null && e.RowFieldValue.ToString() == "成功率%")
{
//如果当前列字段不为空,则表示当前时Grand Total列
//也可以按照下面的写法,代表如果时日期列的时候
//if(e.ColumnFieldValue.ToString()=="日期")
if (e.ColumnField != null)
{
//此时也需要分为两种情况,一种时班次在FilterArea的时候,另外一种是班次在RowArea的时候
//因为当在RowArea的时候,每一行数据只对应唯一的一种班次,但是在FilterArea的时候还需要能够计算同时选中白班和夜班的情况
if (pivotGridField4.Area == PivotArea.FilterArea)
{
PivotDrillDownDataSource pds = e.CreateDrillDownDataSource();//获取当前单元格所关联的数据
//此处的实现有更加规范统一的方法,此处仅作为示例,所以简化了逻辑,并使用了更为固定的实现方式,不够灵活
string[] sV = pivotGridField4.GetAvailableValues().Select(t => t.ToString()).ToArray();//获取到选中的班次
string cd = pds.GetValue(0, "日期").ToString();//获取当前行的日期数据
//因为每一个分组的数据即可能变更Area,同时还可能展开和合并,此时pds就会有多行数据,这里的代码为了简化,只作为一个示例程序,因此没有
//写出这些逻辑,如果有兴趣可以自己去实现相关功能
//注意此处用的datas数据类型为List,主要为了简化代码,直接使用Linq,因为PivotGridControl的DataSource属性只支持DataSet和DataTable这种类型
double okNum = datas.Where(t => sV.Any(v => v == t.班次) && t.数据类型 == "成功数" && t.日期 == cd).Select(t => t.数据).Sum();
double toNum = datas.Where(t => sV.Any(v => v == t.班次) && t.数据类型 == "总数" && t.日期 == cd).Select(t => t.数据).Sum();
e.CustomValue = Math.Round(okNum / toNum * 100, 2);
}
else
{
PivotDrillDownDataSource pds = e.CreateDrillDownDataSource();
string ct = pds.GetValue(0, "班次").ToString();
string cd = pds.GetValue(0, "日期").ToString();
double okNum = datas.Where(t => t.班次 == ct && t.数据类型 == "成功数" && t.日期 == cd).Select(t => t.数据).Sum();
double toNum = datas.Where(t => t.班次 == ct && t.数据类型 == "总数" && t.日期 == cd).Select(t => t.数据).Sum();
e.CustomValue = Math.Round(okNum / toNum * 100, 2);
}
}
else
{
if (pivotGridField4.Area == PivotArea.FilterArea)
{
PivotDrillDownDataSource pds = e.CreateDrillDownDataSource();
string[] sV = (string[])pivotGridField4.GetAvailableValues().Select(t => t.ToString()).ToArray();
//如果是统计列,则不需要指定具体日期,而是需要统计出所有日期的数据
double okNum = datas.Where(t => sV.Any(v => v == t.班次) && t.数据类型 == "成功数").Select(t => t.数据).Sum();
double toNum = datas.Where(t => sV.Any(v => v == t.班次) && t.数据类型 == "总数").Select(t => t.数据).Sum();
e.CustomValue = Math.Round(okNum / toNum * 100, 2);
}
else
{
PivotDrillDownDataSource pds = e.CreateDrillDownDataSource();
string ct = pds.GetValue(0, "班次").ToString();
double okNum = datas.Where(t => t.班次 == ct && t.数据类型 == "成功数").Select(t => t.数据).Sum();
double toNum = datas.Where(t => t.班次 == ct && t.数据类型 == "总数").Select(t => t.数据).Sum();
e.CustomValue = Math.Round(okNum / toNum * 100, 2);
}
}
}
else
{
e.CustomValue = e.SummaryValue.Summary;//其他的字段则使用求和公式即可
}
}
结果如下:
班次在RowArea的时候
班次倍拖动到FilterArea的时候
标签:PivotGridControl,班次,自定义,公式,Sum,数据类型,pds,&&,Select From: https://www.cnblogs.com/ckym/p/17703729.html