<< Click to display table of contents >>



TRVCrossTab contains properties defining properties of cross tabulation reports.

Unit RVReportTable;


TRVCrossTab = class (TPersistent);




TRVCrossTab is a class TRVReportTableItemInfo.CrossTabulation property.

It defines the position of the cross-tab header in the table (Column and FirstRow properties) and its levels (Levels property).

If Levels collection has at least one item, this table represents a cross-tab report.

A cross-tab report allows to display data as a grid, with rows representing one group of data ("row fields"), columns representing another group of data ("column fields"), and intersection of rows and columns containing a summarized information ("value fields").

TRVCrossTab represents group of data related to columns of a cross-tab report. Column fields are specified in Levels[].FieldName. Each item in this collection corresponds to one level of a cross-tab report.

A report table may contain several cross-tab reports: as many reports as the count of items in Table.RowGenerationRules. Row fields are listed in Table.RowGenerationRules[].KeyFieldNames, column fields are the same for all row generation rules. All other fields can be considered as value fields.

Cross-tab header

A structure of a cross-tab report is determined by the structure of cells in the cross-tab header. This header is located at the position specified in FirstRow and Column properties. A cross-tab header defines:

how many summary columns exist on each level;

how many columns correspond to each combination of values of value fields

Examples and the detailed information about cross-tab headers can be found in the topic about FirstRow and Column properties.

In the text below, the term "cross-tab columns" means columns below the cross-tab header.


Any value field of integer or floating point type can be used as a parameters of functions fields. A range of values used to calculate a function depends on the cell position.

Building a cross-tab report

For each row generation rule, report generator creates a cross-tab report in the following way.

Stage 0: generating cross-tab columns

Stage 1: creating report rows and filling cells of cross-tab columns

For each record of the results of DataQuery, the report generator compares values of KeyFieldNames with the previous report rows. If this record contains a unique set of values of these fields, a new report row is added*; otherwise, value fields from this record are written to the existing row having the same set of values in KeyFieldNames fields.

Value fields are written in the intersection of this row and a cross-tab column** corresponding to the set of values of Items[].FieldName, equal to this record. Thus, column fields work like a filter of data.

At this stage, two errors are possible:

a record contains values of Levels[].FieldName fields, not corresponding to any column fields (it is not possible if ColumnGenerationType = rvcgtAutoSeparate and rvcgtAutoGroup, but possible with other column generation types); OnError event occurs with rvrgeCrossTabRecordDoesNotMatch parameter, and this record is ignored;

a record contains values of Levels[].FieldName and KeyFieldNames fields, equal to values of another record (i.e., two or more records corresponds to the same cell*** of a cross-tab report); OnError event occurs with rvrgeCrossTabDuplicateRecords parameter, and this record is ignored (only the first record containing this set of values is used).

The results of this stage:

all table rows corresponding to this row generation rule are added;

all cells of cross-tabs columns of these rows are filled, except for cells of summary columns;

the report generator accumulates data necessary for calculating aggregate functions in summary columns and rows.

Stage 2: filling the rest of cells of report rows

The report generator navigates through records of results of DataQuery again. This time it enumerates only first records corresponding to each report row. At this stage, the rest of cells of the report rows are filled. It was not possible at the first stage, because we did not have data for calculating aggregate functions.


* strictly speaking, it may be not a single row, but a group of RowCount rows

** strictly speaking, it may be not a single column, but several columns corresponding to each set of values in column fields; this count of columns is defined in the bottom row of the cross-tab header, see the topic about FirstRow and Column properties

*** strictly speaking, it may be a group of cells having the number of rows and columns described in "*" and "**" notes