Axosoft uses ActiveReports as its report generation utility. To create more advanced custom reports, a good understanding of ActiveReports architecture and scripting are necessary.
A report section contains a group of controls that are processed and printed at the same time as a single unit.
A report can have one report header section that prints at the beginning of the report. This section generally is used to print a report title, a summary table, a chart or any information that needs only to appear once at the report's start.
A report can have one report footer section that prints at the end of the report. This section is used to print a summary of the report, grand totals or any information that needs to print once at the report's end.
A report can have one page header section that prints at the top of each page. It is the first section that prints on the page except when the page contains a report header section. The page header section is used to print column headers, page numbers, a page title or any information that needs to appear at the top of each page in the report.
Note: Bound controls in the PageHeader or PageFooter are not supported. The data in such controls may not be in sync with the data displayed in other sections on the page.
A report can have one page footer section that prints at the bottom of each page. It is used to print page totals, page numbers or any other information that needs to appear at the bottom of each page.
A report can consist of single or multiple nested groups, with each group having its own header and footer sections. The header section is inserted and printed immediately before the detail section. The footer section is inserted and printed immediately after the detail section.
A report has one detail section. The detail section is the body of the report and one instance of the section is created for each record in the report.
ActiveReports' report execution begins by raising the ReportStart event. At this point, accessing data source properties might cause DataInitialize to fire. The report validates any changes made to the report structure in ReportStart.
Printer settings are applied next.
If DataInitialize is not fired during the ReportStart event, it will next be fired. The data source will be opened. If there are any parameters in the data source with unset values and ShowParameterUI is set to “True”, ActiveReports displays a parameters dialog and fires ParameterUIClosed when the dialog is closed. If the report is a subreport and requires parameters, ActiveReports binds the subreport parameters to any fields in the parent report.
Next, the FetchData event fires. If there is no data, the NoData event is raised.
Note: The DataInitialize and FetchData events are the only events in which the Fields collection should ever be referenced.
Group sections are bound and sections begin rendering on pages.
Events are then fired for processing the report header, followed by page header, groups, detail and page footer for each page in the report. The cancel flag is checked after each event.
The speed in processing and output generation of ActiveReports is attributed to its intelligent, multi-threaded, single-pass processing. ActiveReports will process and render each page as soon as the page is ready. If ActiveReports is not able to fully render a page because of unknown data elements or because the layout is not final, it places the page in cache until the data is available.
Summary fields and KeepTogether constraints are two reasons that a page might not be rendered completely. The summary field is not complete until all the data needed for calculation is read from the data source. When a summary field such as a grand total is placed ahead of its completion level, such as in the report header, the report header and all following sections will be delayed until all of the data is read.
The KeepTogether property determines whether a section should print in its entirety on the same page. When this property is set to “True”, the section will print on the same page without any page breaks. A “False” setting allows the section to be split across two or more pages. If the KeepTogether property is set to “True”, but the section is too large for the current page, or to fit fully on the next page, the KeepTogether property will be ignored.
The GroupKeepTogether property determines whether group header and footer sections will print as a single block on the same page. The property defaults to “None” which allows the group block to be split across pages. When you set this property to “All”, ActiveReports attempts to print the complete block on the same page without any page breaks. When a complete block does not fit on a single page, it will be split across two or more pages. The third option, FirstDetail, prevents any widowed group header sections. The group header will always print with at least one detail section.
There are three events that fire for each section, regardless of its type or content. The sequence of these events depends on the summary objects and their section dependencies. Because there are many possible report designs, the event-firing sequence must be dynamic in order to accommodate individual report demands. The only guaranteed sequence is that a section's Format event fires before the BeforePrint event, which in turn occurs before the AfterPrint event but not necessarily all together. Reports should not be designed to rely on these events firing in immediate succession. Out of the three events, the Format event generally is used the most often, followed by the BeforePrint event and, in rare circumstances, the AfterPrint event.
Note: You should never reference the report's Fields collection in these section events. The DataInitialize and FetchData events are the only events in which the Fields collection should ever be referenced.
This event fires after data is loaded and bound to the fields but before the section is laid out for printing. Use this event to modify the layout of a section or any of the controls in the section. This is the only event in which a section's height can be changed. Also use the Format event to pass information, such as an SQL string, to a subreport. Because a section's height is unknown until the Format event finishes, it is possible for a section's Format event to fire while the report is on a page to which the section is not rendered. For example, the _Detail_Format_ event fires but the section is too large to fit on the page. This causes the PageFooter event and the PageEnd event to fire on the current page, and the PageStart, any other Header events, and possibly the FetchData event to fire before the section is rendered to the canvas on the next page.
If the CanGrow or CanShrink property of any control contained within a section, or the section itself, is set to “True”, all of the growing and shrinking of controls contained in this section, and the section itself, takes place in the Format event. Because of this, information about a control or a section's height cannot be obtained in this event.
This event fires before the section is rendered to the page. You can use this event to modify the values of the controls before they are printed. Any changes made here will not affect the height of the section. We recommend that you do not access any fields in a DataSource's dataset in this event. Also use this event to do page-specific formatting since the report knows which page the section will be rendered to when this event fires. Once this event has finished, the section cannot be changed in any way because the section is rendered to the canvas immediately after this event fires.
The growing and shrinking of the section and all controls contained in a section have already taken place by the time this event fires. Use this section to resize any controls if needed. Since all controls and section growth have already taken place by the time this event fires, this event may be used to get an accurate height of the section, or, if needed, any controls contained in it. Any controls in the BeforePrint event may be resized but not the height of the section itself.
This event fires after the section is rendered to the canvas object. You can use this event to draw directly to the canvas. Do not use the AfterPrint event to make any changes to the section since the section has already been rendered to the canvas at this point.
Although AfterPrint was an important event prior to ActiveReports Version 1 Service Pack 3, it is rarely used in any of the newer builds of ActiveReports. When you place code in the section events, you likely will place your code in either the Format event or the BeforePrint event. This event is still useful for drawing on the page after text has already been rendered to the page.