Учим MS SQL Server Reporting Services 2008 R2 показывать HTML в отчетах

в 12:39, , рубрики: html, javascript, MS SQL, Reporting Services 2008 R2, SSRS, SSRS 2008 R2, отчеты, метки: , , , , ,

Учим MS SQL Server Reporting Services 2008 R2 показывать HTML в отчетах

Проблема

Недавно столкнулся с необходимостью показать в отчете SSRS 2008 R2 HTML-таблицы, хранящиеся в базе данных.
И здесь на сцену статисты выносят заботливо подготовленные «грабли». Все дело в том, что Report Manager в SSRS 2008 R2 поддерживает только ограниченное количество тегов HTML, и табличные в их число не входят.
Согласно официальной документации, поддерживаются только следующие теги:

  • Ссылки: A HREF
  • Шрифт: FONT
  • Заголовки, блочные элементы: H{n}, DIV, SPAN,P, LI
  • Форматирование текста: B, I, U, S
  • Списки: OL, UL, LI

Список атрибутов CSS также сильно урезан.

После продолжительного поиска в интернете, стало понятно, что ни один из вариантов, предлагаемых сообществом разработчиков, меня не устроит.

Исследование

Варианты предлагались следующие:

  • Рендерить HTML в картинку на стороне сервера с помощью специально разработанного компонента (Custom Report Items)
  • Заменить теги на поддерживаемые с симуляцией таблиц (нужно писать скрипт в самом отчете)

В одном из обсуждений натолкнулся на подсказку — Javascript на стороне клиента. Готового решения не было.
Начал с попыток проанализировать какой код выполняется на стороне клиента при отображении отчета. Подсмотрел в код отчета в браузере и нашел внедренный скрипт ReportingServices.js:

<script language="JScript" src="/Reports_SQLEXPRESS/js/ReportingServices.js" type="text/Javascript"></script>

Сам скрипт у меня на сервере лежал здесь:

c:Program FilesMicrosoft SQL ServerMSRS10_50.SQLEXPRESSReporting ServicesReportManagerjsReportingServices.js

Нашел пару статей на тему Javascript-инъекции с помощью данного скрипта, но основная проблема была в том, что мои модификации выполнялись только один раз при отображении первой страницы отчета, и при переходе на следующие страницы интерфейсные элементы уже не перерисовывались (AJAX).
Попытки глубже разобраться в принципах работы SSRS продолжились изучением фрагментов кода основных DLL-ей сервера с помощью DevExtras CodeReflect и препарированием отчетов в IE9 developer tool/Opera Dragonfly.
В результате нашел следующее:

  • Для WebForms которые используют Ajax, есть ряд событий, определяющих жизненный цикл страницы
  • Одно из таких событий — Load, вызывается каждый раз, при загрузке страницы и всех вызовов Ajax
  • Подробности в статье Ajax Client Life-Cycle Events: http://msdn.microsoft.com/en-us/library/bb386417.aspx

Для того чтобы добавить свой обработчик — нужно создать JS-функцию pageLoad, которая автоматически будет выполняться при возникновении события Load:

function pageLoad(sender, args) {
	//здесь наш код, например alert("Работает!");
}

Вставляю данную конструкцию в самое начало скрипта ReportingServices.js. Работает!

Решение

Собственно, дальше уже головоломка собралась и получилось следующее решение:

  1. Добавляем в начало скрипта %SSRS Install Dir%Reporting ServicesReportManagerjsReportingServices.js следующую функцию:
    function pageLoad() {
       var toDecode = document.getElementsByTagName("div");    // получаем все DIVы
       for (var i = 0; i < toDecode.length; ++i){       // перебираем
          if(toDecode[i].innerHTML.indexOf("HTMLInject:") == 0){   // DIV содержит префикс?
             Decoded = toDecode[i].innerText || toDecode[i].textContent; // поддержка IE, Opera, FF
             toDecode[i].innerHTML = Decoded.slice(11);     //  вырезаем префикс & TXT --> HTML
          }
       }
    }
    

  2. Теперь, чтобы вывести поле как HTML, в свойствах placeholder'а в поле Value надо написать следующее:
    ="HTMLInject:"+Fields!FieldName.Value
    

    , где FieldName — имя поля датасета, содержащего HTML.
    Учим MS SQL Server Reporting Services 2008 R2 показывать HTML в отчетах

    При этом свойство «GeneralMarkup type» самого поля нужно поставить в значение "None — Plain text only".

    Учим MS SQL Server Reporting Services 2008 R2 показывать HTML в отчетах

  3. При необходимости изменения стилей HTML — можно внести правки в этот CSS: %SSRS Install Dir%ReportingServicesReportManagerStylesReportingServices.css Однако, мне повезло и мои HTML таблицы были отформатированы классами, которые я и добавил в CSS-файл.

А теперь примеры

Так по-умолчанию показывается поле («None — Plain text only»):
Учим MS SQL Server Reporting Services 2008 R2 показывать HTML в отчетах

Так показывает таблицы, если тип разметки поставить в «HTML — Interpret HTML tags as styles»:Учим MS SQL Server Reporting Services 2008 R2 показывать HTML в отчетах

Мой вариант:
Учим MS SQL Server Reporting Services 2008 R2 показывать HTML в отчетах

Про/контра такого решения

Достоинства:

  • Работает
  • Легко и быстро сделать

Недостатки:

  • Работает только при отображении отчетов в веб-интерфейсе. В других форматах отчетов (Excel, PDF, Word...) отображается весь HTML с тегами. Как обходное решение можно использовать несколько столбцов для одного поля и признак видимости "Show or hide based on an expression" с формулой "=Globals!RenderFormat.Name"(то есть показывать только один столбец, в зависимости от формата отчета). Далее, в отчетах для других форматов уже можно разработать функцию для плейсхолдера, чтобы как-то причесать HTML (например заменой на поддерживаемые теги, или отображением как картинки).
  • Слетает навигация по меню отчета (DocumentMap) — то есть якоря в документе расставляются некорректно и для отрендеренных в HTML элементов может происходить смещение на величину, составляющую разницу между тем, как собирался показать SSRS наше поле, и как в итоге показал.
  • Быстродействие на сложных отчетах и медленных клиентах
  • XSS

Выводы

Вот так, с помощью нехитрых приспособлений, можно научить SSRS показывать HTML… Но ЗАЧЕМ?!
Сотни постов, от растерянных до гневных, переполняют интернеты из-за такой мелочи.
Даже BIRT это уже давно умеет, а новейшая версия SSRS2012 еще нет (пруфлинк: http://technet.microsoft.com/en-us/library/ff519562.aspx).
Есть мысли, что MS реализовала показ HTML в таком ограниченном виде чтобы не пострадала безопасность/стабильность системы отчетности, но похоже, что все альтернативные решения напоминают пресловутый «троллейбус».

Автор: Cyr

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js