Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/meta.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# GitHub Repository metadata
url: vcl-reports-non-interactive-export
website: https://docs.devexpress.com/VCL/405469/ExpressReports/vcl-reports
description: Generate DevExpress VCL Reports in backend and service applications.
tags: [vcl, pdf, reports, backend, service, cli, console]
46 changes: 43 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,10 @@

# Default Delphi compiler directories
# Content of this directories are generated with each Compile/Construct of a project.
# Most of the time, files here have not there place in a code repository.
#Win32/
#Win64/
# Most of the time, files here have not their place in a code repository.
Win32/
Win64/
Win64x/
#OSX64/
#OSXARM64/
#Android/
Expand Down Expand Up @@ -61,6 +62,7 @@
*.cfg
*.hpp
*Resource.rc
*.rsp

# Delphi local files (user-specific info)
*.local
Expand All @@ -75,8 +77,46 @@ __history/
__recovery/
*.~*


# ------------------------------------------------------------
# C++Builder specific
# ------------------------------------------------------------

# C++Builder compiler outputs
*.obj
*.hpp
*.ilc
*.ild
*.ilf
*.ils
*.map
*.tds

# Precompiled headers
*.pch

# C++Builder packages and libraries
*.bpl
*.bpi
*.lib
*.a
*.dll
*.so

# C++Builder intermediate / cache files
*.cbproj.local
*.cbproj.identcache
*.cbproj.user
*.cbtemp


# Castalia statistics file (since XE7 Castalia is distributed with Delphi)
*.stat

# Boss dependency manager vendor folder https://github.com/HashLoad/boss
modules/

# Output files
*.pdf
*.docx
*.zip
159 changes: 159 additions & 0 deletions Delphi/Order.repx

Large diffs are not rendered by default.

76 changes: 76 additions & 0 deletions Delphi/PDFReportGenerator.dpr
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
program PDFReportGenerator;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils, System.Classes, System.StrUtils, dxBackend, dxBackend.Bundled,
dxBackend.ConnectionString.SQL, dxReport, dxReport.Parameters;
var
AOrderID: string;

// Export a report to a PDF file in non-interactive mode:
// without showing the report in the Report Designer or Report Viewer, or otherwise using UI.
// Parameters:
Comment thread
NickVolynkin marked this conversation as resolved.
// AOrderID: order ID to use in report data, for example, '11077'
procedure ExportReportToPdf(const AOrderID: string);
var
AConnection: TdxBackendDatabaseSQLConnection;
AReport: TdxReport;
AStream: TMemoryStream;
AOutputFileName: string;

begin
// Step 1: Create a report instance and load the report layout
AReport := TdxReport.Create(nil);
try
// Set an internal report name (does not affect the exported PDF content and file name)
AReport.ReportName := 'OrderReport';
// Load the report layout from the specified file
AReport.Layout.LoadFromFile('Order.repx');

// Step 2: Create a database connection
AConnection := TdxBackendDatabaseSQLConnection.Create(nil);
try
// Assign a database name matching the name specified in the report layout
AConnection.DisplayName := 'NWindConnectionString';
// Assign a connection string required to use the local SQLite database
AConnection.ConnectionString := 'XpoProvider=SQLite; Data Source=nwind.db; Mode=ReadOnly';

// Step 3: Define Report Parameter Values
AReport.LoadParametersFromReport;
// Set the "OrderIdParameter" value in the report layout
AReport.Parameters['OrderIdParameter'].Value := AOrderID;

// Step 4: Export a report to PDF
AStream := TMemoryStream.Create;
try
// Export a report to a memory stream in the PDF format
AReport.ExportToPDF(AStream);
// Save memory stream content to a file
AOutputFileName := 'Order_' + AOrderID + '.pdf';
AStream.SaveToFile(AOutputFileName);
Writeln('Report saved to: ', AOutputFileName);
finally
AStream.Free;
end;
finally
AConnection.Free;
end;
finally
AReport.Free;
end;
end;

// The helper application entry point that parses command-line parameters and calls the export procedure
begin
if ParamCount < 1 then
begin
Writeln('Error: OrderID parameter is required. For example: PDFReportGenerator.exe 11077');
Halt(1); // Exit with error code 1
end;

