New to Telerik Reporting? Download free 30-day trial

Sum Distinct Values

Environment

Product Progress® Telerik® Reporting

Description

I have data where certain groups are, unfortunately, duplicated, resulting in an incorrect total when summing all of the data. For example, the following CSV:

group,total
group1,10
group2,20
group2,20
group3,30

When I use the normal =Sum(Fields.total) aggregate function, the total sum ends up being 80 because it does not take into account that the second group2 is a duplicate, and adds its total to the absolute total. How can I avoid this and get the correct total sum?

Solution

In order to ignore any repeated group values, we need to implement a custom aggregate function that keeps a list of all groups that we have already passed through so that any duplicate values are ignored. For example:

[AggregateFunction(Description = "Disctinct Sum Aggregate", Name = "DisctinctSumAggregate")]
class CustomSumAggregate : IAggregateFunction
{
    readonly List<string> coveredGroups = new List<string>();
    float sum;

    public void Accumulate(object[] values)
    {
        // The aggregate function expects two parameters
        object groupObj = values[0];
        object totalObj = values[1];

        // null values are not aggregated
        if (null == groupObj || null == totalObj)
        {
            return;
        }

        if(coveredGroups.IndexOf(groupObj.ToString()) == -1)
        {
            coveredGroups.Add(groupObj.ToString());

            float.TryParse(totalObj.ToString(), out float total);

            // The actual accumulation
            this.sum += total;
        }
    }

    public object GetValue()
    {
        return string.Format("{0:C}", this.sum.ToString());
    }

    public void Init() {}

    public void Merge(IAggregateFunction aggregateFunction)
    {
        CustomSumAggregate aggregate = (CustomSumAggregate)aggregateFunction;

        if (aggregate.sum > 0)
        {
            this.sum += aggregate.sum;
        }
    }
}

Then, in the report definition, the function may be called with the following expression: = DisctinctSumAggregate(Fields.group, Fields.total).

See Also

In this article