Published on

November 4, 2014

Обучение SSRS новому трюку: применение стандартных заголовков и нижних колонтитулов к отчетам

Недавно у меня был клиент, у которого было простое, но практичное требование к их отчетам SSRS: они хотели, чтобы все отчеты имели стандартные заголовки и нижние колонтитулы. Однако они хотели использовать один файл шаблона для применения этих заголовков и нижних колонтитулов, и любые обновления шаблона должны отражаться во всех отчетах одновременно. Это представляло интересную задачу, но я смог придумать решение, которое можно применить к полной версии SSRS.

Обзор архитектуры SSRS

Прежде чем перейти к конкретике решения, давайте кратко обсудим архитектуру SSRS. Определения отчетов в SSRS обычно создаются в Visual Studio или Report Builder, и эти файлы на самом деле являются XML-документами, которые ссылается на опубликованную схему, предоставленную Microsoft. SSRS также предлагает мощный API и утилиту командной строки под названием rs Utility, которая может компилировать и запускать файлы кода VB.NET против SOAP API Reporting Services.

Решение

Реализация решения довольно проста. В исходном решении мы обновляли соответствующие XML-элементы в файле .rdlc во время выполнения по определенному шаблону документа. Чтобы применить это к полному серверу отчетов, нам нужно найти шаблонный документ на сервере и применить соответствующие XML-элементы ко всем файлам отчетов в цикле.

Есть несколько вещей, которые следует учитывать при работе с файлами шаблона и отчета .rdl:

  1. Убедитесь, что все элементы в вашем файле Custom.rdl имеют уникальные имена. SSRS требует, чтобы все элементы в определении отчета имели уникальные имена. Если у вас есть текстовое поле в вашем шаблоне с именем Textbox1, и вы пытаетесь обновить все файлы отчетов, вы можете столкнуться с ошибкой. Рекомендуется называть каждый элемент отчета в заголовке с уникальным идентификатором.
  2. Избегайте использования встроенных изображений в файле шаблона. Скрипт может работать неправильно, если вы это сделаете. Вместо этого загрузите изображение на сервер отчетов и ссылайтесь на него внешне в определениях отчетов.

Вот код для файла скрипта:

'Скрипт для применения пользовательского заголовка и нижнего колонтитула из файла Custom.rdl, сохраненного на ReportServer, ко всем файлам отчетов на ReportServer
'использует конечную точку Mgmt2010 / исполняемый файл против автономного или интегрированного с SharePoint экземпляра
'Сохраните файл с расширением .rss и запустите его с помощью rs.exe из командной строки.
'Автор Jared Zagelbaum 11/2014 jaredzagelbaum.wordpress.com
Sub Main()
    Dim reportDefinition As Byte() = Nothing
    Dim doc As New System.Xml.XmlDocument
    Dim nsmanager As New XmlNamespaceManager(doc.NameTable)
    Dim templateHeader As System.Xml.XmlElement
    Dim templateFooter As System.Xml.XmlElement
    Dim reportHeader As System.Xml.XmlElement
    Dim reportFooter As System.Xml.XmlElement
    nsmanager.AddNamespace("rd", "http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition")
    Dim items As CatalogItem() = rs.ListChildren("/", True)
    'найти файл шаблона
    For Each item As CatalogItem In items
        If item.TypeName = "Report" And item.Name = "Custom" Then
            reportDefinition = rs.GetItemDefinition(item.Path)
            Dim stream As New MemoryStream(reportDefinition)
            doc.Load(stream)
            Exit For
        End If
    Next
    'загрузить шаблонный заголовок / нижний колонтитул в переменную
    templateHeader = doc.SelectSingleNode("/rd:Report/rd:ReportSections/rd:ReportSection/rd:Page/rd:PageHeader", nsmanager)
    templateFooter = doc.SelectSingleNode("/rd:Report/rd:ReportSections/rd:ReportSection/rd:Page/rd:PageFooter", nsmanager)
    'перебор элементов каталога и замена заголовков отчетов шаблоном
    For Each item As CatalogItem In items
        If item.TypeName = "Report" And item.Name <> "Custom" Then
            reportDefinition = rs.GetItemDefinition(item.Path)
            Dim stream As New MemoryStream(reportDefinition)
            Dim outstream As New MemoryStream()
            doc.Load(stream)
            reportHeader = doc.SelectSingleNode("/rd:Report/rd:ReportSections/rd:ReportSection/rd:Page/rd:PageHeader", nsmanager)
            reportFooter = doc.SelectSingleNode("/rd:Report/rd:ReportSections/rd:ReportSection/rd:Page/rd:PageFooter", nsmanager)
            reportHeader.InnerXml = templateHeader.InnerXml
            reportFooter.InnerXml = templateFooter.InnerXml
            doc.Save(outstream)
            reportDefinition = outstream.ToArray()
            rs.SetItemDefinition(item.Path, reportDefinition, Nothing)
            stream.Dispose()
            outstream.Dispose()
        End If
    Next
End Sub
	

Сохраните этот скрипт с расширением .rss и выполните его из командной строки на вашем сервере отчетов. Скрипт может работать как с автономными, так и с интегрированными с SharePoint экземплярами SSRS без изменений.

Вывод

API и утилита rs.exe, предоставленные SSRS, предлагают мощный способ автоматизировать задачи и выполнять массовые обновления определений отчетов. Используя эти инструменты, мы смогли научить SSRS новому трюку и применить стандартные заголовки и нижние колонтитулы ко всем отчетам с использованием одного файла шаблона. С некоторыми модификациями этот скрипт можно расширить для добавления общих элементов в отчеты или ссылки на общие наборы данных.

Не забудьте настроить ссылку на пространство имен и XPath, если вы используете более старую версию SSRS. Кроме того, важно отметить, что большая часть работы заключается в понимании того, как эффективно использовать API и утилиту. Надеюсь, это решение будет полезно другим, сталкивающимся с подобными требованиями.

Click to rate this post!
[Total: 0 Average: 0]

Let's work together

Send us a message or book free introductory meeting with us using button below.