Как создать собственный итог в матрице FastReport .NET

08.10.2018

Объект Матрица в FastReport .NET очень хорошо выполняет типовые задачи по отображению сводных таблиц. Но, когда задачи не стандартные нам поможет только скрипт отчета. Именно в скрипте можно реализовать почти любые требования.

Как вы знаете, матрица имеет встроенную функцию отображения итогов по полям и колонкам. Обычно, итог в сводной таблице — это сумма. Однако, как быть, если вы хотите итог с собственной формулой расчета. А если вы хотите выводить итоги выборочно, для определенных столбцов?

Чтобы сделать все это нужно отключить стандартные итоги и создать собственный столбец, в котором будет рассчитываться ваш итог. Но, если вы все-таки используете стандартные итоги, то, чтобы их значения тоже попали в пользовательский итог, нужно использовать событие матрицы AfterTotals. Оно произойдет после построения матрицы со всеми стандартными итогами, так что все данные будут в нашем распоряжении. Это событие не позволяет вам добавлять и изменять данные в матрицы, то есть использовать методы AddValue и SetValue.

Итак, рассмотрим пример.

Создаем матрицу с простейшим шаблоном:

 

Чтобы создать измерение или показатель в матрицу, нужно вставить выражение в соответствующую ячейку. Т.к. мы заполняем матрицу из кода, то нам нужны фиктивные выражения просто чтобы создать структуру. Для этого поместите любое выражение из панели «Данные» в ячейку и отчистите текст выражения, с помощью редактора выражения.

Создаем обработчик события AfterData для матрицы. В нем мы будем добавлять данные:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
private void Matrix1_AfterData(object sender, EventArgs e)
 {
 Matrix1.AddValue(new Object[] { "January", "Salary" }, new Object[] { "1" }, new Object[] { 1000});
 Matrix1.AddValue(new Object[] { "January", "Bonus" }, new Object[] { "1" }, new Object[] { 500});
 Matrix1.AddValue(new Object[] { "January", "Penalty" }, new Object[] { "1" }, new Object[] { 200});
 Matrix1.AddValue(new Object[] { "February", "Salary" }, new Object[] { "1" }, new Object[] { 1000});
 Matrix1.AddValue(new Object[] { "February", "Bonus" }, new Object[] { "1" }, new Object[] { 500});
 Matrix1.AddValue(new Object[] { "February", "Penalty" }, new Object[] { "1" }, new Object[] { 200});
 Matrix1.AddValue(new Object[] { "February", "Total" }, new Object[] { "1" }, new Object[] { 0});
 
 Matrix1.AddValue(new Object[] { "January", "Salary" }, new Object[] { "2" }, new Object[] { 500});
 Matrix1.AddValue(new Object[] { "January", "Bonus" }, new Object[] { "2" }, new Object[] { 300});
 Matrix1.AddValue(new Object[] { "January", "Penalty" }, new Object[] { "2" }, new Object[] { 250});
 Matrix1.AddValue(new Object[] { "February", "Salary" }, new Object[] { "2" }, new Object[] { 500});
 Matrix1.AddValue(new Object[] { "February", "Bonus" }, new Object[] { "2" }, new Object[] { 300});
 Matrix1.AddValue(new Object[] { "February", "Penalty" }, new Object[] { "2" }, new Object[] { 250});
 Matrix1.AddValue(new Object[] { "February", "Total" }, new Object[] { "2" }, new Object[] { 0});}

Здесь, мы добавляем значения для каждой ячейки матрицы. В нашем случае – это две строки данных. Обратите внимание, что мы добавили только один итог, для февраля. Пока он имеет нулевое значение, но вскоре мы рассчитаем его в событии AfterTotals.

Далее нам понадобится метод получения значения ячейки:

1
2
3
4
5
 private float GetValue(int columnIndex)
 {
 object value = Matrix1.Data.GetValue(columnIndex, rowIndex, 0);
 return new Variant(value);
 }

Все просто – передаем индекс колонки, а получаем – значение.

Также нам потребуется переменная класса – rowIndex:

private int rowIndex;

А теперь добавим метод присвоения значения ячейке:

1
2
3
4
5
private void SetValue(string complexValue, float value)
 {
 int columnIndex = Matrix1.Data.Columns.Find(complexValue.Split(';'));
 Matrix1.Data.SetValue(columnIndex, rowIndex, value);
 }

Теперь, перейдем к вычислению результата. Добавим обработчик события AfterTotals для матрицы:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void Matrix1_AfterTotals(object sender, EventArgs e)
 {
 int[] rowIndices = Matrix1.Data.Rows.GetTerminalIndices();
 for (int i = 0; i < rowIndices.Length; i++)
 {
 rowIndex = rowIndices[i];
 
 int[] columnIndices = Matrix1.Data.Columns.GetTerminalIndices(new Object[] { "February" });
 float oplataSum = 0;
 foreach (int columnIndex in columnIndices)
 {
 oplataSum += GetValue(columnIndex);
 }
 SetValue("February;Total", oplataSum);
 }
 }

Здесь, мы получаем массив индексов строк матрицы. Затем, проходим цикл по этим индексам строк. Для каждой строки получаем массив индексов столбцов. В цикле по индексам столбцов производим нарастающую сумму. В конце присваиваем полученную сумму ячейке "February;Total".

А теперь запустим отчет:

Итог, как и предполагалось, выводится для группы February. Причем суммы от «штатного» итога тоже обработаны.

Таким образом мы можем создавать собственные итоги для нужных столбцов и строк.

20 ноября 2024

Локализация и смена языков в FastReport VCL

FastReport VCL поддерживает 40 языков для локализации интерфейса и позволяет изменять язык на лету через меню или код, без перекомпиляции.
1 ноября 2024

Новые возможности редактора отчетов FastReport VCL

Рассматриваем новые возможности редактора отчетов: выносные линии, подсветка пересекающихся объектов, обновлённые деревья отчетов и данных.
30 октября 2024

Использование стилей при создании отчетов в FastReport VCL

В статье подробно рассматривается одна из новых возможностей FastReport VCL – применение стилей и страниц стилей.