Back to Devexpress

TdxReport.Layout Property

vcl-dxreport-dot-tdxreport-f6e9ca6c.md

latest15.7 KB
Original Source

TdxReport.Layout Property

Provides access to the report template layout (in XML).

Declaration

delphi
property Layout: TStringList read;

Property Value

TypeDescription
TStringList

Stores an XML report template (REPX).

|

Remarks

The TdxReport component generates report documents based on an XML-based report definition (template) in the REPX format. A REPX report definition contains report controls, properties, and data bindings.

Use the Layout property to load, save, and access the report template (in REPX).

Design-Time Functionality

The following design-time edit options are available for the Layout property value:

Report Viewer and Designer Dialogs

Right-click a TdxReport component on a form to display the component’s context menu:

Click the Designer… or Viewer… item to display the Web-based Report Designer or Report Viewer dialog at design time.

In addition, a double-click on a form’s TdxReport component displays the Report Designer dialog for the component.

String List Editor

Click the ellipsis button to the right of the Layout property in the Object Inspector to display a text editor.

You can use this editor to paste a REPX template definition from a different source or edit the current report template directly.

Note

If a report template is set/specified at design time, the Layout property stores the REPX layout in a DFM project file.

Available Options

Call Layout.LoadFromFile/Layout.LoadFromStream and Layout.SaveToFile/Layout.SaveToStream procedures to import and export report templates in the REPX format.

You can use Layout.Strings and Layout.Text properties to access and modify report layout content directly (if required).

Refer to the TStringList class description for detailed information on all available options.

End-User Layout Edit Functionality

Call the ShowDesigner procedure to display the Web-based Report Designer dialog.

All saved changes made in this dialog update the Layout property value and raise the OnLayoutChanged event[1]. For example, you can handle this event to save report template changes to a file.

Tip

Refer to the following topic for detailed information on all tools available for report template creation: Report Designer.

Code Examples

Related GitHub-Hosted Example Projects

View Example: Store Report Layouts within Text FilesView Example: Store Report Layouts in a Database

Load a Report Template from a File

The following code example allows a user to load a report template file and display it in the Report Designer dialog:

delphi
uses
  dxReport, // Declares the TdxReport class
  dxShellDialogs; // Declares the TdxOpenFileDialog class
// ...

procedure TMyForm.cxBtnLoadReportTemplateClick(Sender: TObject);
begin
  if dxOpenFileDialog1.Execute then
  begin
    dxReport1.ReportName := ChangeFileExt(ExtractFileName(dxOpenFileDialog1.FileName), '');
    dxReport1.Layout.LoadFromFile(dxOpenFileDialog1.FileName);
    dxReport1.ShowDesigner;
  end;
end;
cpp
#include "dxReport.hpp" // Declares the TdxReport class
#include "dxShellDialogs.hpp" // Declares the TdxOpenFileDialogs class

// Add the following linker directive to the corresponding CPP source file:
#pragma link "dxReport" // Required to use dxReport.hpp declarations
#pragma link "dxShellDialogs" // Required to use dxShellDialogs.hpp declarations
// ..

void __fastcall TMyForm::cxBtnLoadReportTemplateClick(TObject *Sender)
{
  if(dxOpenFileDialog1->Execute())
  {
    dxReport1->ReportName = ChangeFileExt(ExtractFileName(dxOpenFileDialog1->FileName), "");
    dxReport1->Layout->LoadFromFile(dxOpenFileDialog1->FileName);
    dxReport1->ShowDesigner();
  }
}

Save Report Layout Changes to File on Every Change

The following code example saves the current report to a REPX file every time a user saves pending changes in the Report Designer dialog:

delphi
uses
  dxReport; // Declares the TdxReport class
// ...

procedure TMyForm.dxReport1LayoutChanged(ASender: TdxReport);
begin
  ASender.Layout.SaveToFile(ASender.ReportName + '.repx');
end;
cpp
#include "dxReport.hpp" // Declares the TdxReport class

// Add the following linker directive to the corresponding CPP source file:
#pragma link "dxReport" // Required to use dxReport.hpp declarations
// ..

void __fastcall TMyForm::dxReport1LayoutChanged(TdxReport *ASender)
{
  ASender->Layout->SaveToFile(ASender->ReportName + ".repx");
}

Save Report Layout to Database on Every Change

The following code example saves the current report to an existing BLOB dataset field every time a user saves pending changes in the Report Designer dialog:

delphi
uses
  dxReport, // Declares the TdxReport class
  dxmdaset; // Declares the TdxMemData class and related types
// ...

