Introduction
In order to display a report by using ReportViewer Control, we need a DataSource that contains the data to be shown and a Report document that describes how that data should be displayed.
This article presents how to form a Report Display Component to display data within different DataSet
objects that are described by a Report document (*.rdlc).
During my previous searches about displaying data within generic DataSet
objects, I've encountered a set of different solutions. Most of them assumed DataSet
objects are accessible during design time. Some others used TableAdapter
objects that include SQL statements and/or Connection strings, etc. Probably, these solutions cover most of the situations a developer can encounter. But what if you don't have access to DataSet
objects during design time, what if the overall architecture of the software doesn't let you to use SQL statements or connection strings on the architectural level you are currently working, what if you need to use data without knowing its structure until runtime, what if you need dynamic data sources rather than static?
I'm currently in need of a component that displays generic reports. My organization is developing accounting software and in accounting domain there are lots of changes in reports. After distributing and deploying the software, organization must give supporting service about newly added or changed reports. In the maintenance phase, it is costly to distribute a whole update that often. So what we need is some kind of a Report Import / Generic Report Display ability.
Before We Begin
As I've said before, in order to display a report, we need a DataSource
(in this article, a populated DataSet
instance) and a report document (*.rdlc file ). Once we have the Report-DataSet
pair, we can display any report we want.
Figure 1a: Logical representation of the Report Display Component
How Do We Use DataSet as a Data Source?
A DataSet
is an object that includes tabular data which can be represented by using XML format. What we need to know is that the structure of the data can be described by an XSD schema document which is also another XML based document.
DataSet <code>dsHesapPlan = new DataSet();
dsHesapPlan.DataSetName = "HESAP_PLAN";
dsHesapPlan.WriteXmlSchema();
dsHesapPlan.WriteXml();
Figure 1.b: Useful operations on a DataSet
Let's take a look at the schema of the DataSet
, which we get by running the method dsHesapPlan.WriteXmlSchema()
:
Figure 1.c: Sample DataSet Schema which will be useful when designing the report.
Highlighted areas show naming information that will be used later.
What is a *.rdlc Report Document?
An rdlc Report Document is also another XML based document that defines how the data should be displayed. I'm not going to demonstrate how to form a report here. But there are some things you should know, so I'll form a checklist of actions to build a report.
- Form a schema of the
DataSet
which you will use (dsHesapPlan.WriteXmlSchema()
).
- Add the schema to your Visual Studio Project. The schema will be visible within the Data Sources window.
- By using this schema, design your report.
- After you complete designing the report, save the project.
- Inside your project folder, you'll find the *.rdlc report document. Take it for redistribution.
Here is a part of the structure of a *.rdlc Report Document:
Figure 1.d: Sample *.rdlc Report Document.
Highlighted areas show naming information which must show consistency with your DataSet definitions.
How to Bind a DataSet-Report Pair?
So, now we have a Report and a DataSet
that can be bundled and sent to the client. Now what we need is a system to know what to do with this DataSet
-Report pair.
Note that, you can send the report as the *.rdlc file itself. And DataSet
can be distributed in a set of different ways. For example, executing CREATE
scripts in client side to generate STORED PROCEDUREs
that return the data forming the desired DataSet
, or, by XML data itself, etc.
This part of the article assumes you have the properly designed Report document and the DataSet
.
The following code shows how to bind a Report-DataSet
pair to a ReportViewer
object dynamically.
getDataSet(ref <code>dsHesapPlan);
string reportPath = "Reports/AccountReport.rdlc";
ReportViewer rView = new ReportViewer();
rView.Dock = DockStyle.Fill;
this.Controls.Add(rView);
rView.LocalReport.DataSources
.Add(new ReportDataSource("HESAP_PLAN_dtLast", dsHesapPlan.Tables[0]));
rView.LocalReport.ReportPath = reportPath;
Figure 1.e: How to bind the DataSet and the generic Report dynamically.
Conclusion
This technique may be useful for developers experiencing similar problems with me. Surely, it is possible to build a real smart system to understand and display a report. I hope this article guides efforts for building such a system.
You may visit www.rdleditor.com for a series of related links.