ReportViewer預設的匯出格式只有PDF、Word跟Excel三種,如果還想再增加匯出TIFF檔的選項,該怎麼做?

由於ReportViewer未提供匯出檔案格式的設定選項,網路上可找到一些替代做法:

  1. 設定ShowExportControls=false,隱藏工具列上的匯出鈕,在網頁加入自訂匯出鈕,於Server-Side OnClick事件以Render() API自行產生匯出檔並傳回。(參考: 皮尼網這走- Cliend-Side Report 匯出 Excel, PDF)
  2. 透過Javascript事後修改頁面的匯出格式下拉選單(參考: 如何改變 ReportViewer 的預設匯出格式為指定格式:PDF(一點通系列 - MVP 撰寫))

兩種做法多少都得費點小工。事實上Reserved.ReportViewerWebControl.axd本就支援TIFF檔,只差在預設匯出格式下拉選單未提供連結而已,理論上只需仿照原有選項再多加一個TIFF項目即可,但經初步評估,ReportViewer 2005/2008的匯出格式選單是單純<select>,ReportViewer 2010/2012則改成較華麗的Microsoft AJAX Menu,要新增選項頗花手腳。駭客熱血再起,就追進ReportViewer原始碼,發現一個有趣的方法: LocalReport.ListRenderingExtensions 方法 (Microsoft.Reporting.WebForms),而ReportViewer就是依這個清單決定支援哪些匯出格式,用一小段程式來檢視RDLC LocalReport支援的匯出選項:

    foreach (var opt in ReportViewer1.LocalReport.ListRenderingExtensions())
    {
        Response.Write(string.Format("<li>{0}-{1}-{2}</li>",
            opt.Name, opt.LocalizedName, opt.Visible));
    }
    Response.End();

結果如下:

  • Excel-Excel 2003-False
  • EXCELOPENXML-Excel-True
  • IMAGE-TIFF 檔案-False
  • PDF-PDF-True
  • WORD-Word 2003-False
  • WORDOPENXML-Word-True

有趣吧? 原來RDLC還有三種額外格式: Excel 2003、TIFF以及Word 2003,只是選項的Visible屬性被設為False而被隱藏。換句話說,只要把該屬性改成True,不費吹灰之力,選項就會在選單中出現囉~

唯一的小挑戰--Visible是唯讀屬性,無法直接修改,但這可難不倒程式魔人: 二話不說,我在檯面上覆蓋一張Reflection牌,結束這回合...

using System;
using System.Linq;
using System.Reflection;
using Microsoft.Reporting.WebForms;
 
public partial class Report : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            using (var ctx = new MarathonEntities())
            {
                var data = ctx.RaceRecords.OrderBy(o => o.Rank).ToList();
                ReportViewer1.LocalReport.DataSources.Add(
                    new ReportDataSource("RaceDataSet", data));
                TurnOnImageExportOption(ReportViewer1.LocalReport);
            }
        }
    }
    protected void TurnOnImageExportOption(LocalReport report)
    {
        RenderingExtension imageOption = report.ListRenderingExtensions()
            .SingleOrDefault(o => o.Name == "IMAGE");
        if (imageOption != null)
        {
            //Set IsVisible property to true via Reflection
            FieldInfo fiVisible = imageOption.GetType().GetField("m_isVisible",
                BindingFlags.NonPublic | BindingFlags.Instance);
            fiVisible.SetValue(imageOption, true);
        }
    }
}

薑!薑!薑!薑~ 只用不到五行程式碼,TIFF檔選項就出現了!

PS: 類似做法也可以用來隱藏選項、調整選項順序,很酷吧! 不過這種Hacking解法涉及元件未公開的API,可能會在元件改版後失效,跟手機JB的概念差不多,不在官方支援之列,特此說明。


Comments

# by Boris

請問如果要在ReportViewer匯出excel指定檔名待如何做呢?

# by Boris

找到解決的方法了,謝謝!

Post a comment