procedure TMyForm.dxReport1LayoutChanged(ASender: TdxReport);
begin
  dxMemData1.Edit;
  dxMemData1.FieldByName('TemplateName').AsString := ASender.ReportName;
  dxMemData1.FieldByName('TemplateLayout').Assign(ASender.Layout);
  dxMemData1.Post;
end;
cpp
#include "dxReport.hpp" // Declares the TdxReport class
#include "dxmdaset.hpp" // Declares the TdxMemData class and related types

// Add the following linker directives to the corresponding CPP source file:
#pragma link "dxReport" // Required to use dxReport.hpp declarations
#pragma link "dxmdaset" // Required to use dxmdaset.hpp declarations
// ...

void __fastcall TMyForm::dxReport1LayoutChanged(TdxReport *ASender)
{
  dxMemData1->Edit();
  dxMemData1->FieldByName("TemplateName")->AsString = ASender->ReportName;
  dxMemData1->FieldByName("TemplateLayout")->Assign(ASender->Layout);
  dxMemData1->Post();
}

Load a Report Template from a Database

The following code example loads a report template layout and its name from a memory-based dataset (TdxMemData):

delphi
uses
  dxReport, // Declares the TdxReport class
  dxmdaset; // Declares the TdxMemData class
// ...

procedure TMyForm.cxBtnLoadReportTemplateClick(Sender: TObject);
begin
  if(dxMemData1.RecordCount = 0) and not (dxMemData1.State = dsInsert) then
  begin
    ShowMessage('The database is empty');
    Exit;
  end;
  dxReport1.ReportName := dxMemData1.FieldByName('TemplateName').AsString;
  dxReport1.Layout.Assign(dxMemData1.FieldByName('TemplateLayout'));
  dxReport1.ShowDesigner;
end;
cpp
#include "dxReport.hpp" // Declares the TdxReport class
#include "dxmdaset.hpp" // Declares the TdxMemData class

// Add the following linker directive to the corresponding CPP source file:
#pragma link "dxReport" // Required to use dxReport.hpp declarations
#pragma link "dxmdaset" // Required to use dxmdaset.hpp declarations
// ..

void __fastcall TMyForm::cxBtnLoadReportTemplateClick(TObject *Sender)
{
  if((dxMemData1->RecordCount == 0) && (dxMemData1->State != dsInsert))
  {
    ShowMessage("The database is empty");
    return;
  }
  dxReport1->ReportName = dxMemData1->FieldByName("TemplateName")->AsString;
  dxReport1->Layout->Assign(dxMemData1->FieldByName("TemplateLayout"));
  dxReport1->ShowDesigner();
}

Generate Reports Based on In-Memory Data

The following code example loads an XML-based report template (TdxReport.Layout) from a REPX file, populates the template with test data defined in a connection string, and exports the resulting report as a PNG image:

delphi
uses
  dxReport, // Declares the TdxReport component and related types
  dxBackend.ConnectionString.JSON; // Declares the TdxBackendInMemoryJSONConnection component
// ...

procedure TMyForm.Button1Click(Sender: TObject);
var
  AJSONDataConnection: TdxBackendInMemoryJSONConnection;
  AReport: TdxReport;
  AFileStream: TFileStream;
begin
  AJSONDataConnection := TdxBackendInMemoryJSONConnection.Create(Self);
  try
    AJSONDataConnection.Name := 'JSONData';
    // Specify in-memory report data as a connection string
    AJSONDataConnection.ConnectionString :=
      'Json=''[{"id":1, "caption":"test1"},{"id":2, "caption":"test2"}]''';
    AReport := TdxReport.Create(Self);
    try
      AReport.ReportName := 'Report';
      AReport.Layout.LoadFromFile('Report.repx'); // Loads a report template
      AFileStream := TFileStream.Create('Report.png', fmOpenReadWrite);
      try
        AReport.ExportToImage(AFileStream); // Exports the report in the default image export format (PNG)
      finally
        AFileStream.Free;
      end;
    finally
      AReport.Free;
    end;
  finally
    AJSONDataConnection.Free;
  end;
end;
cpp
#include "dxReport.hpp" // Declares the TdxReport component
#include "dxBackend.ConnectionString.JSON.hpp" // Declares the TdxBackendInMemoryJSONConnection component

// Add the following linker directives to the corresponding CPP source file:
#pragma link "dxReport" // Required for dxReport.hpp declarations
#if defined(_WIN64) // Required to use dxBackend.ConnectionString.JSON.hpp declarations
  #pragma link "dxBackend.ConnectionString.JSON.o"
#else
  #pragma link "dxBackend.ConnectionString.JSON.obj"
