Tuesday, October 19, 2010

Fast Report new plans

With the development of its latest tools and great strategy, Fast report has started making roots in Africa, as the first and favourite reporting tool.

FastReport .Net 1.5 released!

What's new?

Version 1.5
---------------
+ added import from RDL format (Report Definition Language)
+ added XPS export
+ added Word 2007 (docx) export
+ added DataBand.ResetPageNumber property
+ added properties PDFExport.JpegQuality and PDFExport.RichTextQuality (default value is 90 in both)
+ added Slovak localization
+ added support for custom functions in the matrix totals
+ added calculation of percents in the Matrix object
+ added TotalsFirst option for the matrix totals
+ added property HTMLExport.Layers and a checkbox in the dialog of the HTML export (enable layers in HTML file)
+ added Config.ReportSettings.ReportPrinted event
+ added DataLoaded event to all dialog controls that support data filtering
+ added inline printing from browser in WebReport
+ added property WebReport.PrintInPdf (enable for PDF printing or disable for browser printing)
+ added properties WebReport.PrintWindowWidth, WebReport.PrintWindowHeight
+ added properties WebReport.ShowWord2007Export, WebReport.DocxMatrixBased
* DbfExport properties FieldNamesFileName, LoadFieldNamesFromFile replaced with FieldNames property
* improved TextObject.Duplicates
- fixed text object's html tags + "underline" font style
- fixed "keep with data" + multicolumn databand
- fixed bug with paper size
- fixed bug when rendering several side-by-side Table objects
- fixed bug with report outline
- fixed bug in RTF export with similar pictures
- fixed bug with CheckedListBoxControl + cascaded filter
- fixed bug with subreport and multi-column band
- fixed bug with FirstTabOffset
- fixed bug with static query parameters and master-detail report
- fixed bug in the PowerPoint export
- fixed bug with Matrix and EvenStyle

FastCube 1.8 released

Fast Cube has been released and more added, check the following:

+ Added support of Embarcadero Rad Studio XE (Delphi XE/C++Builder XE)
+ Added property RunScriptInDesigner in TfrcCube.
+ Added search by first symbol (after pressing a key) in popup lists (list of fields and the lists of unique values)
+ Added TeeChart 2010 support
- Fixed error: AV when calculation measure is moved in field list
- Fixed range drawing when XP themes are enabled.
- Fixed error with UnicodeString measures
- Fixed error: AV after compiling project without using runtime packages in BCB 6
- Fixed error with ftMemo fields
- Fixed error of TfcGrid printing

Friday, July 23, 2010

How-to store FastReport.NET report templates in database

Some applications require the storing of report templates in a database. This simplifies template support - all reports are stored in one place, and allows to differentiate the access rights to different templates. I noted only one shortcoming of this technique - slight complication of the code in the client application.
For example, we need to create Access database (mdb) named "reports" and a table for storing our report templates. I named this table "reports_table". Three tables are enough in our data table:
№ Field name Type Description
1 Id counter Auto-increment, index
2 ReportName text Name of report
3 ReportFile BLOB Binary data with template

You can store templates in any other database similar to the one in our example.
To do this:
• open the designer;
• show custom form with a list of templates from our database instead of standard dialog when users open a file in the designer;
• load template in the designer after selecting it in the custom form;
• Save the template in a database where the user saves a file in the designer.
Despite the apparent complexity, the tasks above will be simple because FastReport.NET has special features.
Create a new project in Visual Studio first. Then you need to drag-n-drop "Report" object from toolbox to the empty form. Also drag the " EnvironmentSettings" object (properties of reporting engine).

