Skip to content

cDRReport Class

Properties - Methods - Events

The cDRReport class is a subclass of the cDRAPI ActiveX wrapper class, which should not be used for object instantiation. The cDRAPI class is marked as abstract, and thus the cDRReport class should be used. The interface in the cDRReport class protects against writing incorrect code instructions.

For printer selection and controlling the PrintReport method, you use an object of the cPrintDialog class, which is provided with the DataFlex Reports library.

How to use the cDRReport class?

Running reports side-by-side can be achieved by creating multiple instances of the cDRReport class simultaneously, provided the preview output is not sent to a modal dialog. You can run ReportA and then ReportB using a single instance of the cDRReport class.

The most important property of the cDRReport object is the psReportNamename of the report (e.g., CustomerList.dr). Without this, the engine won't know which report to execute. The property can be set statically or dynamically. The report filename in psReportName may contain a path. Typically, no path is specified if the report resides in a folder of the application's workspace. If a path is not specified, an attempt is made to locate the report using the OpenReport function. The following sequence is used to locate the report until the report file is found or no report file by the specified name exists:

  1. The folder location can be stored in a property named psReportPath. Even if this property is not empty, the report file may not be there.
  2. Only when compiling and running with DataFlex 17.1 or later, the Reports folder is searched for the report. The location of the Reports folder is returned by a function named ReportsFolder. The default is a folder named Reports in the root of the workspace.
  3. The folders of the application's data paths are enumerated to locate the report. The application's data paths are stored in the DataPath setting in the workspace file (e.g., config.ws). This value is programmatically accessible via the psDataPath property of the workspace object in the application.

Note that when the project does not have an application object (instance of cApplication) - which is very rare - there is no workspace object, no data paths, and no Reports folder. The path to the report filename needs to be part of the file in psReportName, or the psReportPath property must be set to the location of the reports.

Before report settings can be queried or altered, the report must be opened using the OpenReport function. The OpenReport function returns the report ID, which is a GUID (Globally Unique Identifier). If the report cannot be opened, the return value will be an empty string.

If the report uses tables from the DataFlex embedded database (or tables from an external database described by intermediate (INT) files), the class will attempt to automatically locate the database and tables and adjust paths in the report at runtime. This change of table location is not persistent. If the workspace contains multiple tables with the same name or uses a different technique to locate and open tables, it is advisable to set the pbAutoLocateDFFiles property to false.

If a manual change of the location of the database and tables is desired, the properties psDatabaseName, DatabaseType, psDatabaseConnection, and psTableSchema should be used. The psDatabaseName contains the name of the filelist or the first table in an environment using the embedded DataFlex database. DatabaseType indicates whether an embedded DataFlex database or an ODBC datasource is used. psDatabaseConnection contains the DataFlex DF_OPEN_PATH or the DSN that provides access to the ODBC datasource, and psTableSchema contains the path to a table when the embedded DataFlex database is used and tables are not opened via the filelist or the table schema if available in the case of an ODBC datasource.

The property psTableName returns the name of the N-th table in the report. The function TableCount returns the number of tables present in the report. If the report is based on an ODBC or Stored Procedure datasource, it is possible to let the integration wizard generate code to assist in changing the DSN for the report; look for a method called ChangeODBCDataSource.

An opened report can be displayed; its data can be exported or printed to a print device. Sending the RunReport message to the report will open the report and then output it to the screen, printer, or file. The method of output is controlled by the property peOutputDestination, which can have the values PRINT_TO_WINDOW, PRINT_TO_PRINTER, PRINT_TO_PRINTER_NO_DIALOG, or PRINT_TO_FILE. The report remains open after output. If the report was not opened before sending RunReport to the report object, it results in an attempt to open the report by calling the OpenReport method. As mentioned above, the OpenReport message can be sent to only open the report and change or query some settings with or without creating output.

During OpenReport, it is possible to show a status panel to the end-user. This is controlled by the property pbShowStatusPanel in combination with the property phoStatusPanel, which holds the object ID of the status panel. Both properties need to be set by the developer and are false and 0 by default.

If the output of the report is expected to take some time, it would be beneficial to display information about reading and processing data to the end-user. This can be done by implementing the event OnProgressRecordsRead and displaying the number of records read and/or the event OnProgressFormatPage to show how many pages have been formatted out of the total number of pages. The integration wizard already writes the code for these events in the cDRReport object.

Instead of running the report and depending on the property peOutputDestination, it is possible to open the report (with the OpenReport function) and then either send the message DisplayReport, ExportReport, or PrintReport. The report must be opened before one of these three messages can be sent.

When the report executes, the DataFlex application continues to respond to mouse clicks, function keys, etc., since the report data reading and formatting process is done in an ActiveX module.

For exporting or printing the report, it is not necessary for the ActiveX to be displayed in a DataFlex container object (e.g., a (db)View).

