Объект Матрица в 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. Причем суммы от «штатного» итога тоже обработаны.
Таким образом мы можем создавать собственные итоги для нужных столбцов и строк.