AOrderID := ParamStr(1); // Read the first parameter as OrderID
ExportReportToPdf(AOrderID);
end.
1,137 changes: 1,137 additions & 0 deletions Delphi/PDFReportGenerator.dproj

Large diffs are not rendered by default.

Binary file added Delphi/PDFReportGenerator.res
Binary file not shown.
Binary file added Delphi/PDFReportGenerator_Icon.ico
Binary file not shown.
Binary file added Delphi/nwind.db
Binary file not shown.
185 changes: 182 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,191 @@
[![](https://img.shields.io/badge/💬_Leave_Feedback-feecdd?style=flat-square)](#does-this-example-address-your-development-requirementsobjectives)
<!-- default badges end -->

# DevExpress VCL Reports — Generate Reports in a Backend / Service Application

This example uses DevExpress Reports for Delphi/C++Builder to generate reports in a command line application.
The application accepts an order ID parameter, queries the database for order data,
and exports an "order" report as a PDF file.

This example bypasses the DevExpress Report Viewer dialog and generates a report
using the DevExpress Reports backend.
Use the approach demonstrated in this sample project to implement
Web API backends, Windows Services, workflows, and scheduled jobs.
This approach can be particularly beneficial for the following usage scenarios
(reports generated without direct user interaction):

- Mass-export reports to PDF, DOCX, image, and other formats.
- Share, email, and print report documents silently.
- Implement custom report management UIs.

---

![A PDF report example generated by a command line application (demonstrates order number 11077)](./images/report.png)

---

## Prerequisites

[DevExpress Reports Prerequisites][req]

[req]: https://docs.devexpress.com/VCL/405773/ExpressCrossPlatformLibrary/vcl-backend/reports-dashboards-app-deployment#vcl-reportsdashboards-prerequisites

## Test the Example

1. Open and build the Delphi project in the RAD Studio.
2. Start a console session and navigate to the _Delphi_ project directory.
3. Run the app and specify the order ID (a number between 10248 and 11077):

```console
> PDFReportGenerator.exe 11077

Report saved to: ..\Order_11077.pdf
```
4. Generate reports for other order IDs and compare generated PDF files.

## Implementation Details

Follow the steps below to create an application that imports a report layout from a file,
binds the layout to data, and exports the generated report to a PDF file.


### Step 1: Initialize a Report and Import a Report Layout

An application requires a template report layout previously created in the [Report Designer][designer].
You can [import a report layout from a REPX file][file] or [load a layout from a database][database].

[designer]: https://docs.devexpress.com/VCL/405469/ExpressReports/vcl-reports
[file]: https://github.com/DevExpress-Examples/vcl-reports-store-layout-template-file
[database]: https://github.com/DevExpress-Examples/vcl-reports-store-layout-template-database

This example imports a report layout from the `Order.repx` file.

**Delphi:**
```pas
AReport := TdxReport.Create(nil); // AReport: TdxReport;
try
// Set an internal report name (does not affect the exported content)
AReport.ReportName := 'Order Report';
// Load the report layout from the specified file
AReport.Layout.LoadFromFile('Order.repx');
// ...
finally
AReport.Free;
end;
```


### Step 2: Create a Database Connection

Create a database connection component to supply data to the report.
This example uses a SQL connection component with a built-in SQLite engine to load the Northwind sample database stored in `nwind.db`.

```pas
// AConnection: TdxBackendDatabaseSQLConnection;
AConnection := TdxBackendDatabaseSQLConnection.Create(nil);
try
// Assign a database name matching the name specified in the report layout
AConnection.DisplayName := 'NWindConnectionString';
// Assign a connection string required to use the local SQLite database
AConnection.ConnectionString := 'XpoProvider=SQLite; Data Source=nwind.db; Mode=ReadOnly';
// ...
finally
AConnection.Free;
end;
```

For detailed information on data source management and supported database engines, refer to the following help topic:
[VCL Backend: Supported Database Systems][dbms].

[dbms]: https://docs.devexpress.com/VCL/405703/ExpressCrossPlatformLibrary/vcl-backend/vcl-backend-supported-database-systems

### Step 3: Define Report Parameter Values

A report layout may include one or more parameters.
Parameters allow you to modify database queries and generate different reports
based on the same report template and underlying data.
For example, `Order.repx` includes a single `OrderIDParameter` that filters data by order ID.

To modify parameters, load them using the `LoadParametersFromReport` method
and assign values to `Report.Parameters` list members as follows:

**Delphi:**
```pas
AReport.LoadParametersFromReport;
// Set the "OrderIdParameter" value in the report layout
AReport.Parameters['OrderIdParameter'].Value := AOrderID;
```


### Step 4: Export Report Content to a File

This example exports a report to a PDF file:

**Delphi:**
```pas
AStream := TMemoryStream.Create; // AStream: TMemoryStream;
try
// Export a report to a memory stream in the PDF format
AReport.ExportToPDF(AStream);
// Save memory stream content to a file
AStream.SaveToFile('Order_' + AOrderID + '.pdf');
finally
AStream.Free;
end;
```

### Export Multiple Reports

The approach outlined in this example allows you to generate and export multiple reports based on the same layout and data
using a list of parameters.
You need to initialize the report layout and data connection once (steps 1 and 2)
and repeat steps 3 and 4 for each parameter.

**Delphi:**

```pas
// ...
AReport.LoadParametersFromReport;

for AOrderID in AOrderIDList:
AReport.Parameters['OrderIdParameter'].Value := AOrderID;

AStream := TMemoryStream.Create; // AStream: TMemoryStream;
try
// Export a report to a memory stream in the PDF format
AReport.ExportToPDF(AStream);
// Save memory stream content to a file
AStream.SaveToFile('Order_' + AOrderID + '.pdf');
finally
AStream.Free;
end;
end;
```


## Files to Review

- [`Delphi/PDFReportGenerator.dpr`](./Delphi/PDFReportGenerator.dpr) generates a report in non-interactive (headless) mode.
- [`Order.repx`](./Order.repx) contains a report layout designed to generate a customer order report.
You can view and edit this file using the [file storage example application](https://github.com/DevExpress-Examples/vcl-reports-store-layout-template-file).
- [`nwind.db`](./nwind.db) contains the Northwind sample database.


## Documentation and Examples

- [Introduction to VCL Reports](https://docs.devexpress.com/VCL/405469/ExpressReports/vcl-reports)
- [Tutorial: Create a table report using the Report Wizard](https://docs.devexpress.com/VCL/405760/ExpressReports/getting-started/create-table-report-using-report-wizard)
- [How to store report layouts in REPX files (example application)](https://github.com/DevExpress-Examples/vcl-reports-store-layout-template-file)
- [How to store report layouts in a database (example application)](https://github.com/DevExpress-Examples/vcl-reports-store-layout-template-database)
- [How to use SQLite as a data source for reports (as demonstrated in the current example)](https://docs.devexpress.com/VCL/405750/ExpressCrossPlatformLibrary/vcl-backend/database-engines/vcl-backend-sqlite-support)
- [API reference: `TdxReport.Layout` Property](https://docs.devexpress.com/VCL/dxReport.TdxReport.Layout)
- [API reference: `TdxBackendDatabaseSQLConnection` Component](https://docs.devexpress.com/VCL/dxBackend.ConnectionString.SQL.TdxBackendDatabaseSQLConnection)



<!-- feedback -->
## Does this example address your development requirements/objectives?
## Does This Example Address Your Development Requirements/Objectives?

[<img src="https://www.devexpress.com/support/examples/i/yes-button.svg"/>](https://www.devexpress.com/support/examples/survey.xml?utm_source=github&utm_campaign=vcl-reports-filter-export-report-pdf-in-console-app&~~~was_helpful=yes) [<img src="https://www.devexpress.com/support/examples/i/no-button.svg"/>](https://www.devexpress.com/support/examples/survey.xml?utm_source=github&utm_campaign=vcl-reports-filter-export-report-pdf-in-console-app&~~~was_helpful=no)
[<img src="https://www.devexpress.com/support/examples/i/yes-button.svg"/>](https://www.devexpress.com/support/examples/survey.xml?utm_source=github&utm_campaign=vcl-reports-non-interactive-export&~~~was_helpful=yes) [<img src="https://www.devexpress.com/support/examples/i/no-button.svg"/>](https://www.devexpress.com/support/examples/survey.xml?utm_source=github&utm_campaign=vcl-reports-non-interactive-export&~~~was_helpful=no)

(you will be redirected to DevExpress.com to submit your response)
<!-- feedback end -->
Binary file added images/report.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.