You can setup many settings of the report and the designer in "environmentSettings1" object. You have to override the event handlers CustomOpenDialog, CustomOpenReport, CustomSaveDialog and CustomSaveReport.
Event handler CustomOpenDialog allows releasing any algorithm of the load report template in the designer - load template from the database field and load it in the designer or set e.Cancel = true; when loading fails.
The problem reduces to showing a dialogue with a list of files from which you want to select the report template from the database and load the template in the designer. Of course, if the user presses the Cancel button in this dialog, we set e.Cancel = true. The loading process is clear but saving code need some details.
The user can choose two ways to save a file - simply by clicking "Save", in this case report should be rewritten to the old place, or the second option - "Save as...”, the user is expected to select path of file. Storage location of report templates cannot be changed in our case. You need to save template in the old place (database field) in both ways - capture the CustomSaveDialog event by empty function and save template in database in the CustomSaveReport event.
Now you need to add a new data source to the project - reports.mdb.Drop the button on form for launching of the reports designer.

Write in the Click event handler:
private void button1_Click(object sender, EventArgs e)
{
report1.Design();
}

Create an additional dialog form for template selection:

Assign the buttons OK and Cancel corresponding to DialogResult.
Do not forget to bind your data source to DataGrid - select the field name of the record and make the index field invisible.
You need to save the selected index when you click on the ‘OK’ button:
public int reportID;
...
private void OKBtn_Click(object sender, EventArgs e)
{
// save id of report for use in future
reportID = (int)dataGridView1.CurrentRow.Cells[0].Value;
}

We return to our first form. It is time to handle the events of opening and saving a report. We make loading the first thing to do:
// define variable for store of report ID
private int reportID;
// define array byte[] for store of template
private byte[] blob;

....
private void environmentSettings1_CustomOpenDialog(object sender,
FastReport.Design.OpenSaveDialogEventArgs e)
{
using (ReportListForm reportListForm = new ReportListForm())
{
// show dialog for report selection
if (reportListForm.ShowDialog() == DialogResult.OK)
{
// get report ID
reportID = reportListForm.reportID;
// load report in array from BLOB
blob =
(byte[])this.reports_tableTableAdapter.GetDataByID(reportID).Rows[0]["ReportFile"];
// read file name of report for designers title
e.FileName =
(string)this.reports_tableTableAdapter.GetDataByID(reportID).Rows[0]["ReportName"];
}
else
// cancel loading
e.Cancel = true;
}
}

Second handler CustomOpenReport for loading the template in designer should look like this:
private void environmentSettings1_CustomOpenReport(object sender,
FastReport.Design.OpenSaveReportEventArgs e)
{
using (MemoryStream stream = new MemoryStream())
{
// skip all garbage created by MS Access in begin of blob field - we seek the tag of XML
int start = 0;
for (int i = 0; i < blob.Length - 1; i++)
{
if (blob[i] == (byte)'<' && blob[i + 1] == (byte)'?')
{
start = i;
break;
}
}
// copy of blob content in stream
stream.Write(blob, start, blob.Length - start);
stream.Position = 0;
// load template in designer
e.Report.Load(stream);
}
}

We used mdb-database to store report templates. MS Access write special header in begin of BLOB field. We need to skip this header and find begin of xml file (report templates stored in xml).
We turn to the organization and save the template using the designer. As written above, we need to override the event handler CustomSaveDialog by an empty function to prevent a user from unnecessary actions:
private void environmentSettings1_CustomSaveDialog(object sender,
FastReport.Design.OpenSaveDialogEventArgs e)
{
// empty
}

Event handler CustomSaveReport should look like this:
private void environmentSettings1_CustomSaveReport(object sender,
FastReport.Design.OpenSaveReportEventArgs e)
{
// create stream for store of template
using (MemoryStream stream = new MemoryStream())
{
// save template in stream
e.Report.Save(stream);
// copy stream in array
byte[] blob = stream.ToArray();
// save array in BLOB
this.reports_tableTableAdapter.UpdateReport(blob, reportID);
}
}
The methods GetDataByID and UpdateReport are created in the dataset designer- you can see them in the example project.
Compile and run application, then press a button to open the designer:

Click menu item "Open":

Select any report template and press OK.

You can change the report and save the template after that- new template will be stored in database.
Full source code of this example is available in an attached zip archive (databases with reports are included).

Reporting in Delphi threads

