• PivotGridControl自定义行数据的统计公式


    我们在使用PivotGridControl进行数据统计的时候,用时候需要在不同的行使用不同的汇总公式的情况,本文就是为了说明怎么实现此功能,如下图说明

     

    数据源:

     

    注意:此时数据列指定的SummaryType设置的是Sum;并且数据列指定了为double类型

     

     

    SummaryType指定的几种聚合函数,Max、Min、Count适用于所有类型,只有数字类型可以适配所有聚合函数

     

    以上示例很明显的错误:在GrandTotal列,成功数和总数直接使用求和的公式没有问题,但是成功率也使用求和的公式就出现了问题。

    根据这样的场景在成功率这一行,必须使用的是总成功数/总总数的公式。这就需要在指定的行实现自定义的公式。

     

    那么怎么实现这样的功能呢?

    1. 将数据字段的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的时候

     

  • 相关阅读:
    开源图编辑库 NebulaGraph VEditor 的设计思路分享
    2022年最新Python大数据之Python基础【八】文件的操作与类
    面试三(多进程调用同一个动态库问题)
    【c++入门(2)】关联容器map
    localhost与127.0.0.1和本机ip的区别
    供应商滥用“云原生”标签,客户表示并不care
    win禁用shift切换输入法
    【论文阅读】时序动作检测系列论文精读(2020年)
    day63--单调栈3
    数学建模学习(99):多目标寻优 非支配排序遗传算法NSGA III
  • 原文地址:https://www.cnblogs.com/ckym/p/17703729.html