Управление кросс-таблицей из скрипта
Если визуальных средств настройки таблицы недостаточно, можно использовать скрипт для тонкой настройки внешнего вида таблицы. Объект "Кросс-таблица" имеет следующие события:
Событие | Описание |
---|---|
OnAfterPrint |
Событие вызывается после печати таблицы. |
OnBeforePrint |
Событие вызывается перед печатью таблицы. |
OnCalcHeight |
Событие вызывается перед подсчетом высоты строки таблицы. Обработчик события может вернуть нужное значение высоты или 0 для того, чтобы скрыть строку. |
OnCalcWidth |
Событие вызывается перед подсчетом ширины столбца таблицы. Обработчик события может вернуть нужное значение ширины или 0 для того, чтобы скрыть столбец. |
OnPrintCell |
Событие вызывается перед отображением ячейки таблицы. Обработчик события может изменить оформление или содержимое ячейки. |
OnPrintColumnHeader |
Событие вызывается перед отображением заголовка колонок таблицы. Обработчик события может изменить оформление или содержимое ячейки заголовка. |
OnPrintRowHeader |
Событие вызывается перед отображением заголовка строк таблицы. Обработчик события может изменить оформление или содержимое ячейки заголовка. |
В событиях удобно использовать следующие методы объекта "Кросс-таблица":
Метод | Описание |
---|---|
function ColCount: Integer |
Возвращает количество колонок в таблице. |
function RowCount: Integer |
Возвращает количество строк в таблице. |
function IsGrandTotalColumn(Index: Integer): Boolean |
Возвращает True, если колонка с указанным номером является итоговой. |
function IsGrandTotalRow(Index: Integer): Boolean |
Возвращает True, если строка с указанным номером является итоговой. |
function IsTotalColumn(Index: Integer): Boolean |
Возвращает True, если колонка с указанным номером является колонкой промежуточных итогов. |
function IsTotalRow(Index: Integer): Boolean |
Возвращает True, если строка с указанным номером является строкой промежуточных итогов. |
procedure AddValue(const Rows, Columns, Cells: array of Variant) |
Добавляет значение в таблицу. |
Рассмотрим на примере, каким образом можно выделить третью колонку цветом фона (в нашем примере – это данные за ноябрь 1999 года). Для этого выделим кросс-таблицу и создадим обработчик события OnPrintCell:
Pascal script:
procedure Cross1OnPrintCell(Memo: TfrxMemoView;
RowIndex, ColumnIndex, CellIndex: Integer;
RowValues, ColumnValues, Value: Variant);
begin
if ColumnIndex = 2 then
Memo.Color := clRed;
end;
C++ Script:
void Cross1OnPrintCell(TfrxMemoView Memo, int RowIndex, int ColumnIndex, int CellIndex,
Variant RowValues, Variant ColumnValues, Variant Value)
{
if (ColumnIndex == 2) { Memo.Color = clRed; }
}
Мы увидим следующий результат:
Чтобы выделить цветом заголовок колонки, создадим обработчик события OnPrintColumnHeader:
Pascal script:
procedure Cross1OnPrintColumnHeader(Memo: TfrxMemoView;
HeaderIndexes, HeaderValues, Value: Variant);
begin
if (VarToStr(HeaderValues[0]) = '1999') and
(VarToStr(HeaderValues[1]) = '11') then
Memo.Color := clRed;
end;
C++ Script:
void Cross1OnPrintColumnHeader(TfrxMemoView Memo,
Variant HeaderIndexes, Variant HeaderValues, Variant Value)
{
if ((VarToStr(HeaderValues[0]) == "1999") &&
(VarToStr(HeaderValues[1]) == "11"))
{
Memo.Color = clRed;
}
}
Результат:
Поясним работу скриптов. Обработчик события OnPrintCell вызывается перед печатью ячейки, которая содержится в теле таблицы (при печати ячеек из заголовка таблицы вызывается обработчик OnPrintColumnHeader или OnPrintRowHeader). При этом в обработчик OnPrintCell передается ссылка на объект "Текст", который представляет собой ячейку таблицы (параметр Memo
), и "адрес" ячейки в двух вариантах: номер строки, колонки и ячейки (последнее актуально, если в вашей таблице многоуровневые ячейки) в параметрах RowIndex
, ColumnIndex
, CellIndex
соответственно. Второй вариант "адреса" – это параметры RowValues
и ColumnValues
. Параметр Value
– это содержимое ячейки.
Для определения "адреса" вы можете использовать как первый вариант (RowIndex
, ColumnIndex
), так и второй (RowValues
, ColumnValues
) – что удобнее в конкретном случае. В нашем случае нужно было выделить третью колонку – поэтому удобнее анализировать первый вариант. Т.к. нумерация колонок и строк начинается с 0, проверка ColumnIndex
= 2 позволила нам определить 3-ю колонку.
Можно было поступить иначе, анализируя нужную колонку по ее данным (нам нужен 11 месяц 1999 года):
Pascal script:
procedure Cross1OnPrintCell(Memo: TfrxMemoView;
RowIndex, ColumnIndex, CellIndex: Integer;
RowValues, ColumnValues, Value: Variant);
begin
if (VarToStr(ColumnValues[0]) = '1999') and
(VarToStr(ColumnValues[1]) = '11') then
Memo.Color := clRed;
end;
C++ Script:
void Cross1OnPrintCell(TfrxMemoView Memo,
int RowIndex, int ColumnIndex, int CellIndex,
Variant RowValues, Variant ColumnValues, Variant Value)
{
if ((VarToStr(ColumnValues[0]) == "1999") &&
(VarToStr(ColumnValues[1]) == "11"))
{
Memo.Color = clRed;
}
}
Значения, передаваемые в параметрах RowValues
и ColumnValues
– это массивы типа Variant
с нулевой базой. Нулевой элемент – это значение верхнего уровня заголовка таблицы, первый – значение следующего уровня и т.д. В нашем случае ColumnValues[0] – это года, ColumnValues[1] – месяцы.
Зачем нужно преобразование VarToStr
? Это гарантирует отсутствие ошибок приведения типов. FastReport при операциях с типом Variant
пытается автоматически приводить строки в числовой формат, что в нашем случае вызовет ошибку при попытке приведения значения столбцов 'Total' и 'Grand Total'.
Обработчик события OnPrintColumnHeader вызывается при печати ячеек заголовка столбца. Набор параметров похож на параметры обработчика OnPrintCell, но здесь "адрес" ячейки (параметры HeaderIndexes
, HeaderValues
) передается иначе.
Параметр HeaderValues
возвращает те же значения, что и параметры ColumnValues
, RowValues
в обработчике OnPrintCell. Параметр HeaderIndexes
также является массивом значений типа Variant
и содержит адрес ячейки заголовка в другой форме: нулевой элемент – это порядковый номер верхнего уровня заголовка таблицы, первый – номер следующего уровня и т.д.
Принцип нумерации ячеек заголовка станет понятен, если взглянуть на рисунок:
В нашем случае удобно анализировать значение HeaderValues
, но можно написать и такой обработчик:
Pascal script:
procedure Cross1OnPrintColumnHeader(Memo: TfrxMemoView;
HeaderIndexes, HeaderValues, Value: Variant);
begin
if (HeaderIndexes[0] = 0) and (HeaderIndexes[1] = 2) then
Memo.Color := clRed;
end;
C++ Script:
void Cross1OnPrintColumnHeader(TfrxMemoView Memo,
Variant HeaderIndexes, Variant HeaderValues, Variant Value)
{
if ((HeaderIndexes[0] == 0) && (HeaderIndexes[1] == 2)) { Memo.Color = clRed; }
}