Sometimes we need create many reports in multiple threads simultaneously. This may be the development of a web service, or output information from an existing multithreaded application in a certain needed document format (PDF as example).
I noted that FastReport VCL library is a better solution for document generation in multiple formats. This component library is easy to use and has a convenient report designer which allows you to easily connect to different data sources, among which may be internal application data - arrays, sets of parameters, etc.
Traditional use of FastReport does not give any difficulties, but now we have to use this report generator in a multithreaded application. The output file format will be PDF.
TfrxReport class has a description of several properties which need to be set immediately after the creation of the object.
You need to remember that the object must work in a thread without the creation of dialogs, progress bars and other visual information.
Here is an example of creating and setting an object of class TfrxReport before the execution of the report:
// create report
FReport := TfrxReport.Create(nil);
// disable all messages
FReport.EngineOptions.SilentMode := True;
// enable safe work in threads
FReport.EngineOptions.EnableThreadSafe := True;
// disable cache
FReport.EngineOptions.UseFileCache := false;
// disable progress bar
FReport.ShowProgress := False;

Some reports have integrated dialog forms, and showing them should be banned for obvious reasons. We need to override an event handler TfrxReport.Engine.OnRunDialog by the procedure ShowReportDialog for to any dialogs.
// handle all dialogs by ShowReportDialog
FReport.Engine.OnRunDialog := ShowReportDialog;

Our procedure will be executed instead of showing each report dialog. We can change the state of any control in a dialog, but we will leave this procedure empty.
procedure TTestThread.ShowReportDialog(Page: TfrxDialogPage);
begin
// empty
end;

Then we create an object of TfrxPDFExport and disable the showing of dialog window and progress bar.
PDF := TfrxPDFExport.Create(nil);
PDF.ShowDialog := False;
PDF.ShowProgress := False;

All operations on the creation and exporting of report objects can be done in the constructor of the thread. The destructor of the thread should look like:
destructor TTestThread.Destroy;
begin
// destroy all created objects
PDF.Free;
FReport.Free;
inherited;
end;

Necessary objects are created and configured. Now you can load the report template from a file and run a report in the implementation of the main thread procedure Execute. There, it will also be exported to the desired format.

// load report template
FReport.LoadFromFile(FFileName);
// set report variables
FReport.Variables['ThreadID'] := QuotedStr(FId);
// run report
if FReport.PrepareReport then
begin
// save result in PDF
PDF.FileName := FOutPath + '\report_'+ FId +
'_' + FormatDateTime('YYYYYMMDDHHMMSS', Now) + '.pdf';
FReport.Export(PDF);
end;

Try building reports without using RichText objects because by so doing you can get an unstable application.

Do not forget to include ActiveX controls in uses module, and add a call to CoInitialize (nil); in the procedure Execute before creating a report if the report is connected to ADO. Call to CoUninitialize at the end of the thread procedure.

// thread function
procedure TTestThread.Execute;
begin
// initialize COM library in current thread
CoInitialize(nil);
try
// load report template from the file
FReport.LoadFromFile(FFileName);
...
...
...
finally
// Uninitialize COM
CoUninitialize;
end;
end;
end;

You can see an attached example with the application which creates 10 reports in multiple threads and write many PDF files.

Thursday, June 24, 2010

FastCube 1.7 released!

