Usually reports are stored in one place but in separate files. With the increasing amount of files there are difficulties in structuring and searching. Reflecting on this subject, I came across one very interesting property of the Report object - ReportSourceString. This property holds the entire report template in a string.
Which means that it is possible to store the report template in any database. We can store all the reports in one place.
In order to save reports to the database, we need to write our own methods to save and load the report. Let's get started.
First of all, let's create a database to store reports. I have used MS Access.
The table has the following structure:
Field name |
Data type |
id |
Counter |
Name |
Text |
Template |
MEMO |
Create a Windows Forms application. Add a connection to our database. Place the button components on the form: DataSet, BindingSource and Report.
Looking ahead, I will say that we need a dialogue form, in which we will ask the name of the report when saving / loading:
For the buttons must be set DialogResult property in accordance with their name.
Getting Started Programming. We use the following FastReports libraries:
1 2 3 |
using FastReport; using FastReport.Utils; using FastReport.Design; |
And create an instance of the dialogue form:
1 |
public SaveLoadForm form2 = new SaveLoadForm();
|
Create the event handler to save a report:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
void cmdSave_CustomAction(object sender, EventArgs e) { ReportsDataSet.ReportsRow row; row = reportsDataSet1.Reports.NewReportsRow(); if (form2.ShowDialog() == DialogResult.OK) { row.Name = form2.ReportName; row.Template = report1.ReportResourceString; this.reportsDataSet1.Reports.Rows.Add(row); ReportsDataSetTableAdapters.ReportsTableAdapter adapter = new ReportsDataSetTableAdapters.ReportsTableAdapter(); adapter.Update(reportsDataSet1.Reports); } } |
Here, we create a new row in the report table. Then start the dialog form. The report name will be entered in the form. . Assign the value of the dialogue form's text field to the Name field. Write the report template as text in the Template field.
Thereafter, save the changes to the table via the adapter.
Now create an event handler of the report downloading:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
void cmdOpen_CustomAction(object sender, EventArgs e) { if (form2.ShowDialog() == DialogResult.OK) { for (int i = 1; i < reportsDataSet1.Reports.Rows.Count; i++) if (reportsDataSet1.Reports[i].Name == form2.ReportName) { report1.ReportResourceString = reportsDataSet1.Reports[i].Template.ToString(); } Designer designer = sender as Designer; designer.SetModified(this, "EditData"); } } |
We also call the dialog form. In the cycle we are looking for the report with the name that corresponds to the one entered in the text field. The report loads from Template field into ReportResourceString property. Then, the designer is updated to reflect the changes.
So, we wrote two handlers. Now it is necessary to intercept the standard event handlers and substitute our handlers.
As you can see, we intercept the event to save and load a report by substituting the custom handlers.
In the OnClick event of button in the main form, add the following code:
1 2 3 4 5 |
private void DesignBtn_Click(object sender, EventArgs e) { Config.DesignerSettings.DesignerLoaded += DesignerSettings_DesignerLoaded; report1.Design(); } |
Override the handler loading the report designer.
Thus, we have created an application that allows you to save and load reports in MS Access database. You can organize the storage of reports in a desired database through property ReportSourceString report.