вторник, ноября 24, 2009

Адвансированный экспорт

Заказчик проекта, который мы завершаем, вдруг захотел адвансированную функциональность, чтобы майкрософтовские отчёты, который открываются из ASP.NET приложения, экспортировались не так, как они выглядят на предварительном просмотре, а по-другому. Ломая голову над тем, как же это реализовать, в поле зрения попало несколько вариантов. Один из них - реализовать дополнительный Rendering Extension, про что сам Microsoft говорит, что лучше этого всячески избегать. Вариант был немного частично опробован и исключён из рассмотрения. Варианты с добавлением кнопок на пользовательский интерфейс были отметены сразу же, потому что внешний вид утверждён и дополнительную кнопку поверх Report Viewer лепить нельзя.
Через некоторое время мук творчества был разработан вот такой вариант решения:
1) на базе существующего отчёта, экспорт которого надо изменить, создаётся дополнительный отчёт, внешний вид которого соответвует тому виду, который заказчик хочет при экспорте;

2) на страницу, где расположен ReportViewer, добавляем
<iframe id="reportDownloader" src="../blank.html" width="10" height="10" style="display:none;"></iframe>

3) следующий javascript поможет нам перехватить вызов экспорта на клиенте

function HandleClientSideExportAlt()
{
  var formatDropDown = GetControl(this.m_formatsID);
  if (formatDropDown.selectedIndex == 0) return false;
  var selectedFormat = formatDropDown.value;
  var fullExportUrl = "/AdvancedExport.aspx?exportFormat=" + escape(selectedFormat);
  document.getElementById('reportDownloader').src = fullExportUrl;
  formatDropDown.selectedIndex = 0;
  this.m_exportController.SetViewerLinkActive(false);
  return true;
}

RSToolbar.prototype.HandleClientSideExport = HandleClientSideExportAlt;

4)в коде страничке AdvancedExport.aspx в теле метода Page_Load реализуем экспорт серверного отчёта:

String ExportFormat = String.IsNullOrEmpty(Request["exportFormat"]) ? "EXCEL" : Request["exportFormat"].ToUpper();

String exportFileName = String.Format("Report{0}.{1}",
DateTime.Now.ToString("ddMMyyhhmmss"),
ExportFormat.Contains("EXCEL") ? "xls" : "pdf");

using (ReportViewer rv = new ReportViewer())
{
  ServerReport serverReport = rv.ServerReport;

  serverReport.ReportServerUrl = ...
  serverReport.ReportPath = ... <- имя нового экспортируемого отчёта
  serverReport.SetParameters(...);

  Warning[] warnings;
  string[] streamids;
  string mimeType;
  string encoding;
  string extension;

  byte[] bytes = serverReport.Render(ExportFormat, null, out mimeType, out encoding, out extension, out streamids, out warnings);
  Response.Clear();
  Response.ContentType = mimeType;
  Response.AddHeader("content-length", bytes.Length.ToString());
  Response.AddHeader("Content-Disposition", string.Format("attachment;filename={0}", exportFileName));
  Response.BinaryWrite(bytes);
}

Для примера приведён вариант распознавания экспорта в Excel или PDF, но таким же образом можно реализовать и для других форматов.

Комментариев нет:

Отправить комментарий