+ Added script event OnGetFieldConv in TfrcCube.
+ Added parameter ACalcRowHeight: boolean in TfcGrid.SelectCell
+ Added events TfcSlice.OnBeforeRemoveSliceFieldFromRegion and TfcSlice.OnBeforeAddedSliceFieldToRegion
+ Added option mdsoAllowFilterAllValues in TfcSlice.Options
+ Added property TfcChart.SkipNullPoints: boolean
+ Added option mdsoSaveFiltersEnabledValues for TfcSlice (to save enabled filters Values (instead of disabled values) in Schema)
+ New key combinations Ctrl+Up and Ctrl+Down in TfcGrid and TfcDetailGrid
+ Added event TfcGrid.OnUpdateSelection: TNotifyEvent
+ TfcGridStyle.UseParentFont is set to False when Style properties are changed.
* Values of numerical measure are copied to clipboard without format.
* Alignments are imported from TfcGrid if are used OnGetStyles in TfrcGrid
- Fixed styles copying. Caused wrong colors in xls and html exports.
- Fixed grid printing errors.
- Fixed errors in fields converter.
- Fixed error with PopUp list with Form.FormStyle=fsStayOnTop
- Fixed error of fcChart printing.
- Fixed error of saving Null value in schema with mdsoSaveFiltersByValue option
- Fixed error in Recompile Wizard: installation packages in Delphi 11.
- Fixed grid copy to clipboard operation for D9+
- Fixed memory corruption by the DrawText routine which caused random crashes
- Fixed error in the Recompile Wizard for C++Builder 6 with FastScript in the Standart edition
- Fixed few problems with FreePascal and Lazarus
- Fixed Sort by focused row/column.
- Fixed error: AV in TfcGridReport
- Fixed error: AV when schema contains a field which is absent in cube

About FastReport VCL 5

Recently, many ask me: "Will you develop FastReport.Net only?", "Why don’t we see new builds of FastReport VCL 4?"

I will will tell you a small secret. The team which developed FastReport VCL is now developing FastReport VCL 5!

And it will contain many new useful features for Delphi and C++Builder developers.

We plan to release FastReport VCL 5 this autumn. See a not full list of news in FastReport VCL 5:

Improved Engine:
- improved shift mechanism;
- duplicated combining;
- new aggregates;
- improved cross object;
- changes in xml format(write collections in XML);
- improved report inheritance;
- hierarchy;
- watermarks/ objects fill;
- improved linear barcodes;
- improved interactive reports: OnMouseEnter/OnMouseLeave events;
- detailed reports;
- multi-tab preview for detailed reports;

New Objects:
- new 2D barcodes: DataMatrix and PDF417;
- Table object;
- Cellular text;
- Zip Code;

New exports:
- BIFF XLS export;
- PPTX export;
- XLSX export;
- DOCX export;

And two screenshots (compare with FastReport.Net!)

Friday, April 30, 2010

FastReport.NET, creating reports from code.

