Вы уже ознакомились с примером простейшего отчёта, а теперь попробуем чуть усложнить задачу - вставить в отчёт картинку.
Как и в прошлый раз, удалим для наглядности все бэнды, кроме заголовка. Растянем бэнд пошире и поместим на него картинку. Затем чуть выше вставленной картинки разместим заголовок. После этого поверх картинки помещаем текст с полупрозрачным фоном. Все эти операции проделываем в дизайнере отчётов и сохраняем сформированный шаблон отчёта. У меня получился такой шаблон:
Таблица, которую вы видите на экране - всего лишь картинка, вставленная в шаблон отчёта. Посмотрим как этот отчёт сохранился в шаблоне отчёта.
<?xml version="1.0" encoding="utf-8"?> <Report ScriptLanguage="CSharp" ReportInfo.Created="05/21/2015 00:40:44" ReportInfo.Modified="05/21/2015 02:32:15" ReportInfo.CreatorVersion="1.0.0.0"> <Dictionary/> <ReportPage Name="Page1"> <ReportTitleBand Name="ReportTitle1" Width="718.2" Height="661.5"> <PictureObject Name="Picture1" Left="18.9" Top="75.6" Width="670.95" Height="576.45" Image="iVBORw0KGgoAAAANSUhEUgAABHUAAAPTCAIAAACxEqIHAAAAAXNSR0IArs4c6QAAAAg=="/> <TextObject Name="Text1" Left="66.15" Top="28.35" Width="623.7" Height="18.9" Text="Everest instruction set" HorzAlign="Center" Font="Arial, 10pt, style=Bold"/> <TextObject Name="Text2" Left="94.5" Top="132.3" Width="330.75" Height="18.9" Border.ShadowColor="116, 0, 0, 0" Fill.Color="149, 255, 255, 255" Text="Yellow opcodes are reserved for future use." HorzAlign="Center" VertAlign="Center"/> </ReportTitleBand> </ReportPage> </Report>
Сразу замечу: при формировании вышеприведённого XML кода я схитрил. Посмотрите на свойство Image объекта PictureObject - не кажется ли оно подозрительно коротким? В оригинальном отчёте картинка, вставленная в отчёт, формирует строку длиной в 184770 символов, полученных трансформацией из 138499 байтовой картинки. Дело в том, что внутри отчёта картинка хранится в формате Base64; при такой конвертации картинка занимает больше памяти, но это цена, которую приходится платить за внедрение двоичных данных в формат XML. Размер шаблона отчёта составляет 186547 байт. В данном примере при внедрении картинки в шаблон отчёта, её размер увеличивается приблизительно на 33%.
Посмотрим, что получилось в подготовленном отчёте:
Размер подготовленного отчёте чуть снизился по сравнению с его шаблоном. Причина снижения в том, что подготовленный отчёт упакован с помощью gzip. Причина небольшого коэффициента компрессии в том, картинка в формате PNG уже сжата, а сжатые данные, даже если закодированы в base64, не дают высокого коэффициента сжатия.
Как и в шаблоне отчёта, перед публикацией кода подготовленного отчёта, я обрезаю свойство отчёта, содержащее упкакованное представление картинки.
<?xml version="1.0" encoding="utf-8"?> <preparedreport> <pages> <page1> <b1> <p1 ImageIndex="0"/> <t1/> <t2/> </b1> </page1> </pages> <sourcepages> <ReportPage Name="Page1"> <ReportTitleBand Name="ReportTitle1" Width="718.2" Height="661.5"> <PictureObject Name="Picture1" Left="18.9" Top="75.6" Width="670.95" Height="576.45"/> <TextObject Name="Text1" Left="66.15" Top="28.35" Width="623.7" Height="18.9" Text="Everest instruction set" HorzAlign="Center" Font="Arial, 10pt, style=Bold"/> <TextObject Name="Text2" Left="94.5" Top="132.3" Width="330.75" Height="18.9" Border.ShadowColor="116, 0, 0, 0" Fill.Color="149, 255, 255, 255" Text="Yellow opcodes are reserved for future use." HorzAlign="Center" VertAlign="Center"/> </ReportTitleBand> </ReportPage> </sourcepages> <dictionary> <b1 name="Page0.ReportTitle1"/> <p1 name="Page0.Picture1"/> <page1 name="Page0"/> <t1 name="Page0.Text1"/> <t2 name="Page0.Text2"/> </dictionary> <bookmarks/> <outline/> <blobstore> <item Stream="iVBORw0KGgoAAAANSUhEUgAABHUAAAPTCAIAAACxEqIHAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADr4AAA6+AepCscg=="/> </blobstore> </preparedreport>
Настало время открыть маленькую тайну: как же на самом деле происходит печать, отрисовка или конвертация отчёта из подготовленного отчёта. Страницы подготовленного отчёта находятся в секции <pages>. В данном <pages> это контейнер, содержащий страницы подготовленного отчёта <page1>. При печати отчёта для получения свойств страницы, генератор отчётов поступает следующим образом: ищет одноимённый тэг в секции <dictionary> и получает имя элемента отчёта. Полученное имя используется для обращения к шаблонным элементам отчёта, содержащих общие свойства для всех ссылающихся на них элементов.
Есть во всей этой схеме одна тонкость: в секции <sourcepages> вы не найдёте страницу с именем Page0, а в секции <dictionary> нет ни одной ссылки на Page1. Хитрость заключается в том, что при использовании словаря для нахождения соответствия элемента подготовленного отчётов элементу шаблона отчёта, номер страницы необходимо увеличить на единицу. Поясню на примере - если нам неходимо получить базовые атрибуты элемента <page1>, то находим его в секции <dictionary>, и из свойства Name получаем имя этого элемента в секции <souurcepages>. В случае, если элемент является страницей отчёта, при поиске соответствия меняем Page0 на Page1. О причинах такого поведения будет рассказано в другой раз, пока же примите необходимость подмены номера как данность.
Обратите внимание на свойство Image элемента <PictureObject>. Заметили, что это свойство исчезло у объекта <PictureObject> подготовленного отчёта? Свойство Image, которое содержит данные картинки, переместилось в секцию <blobstore>, при этом элемент <PictureObject> подготовленного отчёта описывает лишь свойства картинки, но уже не содержит графические данные. Для использования картинки в подготовленном отчёте используется элемент <p1> и его свойство ImageIndex. При печати подготовленного отчёта происходит следующее - объект <p1> находится в секции <dictionary> и по его имени находится ссылка на подходящий элемент <PictureObject>, из которого выбираются базовые свойства картинки - размер, позиция и т.д.
Свойство ImageIndex элемента <p1> указывает на двоичные данные в секции <blobstore>. Эта секция состоит из множества элементов <item>, свойство Stream которых содержит образ картинки. Свойство ImageIndex определяет порядковый номер элемента <item>.
Теперь вы имеете неплохое представление о внутренней структуре шаблона отчёта и подготовленного отчёта. В следующий раз мы чуть более внимательно посмотрим на свойства какого-нибудь элемента отчёта.