ASP.NETでExcelシート(XMLスプレッドシート)を生成する

昔と違ってオートメーションで苦労することは無くなった。
今であればOpenXML APIを使う、LINQ to XMLを使う、XPath+XSLを使う、等、方法としてはいろいろな選択しがあると思うが、一番簡単なのは以下の方法。


1. Excel(2003以降)で実際に使用するワークシートを作る(これを雛形にする)
2. XMLスプレッドシート(Excel 2007ではXMLスプレッドシート 2003)形式で保存する※
3. 保存したXMLスプレッドシートテキストエディタ等で開く
4. ASP.NETのビューページ(Download.aspx)を生成してコンテンツ部分にXMLスプレッドシートを貼り付ける

  • Download.aspxの冒頭

これでOK。ビューをレンダリングすればXMLスプレッドシートのダウンロードが開始される。

  • AddressControler.cs
    public ActionResult Download()
    {
        return View("Download");
    }

ダウンロード時にExcelを起動したいのならビュー側でMIMEを指定すれば良い。(コントローラ側で指定しても何故か上手くいかない。ビューの初期化でヘッダを設定しているのか?)

<%@ Page Language="C#"  ContentType="application/vnd.ms-excel" 〜

また、このXMLスプレッドシートをテンプレートとして、特定の行(Row)やセル(Cell)を置き換えることで、ダイナミックにExcel帳票を作成することもできる。

  • AddressControler.cs
    public ActionResult Download()
    {
        //LINQ to SQLでAddressオブジェクトのリストを作る
        var addresses = service.FindAllAddresses().ToList();
        return View("Download", addresses);
    }
  • Download.aspx
<%@ Page Language="C#"  ContentType="application/vnd.ms-excel" Inherits="System.Web.Mvc.ViewPage<IEnumerable<AddressBook.Models.Address>>" %>
〜
 <Worksheet ss:Name="Sheet1">                            <!-- 行数をモデルの行数+5に設定(5はヘッダ行数) -->
  <Table ss:ExpandedColumnCount="6" ss:ExpandedRowCount="<%= Model.Count()+5 %>" x:FullColumns="1"
〜
 <!-- 行データをモデルオブジェクトのリストで置き換える --> 
 <% foreach (var item in Model) { %>
   <Row ss:AutoFitHeight="0">
    <Cell><Data ss:Type="String"><%=item.Name.TrimEnd()%></Data></Cell>
    <Cell><Data ss:Type="String"><%=item.Address.TrimEnd()%></Data></Cell>
    <Cell><Data ss:Type="String"><%=item.Email.TrimEnd()%></Data></Cell>
    <Cell><Data ss:Type="String"><%=item.Gender.TrimEnd()%></Data></Cell>
    <Cell><Data ss:Type="String"><%=item.Married.TrimEnd()%></Data></Cell>
    <Cell><Data ss:Type="String"><%=item.UpdDate.ToString("s").TrimEnd()%></Data></Cell>
   </Row>
 <% } %>

ASP.NET MVCジェネリクスによって強く型付けされたViewPageクラスは、上のようにモデルのプロパティを直接扱えるので便利だ。

※OpenXMLがISO標準に認定されたこともあり、XMLスプレッドシート2003の今後には不安が残るのがこの方法の弱点だ。その場合は大人しくOpenXMLを使うべきなんだろうが、JSP同様、コンテンツをビューの雛形として使うのは楽ちんなんだよなぁ。(OpenXMLはパッケージを開けてみないと分らないしコピペもできない)