Usually, when programming using the FastReport.NET library, there is need to load the report template from a file, show the user in the preview window, and give the user the chance to change the report template, immediately print or export the report.
However, sometimes there can be a need to create a report template from code. In this article, I will try to look at an example of creating a report from C# code.
To start with, we need to imagine how the report should be. So, what should be in the report:
1. One page.
2. Report header.
3. Page header.
4. Page heading, containing 6 columns.
5. Table with data, received from a demo database (nwind.xml).
6. Page footer.
7. Report footer.
Now, let’s go to the creation of the report.
First, we need to create a report, create the data source and register it:
report = new Report();
dataset = new DataSet();
dataset.ReadXml(@"..\..\nwind.xml");
report.RegisterData(dataset);
report.GetDataSource("Products").Enabled = true;
Here, the products table from the demo database is used as the data source.
In the following code fragment, we will create the report page:
ReportPage page = new ReportPage();
page.CreateUniqueName();
page.TopMargin = 10.0f;
page.LeftMargin = 10.0f;
page.RightMargin = 10.0f;
page.BottomMargin = 10.0f;
report.Pages.Add(page);
In the second code row, a unique name for the page is created. The method CreateUniqueName () is accessible in any FastReport.NET component. As a result, the report page got the name “Page1”. If you want to give the page a different name, for example “FirstPage”, then, instead of using the CreateUniqueName method, you can use the Name property:
page.Name = "FirstPage";
In the following four code rows (by using the properties TopMargin, LeftMargin, RightMargin and BottomMargin) the page fields are being given, each one is given 1 см.Since by default, the page is created with fields of the same size, then in this case using these properties is not obligatory.They are useful, when there is a need to give fields certain sizes not 1 cm. Pay attention that the property saves the size of the fields in millimeters.
In the last code rode, the created page is added to the report.
And let’s create the report header, via the ReportTitle page property:
page.ReportTitle = new ReportTitleBand();
page.ReportTitle.CreateUniqueName();
page.ReportTitle.Height = 4.0f * Units.Centimeters;
Everything is clear with the first two rows, but the third needs to be understood .In this row the header height is given as 4 cm. Since the property stores height in pixels, then there is need to use Units.Centimeters – number o f pixels in one centimeter.In order to rename, we need to connect to FastReport.Utils.
We create the text object in the header:
TextObject titleText = new TextObject();
titleText.CreateUniqueName();
titleText.Left = 1.0f * Units.Centimeters;
titleText.Top = 1.0f * Units.Centimeters;
titleText.Width = 17.0f * Units.Centimeters;
titleText.Height = 2.0f * Units.Centimeters;
titleText.HorzAlign = HorzAlign.Center;
titleText.VertAlign = VertAlign.Center;
titleText.Font = new Font("Chiller", 32.0f, FontStyle.Bold);
titleText.TextColor = Color.DarkGreen;
titleText.FillColor = Color.DarkOrange;
titleText.Border.Color = Color.DarkOrchid;
titleText.Border.Lines = BorderLines.All;
titleText.Border.Width = 4.0f;
titleText.Text = "Report from code demo";
page.ReportTitle.Objects.Add(titleText);
Here, the position of the object relative to the report header is indicated via the properties Left and Top, but the size is given with the help of the width and height properties. The following two rows set the horizontal and vertical aligning of the text in the object. The font of the text can be chosen with the Font property.In this case, the name, size and style of the font is shown.The following three rows give the: text color,filled text object color and the color of its border. The last two rows show which border will be visible and its width in pixels.In the last row, the text is given. And the last row of the text object is added to the report header.
Page header is given in the same way. But apart from the page header text, six text objects which are table headings are created in it. Need to point out that, report header and page header are similar in many aspects.The main important difference is that, report header is printed on the first page of the report, and page header on every page.
Need to pay attention to the code creating the page header text object:
TextObject headerText = new TextObject();
headerText.CreateUniqueName();
headerText.Bounds = new RectangleF(0.0f, 0.5f * Units.Centimeters,
19.0f * Units.Centimeters, 1.0f * Units.Centimeters);
headerText.HorzAlign = HorzAlign.Center;
headerText.VertAlign = VertAlign.Center;
headerText.Font = new Font("Book Antique", 16.0f,
FontStyle.Bold | FontStyle.Italic);
headerText.TextColor = Color.Teal;
headerText.FillColor = Color.YellowGreen;
headerText.Border.Lines = BorderLines.All;
headerText.Border.TopLine.Color = Color.Indigo;
headerText.Border.LeftLine.Color = Color.Gold;
headerText.Border.RightLine.Color = Color.Gold;
headerText.Border.BottomLine.Color = Color.Indigo;
headerText.Border.TopLine.Width = 3.0f;
headerText.Border.LeftLine.Width = 2.0f;
headerText.Border.RightLine.Width = 2.0f;
headerText.Border.BottomLine.Width = 3.0f;
headerText.Text = TableName + " Table";
page.PageHeader.Objects.Add(headerText);
The Bounds property, allows creating a rectangle, which describes object border.that is.it’s possible to give the position, width and height of the object with one row. And also a row in which the color and border width of the text object is given.Interesting that, it s possible to set the color of each of the borders separately.
Now we create the databand:
DataBand band = new DataBand();
page.Bands.Add(band);
band.CreateUniqueName();
band.DataSource = report.GetDataSource("Products");
band.Height = 0.5f * Units.Centimeters;
Only the fourth row needs to be explained, in which the data source for the band is shown.
Further, we create six text objects in the band, which will be connected to the table fields.Let’s get the creation of one of the objects, the rest will be created in the same manner:
TextObject bandText = new TextObject();
bandText.CreateUniqueName();
bandText.HorzAlign = HorzAlign.Center;
bandText.Bounds = new RectangleF(0.0f * Units.Centimeters, 0.0f,
1.0f * Units.Centimeters, 0.5f * Units.Centimeters);
bandText.Border.Lines = BorderLines.All;
bandText.Text = "[Products.ProductID]";
band.AddChild(bandText);
The last two rows, the first of which creates a connection to the ProductID field in the Products table.And the second adds the text to the band. Giving the text object parent can also be done in one more way:
bandText.Parent = band;
The following code fragment creates the pagefooter with the text object in it:
page.PageFooter = new PageFooterBand();
page.PageFooter.CreateUniqueName();
page.PageFooter.Height = 0.5f * Units.Centimeters;
TextObject footerText = new TextObject();
footerText.CreateUniqueName();
footerText.HorzAlign = HorzAlign.Right;
footerText.VertAlign = VertAlign.Center;
footerText.Bounds = new RectangleF(0.0f, 0.0f,
19.0f * Units.Centimeters, 0.5f * Units.Centimeters);
footerText.TextColor = Color.Teal;
footerText.FillColor = Color.YellowGreen;
footerText.Border.Lines = BorderLines.All;
footerText.Border.TopLine.Color = Color.Indigo;
footerText.Border.LeftLine.Color = Color.Gold;
footerText.Border.RightLine.Color = Color.Gold;
footerText.Border.BottomLine.Color = Color.Indigo;
footerText.Border.TopLine.Width = 3.0f;
footerText.Border.LeftLine.Width = 2.0f;
footerText.Border.RightLine.Width = 2.0f;
footerText.Border.BottomLine.Width = 3.0f;
footerText.Text = "Page [Page]";
page.PageFooter.Objects.Add(footerText);
Pay attention to the penultimate row.Page footer text ("Page [Page]") is given in it. Here, apart from the Page text, Page – system variable, which stores the current report page is stored, is used.Its use allows to easly number the pages.
The last code fragment creates the report footer:
page.ReportSummary = new ReportSummaryBand();
page.ReportSummary.CreateUniqueName();
page.ReportSummary.Height = 4.0f * Units.Centimeters;
footerText = new TextObject();
footerText.CreateUniqueName();
footerText.Left = 1.0f * Units.Centimeters;
footerText.Top = 1.0f * Units.Centimeters;
footerText.Width = 17.0f * Units.Centimeters;
footerText.Height = 2.0f * Units.Centimeters;
footerText.HorzAlign = HorzAlign.Center;
footerText.VertAlign = VertAlign.Center;
footerText.Font = new Font("Chiller", 32.0f, FontStyle.Bold);
footerText.TextColor = Color.DarkGreen;
footerText.FillColor = Color.DarkOrange;
footerText.Border.Color = Color.DarkOrchid;
footerText.Border.Lines = BorderLines.All;
footerText.Border.Width = 4.0f;
footerText.Text = "Total Pages [TotalPages#]";
page.ReportSummary.Objects.Add(footerText);
Here in the penultimate row uses system variable TotalPages#,in which the total number of pages in the report is saved. The main difference between the report footer and page footer is just the same the difference between the report header and the page header, -page footer is printed on every page and report footer only on the last page.
On figs 1 and 2, report template is shown , and report pages in preview.


