Copying report bands to another with all the contents

Sometimes there is a need to use parts of one report in another. In simple cases, you can use report inheritance to do this.

For example, there is a case when all reports have common elements (a company logo, signature, etc.). Then these objects can be moved to a parent report and when creating child reports, they will be copied automatically. Thus, you do not need to copy them manually every time which greatly simplifies and speeds up the creation of new reports. In addition, if you change something in the parent report, these changes will also be reflected in all of the child reports.

However, report inheritance has a number of limitations. There are cases when a report had one "parent" and it became necessary to make a “parent” a completely different report. It might seem enough to change BaseReport property, but, unfortunately, it won’t work out.

Nevertheless, such a problem can be solved in a fancy way — by replacing bands from one report code with bands from another.
Let's assume that there is a baseline report (base.frx) and its bands need to be copied to a child report (child.frx). You need to replace PageHeader, PageFooter, and DataBand with "Data1" name. The following code examples assume that both reports are located in the root folder of C drive.

First, you need to download both reports:

Report base = new Report();
Report child = new Report();

The next step is to get the pages from both reports. It is important to know the page names. The following example assumes that the page name in both reports is "Page1":

ReportPage basePage = base.FindObject("Page1") as ReportPage;
ReportPage childPage = child.FindObject("Page1") as ReportPage;

If you do not know the page names, you can get them from the index. For example, further we get access to the first pages of both reports:

ReportPage basePage = baseReport.Pages[0] as ReportPage;
ReportPage childPage = childReport.Pages[0] as ReportPage;

Both options are appropriate and lead to the same result.

Now you can replace PageHeader and PageFooter. It's pretty simple:

childPage.PageHeader = basePage.PageHeader;
childPage.PageFooter = basePage.PageFooter;

These lines copy the two bands with all the properties and settings. In addition, all the objects located on them are duplicated and the properties are not lost.

Next, replace DataBand with "Data1" name:

DataBand baseBand = basePage.FindObject("Data1") as DataBand;
DataBand childBand = childPage.FindObject("Data1") as DataBand;
// you need to get the Data1 index in the child report
int childBandIndex = childPage.Bands.IndexOf(childBand);
// you can now delete it
// and insert the band from the base report in its place
childPage.Bands.Insert(bandIndex, baseBand);

In the end, the band with all the properties and child objects is copied, and the binding to the data source which is responsible for DataSource property is transferred as well. Without this binding, the band will not work correctly and will not output data from the database.

We just need to copy the data sources. This is done with the following code snippet:

for (int i = 0; i < baseReport.Dictionary.DataSources.Count; i++)

Thus, all data sources have been copied. If it is not necessary, you can clone only those desired.

That's it. A couple of dozen code lines made it possible to copy the bands and objects from one report to another. If you have a lot of objects on the bands, it's quite long and dull to duplicate them with a designer, and it takes even longer to create them from scratch.

Of course, if the baseline report had only the bands copied in this example, then this task can be performed even easier — by trivial copying and pasting of the report file. Jokes aside, you can use this method to copy one or more bands from a set when you don't need all of them in a new report. Or, you can take a page header from one report, a data band from another, and a footer from a third one.