|
4 | 4 | [](https://docs.devexpress.com/GeneralInformation/403183) |
5 | 5 | [](#does-this-example-address-your-development-requirementsobjectives) |
6 | 6 | <!-- default badges end --> |
7 | | -# DevExpress VCL Reports - Store Report Layouts in a Database |
8 | 7 |
|
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 |
10 | 9 |
|
11 | | -## Testing the example |
| 10 | +This example application stores [DevExpress report layouts][TdxReport.Layout] in a database. |
| 11 | +The application allows users to create and save report layouts, modify existing layouts, and open layouts in Report Designer/Viewer. |
| 12 | + |
| 13 | + |
| 14 | +## Prerequisites |
| 15 | + |
| 16 | +[DevExpress Reports Prerequisites][req] |
| 17 | + |
| 18 | +[req]: https://docs.devexpress.com/VCL/405773/ExpressCrossPlatformLibrary/vcl-backend/reports-dashboards-app-deployment#vcl-reportsdashboards-prerequisites |
| 19 | + |
| 20 | + |
| 21 | +## Test the Example |
| 22 | + |
| 23 | +- Run the sample app and click **New Report** to create an empty database record. |
| 24 | +- Click **Show Designer** to display the [Report Designer][dx-report-designer] dialog. |
| 25 | +- Create a report layout using tools available within the UI. |
| 26 | +- Click the hamburger button, select the **Save** option, and close the dialog. |
| 27 | +- Close the app. The [TdxMemData] component will store layout data in the [data.dat] file between sessions. |
| 28 | +- Run the sample app again. Click **View Designer** to load the saved report layout, |
| 29 | + or **View Report** to preview a layout-based report in the [Report Viewer][dx-report-viewer] dialog. |
| 30 | + |
| 31 | +## Implementation Details |
| 32 | + |
| 33 | +Follow the instructions in this example to store report layouts in a database of your choice, |
| 34 | +using the corresponding `TDataSet` descendant. |
| 35 | + |
| 36 | +The example uses a memory-based dataset |
| 37 | +([TdxMemData] from the DevExpress library, inherited from [TDataSet], shipped with the standard VCL library). |
| 38 | +Applications in this example isolate data components in separate data modules: [uData.pas] (Delphi) and [uData.cpp] (C++Builder). |
| 39 | + |
| 40 | +The instructions assume that you start with a Delphi or C++Builder project that has |
| 41 | +a configured data source for DevExpress Reports. |
| 42 | +To configure a report data source in your project, refer to the following tutorial: [Create a Table Report Using the Report Wizard][report-wizard]. |
| 43 | +This example uses a SQLite sample database ([nwind.db]) as a report data source. |
| 44 | + |
| 45 | +### Step 1: Create a Dataset to Store Report Layout Data |
| 46 | + |
| 47 | +Follow these steps to create a memory-based dataset to store report layout data: |
| 48 | + |
| 49 | +1. Create a [TdxMemData] component on a form (`mdLayouts` in the example). |
| 50 | +2. Create a [TDataSource] component on a form (`dsLayouts` in the example). |
| 51 | + Assign the `TDataSource.DataSet` value to the previously created dataset component: |
| 52 | + |
| 53 | + > <img src="./images/create-bind-data-source.png" style="width: 50%" alt=""/> |
| 54 | +
|
| 55 | +3. Open the context menu of the dataset component and select **Field Editor…**: |
| 56 | + |
| 57 | + > <img src="./images/open-context-menu.png" style="width: 50%" alt=""/> |
| 58 | +
|
| 59 | +4. Click **Add…** to create a BLOB field for layout data: |
| 60 | + |
| 61 | + > <img src="./images/create-layout-field.png" style="width: 50%" alt=""/> |
| 62 | +
|
| 63 | +5. Click **Add…** to create a string field for layout name: |
| 64 | + |
| 65 | + > <img src="./images/create-name-field.png" style="width: 50%" alt=""/> |
| 66 | +
|
| 67 | +6. (*Optional*) Preload persistent data to the dataset make layouts available in the application upon first launch. |
| 68 | + Open the context menu of the dataset component, select **Persistent Editor…**, click **Load…** and select a DAT file. |
| 69 | + |
| 70 | + > <img src="./images/create-persistent-data.png" style="width: 50%" alt=""/> |
| 71 | +
|
| 72 | + This example has an example report layout designed to use data from the Northwind sample database. |
| 73 | + You can preload it from [example.dat](./Delphi/example.dat). |
| 74 | + |
| 75 | + Alternatively, you can use the Report Designer in further steps to import report data from files or raw string data. |
| 76 | + |
| 77 | + |
| 78 | +### Step 2: Supply Layout Data to TdxReport |
| 79 | + |
| 80 | +Supply the [TdxReport] component with two values: |
| 81 | +report name ([TdxReport.ReportName]) and layout ([TdxReport.Layout]): |
| 82 | + |
| 83 | +```pas |
| 84 | +procedure TMainForm.LoadReportNameAndLayout(); |
| 85 | +begin |
| 86 | + if (DataModule1.mdLayouts.RecordCount = 0) and not (DataModule1.mdLayouts.State = dsInsert) then |
| 87 | + begin |
| 88 | + ShowMessage('The database is empty'); |
| 89 | + Exit; |
| 90 | + end; |
| 91 | + // Load the report name from the database |
| 92 | + dxReport1.ReportName := DataModule1.mdLayoutsName.AsString; |
| 93 | + // Load the report layout from the database |
| 94 | + dxReport1.Layout.Assign(DataModule1.mdLayoutsLayout); |
| 95 | +end; |
| 96 | +``` |
| 97 | + |
| 98 | +To load a different report, assign a new report name and layout. |
| 99 | +No cleanup is required between reports. |
| 100 | + |
| 101 | +<!-- |
| 102 | +1. Assign report name and layout when application starts. |
| 103 | +2. Assign report name and layout when user selects a different grid row. |
| 104 | +3. (Optional) Change report name when user edits it in the grid view. |
| 105 | +--> |
| 106 | + |
| 107 | + |
| 108 | +### Step 3: Display Report Designer and Viewer |
| 109 | + |
| 110 | +Once you have assigned name and layout to the [TdxReport] component, |
| 111 | +you can display the Report Designer and Viewer components: |
| 112 | + |
| 113 | +```pas |
| 114 | +procedure TMainForm.btnDesignClick(Sender: TObject); |
| 115 | +begin |
| 116 | + // Display the Report Designer |
| 117 | + dxReport1.ShowDesigner; |
| 118 | +end; |
| 119 | +
|
| 120 | +procedure TMainForm.btnPreviewClick(Sender: TObject); |
| 121 | +begin |
| 122 | + // Display the Report Viewer |
| 123 | + dxReport1.ShowViewer; |
| 124 | +end; |
| 125 | +``` |
| 126 | + |
| 127 | +### Step 4: Store Report Layout Data in the Dataset |
| 128 | + |
| 129 | +When a user edits and saves a report in the Report Designer, |
| 130 | +the value of [TdxReport.Layout] changes and an [OnLayoutChanged] event is called. |
| 131 | +Handle this event to store the updated layout in the active dataset record. |
| 132 | + |
| 133 | +```pas |
| 134 | +procedure TMainForm.dxReport1LayoutChanged(ASender: TdxReport); |
| 135 | +begin |
| 136 | + // Start editing the active dataset record |
| 137 | + DataModule1.mdLayouts.Edit; |
| 138 | + // Save the report name |
| 139 | + DataModule1.mdLayoutsName.AsString := dxReport1.ReportName; |
| 140 | + // Save the report layout |
| 141 | + DataModule1.mdLayoutsLayout.Assign(dxReport1.Layout); |
| 142 | + // Finish editing and write a modified record |
| 143 | + DataModule1.mdLayouts.Post; |
| 144 | +end; |
| 145 | +``` |
| 146 | + |
| 147 | +### Step 6: Persist the Database State Between Application Sessions |
| 148 | + |
| 149 | +This step is specific to the memory-based [TdxMemData] datasource. |
| 150 | + |
| 151 | +To persist the database state when user closes the application |
| 152 | +and restore the state when user restarts the application, |
| 153 | +handle the `Create` and `Destroy` events of the data module: |
| 154 | + |
| 155 | +```pas |
| 156 | +const |
| 157 | + DataFileName = 'data.dat'; |
| 158 | +
|
| 159 | +procedure TDataModule1.DataModuleCreate(Sender: TObject); |
| 160 | +begin |
| 161 | + if FileExists(DataFileName) then |
| 162 | + mdLayouts.LoadFromBinaryFile(DataFileName) |
| 163 | +end; |
| 164 | +
|
| 165 | +procedure TDataModule1.DataModuleDestroy(Sender: TObject); |
| 166 | +begin |
| 167 | + if mdLayouts.RecordCount > 0 then |
| 168 | + mdLayouts.SaveToBinaryFile(DataFileName) |
| 169 | +end; |
| 170 | +``` |
| 171 | + |
| 172 | + |
| 173 | +## Files to Review |
| 174 | + |
| 175 | +- [uData.pas] (Delphi) and [uData.cpp] (C++Builder) read and store layout data in a database represented by an in-memory storage component. |
| 176 | +- [uMainForm.pas] (Delphi) and [uMainForm.cpp] (C++Builder) supply layout data from the data module to [TdxReport] and display Report Designer and Viewer. |
| 177 | +- [data.dat] persists the memory-based dataset between application sessions. |
| 178 | +- [nwind.db] contains the Northwind sample database used as a data source for report content. |
12 | 179 |
|
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. |
19 | 180 |
|
20 | 181 | ## Documentation |
21 | 182 |
|
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) |
| 183 | +- [Introduction to VCL Reports][reports-intro] |
| 184 | +- [Tutorial: Create a table report using the Report Wizard][report-wizard] |
| 185 | +- [Use SQLite as a data source for reports (as demonstrated in the current example)][sqlite-data-source] |
| 186 | +- [Store report layouts in REPX files at design-time][reports-design-time-store] |
| 187 | +- API reference: |
| 188 | + - [TdxReport.ReportName] (internal report name that is not included in the layout) |
| 189 | + - [TdxReport.Layout] (an XML-based layout template that can be stored in the BLOB field of a database) |
| 190 | + - [TdxMemData] (used to store report layout data in application runtime and between sessions) |
| 191 | + - [TDataSet] (ancestor of the `TdxMemData`, contains generic database connection methods) |
| 192 | + - [TdxBackendDatabaseSQLConnection] (used to supply data to reports) |
| 193 | + |
| 194 | +<!-- documentation links --> |
| 195 | +[reports-intro]: https://docs.devexpress.com/VCL/405469/ExpressReports/vcl-reports |
| 196 | +[report-wizard]: https://docs.devexpress.com/VCL/405760/ExpressReports/getting-started/create-table-report-using-report-wizard |
| 197 | +[sqlite-data-source]: https://docs.devexpress.com/VCL/405750/ExpressCrossPlatformLibrary/vcl-backend/database-engines/vcl-backend-sqlite-support |
| 198 | +[reports-design-time-store]: https://docs.devexpress.com/VCL/dxReport.TdxReport.Layout#string-list-editor |
| 199 | +[dx-report-viewer]: https://docs.devexpress.com/XtraReports/401850/web-reporting/web-document-viewer |
| 200 | +[dx-report-designer]: https://docs.devexpress.com/XtraReports/119176/web-reporting/web-end-user-report-designer |
| 201 | + |
| 202 | + |
| 203 | +<!-- reference links --> |
| 204 | +[TdxReport]: https://docs.devexpress.com/VCL/dxReport.TdxReport |
| 205 | +[TdxReport.Layout]: https://docs.devexpress.com/VCL/dxReport.TdxReport.Layout |
| 206 | +[TdxReport.ReportName]: https://docs.devexpress.com/VCL/dxReport.TdxReport.ReportName |
| 207 | +[TdxReport.ShowDesigner]: https://docs.devexpress.com/VCL/dxReport.TdxReport.ShowDesigner |
| 208 | +[TdxReport.ShowViewer]: https://docs.devexpress.com/VCL/dxReport.TdxReport.ShowViewer |
| 209 | +[TdxBackendDatabaseSQLConnection]: https://docs.devexpress.com/VCL/dxBackend.ConnectionString.SQL.TdxBackendDatabaseSQLConnection |
| 210 | +[TdxMemData]: https://docs.devexpress.com/VCL/dxmdaset.TdxMemData |
| 211 | +[OnLayoutChanged]: https://docs.devexpress.com/VCL/dxReport.TdxReport.OnLayoutChanged |
| 212 | + |
| 213 | +<!-- external documentation links --> |
| 214 | +[TDataSet]: https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TDataSet |
| 215 | +[TDataSource]: https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TDataSource |
| 216 | +[ftString]: https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TFieldType |
| 217 | +[ftWideString]: https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TFieldType |
| 218 | +[ftBlob]: https://docwiki.embarcadero.com/Libraries/Athens/en/Data.DB.TFieldType |
| 219 | + |
| 220 | +<!-- in-repository links --> |
| 221 | +[uData.pas]: ./Delphi/uData.pas |
| 222 | +[uData.cpp]: ./CPB/uData.cpp |
| 223 | +[data.dat]: ./Delphi/data.dat |
| 224 | +[uMainForm.pas]: ./Delphi/uMainForm.pas |
| 225 | +[uMainForm.cpp]: ./CPB/uMainForm.cpp |
| 226 | +[nwind.db]: ./Delphi/nwind.db |
| 227 | + |
| 228 | + |
| 229 | +## More Examples |
| 230 | + |
| 231 | +- [Store report layouts in REPX files][file-example] |
| 232 | + |
| 233 | +[file-example]: https://github.com/DevExpress-Examples/vcl-reports-store-layout-template-file |
| 234 | + |
| 235 | + |
24 | 236 | <!-- feedback --> |
25 | 237 | ## Does This Example Address Your Development Requirements/Objectives? |
26 | 238 |
|
27 | 239 | [<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-store-layout-template-database&~~~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-store-layout-template-database&~~~was_helpful=no) |
28 | 240 |
|
29 | 241 | (you will be redirected to DevExpress.com to submit your response) |
30 | 242 | <!-- feedback end --> |
31 | | - |
32 | | - |
33 | | - |
|
0 commit comments