Fig 1.

Fig 2.

Adding dialogue window to a Report.
We looked at an example of creating a report from code.However, the possibilities of working with reports from coed in FastReport.NET is not limited. Nothing disturbs us from modifying reports which already exist.Lets examine this by looking at an example of adding a dialogue window into a report, and this on its own is an interesting task.
In order to concentrate on the addition of the dialogue, we will create a very simple report containing empty pages in the designer. To do this, simply click menu File New, then select blank report in the drop down menu. The report is ready, you can save it.
And now, about the dialogue window. Its form is shown in fig 3.


Fig 3
Here everything is simple as well.The function for this window is as follows:
1. The window appears before the report preview window shows up.
2. If you click OK, then preview will be shown.
3. If you click Cancel, then we won’t see the preview window.
Window creation code:
report.Load("report.frx");
DialogPage dialog = new DialogPage();
dialog.Name = "Dialog1";
dialog.Form.Size = new Size(125, 125);
report.Pages.Add(dialog);


The first code loads the report from the file which we have created before.For simplicity, the report was saved in the application folder, and otherwise, the load function will have to be given the full folder file.The following three rows create the dialogue window, gives it the name and size. The last row adds the form to the report page list.
And now, the OK button:
ButtonControl buttonOK = new ButtonControl();
buttonOK.Name = "ButtonOK";
buttonOK.Location = new Point(25, 25);
buttonOK.Size = new Size(75, 25);
buttonOK.Text = "OK";
buttonOK.DialogResult = DialogResult.OK;
dialog.Controls.Add(buttonOK);

