Skip to content

Commit e874c26

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 e874c26

File tree

7 files changed

+225
-17
lines changed

7 files changed

+225
-17
lines changed

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

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.
19178

20179
## Documentation
21180

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

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

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)