123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484 |
- using System;
- namespace FastReport.AdvMatrix
- {
- /// <summary>
- /// Holds context required for aggregate functions evaluation.
- /// </summary>
- 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);
- }
- /// <summary>
- /// Gets aggregate value. This method is for internal use only.
- /// </summary>
- /// <param name="aggregateName">Name of aggregate.</param>
- /// <param name="expression">Expression.</param>
- /// <returns>Aggregate value.</returns>
- 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);
- }
- /// <summary>
- /// Gets value of the specific column. This method is for internal use only.
- /// </summary>
- /// <param name="value">The column value.</param>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets value of the specific row. This method is for internal use only.
- /// </summary>
- /// <param name="value">The row value.</param>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets value of the first column. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <param name="useIneractiveSort">Determines if the interactive sort must be respected.</param>
- /// <param name="useThisGroup">Determines if the same level group should be used to search for item.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets value of the last column. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <param name="useIneractiveSort">Determines if the interactive sort must be respected.</param>
- /// <param name="useThisGroup">Determines if the same level group should be used to search for item.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets value of the first row. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <param name="useIneractiveSort">Determines if the interactive sort must be respected.</param>
- /// <param name="useThisGroup">Determines if the same level group should be used to search for item.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets value of the last row. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <param name="useIneractiveSort">Determines if the interactive sort must be respected.</param>
- /// <param name="useThisGroup">Determines if the same level group should be used to search for item.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets value of previous column. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <param name="useIneractiveSort">Determines if the interactive sort must be respected.</param>
- /// <param name="useThisGroup">Determines if the same level group should be used to search for item.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets value of previous row. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <param name="useIneractiveSort">Determines if the interactive sort must be respected.</param>
- /// <param name="useThisGroup">Determines if the same level group should be used to search for item.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets value of next column. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <param name="useIneractiveSort">Determines if the interactive sort must be respected.</param>
- /// <param name="useThisGroup">Determines if the same level group should be used to search for item.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets value of next row. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <param name="useIneractiveSort">Determines if the interactive sort must be respected.</param>
- /// <param name="useThisGroup">Determines if the same level group should be used to search for item.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets column total value. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value or null.</returns>
- public dynamic GetGrandColumnTotal(object dummy = null)
- {
- if (!CheckAggregate())
- return null;
- return GetAggregateValue(ColumnItem.Index, Descriptor.RowIndex);
- }
- /// <summary>
- /// Gets row total value. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value or null.</returns>
- public dynamic GetGrandRowTotal(object dummy = null)
- {
- if (!CheckAggregate())
- return null;
- return GetAggregateValue(Descriptor.ColumnIndex, RowItem.Index);
- }
- /// <summary>
- /// Gets grand total value. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value or null.</returns>
- public dynamic GetGrandTotal(object dummy = null)
- {
- if (!CheckAggregate())
- return null;
- return GetAggregateValue(Descriptor.ColumnIndex, Descriptor.RowIndex);
- }
- /// <summary>
- /// Gets column group total value. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets row group total value. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value or null.</returns>
- 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);
- }
- /// <summary>
- /// Gets column group max value. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value or null.</returns>
- 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;
- }
- /// <summary>
- /// Gets column group min value. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value or null.</returns>
- 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;
- }
- /// <summary>
- /// Gets row group max value. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value or null.</returns>
- 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;
- }
- /// <summary>
- /// Gets row group min value. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value or null.</returns>
- 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;
- }
- /// <summary>
- /// Gets percent of column total. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value.</returns>
- public dynamic GetPercentOfColumnTotal(object dummy = null)
- {
- if (!CheckAggregate())
- return null;
- return Div(GetAggregateValue(ColumnItem.Index, RowItem.Index), GetColumnTotal());
- }
- /// <summary>
- /// Gets percent of row total. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value.</returns>
- public dynamic GetPercentOfRowTotal(object dummy = null)
- {
- if (!CheckAggregate())
- return null;
- return Div(GetAggregateValue(ColumnItem.Index, RowItem.Index), GetRowTotal());
- }
- /// <summary>
- /// Gets percent of grand total. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <returns>The value.</returns>
- public dynamic GetPercentOfGrandTotal(object dummy = null)
- {
- if (!CheckAggregate())
- return null;
- return Div(GetAggregateValue(ColumnItem.Index, RowItem.Index), GetGrandTotal());
- }
- /// <summary>
- /// Gets percent of previous column. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <param name="useIneractiveSort">Determines if the interactive sort must be respected.</param>
- /// <param name="useThisGroup">Determines if the same level group should be used to search for item.</param>
- /// <returns>The value or null.</returns>
- 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));
- }
- /// <summary>
- /// Gets percent of previous row. This method is for internal use only.
- /// </summary>
- /// <param name="dummy">Dummy parameter.</param>
- /// <param name="useIneractiveSort">Determines if the interactive sort must be respected.</param>
- /// <param name="useThisGroup">Determines if the same level group should be used to search for item.</param>
- /// <returns>The value or null.</returns>
- 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));
- }
- }
- }
|