After opening the report, record filters can be set in two ways. One way is via the psFilterFunction property. The syntax of the VB Like function code that needs to be written for this function can be checked via the function TestFilterFunction. This is not a requirement, though. The second way is via the methods AddFilter, RemoveFilter, and RemoveAllFilters. Existing filters can be altered via the method FilterCount in combination with the properties psFilterField, and psFilterValue

The class also provides access to any of the stored functions in the report. The number of functions can be queried via the method FunctionCount. Each function can be addressed via the methods psFunctionName and psFunction. If the function name is known, the FunctionIdByName returns the function ID. It is not possible to add new functions to the report; only existing functions can be changed.

A report may contain one or more sub-reports. A sub-report may contain one or more other sub-reports. The number of nested sub-reports is not limited, but using sub-reports impacts execution speed. The number of sub-reports in a report can be queried via the method SubReportCount, and their IDs can be retrieved via the function SubReportID. The sub-report can and should be accessed in its entirety as if it were a report on its own. If the pbAutoLocateDFFiles is set to false (or when an ODBC datasource is used), the datasources in the sub-reports need to be adjusted manually (if needed). Each method that requires passing a report ID can accept either the main report ID or the ID of a sub-report.

For exporting the report, a choice can be made between exporting to image, CSV (Comma Separated Values), XLS (Excel), RTF, HTML, or PDF (Portable Document Format). In all six options, a variable with the appropriate settings for the export format needs to be passed. For this, use the write-only properties pImageExportOptions, pXLSExportOptions, pHTMLExportOptions, or pPDFExportOptions. The DataFlex Reports print engine may crash if these properties are not set with appropriate information prior to the export.

When the report is displayed in the viewer and page navigation controls are desired, documentation about the methods PreviewFirstPage, PreviewLastPage, PreviewNextPage, PreviewPreviousPage, and the property [piPreviewCurrentPage](windows/pipreview-current-page.md

Any errors generated during any of the class methods, or which are sent to the object by the viewer OCX, are automatically handled by the cDRReport object itself. As with the usual global DataFlex error handler, the method Error_Report is used. This method first determines if it is already handling errors and, if so, skips the new error to avoid recursion. The next step in the process is calling the OnError event, which could be used to log error information into a log file, send an email, etc. When the property pbDisplayError is set to true (the default is true), the error is passed to the standard error handler object. In the OnError event, pbDisplayError could be set to false to prevent the standard DataFlex error handler from picking up the error. If the property pbCancelIfError is true (the default is true), the pbCanceled property will be set to true to avoid follow-up errors in other report methods.

Closing the report can be done with the CloseReport message. Do not do this while the report is still needed (e.g., when viewing pages). When a different report is opened, the old report will automatically be closed. When the ActiveX object is deactivated (the dialog to which it was paged is deactivated or during destruction), the currently opened report will also be closed.

While using the DisplayReport message (or RunReport with the peOutputDestination set to PRINT_TO_WINDOW, which is the default), the report object should be large enough to display the report, or the preview window handle must be set to an object large enough to display the report results. The minimum size of the cDRReport object must be 2 by 2.

Report errors and special fields in the report can be displayed/printed in a specific language. Use the piReportLanguage property to specify the language. The text strings for this language support are read from a database named language.db, which is delivered with DataFlex Reports. A set of popular languages is included with DataFlex Reports.

If the data is sorted locally, the sort order is configurable when using ODBC and is standard for DataFlex data. The used collating sequence is stored in the report.

Reports can be based on runtime data. To pass data, the application must build a two-dimensional variant array that matches the datasource defined in the report and fill it with the data to be displayed, exported, or printed. The variant array is passed to the report via the TableData method.

A report can be based on a stored procedure that delivers the data to the report. The optional parameters of a stored procedure can be accessed via the methods ParameterCount, ParameterName, ParameterType, and the property psParameterValue. These same methods and the property can be used for parameters defined in the report.

Preview results can be shown via the ActiveX object on a (report)view, in a modal dialog, an MDI view, or a tool panel. The pePreviewStyle property controls the display "channel".

Many functions and properties take a report ID as the first argument. This report ID is the GUID (string representation) returned by the OpenReport function. The value can be passed as an empty string (or C_USEMAINDRREPORTID) if the main report should be used. The function or property retrieves the psReportID property value for the report ID.

Translation

All messages and constants used in the cDRReport class and dialogs are available in several languages. For each language, the file that contains the translations is named DRLanguage<languagename>.inc (e.g., DRLanguageDeutsch.inc) and is usually included by adding DRLanguage.inc to the top of the code that requires the translation. The choice for the correct text strings is the same as in the rest of the DataFlex applications, meaning that the compiler constant Language$Current determines what the translation is.

Requests for additional languages can be sent to Data Access Europe by e-mail (support@dataaccess.eu).

The integration wizard uses dynamic translation following the language choice in the DataFlex Reports designer. The translation strings are read from a database named language.db, located in the programs folder where the integration wizard is installed. When the translation cannot be found, the default English translation is used. Note that both the DataFlex Reports designer and the integration wizard use a database named language.db, but the contents differ. The language.db for the designer does not work for integration and vice versa.