Иногда возникает необходимость использовать части одного отчета в другом. В простых случаях для этого можно использовать наследование отчетов.
Например, ситуация, когда во всех отчетах есть общие элементы (логотип компании, подпись и т.д.). Тогда эти объекты можно вынести в родительский отчет и при создании дочерних отчетов они будут скопированы автоматически. Таким образом отпадет необходимость копировать каждый раз вручную, что значительно упростит и ускорит создание новых отчетов. Кроме того, если что-то изменить в родительском отчете, то эти изменения также будут отражены во всех дочерних.
Однако у наследования отчетов есть ряд ограничений. Бывают ситуации, когда у отчета был один “родитель” и возникла необходимость сделать родительским совершенно другой отчет. Может показаться, что достаточно изменить свойство BaseReport, но, к сожалению, это не сработает.
Тем не менее такую задачу можно решить необычным способом, подменив из кода бэнды одного отчета бэндами другого.
Допустим, есть базовый отчет (base.frx) его бэнды нужно скопировать с заменой в дочерний отчет (child.frx). Заменить нужно бэнды PageHeader, PageFooter и DataBand с именем "Data1". Далее в примерах кода предполагается, что оба отчета находятся в корневой папке диска C.
Для начала нужно загрузить оба отчета:
Следующим шагом необходимо получить страницы из обоих отчетов. Важно при этом знать имена страниц. В следующем примере предполагается, что имя страниц в обоих отчетах "Page1":
ReportPage basePage = base.FindObject("Page1") as ReportPage; ReportPage childPage = child.FindObject("Page1") as ReportPage;
Если имена страниц неизвестны, то можно получить их по индексу. Например, далее получаем доступ к первым страницам обоих отчетов:
ReportPage basePage = baseReport.Pages[0] as ReportPage; ReportPage childPage = childReport.Pages[0] as ReportPage;
Оба варианта уместны и приводят к одинаковому результату.
Теперь можно подменить PageHeader и PageFooter. Здесь все просто:
childPage.PageHeader = basePage.PageHeader; childPage.PageFooter = basePage.PageFooter;
Этими строками копируются два бэнда со всеми свойствами и настройками. Кроме того, дублируются все расположенные на них объекты и не теряются свойства.
Далее заменяем DataBand с именем "Data1":
DataBand baseBand = basePage.FindObject("Data1") as DataBand; DataBand childBand = childPage.FindObject("Data1") as DataBand; // необходимо получить индекс Data1 в дочернем отчете int childBandIndex = childPage.Bands.IndexOf(childBand); // теперь его можно удалить childPage.Bands.Remove(childBand); // и вставить на его место бэнд из базового отчета childPage.Bands.Insert(bandIndex, baseBand);
В итоге скопирован бэнд со всеми свойствами и дочерними объектами. А также перенесена привязка к источнику данных, за которую отвечает свойство DataSource. Без этой привязки бэнд не будет работать корректно и выводить данные из базы.
Осталось только скопировать источники данных. Это делается следующим фрагментом кода:
for (int i = 0; i < baseReport.Dictionary.DataSources.Count; i++) { childReport.Dictionary.DataSources.Add(baseReport.Dictionary.DataSources[i]); }
Таким образом, были скопированы все источники данных. Если в этом нет необходимости, то можно клонировать только нужные.
Вот и всё. Пара десятков строк кода позволили скопировать бэнды и объекты из одного отчета в другой. Если на бэндах много объектов, то дублировать их с помощью дизайнера довольно долго и рутинно, а создавать заново - ещё дольше.
Конечно, если в базовом отчете были только скопированные в данном примере бэнды, то эту задачу можно выполнить еще проще - банальным копипастом файла отчета. А если серьезно, то описанным способом можно скопировать один или несколько бэндов из множества, когда все они в новом отчете не нужны. Или вообще, можно взять заголовок страницы из одного отчета, бэнд с данными из другого и подвал страницы из третьего.