Everything is simple here. We create a button, give it a name, position in the window, size and the text on the button. The last two rows are more interesting.The first one determines the standard behavior of the OK button. The second adds the button to the dialogue window.
The cancel button is created in the same way:
ButtonControl buttonCancel = new ButtonControl();
buttonCancel.Name = "ButtonCancel";
buttonCancel.Location = new Point(25, 55);
buttonCancel.Size = new Size(75, 25);
buttonCancel.Text = "Cancel";
buttonCancel.DialogResult = DialogResult.Cancel;
dialog.Controls.Add(buttonCancel);
Need to point out that, the DialogPage and ButtonControl classes,are located within the FastReport.Dialog area.That is why,in order to have access to it, need to coneect to it by via the word using, or by showing the name.

Adding a connection to a report.
Also, you can add a new connection to the report. We will look at this possibility by using an empty report from the previous report.
We need to add the connection to th edemo database(demo.mdb), which is conatained in Fast Reports products called FastReport Studio.
And so, the code:
report.Load("report.frx");
MsAccessDataConnection connection = new MsAccessDataConnection();
connection.Name = "Connection1";
connection.DataSource = "demo.mdb";
report.Dictionary.Connections.Add(connection);
connection.CreateAllTables();
report.GetDataSource("customer").Enabled = true;

There isnt anything complicated here. We load the report. Create the connection, show its name, path to the database (which is located in the application folder), register the connection in the report. The penultimate row loads the whole table.And the last row makes the customer table accesible in the report.
The MsAccessDataConnection class is located in FastReport.Data

Creating reports in visual studio

Creating reports in vs using FastReport is really easy,

We will look at a typical case of using report components in the visual studio environment. During this, the data is taken from a typed source.

· create a Windows Forms Application project;

· add into it data source (in menu"Data|Add New Data Source...");

· switch to the form designer;

· add the DataSet component from the "Data" category, onto the form and connect it to the typed data source, which you have created.

In order to create the report, do the following:

· place the Report component on the form:

.- right click the component , or click the "smart tag" button and, select "Design Report...":

- you will be asked to select the data source for the report. Select the needed table (one or several):

-

· create the report. You can read more about this in the "Users manual ";

· close the report designer;

· add a Button on the form and double click it;

· in the event handler, write:

report1.Show();

· save the project and run it. When clicking on the button, the report will be built.

This method has got some shortcomings. Firstly, in Visual Studio design-time, you are denied the ability to work with "Live" data. This especially affects working with ASP.NET, and also using business objects as data. This implies that viewing the created report can be done only by running your application.

Secondly, methods of working and saving reports are not optimal. For every report, a different report component needs to be created, reports are saved in application’s resource. This can be a problem if there are many reports in your application. However, this lacking can be easily circumvented:

1. Create a report written in the above method;

2. In the report designer, click the "Save” button and save the report in a file;

3. Delete the report component from the form;

4. Use the following code to load and run the report:

using (Report report = new Report())

{

report.Load("your_report.frx");

report.RegisterData(dataSet1, "dataSet1");

report.Show();

}

Here, you can register data by using the report.RegisterData method. Need to indicate the data source, which was used when creating the report (DataSet or BindingSource), and its name аs well.

And yes, you guessed right, that is all you have to do.