// ...

void __fastcall TMyForm::Button1Click(TObject *Sender)
{
  TdxBackendInMemoryJSONConnection *AJSONDataConnection;
  TdxReport *AReport;
  TFileStream *AFileStream;
  AJSONDataConnection = new TdxBackendInMemoryJSONConnection(this);
  try
  {
    AJSONDataConnection->Name = "JSONData";
    // Specify in-memory report data as a connection string
    AJSONDataConnection->ConnectionString =
      "Json=\"\"[{\"id\":1, \"caption\":\"test1\"}, {\"id\":2, \"caption\":\"test2\"}]\"";
    AReport = new TdxReport(this);
    try
    {
      AReport->ReportName = "Report";
      AReport->Layout->LoadFromFile("Report.repx"); // Loads a report template
      AFileStream = new TFileStream('Report.png', fmOpenReadWrite);
      try
      {
        AReport->ExportToImage(AFileStream); // Exports the report in the default image export format (PNG)
      }
      __finally
      {
        delete AFileStream;
      }
    }
    __finally
    {
        delete AReport;
    }
  }
  __finally
  {
    delete AJSONDataConnection;
  }
}

Load and Populate Report Templates from Datasets

This code example loads an XML-based report template (REPX) from a dataset, configures export settings, populates the template with data from another dataset, and displays the report preview:

delphi
uses
  dxReport, // Declares the TdxReport component and related types
  dxBackend.ConnectionString.JSON.DataSet; // Declares the TdxBackendDataSetJSONConnection component
// ...

procedure TMyForm.Button1Click(Sender: TObject);
var
  ADataConnection: TdxBackendDataSetJSONConnection;
  AReport: TdxReport;
  ALayoutStream: TStream;
begin
  ADataConnection := TdxBackendDataSetJSONConnection.Create(Self);
  try
    ADataConnection.Name := 'DataSetJSONData';
    ADataConnection.DataSets.Add('Data', FDataSource);
    AReport := TdxReport.Create(Self);
    try
      AReport.ReportName := 'Report';
      ALayoutStream := FLayoutDataSet.CreateBlobStream(FLayoutDataSet.FieldByName('Layout'), bmRead);
      try
        AReport.Layout.LoadFromStream(ALayoutStream);
      finally
        ALayoutStream.Free;
      end;
      AReport.Language := 'fr-FR';
      AReport.ExportFormats := [TdxReportExportFormat.PDF,
        TdxReportExportFormat.RTF, TdxReportExportFormat.HTML];
      AReport.FilterString := 'id = 5';
      AReport.ShowViewer;
    finally
      AReport.Free;
    end;
  finally
    ADataConnection.Free;
  end;
end;
cpp
#include "dxReport.hpp" // Declares the TdxReport component and related types
#include "dxBackend.ConnectionString.JSON.DataSet.hpp" // Declares the TdxBackendDataSetJSONConnection component

// Add the following linker directives to the corresponding CPP source file:
#pragma link "dxReport" // Required to use dxReport.hpp declarations
#pragma link "dxBackend.ConnectionString.JSON.DataSet" //Required to use TdxBackendDataSetJSONConnection declarations
// ...

void __fastcall TMyForm::Button1Click(TObject *Sender)
{
  TdxBackendDataSetJSONConnection *ADataConnection;
  TdxReport *AReport;
  TStream *ALayoutStream;
  ADataConnection = new TdxBackendDataSetJSONConnection(this);
  try
  {
    ADataConnection->Name = "DataSetJSONData";
    ADataConnection->DataSets->Add("Data", FDataSource);
    AReport = new TdxReport(this);
    try
    {
      AReport->ReportName = "Report";
      ALayoutStream = FLayoutDataSet->CreateBlobStream(FLayoutDataSet->FieldByName("Layout"), bmRead);
      try
      {
        AReport->Layout->LoadFromStream(ALayoutStream);
      }
      __finally
      {
        delete ALayoutStream;
      }
      AReport->Language = "fr-FR";
      AReport->ExportFormats = TdxReportExportFormats() << TdxReportExportFormat::PDF
        << TdxReportExportFormat::RTF << TdxReportExportFormat::HTML;
      AReport->FilterString = "id = 5";
      AReport->ShowViewer();
    }
    __finally
    {
      delete AReport;
    }
  }
  __finally
  {
    delete ADataConnection;
  }
}

Footnotes

  1. The OnLayoutChanged event occurs on every Layout property value change.

See Also

Report Viewer and Designer UI Localization

TdxCustomDashboardControl.Layout Property

TdxReport Class

TdxReport Members

dxReport Unit