Skip to content

Commit b1454f5

Browse files
NickVolynkindmitry-eliseev-devexpressAbadzhevIlia-Nenashev-devX
committed
readme: Add implementation details and reference
- Add a step-by-step instruction with screenshots - Add more reference links to DevExpress and standard VCL library - Update repository description, link, and tags Co-authored-by: Dmitry Eliseev <dmitry.eliseev@devexpress.com> Co-authored-by: Vladimir Abadzhev <vladimira@devexpress.com> Co-authored-by: Ilia Nenashev <ilia.nenashev@devexpress.com>
1 parent 35fa7c2 commit b1454f5

7 files changed

Lines changed: 224 additions & 17 deletions

File tree

.github/meta.yml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# GitHub Repository metadata
22
url: vcl-reports-store-layout-template-database
3-
website:
4-
tags: [vcl, reports, layout, database]
3+
website: https://docs.devexpress.com/VCL/dxReport.TdxReport.Layout
4+
tags: [vcl, reports, layout, database, dataset]
55
description: |
6-
This example stores a report layout (XML-based template) in the BLOB field of a memory-based dataset
7-
(TdxMemData inherited from the TDataSet class shipped with the standard VCL library).
6+
Store a DevExpress report layout in a database and load it at runtime.

README.md

Lines changed: 221 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,233 @@
44
[![](https://img.shields.io/badge/📖_How_to_use_DevExpress_Examples-e9f6fc?style=flat-square)](https://docs.devexpress.com/GeneralInformation/403183)
55
[![](https://img.shields.io/badge/💬_Leave_Feedback-feecdd?style=flat-square)](#does-this-example-address-your-development-requirementsobjectives)
66
<!-- default badges end -->
7-
# DevExpress VCL Reports - Store Report Layouts in a Database
87

9-
This example stores a [report layout](https://docs.devexpress.com/VCL/dxReport.TdxReport.Layout) (XML-based template) in the BLOB field of a memory-based dataset ([TdxMemData](https://docs.devexpress.com/VCL/dxmdaset.TdxMemData) inherited from the [TDataSet](https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TDataSet) class shipped with the standard VCL library).
8+
# DevExpress Reports for Delphi/C++Builder – Store Report Layouts in a Database
109

11-
## Testing the example
10+
This example application stores [DevExpress report layouts][TdxReport.Layout] in a database.
11+
The application allows users to create new layouts, modify existing layouts using the built-in Report Designer,
12+
and save layout customizations to the data source.
13+
14+
15+
## Prerequisites
16+
17+
[DevExpress Reports Prerequisites][req]
18+
19+
[req]: https://docs.devexpress.com/VCL/405773/ExpressCrossPlatformLibrary/vcl-backend/reports-dashboards-app-deployment#vcl-reportsdashboards-prerequisites
20+
21+
22+
## Test the Example
23+
24+
1. Run the sample app and click **New Report**.
25+
1. Click **Design Report** to display the [Report Designer][dx-report-designer] dialog.
26+
1. Create a report layout using tools available within the UI.
27+
1. Click the hamburger button, select the **Save** option, and close the dialog.
28+
1. Close and restart the app.
29+
Click **Design Report** or **Preview Report** to load the saved report in the designer or [Report Viewer][dx-report-viewer].
30+
31+
## Implementation Details
32+
33+
The example uses a DevExpress memory-based dataset as a report layout storage: [TdxMemData].
34+
You can modify the application to use any [TDataSet] descendant instead.
35+
To review the data module implementation, see the following file: [uData.pas]/[uData.cpp].
36+
37+
The instructions assume that you start with a Delphi or C++Builder project that already includes
38+
a configured data source for DevExpress Reports.
39+
To configure a report data source in your project, refer to the following tutorial:
40+
[Create a Table Report Using the Report Wizard][report-wizard].
41+
This example project uses a SQLite sample database ([nwind.db]) as a report data source.
42+
43+
### Step 1: Create a Dataset to Store Report Layout Data
44+
45+
1. Add a [TdxMemData] component to the data module (`mdLayouts` in the example).
46+
1. Add a [TDataSource] component to the data module (`dsLayouts` in the example).
47+
Assign the previously created dataset component to `TDataSource.DataSet`:
48+
49+
> <img src="./images/create-bind-data-source.png" style="width: 50%"
50+
alt="Object Inspector panel displaying TDataSource properties."/>
51+
52+
1. Open the context menu for the dataset component and select **Field Editor…**:
53+
54+
> <img src="./images/open-context-menu.png" style="width: 50%"
55+
alt="Context menu for the TdxMemData component displaying a 'Field Editor' option."/>
56+
57+
1. Click **Add…** to create a BLOB field for layout data:
58+
59+
> <img src="./images/create-layout-field.png" style="width: 50%"
60+
alt="New Field dialog adding a 'Layout' field of type ftBlob"/>
61+
62+
1. Click **Add…** to create a string field for layout names:
63+
64+
> <img src="./images/create-name-field.png" style="width: 50%"
65+
alt="New Field dialog adding a 'Name' field of type ftWideString"/>
66+
67+
1. (*Optional*) Preload persistent data to the dataset to make layouts available in the application upon first launch.
68+
69+
This example includes a sample report layout that displays data from the Northwind sample database.
70+
You can preload it from [example.dat].
71+
Open the context menu for the dataset component, select **Persistent Editor…**, click **Load…**, and select the file.
72+
73+
> <img src="./images/create-persistent-data.png" style="width: 50%"
74+
alt="Context menu for the TdxMemData component displaying a 'Persistent Editor' option."/>
75+
76+
Alternatively, you can use the Report Designer later to import report data from a file.
77+
78+
79+
### Step 2: Load a Report Layout Definition
80+
81+
To load a layout definition to the [TdxReport] component, you must specify
82+
report name ([TdxReport.ReportName]) and layout ([TdxReport.Layout]):
83+
84+
```pas
85+
procedure TMainForm.LoadReportNameAndLayout();
86+
begin
87+
// Ensure that the dataset has at least one layout record or is in the process of creating a record:
88+
if (DataModule1.mdLayouts.RecordCount = 0) and not (DataModule1.mdLayouts.State = dsInsert) then
89+
begin
90+
ShowMessage('The database is empty');
91+
Exit;
92+
end;
93+
// Load the report name and layout from the database:
94+
dxReport1.ReportName := DataModule1.mdLayoutsName.AsString;
95+
dxReport1.Layout.Assign(DataModule1.mdLayoutsLayout);
96+
end;
97+
```
98+
99+
To load a different report, assign a new report name and layout.
100+
The assigned report replaces the current layout definition.
101+
102+
103+
### Step 3: Display Report Designer and Viewer
104+
105+
Once you assigned a name and layout to the [TdxReport] component,
106+
you can display [Report Designer][dx-report-designer] and [Report Viewer][dx-report-viewer] dialogs:
107+
108+
```pas
109+
procedure TMainForm.btnDesignClick(Sender: TObject);
110+
begin
111+
LoadReportFromLayout; // Loads a report layout definition from the database
112+
dxReport1.ShowDesigner; // Displays the Report Designer
113+
end;
114+
115+
procedure TMainForm.btnPreviewClick(Sender: TObject);
116+
begin
117+
LoadReportFromLayout; // Loads a report layout definition from the database
118+
dxReport1.ShowViewer; // Displays the Report Viewer
119+
end;
120+
```
121+
122+
123+
### Step 4: Store Report Layouts in a Dataset
124+
125+
When a user edits and saves a report in the Report Designer,
126+
the value of [TdxReport.Layout] changes and an [OnLayoutChanged] event is called.
127+
Handle this event to save layout changes to the active dataset record.
128+
129+
```pas
130+
procedure TMainForm.dxReport1LayoutChanged(ASender: TdxReport);
131+
begin
132+
// Start editing the active dataset record:
133+
DataModule1.mdLayouts.Edit;
134+
135+
// Save the report name and layout to the database:
136+
DataModule1.mdLayoutsName.AsString := dxReport1.ReportName;
137+
DataModule1.mdLayoutsLayout.Assign(dxReport1.Layout);
138+
139+
// Finish editing and post the modified record to the database:
140+
DataModule1.mdLayouts.Post;
141+
end;
142+
```
143+
144+
145+
### Step 5: Persist Data between Application Sessions
146+
147+
This step is applicable only to the memory-based [TdxMemData] datasource.
148+
149+
To save the dataset to a file and restore data on app restart,
150+
handle `OnCreate` and `OnDestroy` events of the data module:
151+
152+
```pas
153+
const
154+
DataFileName = 'data.dat';
155+
156+
procedure TDataModule1.DataModuleCreate(Sender: TObject);
157+
begin
158+
if FileExists(DataFileName) then
159+
mdLayouts.LoadFromBinaryFile(DataFileName)
160+
end;
161+
162+
procedure TDataModule1.DataModuleDestroy(Sender: TObject);
163+
begin
164+
if mdLayouts.RecordCount > 0 then
165+
mdLayouts.SaveToBinaryFile(DataFileName)
166+
end;
167+
```
168+
169+
170+
## Files to Review
171+
172+
- [uData.pas]/[uData.cpp] stores report layouts.
173+
- [uMainForm.pas]/[uMainForm.cpp] creates a [TdxReport], loads report layouts from the data module, and displays Report Designer/Viewer.
174+
- [data.dat] stores the memory-based dataset state between application sessions.
175+
- [nwind.db] contains the Northwind sample database used as a data source for report content.
12176

13-
* Run the sample app and click **New Report** to create an empty database record.
14-
* Click **Show Designer** to display the [Report Designer](https://docs.devexpress.com/XtraReports/119176/web-reporting/web-end-user-report-designer) dialog.
15-
* Create a report layout using tools available within the UI.
16-
* Click the hamburger button, select the **Save** option, and close the dialog.
17-
* Close the app. The [TdxMemData](https://docs.devexpress.com/VCL/dxmdaset.TdxMemData) component will store layout data between sessions.
18-
* Run the sample app again. Click **View Designer** to load the saved report layout, or **View Report** to preview a layout-based report in the [Report Viewer](https://docs.devexpress.com/XtraReports/401850/web-reporting/web-document-viewer) dialog.
19177

20178
## Documentation
21179

22-
* [TdxReport.Layout Property](https://docs.devexpress.com/VCL/dxReport.TdxReport.Layout)
23-
* [TdxBackendDataSetJSONConnection Component](https://docs.devexpress.com/VCL/dxBackend.ConnectionString.JSON.DataSet.TdxBackendDataSetJSONConnection)
180+
- [Introduction to VCL Reports][reports-intro]
181+
- [Tutorial: Create a table report using the Report Wizard][report-wizard]
182+
- [Use SQLite as a data source for reports (as demonstrated in the current example)][sqlite-data-source]
183+
- [Store report layouts in REPX files at design-time][reports-design-time-store]
184+
- API reference:
185+
- [TdxReport.ReportName] (internal report name that is not included in the layout)
186+
- [TdxReport.Layout] (an XML-based layout template that can be stored in a BLOB data field)
187+
- [TdxMemData] (a DevExpress in-memory dataset implementation)
188+
- [TDataSet] (contains generic database connection methods)
189+
- [TdxBackendDatabaseSQLConnection] (supplies data to reports)
190+
191+
<!-- documentation links -->
192+
[reports-intro]: https://docs.devexpress.com/VCL/405469/ExpressReports/vcl-reports
193+
[report-wizard]: https://docs.devexpress.com/VCL/405760/ExpressReports/getting-started/create-table-report-using-report-wizard
194+
[sqlite-data-source]: https://docs.devexpress.com/VCL/405750/ExpressCrossPlatformLibrary/vcl-backend/database-engines/vcl-backend-sqlite-support
195+
[reports-design-time-store]: https://docs.devexpress.com/VCL/dxReport.TdxReport.Layout#string-list-editor
196+
[dx-report-viewer]: https://docs.devexpress.com/XtraReports/401850/web-reporting/web-document-viewer
197+
[dx-report-designer]: https://docs.devexpress.com/XtraReports/119176/web-reporting/web-end-user-report-designer
198+
199+
200+
<!-- reference links -->
201+
[TdxReport]: https://docs.devexpress.com/VCL/dxReport.TdxReport
202+
[TdxReport.Layout]: https://docs.devexpress.com/VCL/dxReport.TdxReport.Layout
203+
[TdxReport.ReportName]: https://docs.devexpress.com/VCL/dxReport.TdxReport.ReportName
204+
[TdxReport.ShowDesigner]: https://docs.devexpress.com/VCL/dxReport.TdxReport.ShowDesigner
205+
[TdxReport.ShowViewer]: https://docs.devexpress.com/VCL/dxReport.TdxReport.ShowViewer
206+
[TdxBackendDatabaseSQLConnection]: https://docs.devexpress.com/VCL/dxBackend.ConnectionString.SQL.TdxBackendDatabaseSQLConnection
207+
[TdxMemData]: https://docs.devexpress.com/VCL/dxmdaset.TdxMemData
208+
[OnLayoutChanged]: https://docs.devexpress.com/VCL/dxReport.TdxReport.OnLayoutChanged
209+
210+
<!-- external documentation links -->
211+
[TDataSet]: https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TDataSet
212+
[TDataSource]: https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TDataSource
213+
[ftString]: https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TFieldType
214+
[ftWideString]: https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TFieldType
215+
[ftBlob]: https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TFieldType
216+
217+
<!-- in-repository links -->
218+
[uData.pas]: ./Delphi/uData.pas
219+
[uData.cpp]: ./CPB/uData.cpp
220+
[data.dat]: ./Delphi/data.dat
221+
[example.dat]: ./Delphi/example.dat
222+
[uMainForm.pas]: ./Delphi/uMainForm.pas
223+
[uMainForm.cpp]: ./CPB/uMainForm.cpp
224+
[nwind.db]: ./Delphi/nwind.db
225+
226+
227+
## More Examples
228+
229+
- [Store report layouts in REPX files][file-example]
230+
231+
[file-example]: https://github.com/DevExpress-Examples/vcl-reports-store-layout-template-file
232+
233+
24234
<!-- feedback -->
25235
## Does This Example Address Your Development Requirements/Objectives?
26236

@@ -29,5 +239,3 @@ This example stores a [report layout](https://docs.devexpress.com/VCL/dxReport.T
29239
(you will be redirected to DevExpress.com to submit your response)
30240
<!-- feedback end -->
31241

32-
33-

images/create-bind-data-source.png

26.7 KB
Loading

images/create-layout-field.png

33.9 KB
Loading

images/create-name-field.png

34.2 KB
Loading

images/create-persistent-data.png

13.5 KB
Loading

images/open-context-menu.png

13.1 KB
Loading

0 commit comments

Comments
 (0)