using System; namespace FastReport.AdvMatrix { /// /// Holds context required for aggregate functions evaluation. /// public class Context { internal CellDescriptor Descriptor; internal HeaderData ColumnItem; internal HeaderData RowItem; internal AggregateExpressionPair Aggregate; private dynamic Div(dynamic value, dynamic divBy) { if (divBy == null || divBy == 0) return null; if (value is float || value is double || value is decimal) return value / divBy; return value / (double)divBy; } private bool CheckAggregate() { // in case we provide no arguments to the special method call, use the first aggregate in a cell if (Aggregate == null) { if (Descriptor != null && Descriptor.Aggregates.Count > 0) Aggregate = Descriptor.Aggregates[0]; } return Aggregate != null; } private dynamic GetAggregateValue(int columnIndex, int rowIndex) { return Aggregate.GetValue(columnIndex, rowIndex); } /// /// Gets aggregate value. This method is for internal use only. /// /// Name of aggregate. /// Expression. /// Aggregate value. public dynamic GetAggregate(string aggregateName, string expression) { if (Descriptor == null) return null; Aggregate = Descriptor.Aggregates.Find(aggregateName, expression); if (Aggregate == null) return null; return GetAggregateValue(ColumnItem.Index, RowItem.Index); } /// /// Gets value of the specific column. This method is for internal use only. /// /// The column value. /// Dummy parameter. /// The value or null. public dynamic GetSpecificColumn(object value, object dummy = null) { HeaderData columnItem = ColumnItem.GetSpecificItem(value); if (columnItem == null) return null; if (!CheckAggregate()) return null; return GetAggregateValue(columnItem.Index, RowItem.Index); } /// /// Gets value of the specific row. This method is for internal use only. /// /// The row value. /// Dummy parameter. /// The value or null. public dynamic GetSpecificRow(object value, object dummy = null) { HeaderData rowItem = RowItem.GetSpecificItem(value); if (rowItem == null) return null; if (!CheckAggregate()) return null; return GetAggregateValue(ColumnItem.Index, rowItem.Index); } /// /// Gets value of the first column. This method is for internal use only. /// /// Dummy parameter. /// Determines if the interactive sort must be respected. /// Determines if the same level group should be used to search for item. /// The value or null. public dynamic GetFirstColumn(object dummy = null, bool useIneractiveSort = false, bool useThisGroup = true) { HeaderData firstColumnItem = ColumnItem.GetFirstItem(useIneractiveSort, useThisGroup); if (firstColumnItem == null) return null; if (!CheckAggregate()) return null; return GetAggregateValue(firstColumnItem.Index, RowItem.Index); } /// /// Gets value of the last column. This method is for internal use only. /// /// Dummy parameter. /// Determines if the interactive sort must be respected. /// Determines if the same level group should be used to search for item. /// The value or null. public dynamic GetLastColumn(object dummy = null, bool useIneractiveSort = false, bool useThisGroup = true) { HeaderData lastColumnItem = ColumnItem.GetLastItem(useIneractiveSort, useThisGroup); if (lastColumnItem == null) return null; if (!CheckAggregate()) return null; return GetAggregateValue(lastColumnItem.Index, RowItem.Index); } /// /// Gets value of the first row. This method is for internal use only. /// /// Dummy parameter. /// Determines if the interactive sort must be respected. /// Determines if the same level group should be used to search for item. /// The value or null. public dynamic GetFirstRow(object dummy = null, bool useIneractiveSort = false, bool useThisGroup = true) { HeaderData firstRowItem = RowItem.GetFirstItem(useIneractiveSort, useThisGroup); if (firstRowItem == null) return null; if (!CheckAggregate()) return null; return GetAggregateValue(ColumnItem.Index, firstRowItem.Index); } /// /// Gets value of the last row. This method is for internal use only. /// /// Dummy parameter. /// Determines if the interactive sort must be respected. /// Determines if the same level group should be used to search for item. /// The value or null. public dynamic GetLastRow(object dummy = null, bool useIneractiveSort = false, bool useThisGroup = true) { HeaderData lastRowItem = RowItem.GetLastItem(useIneractiveSort, useThisGroup); if (lastRowItem == null) return null; if (!CheckAggregate()) return null; return GetAggregateValue(ColumnItem.Index, lastRowItem.Index); } /// /// Gets value of previous column. This method is for internal use only. /// /// Dummy parameter. /// Determines if the interactive sort must be respected. /// Determines if the same level group should be used to search for item. /// The value or null. public dynamic GetPreviousColumn(object dummy = null, bool useIneractiveSort = false, bool useThisGroup = true) { HeaderData previousColumnItem = ColumnItem.GetPreviousItem(useIneractiveSort, useThisGroup); if (previousColumnItem == null) return null; if (!CheckAggregate()) return null; return GetAggregateValue(previousColumnItem.Index, RowItem.Index); } /// /// Gets value of previous row. This method is for internal use only. /// /// Dummy parameter. /// Determines if the interactive sort must be respected. /// Determines if the same level group should be used to search for item. /// The value or null. public dynamic GetPreviousRow(object dummy = null, bool useIneractiveSort = false, bool useThisGroup = true) { HeaderData previousRowItem = RowItem.GetPreviousItem(useIneractiveSort, useThisGroup); if (previousRowItem == null) return null; if (!CheckAggregate()) return null; return GetAggregateValue(ColumnItem.Index, previousRowItem.Index); } /// /// Gets value of next column. This method is for internal use only. /// /// Dummy parameter. /// Determines if the interactive sort must be respected. /// Determines if the same level group should be used to search for item. /// The value or null. public dynamic GetNextColumn(object dummy = null, bool useIneractiveSort = false, bool useThisGroup = true) { HeaderData nextColumnItem = ColumnItem.GetNextItem(useIneractiveSort, useThisGroup); if (nextColumnItem == null) return null; if (!CheckAggregate()) return null; return GetAggregateValue(nextColumnItem.Index, RowItem.Index); } /// /// Gets value of next row. This method is for internal use only. /// /// Dummy parameter. /// Determines if the interactive sort must be respected. /// Determines if the same level group should be used to search for item. /// The value or null. public dynamic GetNextRow(object dummy = null, bool useIneractiveSort = false, bool useThisGroup = true) { HeaderData nextRowItem = RowItem.GetNextItem(useIneractiveSort, useThisGroup); if (nextRowItem == null) return null; if (!CheckAggregate()) return null; return GetAggregateValue(ColumnItem.Index, nextRowItem.Index); } /// /// Gets column total value. This method is for internal use only. /// /// Dummy parameter. /// The value or null. public dynamic GetGrandColumnTotal(object dummy = null) { if (!CheckAggregate()) return null; return GetAggregateValue(ColumnItem.Index, Descriptor.RowIndex); } /// /// Gets row total value. This method is for internal use only. /// /// Dummy parameter. /// The value or null. public dynamic GetGrandRowTotal(object dummy = null) { if (!CheckAggregate()) return null; return GetAggregateValue(Descriptor.ColumnIndex, RowItem.Index); } /// /// Gets grand total value. This method is for internal use only. /// /// Dummy parameter. /// The value or null. public dynamic GetGrandTotal(object dummy = null) { if (!CheckAggregate()) return null; return GetAggregateValue(Descriptor.ColumnIndex, Descriptor.RowIndex); } /// /// Gets column group total value. This method is for internal use only. /// /// Dummy parameter. /// The value or null. public dynamic GetColumnTotal(object dummy = null) { if (!CheckAggregate()) return null; int rowIndex = RowItem.Parent.Index; if (rowIndex == 0) rowIndex = Descriptor.RowIndex; return GetAggregateValue(ColumnItem.Index, rowIndex); } /// /// Gets row group total value. This method is for internal use only. /// /// Dummy parameter. /// The value or null. public dynamic GetRowTotal(object dummy = null) { if (!CheckAggregate()) return null; int columnIndex = ColumnItem.Parent.Index; if (columnIndex == 0) columnIndex = Descriptor.ColumnIndex; return GetAggregateValue(columnIndex, RowItem.Index); } /// /// Gets column group max value. This method is for internal use only. /// /// Dummy parameter. /// The value or null. public dynamic GetColumnMaxValue(object dummy = null) { if (!CheckAggregate()) return null; dynamic maxValue = null; HeaderDataList parent = RowItem.GetGroup(); if (parent != null) { foreach (HeaderData d in parent) { dynamic value = GetAggregateValue(ColumnItem.Index, d.Index); if (maxValue == null || maxValue < value) maxValue = value; } } return maxValue; } /// /// Gets column group min value. This method is for internal use only. /// /// Dummy parameter. /// The value or null. public dynamic GetColumnMinValue(object dummy = null) { if (!CheckAggregate()) return null; dynamic minValue = null; HeaderDataList parent = RowItem.GetGroup(); if (parent != null) { foreach (HeaderData d in parent) { dynamic value = GetAggregateValue(ColumnItem.Index, d.Index); if (minValue == null || minValue > value) minValue = value; } } return minValue; } /// /// Gets row group max value. This method is for internal use only. /// /// Dummy parameter. /// The value or null. public dynamic GetRowMaxValue(object dummy = null) { if (!CheckAggregate()) return null; dynamic maxValue = null; HeaderDataList parent = ColumnItem.GetGroup(); if (parent != null) { foreach (HeaderData d in parent) { dynamic value = GetAggregateValue(d.Index, RowItem.Index); if (maxValue == null || maxValue < value) maxValue = value; } } return maxValue; } /// /// Gets row group min value. This method is for internal use only. /// /// Dummy parameter. /// The value or null. public dynamic GetRowMinValue(object dummy = null) { if (!CheckAggregate()) return null; dynamic minValue = null; HeaderDataList parent = ColumnItem.GetGroup(); if (parent != null) { foreach (HeaderData d in parent) { dynamic value = GetAggregateValue(d.Index, RowItem.Index); if (minValue == null || minValue > value) minValue = value; } } return minValue; } /// /// Gets percent of column total. This method is for internal use only. /// /// Dummy parameter. /// The value. public dynamic GetPercentOfColumnTotal(object dummy = null) { if (!CheckAggregate()) return null; return Div(GetAggregateValue(ColumnItem.Index, RowItem.Index), GetColumnTotal()); } /// /// Gets percent of row total. This method is for internal use only. /// /// Dummy parameter. /// The value. public dynamic GetPercentOfRowTotal(object dummy = null) { if (!CheckAggregate()) return null; return Div(GetAggregateValue(ColumnItem.Index, RowItem.Index), GetRowTotal()); } /// /// Gets percent of grand total. This method is for internal use only. /// /// Dummy parameter. /// The value. public dynamic GetPercentOfGrandTotal(object dummy = null) { if (!CheckAggregate()) return null; return Div(GetAggregateValue(ColumnItem.Index, RowItem.Index), GetGrandTotal()); } /// /// Gets percent of previous column. This method is for internal use only. /// /// Dummy parameter. /// Determines if the interactive sort must be respected. /// Determines if the same level group should be used to search for item. /// The value or null. public dynamic GetPercentOfPreviousColumn(object dummy = null, bool useIneractiveSort = false, bool useThisGroup = true) { if (!CheckAggregate()) return null; return Div(GetAggregateValue(ColumnItem.Index, RowItem.Index), GetPreviousColumn(dummy, useIneractiveSort, useThisGroup)); } /// /// Gets percent of previous row. This method is for internal use only. /// /// Dummy parameter. /// Determines if the interactive sort must be respected. /// Determines if the same level group should be used to search for item. /// The value or null. public dynamic GetPercentOfPreviousRow(object dummy = null, bool useIneractiveSort = false, bool useThisGroup = true) { if (!CheckAggregate()) return null; return Div(GetAggregateValue(ColumnItem.Index, RowItem.Index), GetPreviousRow(dummy, useIneractiveSort, useThisGroup)); } } }