Open XML オブジェクト モデルを使用してサーバー側ドキュメント生成ソリューションを構築する (パート 2/2)

要約 : 2 つのパートから成るシリーズの後半であるこのパートでは、引き続き、サーバー側ドキュメント統合ソリューションのアーキテクチャについて説明します。新しい Open XML オブジェクト モデルを使用して、ドキュメント パッケージを作成し、ドキュメント パーツを操作することの利点を示します。(16 印刷ページ)

Erika Ehrli、Microsoft Corporation

2007 年 8 月

適用対象 : 2007 Microsoft Office スイート、Microsoft Office Word 2007、Microsoft ASP.NET 2.0、Microsoft Visual Studio 2005、Microsoft SQL Server 2005

目次

  • 概要

  • ビジネスでのシナリオ : サーバー側の売り上げレポート概要ドキュメントを生成する

  • サーバー側ドキュメント生成ソリューションを構築する

  • まとめ

  • 追加情報

関連するサンプルを「2007 Office Sample: Building a Server-Side Document Generation Solution Using the Open XML Object Model (英語)」からダウンロードしてください。

パート 1 の「Open XML オブジェクト モデルを使用してサーバー側ドキュメント生成ソリューションを構築する (パート 1/2)」を参照してください。

概要

このシリーズの最初の記事「Open XML オブジェクト モデルを使用してサーバー側ドキュメント生成ソリューションを構築する (パート 1/2)」では、Microsoft .NET Framework に基づき、Open XML 形式および Open XML オブジェクト モデルを使用して Microsoft Office ドキュメントを作成する、サーバー側ソリューションを設計および構築する方法について説明しています。Open XML 形式のアーキテクチャ、および Open XML オブジェクト モデルを使用したドキュメント パッケージの作成、ドキュメント パーツの操作、WordprocessingML コードの記述についても説明しています。また、サーバー側ドキュメント統合ソリューションのアーキテクチャについても解説しています。

この「Open XML オブジェクト モデルを使用してサーバー側ドキュメント生成ソリューションを構築する (パート 2/2)」では、ビジネスでのシナリオを示し、Microsoft ASP.NET 2.0 アプリケーションを使用して Microsoft Office Word 2007 で売り上げレポートを作成する方法について解説します。

ダウンロード「2007 Office Sample: Building a Server-Side Document Generation Solution Using the Open XML Object Model (英語)」では、Open XML オブジェクト モデルを使用してサーバー側アプリケーションからドキュメントを作成する Microsoft Visual Basic 2005 と Microsoft Visual C# のサンプル ファイルを提供します。

ビジネスでのシナリオ : サーバー側の売り上げレポート概要ドキュメントを生成する

Adventure Works Cycles は、AdventureWorks サンプル データベースで使用されている架空の大手多国籍製造企業です。この企業は、北米、ヨーロッパ、およびアジアのマーケットを対象に、金属製自転車や複合材製自転車の製造および販売を行っています。米国ワシントン州ボセルに従業員 290 人の本拠地を置き、世界中に複数の地域販売拠点を配置しています。売り上げ関連情報は、Adventure Works のビジネスの重要な部分です。

今年度の業績が好調であったため、Adventure Works Cycles では実績に応じて販売担当者に手当を支給しようとしています。経営陣は各販売担当者の実績の概要を必要としており、各販売担当者の連絡先情報、年間総売り上げ高、および地域ごとの各販売担当者の実績の詳細が含まれたドキュメントの作成を経営陣から依頼されました。経営陣は、各個人の実績を他の担当者の実績と比較したいと考えています。

売り上げレポート概要のテンプレートを設計する

ドキュメント統合ソリューションを設計するときには、サンプル ドキュメント テンプレートが役立ちます。テンプレートによって、作成する必要があるレポートのコンテンツとレイアウトを視覚化することができます。

Adventure Works の売り上げレポートでは、ドキュメント生成ソリューションによって、以下のコンテンツおよび情報を提供するドキュメントを作成します。

  • 企業のロゴ

  • タイトル : 売り上げレポート - 従業員の名前

  • 連絡先情報

  • 売り上げ概要

  • 地域ごとの売り上げ : 地域ごとのすべての販売担当者の概要情報を含む表

一般的なプロジェクトでは、この手順は省略できます。図 1 にドキュメント テンプレートを示します。

図 1. 売り上げレポート概要ドキュメント テンプレート

"営業レポートの概要" ドキュメント テンプレート

テンプレートを設計することによって、ドキュメント パッケージの構造、作成するドキュメント パーツ、および同じドキュメントをプログラムによって再生成するために作成する WordprocessingML マークアップについての理解も深まります。

テンプレートを作成した後、標準的な ZIP ユーティリティまたはパッケージ エクスプローラ ツール (Open XML Package Explorer (英語)XMLSpy (英語) など) を使用して、ドキュメント パッケージ内に格納されているファイルの構造や必要なマークアップを確認できます。

サーバー側ドキュメント生成ソリューションを構築する

Adventure Works Cycles の経営陣は、イントラネット上で使用して売り上げ情報を表示できる ASP.NET 2.0 アプリケーションの作成を依頼しています。図 2 に示されているように、Web ページで従業員を選択し、販売担当者の実績情報を含むレポートを Microsoft Office Word 2007 にエクスポートできることが求められています。

図 2. Adventure Works Cycles 経営陣向け ASP.NET 2.0 Web アプリケーション

Adventure Works Cycles 管理の ASP.NET 2.0 Web

Adventure Works の基幹業務 (LOB) データに接続できる ASP.NET 2.0 Web サイトの作成方法と、Word 2007 レポートの作成およびエクスポートの方法を示すために、ここでは以下の 3 つの重要な手順について説明します。

  1. フロントエンド Web サーバーを構築します。

    • Microsoft Visual Studio 2005 で ASP.NET 2.0 Web サイト プロジェクトを作成します。

    • ユーザーが従業員を選択し、概要レポートを Word 2007 にエクスポートできるようにするサイトの Web フォームを作成します。

  2. AdventureWorks データベース サーバーに接続して売り上げ情報を取得するカスタム データ ヘルパー クラスを追加します。

  3. Open XML オブジェクト モデルおよび WordprocessingML を使用することによって、Word 2007 売り上げ概要レポート作成機能を生成するカスタムレポート生成ヘルパー クラスを追加します。

フロントエンド Web サーバーを構築する

ASP.NET 2.0 または Microsoft SharePoint 製品とテクノロジを使用することによって、アプリケーションのフロントエンド Web サーバーを構築できます。この場合、ASP.NET 2.0 と Visual Studio 2005 を使用して、Adventure Works Cycles 用のレポート生成ソリューションを作成します。

ASP.NET 2.0 Web サイト プロジェクトを作成するには

  1. Visual Studio 2005 を起動します。

  2. [ファイル] メニューの [新規作成] をポイントし、[Web サイト] をクリックします。

  3. [新しい Web サイト] ダイアログ ボックスで、[ASP.NET Web サイト] テンプレートをクリックします。

  4. [場所] ボックスの一覧の [HTTP] または [ファイル システム] をクリックします。

  5. Web サイトのパスまたは URL を指定するか、既定値をそのまま使用します。

  6. [言語] ボックスの一覧の [Visual C#] をクリックし、[OK] をクリックします。

Default.aspx という名前の Web フォームと Default.aspx.cs (または Visual Basic 2005 を使用している場合は Default.aspx.vb) という名前のコード ファイルを含む ASP.NET Web サイト プロジェクトが生成されます。

前提条件

このサンプル アプリケーションの目的は、Open XML 形式を使用して Word ドキュメントを生成する方法を示すことです。このアプリケーションを構築するには、以下のものが必要です。

  • Microsoft .NET Framework 3.0。System.IO.Packaging 名前空間を使用する必要があります。.NET Framework Developer Center から .NET Framework 3.0 をダウンロードしてインストールできます。

  • Open XML オブジェクト モデル API。Microsoft Office Developer Center から Microsoft SDK for Open XML Formats Technology Preview をダウンロードしてインストールできます。

Open XML オブジェクト モデルおよび System.IO.Packaging 名前空間 名前空間を操作するには、タイプ ライブラリへの参照を追加します。

プロジェクトに参照を追加するには

  1. ソリューション エクスプローラで、[参照] フォルダを展開します。

    注意

    [参照設定] フォルダが表示されない場合は、[プロジェクト] ノードで [すべてのファイルを表示] をクリックします。

  2. [参照] フォルダを右クリックし、[参照の追加] をクリックします。

  3. [参照] タブをクリックし、WindowsBase.dll がある場所に移動してこのファイルを選択します。

    注意

    この記事の公開時点では、このファイルは local_drive:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0 にあります。

  4. WindowsBase.dll ファイルをクリックし、[OK] をクリックします。

  5. [参照] フォルダを右クリックし、[参照の追加] をクリックします。

  6. [参照] タブをクリックし、Microsoft.Office.DocumentFormat.OpenXml.dll がある場所に移動してこのファイルをクリックし、[OK] をクリックします。

    注意

    Microsoft SDK for Open XML Formats Technology Preview をインストールしている場合、このファイルは、通常、local_drive:\Program Files\2007 Office System Developer Resources\OpenXMLSDK\1.0.0531\lib にあります。

参照を追加すると、Web.config ファイルに以下のマークアップが追加されます。

注意

このコード例には、オンライン表示を見やすくするために改行が含まれています。コードを実行する前に、改行を削除する必要があります。

<compilation debug="true">
   <assemblies>
     <add assembly="Microsoft.Office.DocumentFormat.OpenXml, Version=1.0.531.0,
Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
     <add assembly="WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
   </assemblies>
</compilation>

注意

Microsoft Office ドキュメントを生成するために、サーバーに 2007 Microsoft Office system をインストールする必要はありません。Open XML 形式によって、オートメーションを使用せずにドキュメントを生成および操作できます。

Web フォームを作成する

最後に、図 1 のような Web フォームを作成します。この Web フォームでは、DropDownList コントロールを使用してすべての従業員名を表示します。また、ユーザーが従業員ごとの売り上げ概要レポートを Word 2007 にエクスポートするための Button コントロールも含まれています。

注意

この記事では、Microsoft Visual C# のサンプル コードを示します。この記事と共にダウンロードされたサンプル コードには、Visual C# と Microsoft Visual Basic 2005 の両方のサンプル コードが含まれています。

Web フォームを作成するには

  • default.aspx のコードを、以下のサンプル コードに置き換えます。

    <%@ Page Language="C#" %>
    <%@ Import Namespace="System.Data" %>
    <%@ Import Namespace="System.Data.SqlClient" %>
    <script runat="server">
        protected void btnExportToWord_Click(object sender, EventArgs e) {
            SalesReportBuilder report = new SalesReportBuilder(ddlEmployee.SelectedItem.Value);
            lblResult.Text = "Report saved at: " + report.CreateDocument();
        }
    </script>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">
        <title>Word 2007 Sales Report Generator</title>
    </head>
    <body>
        <form id="form1" runat="server">
            <div>
                <img src="Resources/headerImage.gif" style="width: 264px; height: 107px" alt="Adventure Works"/>
                <h1>
                    <span style="font-family: Verdana">Sales Report Generator</span>
                </h1>
                <hr />
                <h3>
                   <span style="font-family: Verdana; color:Maroon;">Create sales report for employee:</span>
                </h3>
                <table border="0" style="font-family: Verdana">
                    <tr>
                        <td>
                            <asp:DropDownList
                            ID="ddlEmployee"
                            runat="server"
                            DataSourceID="EmployeeDataSource"
                            AutoPostBack="True"
                            DataTextField="FullName"
                            DataValueField="SalesPersonID"
                            Width="200px">
                            </asp:DropDownList>
                            <asp:SqlDataSource
                            ID="EmployeeDataSource"
                            runat="server"
                            ConnectionString="<%$ ConnectionStrings:AWConnString %>"
                            SelectCommand="SELECT [SalesPersonID],[FirstName]
                            + ' ' + [LastName] AS [FullName] FROM [Sales].[vSalesPerson]">
                            </asp:SqlDataSource>
                        </td>
                        <td valign="top">
                            <asp:Button
                            ID="btnExportToWord"
                            runat="server"
                            Text="Export to Word 2007"
                            OnClick="btnExportToWord_Click" />
                        </td>
                    </tr>
                </table>
    
                <br />
                <h3>
                   <span style="font-family: Verdana; color:Blue;">
                      <asp:Label
                      ID="lblResult"
                      runat="server" />
                   </span>
                </h3>
            </div>
        </form>
    </body>
    </html>
    

カスタム データ ヘルパー クラスを構築する

LOB システムおよびデータは、アプリケーションのデータ レイヤー ロジックをカプセル化します。カスタム データ ヘルパー クラスを作成し、さまざまな LOB システムからデータを取得するプロセスをカプセル化できます。

LOB データに接続する

Adventure Works Cycles では、LOB データを AdventureWorks データベースに格納しています。AdventureWorks サンプル データベースは、「SQL Server 2005 Samples and Sample Databases (February 2007) (英語)」からダウンロードしてインストールできます。

次に、ASP.NET Web サイトを AdventureWorks データベースに接続します。

ASP.NET 2.0 Web サイトを AdventureWorks データベースに接続するには

  1. web.config ファイルを開きます。

  2. 以下のように web.config ファイルに接続文字列を追加します。

    注意

    このコード例には、オンライン表示を見やすくするために改行が含まれています。コードを実行する前に、改行を削除する必要があります。

    <connectionStrings>
       <add name="AWConnString" connectionString="Data Source=(local);
    Initial Catalog=AdventureWorks;Integrated Security=True" providerName=
    "System.Data.SqlClient"/>
    </connectionStrings>
    

カスタム データ ヘルパー クラスを構築する

AdventureWorks データベースから売り上げ情報を取得するデータ ヘルパー クラスを作成します。このクラスは 2 つの public メソッドを提供します。

  • GetSalesPersonData.。FullName、Phone、Email、SalesQuota、SalesYTD、および TerritoryName などの従業員のデータを取得します。このデータを使用して、生成されるドキュメントで従業員に関する情報を設定します。

  • GetSalesByTerritory.。各従業員の販売地域に所属するすべての従業員の 2003 年と 2004 年のすべての売り上げを示す表を設定します。これによって、売り上げデータと実績を比較することができます。このデータを使用して、生成されるドキュメントの販売地域ごとの表を設定します。

データ ヘルパー クラスを作成するには

  1. ソリューション エクスプローラで、[プロジェクト] フォルダを右クリックし、[新しい項目の追加] をクリックします。

  2. [新しい項目の追加] ダイアログ ボックスで、[クラス ファイル] をクリックします。

  3. AdventureWorksSalesData.cs というファイル名を指定して、[追加] をクリックします。

  4. [Microsoft Visual Studio] メッセージ ボックスで、[はい] をクリックしてクラス ファイルをプロジェクトの [App_Code] フォルダに追加します。

  5. AdventureWorksSalesData.cs のコードを、以下のサンプル コードに置き換えます。

    using System;
    using System.Data;
    using System.Data.SqlClient;
    using System.Collections.Specialized;
    using System.Configuration;
    
  6. 以下のクラス、フィールド、およびコンストラクタを追加します。

    /// <summary>
    /// Represents the AdventureWorks line of business sales data.
    /// </summary>
    public class AdventureWorksSalesData {
        private string _source;
    
        public AdventureWorksSalesData() {
            _source = ConfigurationManager.ConnectionStrings["AWConnString"].ConnectionString;
        }
    
  7. GetSalesPersonData メソッドを作成します。

        /// <summary>
        /// Get employee's data: FullName, Phone, Email,
        /// SalesQuota, SalesYTD, TerritoryName.
        /// </summary>
        /// <param name="salesPersonID">Data for employee with SalesPersonID</param>
        /// <returns>StringDictionary</returns>
        public StringDictionary GetSalesPersonData(string salesPersonID) {
            StringDictionary SalesPerson = new StringDictionary();
    
            //Connect to a Microsoft SQL Server database and get data
            const string query =
               "SELECT [FirstName] + ' ' + [LastName] AS [FullName],[Phone],
               [EmailAddress], [TerritoryName], [SalesQuota], [SalesYTD] FROM [AdventureWorks]
               .[Sales].[vSalesPerson] WHERE ([SalesPersonID] = @SalesPersonID)";
    
            using (SqlConnection conn = new SqlConnection(_source)) {
                conn.Open();
                SqlCommand cmd = new SqlCommand(query, conn);
                cmd.Parameters.AddWithValue("@SalesPersonID", salesPersonID);
                SqlDataReader dr = cmd.ExecuteReader();
    
                if (dr.Read()) {
    
                    SalesPerson.Add("FullName", (string)dr["FullName"]);
                    SalesPerson.Add("Phone", (string)dr["Phone"]);
                    SalesPerson.Add("Email", (string)dr["EmailAddress"]);
                    if (dr["SalesQuota"] is System.DBNull) {
                        SalesPerson.Add("SalesQuota", "0");
                    }
                    else {
                        SalesPerson.Add("SalesQuota", Convert.ToString((decimal)dr["SalesQuota"]));
                    }
                    if (dr["SalesYTD"] is System.DBNull) {
                        SalesPerson.Add("SalesYTD", "0");
                    }
                    else {
                        SalesPerson.Add("SalesYTD", Convert.ToString((decimal)dr["SalesYTD"]));
                    }
                    if (dr["TerritoryName"] is System.DBNull) {
                        SalesPerson.Add("TerritoryName", "NA");
                    }
                    else {
                        SalesPerson.Add("TerritoryName", (string)dr["TerritoryName"]);
                    }
                }
    
                dr.Close();
                conn.Close();
            }
    
            return SalesPerson;
        }
    
  8. GetSalesByTerritory メソッドを作成します。

        /// <summary>
        /// Get a table that shows all sales for 2003 and 2004 
        /// for all employees that belong to employee's
        /// sales territory so you can compare sales data
        /// and performance.
        /// </summary>
        /// <param name="Territory">Get all sales/employee for territory</param>
        /// <returns>Table with 2003 and 2004 sales/employee</returns>
        public DataTable GetSalesByTerritory(string Territory) {
            //Connect to a Microsoft SQL Server database and get data
            String source = ConfigurationManager.ConnectionStrings["AWConnString"].
            ConnectionString;
            string query = "SELECT [FullName], [2003], [2004] FROM [AdventureWorks].
            [Sales].[vSalesPersonSalesByFiscalYears] WHERE ([SalesTerritory] =
             '" + Territory + "')";
    
            using (SqlConnection conn = new SqlConnection(_source)) {
                conn.Open();
                SqlDataAdapter da = new SqlDataAdapter(query, conn);
                DataSet ds = new DataSet();
                da.Fill(ds, "SalesByTerritory");
                conn.Close();
    
                return ds.Tables["SalesByTerritory"];
            }
        }
    
  9. クラスを閉じます。

売り上げレポート概要ドキュメントを生成するカスタム データ ヘルパー クラスを構築する

LOB ソフトウェアおよびコンポーネントは、アプリケーションのビジネス ロジック層をカプセル化します。カスタム レポート生成ヘルパー クラスを作成して、ドキュメント統合のプロセスをカプセル化できます。これらのクラスでは、Open XML オブジェクト モデルを使用して、ドキュメント パッケージを生成し、LOB データとビジネス要件に基づいてドキュメント コンテンツを出力します。

レポート生成ヘルパー クラスの構造

ここでは、AdventureWorksSalesData クラスから売り上げ情報を取得して、図 2 のようなレポートを作成するレポート生成ヘルパー クラスを作成します。このヘルパー クラスによって、document.xml パーツで共通の書式設定、スタイル、および書き込みメソッドのコードをグループ化することができます。

この部分は、サーバー側ドキュメント生成ソリューションの中核となる部分です。Open XML オブジェクト モデルを使用して、ドキュメント パッケージとドキュメント パーツを作成します。WordprocessingML マークアップを使用して、ドキュメントのコンテンツを定義します。

注意

このシリーズのパート 1 の「Open XML オブジェクト モデルを使用してサーバー側ドキュメント生成ソリューションを構築する (パート 1/2)」では、このレポートを構築するために使用する Open XML パッケージ アーキテクチャおよび WordprocessingML の基本概念について説明しています。

図 1 は、レポート生成クラスで定義するタスクを示しています。この手順について、以下に詳しく説明します。

  1. ドキュメント パッケージを作成します。

    • パッケージを Word 2007 ドキュメントとして作成します。

    • メイン ドキュメント パーツ document.xml を挿入します。

  2. スタイル パーツを挿入し、ドキュメント パッケージに追加します。

  3. イメージ パーツを挿入し、ドキュメント パッケージに追加します。

  4. WordprocessignML マークアップを使用して document.xml のコンテンツを作成します。

    • 段落内にイメージを挿入します。

    • 段落内にタイトルを入力します。

    • 段落内に従業員の連絡先情報を入力します。

    • 段落内に売り上げ概要情報を入力します。

    • 地域別の総売り上げを表形式で入力します。

リソース ファイル

この記事では、Open XML オブジェクト モデルを使用してドキュメントでスタイルやイメージを使用する方法を示します。レポート生成ヘルパー クラスの実装を開始する前に、イメージやスタイルを操作するためのリソース ファイルを追加する必要があります。

ヘッダー イメージ リソース ファイル

Adventure Works Cycles 内のすべてのドキュメントには、図 3 に示されているように、ドキュメントのヘッダーに会社のロゴが入っている必要があります。

図 3. Adventure Works Cycle のロゴ

Adventure Works Cycle 社のロゴ

Open XML オブジェクト モデルを使用して、イメージ パーツをドキュメント パッケージに追加します。ヘッダー イメージを挿入するには、以下のリソースが必要です。

  • イメージ ファイル

  • DrawingML テンプレート ファイル

WordprocessingML マークアップを挿入して、画像をドキュメント コンテンツの一部として表示する方法の詳細については、「Open XML オブジェクト モデルを使用したサーバー側ドキュメント生成ソリューションの構築 (パート 1/2)」の「イメージ パーツと画像」を参照してください。ドキュメントに画像を埋め込むには、<w:drawing> 要素を使用します。すべての DrawingML マークアップを作成する代わりに、このサンプル ソリューションでは、すべての <w:drawing> マークアップを書き込む drawingTemplate.xml を使用します。

プロジェクトにイメージ リソースを追加するには

  1. ソリューション エクスプローラを右クリックし、[新しいフォルダ] をクリックします。

  2. 新しいフォルダに Resources という名前を付けます。

  3. この記事の図 3 を右クリックし、イメージをハード ディスクに保存します。

  4. イメージのファイル名を headerImage.gif に変更します。

  5. ソリューション エクスプローラで、[Resources] フォルダを右クリックし、[既存の項目の追加] をクリックして headerImage.gif イメージを追加します。

  6. ソリューション エクスプローラで、[Resources] フォルダを右クリックし、[新しい項目の追加] をクリックします。

  7. [新しい項目の追加] ダイアログ ボックスで、[XML ファイル] をクリックします。

  8. ファイルに drawingTemplate.xml という名前を付けて、[追加] をクリックします。

  9. drawingTemplate.xml のマークアップを以下のサンプル マークアップに置き換えます。

    注意

    以下のコード例には、オンラインで表示したときに見やすくするための改行が追加されています。実際にコードで使用する前に改行を削除する必要があります。

    <!-- report generator helper class code will replace the {0} with the reference id of the image -->
    <container xmlns:w="http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html"
    xmlns:wp="http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html" 
    xmlns:r="http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html">
      <w:drawing>
        <wp:inline>
          <wp:extent cx="1628936" cy="733586" />
          <wp:docPr name="image.gif" id="1" />
          <a:graphic xmlns:a="http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html">
            <a:graphicData uri="http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html">
              <pic:pic xmlns:pic="http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html">
                <pic:nvPicPr>
                  <pic:cNvPr id="0" name="image.gif" />
                  <pic:cNvPicPr />
                </pic:nvPicPr>
                <pic:blipFill>
                  <a:blip r:embed="{0}" />
                  <a:stretch>
                    <a:fillRect />
                  </a:stretch>
                </pic:blipFill>
                <pic:spPr>
                  <a:xfrm>
                    <a:off x="0" y="0" />
                    <a:ext cx="1630190" cy="734151" />
                  </a:xfrm>
                  <a:prstGeom prst="rect" />
                </pic:spPr>
              </pic:pic>
            </a:graphicData>
          </a:graphic>
        </wp:inline>
      </w:drawing>
    </container>
    

このレポート生成ヘルパー クラスは、Open XML オブジェクト モデルを使用して、次の処理を行います。

  • イメージ パーツを作成し、ドキュメントに追加します。

  • イメージの参照 ID を取得します。

  • drawingTemplate.xml ファイルの {0} をイメージの参照 ID に置き換えます。

  • DrawingML マークアップをメイン ドキュメント パーツの WordprocessingML マークアップに挿入します。

スタイル リソース ファイル

Open XML オブジェクト モデルを使用して、スタイル パーツをドキュメント パッケージに挿入します。WordprocessingML マークアップを使用して、段落、テキスト、範囲、表のスタイルおよび書式設定を定義します。

スタイル パーツを挿入するには、styles.xml ファイルを編集する必要があります。WordprocessingML マークアップを作成して、スタイルを定義する方法の詳細については、「Open XML オブジェクト モデルを使用したサーバー側ドキュメント生成ソリューションの構築 (パート 1/2)」の「イメージ パーツ、スタイル、および書式設定」を参照してください。styles.xml ファイルを使用して、ドキュメント コンテンツに適用できる書式設定プロパティの特定の値のセットを定義します。すべてのマークアップを手動で作成する代わりに、このサンプル ソリューションでは、styles.xml テンプレートを使用します。

styles.xml リソース ファイルをプロジェクトに追加するには

  1. ソリューション エクスプローラで、[Resources] フォルダを右クリックし、[新しい項目の追加] をクリックします。

  2. [新しい項目の追加] ダイアログ ボックスで、[XML ファイル] をクリックします。

  3. ファイルに styles.xml という名前を付けて、[追加] をクリックします。

  4. styles.xml のマークアップを以下のサンプル マークアップに置き換えます。

    注意

    以下のコード例には、オンラインで表示したときに見やすくするための改行が追加されています。実際にコードで使用する前に改行を削除する必要があります。

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <w:styles xmlns:r="http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html" 
    xmlns:w="http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html">
      <w:docDefaults>
        <w:rPrDefault>
          <w:rPr>
            <w:rFonts w:asciiTheme="minorHAnsi" w:eastAsiaTheme="minorEastAsia" w:hAnsiTheme="minorHAnsi" w:cstheme="minorBidi"/>
            <w:sz w:val="22"/>
            <w:szCs w:val="22"/>
            <w:lang w:val="en-US" w:eastAsia="en-US" w:bidi="ar-SA"/>
          </w:rPr>
        </w:rPrDefault>
        <w:pPrDefault>
          <w:pPr>
            <w:spacing w:after="200" w:line="276" w:lineRule="auto"/>
          </w:pPr>
        </w:pPrDefault>
      </w:docDefaults>
      <w:latentStyles w:defLockedState="0" w:defUIPriority="99" w:defSemiHidden="1"
     w:defUnhideWhenUsed="1" w:defQFormat="0" w:count="267">
        <w:lsdException w:name="Normal" w:semiHidden="0" w:uiPriority="0" w:unhideWhenUsed="0" w:qFormat="1"/>
        <w:lsdException w:name="heading 1" w:semiHidden="0" w:uiPriority="9" w:unhideWhenUsed="0" w:qFormat="1"/>
        <w:lsdException w:name="Title" w:semiHidden="0" w:uiPriority="10" w:unhideWhenUsed="0" w:qFormat="1"/>
        <w:lsdException w:name="Default Paragraph Font" w:uiPriority="1"/>
        <w:lsdException w:name="Subtitle" w:semiHidden="0" w:uiPriority="11" w:unhideWhenUsed="0" w:qFormat="1"/>
        <w:lsdException w:name="Strong" w:semiHidden="0" w:uiPriority="22" w:unhideWhenUsed="0" w:qFormat="1"/>
        <w:lsdException w:name="Table Grid" w:semiHidden="0" w:uiPriority="59" w:unhideWhenUsed="0"/>
        <w:lsdException w:name="Light List Accent 2" w:semiHidden="0" w:uiPriority="61" w:unhideWhenUsed="0"/>
      </w:latentStyles>
      <w:style w:type="paragraph" w:default="1" w:styleId="Normal">
        <w:name w:val="Normal"/>
        <w:qFormat/>
      </w:style>
      <w:style w:type="character" w:default="1" w:styleId="DefaultParagraphFont">
        <w:name w:val="Default Paragraph Font"/>
        <w:uiPriority w:val="1"/>
        <w:semiHidden/>
        <w:unhideWhenUsed/>
      </w:style>
      <w:style w:type="table" w:default="1" w:styleId="TableNormal">
        <w:name w:val="Normal Table"/>
        <w:uiPriority w:val="99"/>
        <w:semiHidden/>
        <w:unhideWhenUsed/>
        <w:qFormat/>
        <w:tblPr>
          <w:tblInd w:w="0" w:type="dxa"/>
          <w:tblCellMar>
            <w:top w:w="0" w:type="dxa"/>
            <w:left w:w="108" w:type="dxa"/>
            <w:bottom w:w="0" w:type="dxa"/>
            <w:right w:w="108" w:type="dxa"/>
          </w:tblCellMar>
        </w:tblPr>
      </w:style>
      <w:style w:type="table" w:styleId="LightList-Accent2">
        <w:name w:val="Light List Accent 2"/>
        <w:basedOn w:val="TableNormal"/>
        <w:uiPriority w:val="61"/>
        <w:rsid w:val="00693473"/>
        <w:pPr>
          <w:spacing w:after="0" w:line="240" w:lineRule="auto"/>
        </w:pPr>
        <w:tblPr>
          <w:tblStyleRowBandSize w:val="1"/>
          <w:tblStyleColBandSize w:val="1"/>
          <w:tblInd w:w="0" w:type="dxa"/>
          <w:tblBorders>
            <w:top w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
            <w:left w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
            <w:bottom w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
            <w:right w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
          </w:tblBorders>
          <w:tblCellMar>
            <w:top w:w="0" w:type="dxa"/>
            <w:left w:w="108" w:type="dxa"/>
            <w:bottom w:w="0" w:type="dxa"/>
            <w:right w:w="108" w:type="dxa"/>
          </w:tblCellMar>
        </w:tblPr>
        <w:tblStylePr w:type="firstRow">
          <w:pPr>
            <w:spacing w:before="0" w:after="0" w:line="240" w:lineRule="auto"/>
          </w:pPr>
          <w:rPr>
            <w:b/>
            <w:bCs/>
            <w:color w:val="FFFFFF" w:themeColor="background1"/>
          </w:rPr>
          <w:tblPr/>
          <w:tcPr>
            <w:shd w:val="clear" w:color="auto" w:fill="C0504D" w:themeFill="accent2"/>
          </w:tcPr>
        </w:tblStylePr>
        <w:tblStylePr w:type="lastRow">
          <w:pPr>
            <w:spacing w:before="0" w:after="0" w:line="240" w:lineRule="auto"/>
          </w:pPr>
          <w:rPr>
            <w:b/>
            <w:bCs/>
          </w:rPr>
          <w:tblPr/>
          <w:tcPr>
            <w:tcBorders>
              <w:top w:val="double" w:sz="6" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
              <w:left w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
              <w:bottom w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
              <w:right w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
            </w:tcBorders>
          </w:tcPr>
        </w:tblStylePr>
        <w:tblStylePr w:type="firstCol">
          <w:rPr>
            <w:b/>
            <w:bCs/>
          </w:rPr>
        </w:tblStylePr>
        <w:tblStylePr w:type="lastCol">
          <w:rPr>
            <w:b/>
            <w:bCs/>
          </w:rPr>
        </w:tblStylePr>
        <w:tblStylePr w:type="band1Vert">
          <w:tblPr/>
          <w:tcPr>
            <w:tcBorders>
              <w:top w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
              <w:left w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
              <w:bottom w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
              <w:right w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
            </w:tcBorders>
          </w:tcPr>
        </w:tblStylePr>
        <w:tblStylePr w:type="band1Horz">
          <w:tblPr/>
          <w:tcPr>
            <w:tcBorders>
              <w:top w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
              <w:left w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
              <w:bottom w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
              <w:right w:val="single" w:sz="8" w:space="0" w:color="C0504D" w:themeColor="accent2"/>
            </w:tcBorders>
          </w:tcPr>
        </w:tblStylePr>
      </w:style>
    </w:styles>
    

このレポート生成ヘルパー クラスでは、Open XML オブジェクト モデルを使用して、スタイル パーツを作成し、ドキュメントに追加します。表、段落、および範囲などの一部の WordprocessingML 要素では、前述の styles.xml ドキュメント パーツで定義されたスタイルを使用します。

カスタム レポート生成ヘルパー クラスを構築する

次に、経営陣から求められた売り上げ概要レポートを作成するすべてのビジネス ロジックを含むレポート生成ヘルパー クラスを作成します。

このレポート生成ヘルパー クラスは、ソリューション内の [Reports] フォルダにレポートを保存します。これによって、安全なダウンロード ハイパーリンクをドキュメントに提供することができます。

[Reports] フォルダを作成するには

  1. ソリューション エクスプローラを右クリックし、[新しいフォルダ] をクリックします。

  2. 新しいフォルダに Reports という名前を付けます。

ドキュメント コンテンツを生成するには、System.Xml.XmlWriter を使用して WordprocessingML マークアップを作成します。作成する必要があるマークアップ コードの量は、作成するドキュメント コンテンツの複雑さによって異なります。他のマークアップ言語と同様、WordprocessingML は冗長です。

カスタム レポート生成ヘルパー クラスを作成するには

  1. ソリューション エクスプローラで、[プロジェクト] ノードを右クリックし、[新しい項目の追加] をクリックします。

  2. [新しい項目の追加] ダイアログ ボックスで、[クラス ファイル] をクリックします。

  3. ファイルに AdventureWorksSalesData.cs という名前を付けて、[追加] をクリックします。

  4. [Microsoft Visual Studio] メッセージ ボックスで、[はい] をクリックしてクラス ファイルをプロジェクトの [App_Code] フォルダに追加します。

  5. SalesReportBuilder.cs のコードを、以下の手順で説明するサンプル コードに置き換えます。最初に、以下の using ステートメントを追加します。

    using System;
    using System.Data;
    using System.Collections.Specialized;
    using System.Configuration;
    using System.IO;
    using System.IO.Packaging;
    using System.Text;
    using System.Xml;
    using System.Web;
    using Microsoft.Office.DocumentFormat.OpenXml.Packaging;
    
  6. 以下の名前空間、クラス、フィールド、およびコンストラクタを追加します。

    /// <summary>
    /// Represents the complete sales report document to be generated.
    /// </summary>
    public class SalesReportBuilder {
        const string drawingTemplate = @"~/resources/drawingTemplate.xml";
        const string headerImageFile = @"~/resources/headerimage.gif";
        const string stylesXmlFile = @"~/resources/styles.xml";
        const string wordNamespace = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html";
        const string wordPrefix = "w";
    
        private string _documentName;
        private string _salesPersonID;
        private string _imagePartRID;
    
        public SalesReportBuilder(string salesPersonID) {
            _salesPersonID = salesPersonID;
            //Generate unique filename
            _documentName = HttpContext.Current.Server.MapPath(
            @"~/reports/AdventureWorks" + DateTime.Now.ToFileTime() + ".docx");
        }
    
  7. リージョン パッケージおよびパーツを作成します。このリージョンには、ドキュメント パッケージおよびパーツの作成に使用されるメソッドが含まれます。

    注意

    以下のコード例には、オンラインで表示したときに見やすくするための改行が追加されています。実際にコードで使用する前に改行を削除する必要があります。

        #region Create Package and Parts
        /// <summary>
        /// 1. Create a new package as a Word document.
        /// 2. Add a style.xml part.
        /// 3. Add an embedded image part.
        /// 4. Create the document.xml part content. 
        /// </summary>
        /// <returns>File path location or error message</returns>
        public string CreateDocument() {
            try {
                using (WordprocessingDocument wordDoc = WordprocessingDocument.Create
                (_documentName, WordprocessingDocumentType.Document)) {
    
                    // Set the content of the document so that Word can open it.
                    MainDocumentPart mainPart = wordDoc.AddMainDocumentPart();
    
                    // Create a style part and add it to the document.
                    XmlDocument stylesXml = new XmlDocument();
                    stylesXml.Load(HttpContext.Current.Server.MapPath(stylesXmlFile));
    
                    StyleDefinitionsPart stylePart = mainPart.AddNewPart<StyleDefinitionsPart>();
                    //  Copy the style.xml content into the new part....
                    using (Stream outputStream = stylePart.GetStream()) {
                        using (StreamWriter ts = new StreamWriter(outputStream)) {
                            ts.Write(stylesXml.InnerXml);
                        }
                    }
    
                    // Create an image part and add it to the document.
                    ImagePart imagePart = mainPart.AddImagePart(ImagePartType.Gif);
                    string imageFileName = System.Web.HttpContext.Current.Server.MapPath(headerImageFile);
                    using (FileStream stream = new FileStream(imageFileName, FileMode.Open)) {
                        imagePart.FeedData(stream);
                    }
    
                    // Get the reference ID for the image added to the package.
                    // You will use the image part reference ID to insert the
                    // image to the document.xml file.
                    _imagePartRID = mainPart.GetIdOfPart(imagePart);
    
                    // Create document.xml content.
                    SetMainDocumentContent(mainPart);
                }
    
                return (_documentName);
            }
            catch (Exception ex) {
                return (ex.Message);
    
            }
        }
    
        /// <summary>
        /// Set content of MainDocumentPart. 
        /// </summary>
        /// <param name="part">MainDocumentPart</param>
        public void SetMainDocumentContent(MainDocumentPart part) {
            using (Stream stream = part.GetStream()) {
                CreateWordProcessingML(stream);
            }
        }
    
       /// <summary>
        /// Generate WordprocessingML for Sales Report.
        /// The resulting XML will be saved as document.xml.
        /// </summary>
        /// <param name="stream">MainDocumentPart stream</param>
        public void CreateWordProcessingML(Stream stream) {
    
            // Get sales person data from AdventureWorks database
            // You will write this data to the document.xml file.
            AdventureWorksSalesData salesData = new AdventureWorksSalesData();
            StringDictionary SalesPerson = salesData.GetSalesPersonData(_salesPersonID);
    
            // Create an XmlWriter using UTF8 encoding.
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Encoding = Encoding.UTF8;
            settings.Indent = true;
    
            // This file represents the WordprocessingML of the Sales Report.
            XmlWriter writer = XmlWriter.Create(stream, settings);
            try {
                writer.WriteStartDocument(true);
                writer.WriteComment("This file represents the WordProcessingML of our Sales Report");
                writer.WriteStartElement(wordPrefix, "document", wordNamespace);
                writer.WriteStartElement(wordPrefix, "body", wordNamespace);
    
                WriteHeaderImage(writer);
                WriteDocumentTitle(writer, SalesPerson["FullName"]);
                WriteDocumentContactInfo(writer, SalesPerson["FullName"], SalesPerson["Phone"], SalesPerson["Email"]);
                WriteSalesSummaryInfo(writer, SalesPerson["SalesYTD"], SalesPerson["SalesQuota"]);
                WriteTerritoriesTable(writer, SalesPerson["TerritoryName"]);
    
                writer.WriteEndElement(); //body
                writer.WriteEndElement(); //document
            }
            catch (Exception e) {
                throw;
            }
            finally {
                //Write the XML to file and close the writer.
                writer.Flush();
                writer.Close();
            }
            return;
        }
        #endregion
    
  8. リージョンの書式設定メソッドを作成します。このリージョンには、ドキュメント コンテンツの書式設定に使用される WordprocessingML を作成するためのメソッドが含まれます。

        #region Formatting Methods
        /// <summary>
        /// Write the title paragraph properties to the WordprocessingML document.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the properties to.</param>
        private void WriteTitleParagraphProperties(XmlWriter writer) {
            // Create the paragraph properties element.
            // </w:pPr>
            writer.WriteStartElement(wordPrefix, "pPr",
               wordNamespace);
    
            // Create the bottom border.
            //   <w:pBdr>
            //     <w:bottom w:val=”single” w:sz=”4” 
            //               w:space=”1” w:color=”auto” />
            //   </w:pBdr>
            writer.WriteStartElement(wordPrefix, "pBdr", wordNamespace);
            writer.WriteStartElement(wordPrefix, "bottom", wordNamespace);
            writer.WriteAttributeString(wordPrefix, "val", wordNamespace, "single");
            writer.WriteAttributeString(wordPrefix, "sz", wordNamespace, "4");
            writer.WriteAttributeString(wordPrefix, "space", wordNamespace, "1");
            writer.WriteAttributeString(wordPrefix, "color", wordNamespace, "blue");
            writer.WriteEndElement();
            writer.WriteEndElement();
    
            // Define the spacing for the paragraph.
            //   <w:spacing w:line=”240” w:lineRule=”auto” />
            writer.WriteStartElement(wordPrefix, "spacing", wordNamespace);
            writer.WriteAttributeString(wordPrefix, "line", wordNamespace, "240");
            writer.WriteAttributeString(wordPrefix, "lineRule", wordNamespace, "auto");
            writer.WriteEndElement();
    
            // Close the properties element.
            // </w:pPr>
            writer.WriteEndElement();
        }
    
        /// <summary>
        /// Write the title run properties to the WordprocessingML document.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the properties to.</param>
        private void WriteTitleRunProperties(XmlWriter writer) {
            // Create the run properties element.
            // <w:rPr>
            writer.WriteStartElement(wordPrefix, "rPr", wordNamespace);
    
            // Set up the spacing.
            //   <w:spacing w:val=”5” />
            writer.WriteStartElement(wordPrefix, "spacing", wordNamespace);
            writer.WriteAttributeString(wordPrefix, "val", wordNamespace, "5");
            writer.WriteEndElement();
    
            // Define the size.
            //   <w:sz w:val=”52” />
            writer.WriteStartElement(wordPrefix, "sz", wordNamespace);
            writer.WriteAttributeString(wordPrefix, "val", wordNamespace, "52");
            writer.WriteEndElement();
    
            // Close the properties element.
            // </w:rPr>
            writer.WriteEndElement();
        }
    
        /// <summary>
        /// Write the subtitle paragraph properties to the WordprocessingML document.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the properties to.</param>
        private void WriteSubtitleParagraphProperties(XmlWriter writer) {
            // Create the paragraph properties element.
            // <w:pPr>
            writer.WriteStartElement(wordPrefix, "pPr", wordNamespace);
    
            // Define the spacing for the paragraph.
            //   <w:spacing w:before=”200” w:after=”0” />
            writer.WriteStartElement(wordPrefix, "spacing", wordNamespace);
            writer.WriteAttributeString(wordPrefix, "before", wordNamespace, "200");
            writer.WriteAttributeString(wordPrefix, "after", wordNamespace, "0");
            writer.WriteEndElement();
    
            // Close the properties element.
            // </w:pPr>
            writer.WriteEndElement();
        }
    
        /// <summary>
        /// Write the subtitle run properties to the WordprocessingML document.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the properties to.</param>
        private void WriteSubtitleRunProperties(XmlWriter writer) {
            // Create the run properties element.
            // <w:rPr>
            writer.WriteStartElement(wordPrefix, "rPr", wordNamespace);
    
            // setup as bold
            //   <w:b />
            writer.WriteElementString(wordPrefix, "b", wordNamespace, null);
    
            // Define the size.
            //   <sz w:val=”26” />
            writer.WriteStartElement(wordPrefix, "sz", wordNamespace);
            writer.WriteAttributeString(wordPrefix, "val", wordNamespace, "26");
            writer.WriteEndElement();
    
            // Close the properties element.
            // </w:rPr>
            writer.WriteEndElement();
        }
    
        /// <summary>
        /// Write the bold run property to the WordprocessingML document.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the properties to.</param>
        private void WriteBoldRunProperties(XmlWriter writer) {
            // Create the run properties element.
            // <w:rPr>
            //   <w:b />
            // </w:rPr>
            writer.WriteStartElement(wordPrefix, "rPr", wordNamespace);
            writer.WriteElementString(wordPrefix, "b", wordNamespace, null);
            writer.WriteEndElement();
        }
        #endregion
    
  9. リージョンのスタイル メソッドを作成します。このリージョンには、スタイル プロパティを定義するために使用されるメソッドが含まれます。

        region Styles Methods
        /// <summary>
        /// Write the style property to the WordprocessingML paragraph element.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the style to.</param>
        public void ApplyParagraphStyle(XmlWriter writer, string styleId) {
            // Apply the style in the paragraph properties.
            // <w:pPr>
            //   <w:pStyle w:val=”MyTitle” />
            // </w:pPr>
            writer.WriteStartElement(wordPrefix, "pPr", wordNamespace);
            writer.WriteStartElement(wordPrefix, "pStyle", wordNamespace);
            writer.WriteAttributeString(wordPrefix, "val", wordNamespace, styleId);
            writer.WriteEndElement();
            writer.WriteEndElement();
        }
    
        /// <summary>
        /// Write the style property to the WordprocessingML table element.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the style to.</param>
        public void ApplyTableStyle(XmlWriter writer, string styleId) {
            // Apply the style in the table properties.
            // <w:tblPr>
            //   <w:tblStyle w:val="MyTableStyle" />
            //   <w:tblW w:w="0" w:type="auto" /> 
            //   <w:tblLook w:val="04A0" /> 
            // </w:tblPr>
            writer.WriteStartElement(wordPrefix, "tblPr", wordNamespace);
            writer.WriteStartElement(wordPrefix, "tblStyle", wordNamespace);
            writer.WriteAttributeString(wordPrefix, "val", wordNamespace, styleId);
            writer.WriteEndElement();
            writer.WriteStartElement(wordPrefix, "tblW", wordNamespace);
            writer.WriteAttributeString(wordPrefix, "w", wordNamespace, "0");
            writer.WriteAttributeString(wordPrefix, "type", wordNamespace, "auto");
            writer.WriteEndElement();
            writer.WriteStartElement(wordPrefix, "tblLook", wordNamespace);
            writer.WriteAttributeString(wordPrefix, "val", wordNamespace, "04A0");
            writer.WriteEndElement();
            writer.WriteEndElement();
        }
        #endregion
    
  10. リージョンの document.xml 書き込みメソッドを作成します。このリージョンには、ドキュメントの画像、タイトル、連絡先情報、売り上げ概要、および販売地域別の表の各セクションのコンテンツを定義する WordprocessingML マークアップを生成するためのメソッドが含まれています。

        region document.xml writing methods
        /// <summary>
        /// Writes an image within a paragraph
        /// into the WordprocessingML.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the image to.</param>
        private void WriteHeaderImage(XmlWriter writer) {
            // Load the drawing template into an XML document.
            XmlDocument drawingXml = new XmlDocument();
            string drawingXmlFile = System.Web.HttpContext.Current.Server.MapPath(drawingTemplate);
            drawingXml.Load(drawingXmlFile);
    
            // Load the drawing template into an XML document and pass the reference ID parameter.
            drawingXml.LoadXml(string.Format(drawingXml.InnerXml, _imagePartRID));
    
            // Write the wrapping paragraph and the drawing fragment.
            writer.WriteStartElement(wordPrefix, "p", wordNamespace);
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            drawingXml.DocumentElement.WriteContentTo(writer);
            writer.WriteEndElement();
            writer.WriteEndElement();
        }
    
        /// <summary>
        /// Writes a document title within a paragraph
        /// into the WordprocessingML.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the image to.</param>
        /// <param name="title">Document title</param>
        private void WriteDocumentTitle(XmlWriter writer, string title) {
            // Create the title.
            // <w:p>
            //   <w:r>
            //     <w:t>Sales Report - Employee Name</w:t>
            //   </w:r>
            // </w:p>    
    
            writer.WriteStartElement(wordPrefix, "p", wordNamespace);
            WriteTitleParagraphProperties(writer);
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            WriteTitleRunProperties(writer);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, "Sales Report - " + title);
            writer.WriteEndElement();
            writer.WriteEndElement();
        }
    
        /// <summary>
        /// Writes a document's contact information within a paragraph
        /// into the WordprocessingML.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the image to.</param>
        /// <param name="fullname">Employee's fullname</param>
        /// <param name="phone">Employee's phone number</param>
        /// <param name="email">Employee's e-mail address</param>
        private void WriteDocumentContactInfo(XmlWriter writer, string fullname, string phone, string email) {
    
            // Create the contact information section.
            // <w:p>
            //   <w:r>
            //     <w:t>Contact</w:t>
            //   </w:r>
            // </w:p>
    
            writer.WriteStartElement(wordPrefix, "p", wordNamespace);
            WriteSubtitleParagraphProperties(writer);
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            WriteSubtitleRunProperties(writer);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, "Contact");
            writer.WriteEndElement();
            writer.WriteEndElement();
    
            // Fill in the contact information section.
            // <w:p>
            //   <w:r>
            //     <w:t>Employee's fullname</w:t>
            //     <w:br />
            //     <w:t>sEmployee's e-mail</w:t>
            //     <w:br />
            //     <w:t>Employee's phone</w:t>
            //   </w:r>
            // </w:p>
            writer.WriteStartElement(wordPrefix, "p", wordNamespace);
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, fullname);
            writer.WriteElementString(wordPrefix, "br", wordNamespace, null);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, email);
            writer.WriteElementString(wordPrefix, "br", wordNamespace, null);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, phone);
            writer.WriteEndElement();
            writer.WriteEndElement();
        }
    
        /// <summary>
        /// Writes the sales summary information within a paragraph
        /// into the WordprocessingML document.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the page break to.</param>
        /// <param name="totalsales">Employee's sales YTD</param>
        /// <param name="salesquota">Employee's sales quota</param>
        private void WriteSalesSummaryInfo(XmlWriter writer, string totalsales, string salesquota) {
            string wordNamespace = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html";
            string wordPrefix = "w";
    
            // Create the sales summary section.
            // <w:p>
            //   <w:r>
            //     <w:t>Sales Summary</w:t>
            //   </w:r>
            // </w:p>
            writer.WriteStartElement(wordPrefix, "p", wordNamespace);
            WriteSubtitleParagraphProperties(writer);
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            WriteSubtitleRunProperties(writer);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, "Sales Summary");
            writer.WriteEndElement();
            writer.WriteEndElement();
    
            // Fill in the contact information section.
            // <w:p>
            //   <w:r>
            //     <w:t>Total Sales:</w:t>
            //   </w:r>
            //   <w:r>
            //     <w:t>Employee's sales YTD</w:t>
            //   </w:r>
            //   <w:br />
            //   <w:r>
            //     <w:t>Employee's sales quota</w:t>
            //   </w:r>
            //   <w:r>
            //     <w:t>$1000.00</w:t>
            //   </w:r>
            // </w:p>
            writer.WriteStartElement(wordPrefix, "p", wordNamespace);
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, "Total Sales:");
            writer.WriteElementString(wordPrefix, "tab", wordNamespace, null);
            writer.WriteEndElement();
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, totalsales);
            writer.WriteEndElement();
            writer.WriteElementString(wordPrefix, "br", wordNamespace, null);
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, "Sales Quota:");
            writer.WriteElementString(wordPrefix, "tab", wordNamespace, null);
            writer.WriteEndElement();
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, salesquota);
            writer.WriteEndElement();
            writer.WriteEndElement();
        }
    
        /// <summary>
        /// Writes the territory sales totals as a table to the WordprocessingML document.
        /// </summary>
        /// <param name="writer">The XmlWriter to write the page break to.</param>
        private void WriteTerritoriesTable(XmlWriter writer, string territory) {
            string wordNamespace = "http://schemas.liquid-technologies.com/OfficeOpenXML/2006/default.html";
            string wordPrefix = "w";
    
            // Create the territory section header.
            // <w:p>
            //   <w:r>
            //     <w:t>Sales by Territory</w:t>
            //   </w:r>
            // </w:p>
            writer.WriteStartElement(wordPrefix, "p", wordNamespace);
            WriteSubtitleParagraphProperties(writer);
            ApplyParagraphStyle(writer, "Heading 3");
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            WriteSubtitleRunProperties(writer);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, "Sales by Territory - " + territory);
            writer.WriteEndElement();
            writer.WriteEndElement();
    
            // Open the table element.
            writer.WriteStartElement(wordPrefix, "tbl",
               wordNamespace);
            ApplyTableStyle(writer, "LightList-Accent2");
    
            // Write table headings.
            writer.WriteStartElement(wordPrefix, "tr", wordNamespace);
            writer.WriteStartElement(wordPrefix, "tc", wordNamespace);
            writer.WriteStartElement(wordPrefix, "p", wordNamespace);
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, "Employee");
            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.WriteEndElement();
    
            writer.WriteStartElement(wordPrefix, "tc", wordNamespace);
            writer.WriteStartElement(wordPrefix, "p", wordNamespace);
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, "2003");
            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.WriteEndElement();
    
            writer.WriteStartElement(wordPrefix, "tc", wordNamespace);
            writer.WriteStartElement(wordPrefix, "p", wordNamespace);
            writer.WriteStartElement(wordPrefix, "r", wordNamespace);
            writer.WriteElementString(wordPrefix, "t", wordNamespace, "2004");
            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.WriteEndElement();
    
            // write the close row
            writer.WriteEndElement();
    
            // write a row for each territory
            AdventureWorksSalesData salesData = new AdventureWorksSalesData();
            DataTable dt = salesData.GetSalesByTerritory(territory);
    
            foreach (DataRow myRow in dt.Rows) {
                writer.WriteStartElement(wordPrefix, "tr", wordNamespace);
    
                foreach (DataColumn myCol in dt.Columns) {
                    writer.WriteStartElement(wordPrefix, "tc", wordNamespace);
                    writer.WriteStartElement(wordPrefix, "p", wordNamespace);
                    writer.WriteStartElement(wordPrefix, "r", wordNamespace);
                    writer.WriteElementString(wordPrefix, "t", wordNamespace, myRow[myCol].ToString());
                    writer.WriteEndElement();
                    writer.WriteEndElement();
                    writer.WriteEndElement();
    
                }
                // Write the close row.
                writer.WriteEndElement();
            }
            // end the table element
            writer.WriteEndElement();
        }
    
        #endregion
    
    }
    
  11. クラスを閉じます。

アプリケーションを実行する

これで、アプリケーションを実行し、従業員を選択して、売り上げ概要レポートを Word 2007 にエクスポートする準備ができました。アプリケーションによって、生成されたレポートがローカル ハード ディスクに保存されます。

アプリケーションを実行するには

  1. F5 キーを押して Web アプリケーションをビルドして実行します。

  2. DropDownList コントロールで従業員を選択します。

  3. [Export to Word 2007] をクリックします。

    生成されたドキュメントのファイル パスが表示されます。

  4. ドキュメントを開いて、生成されたファイルを確認します。

サーバー側ソリューションでドキュメントを作成した後、2007 Microsoft Office プログラムを使用してレポートを開いて、ドキュメントを表示または操作できます。

以前のバージョンの Microsoft Office を使用しているユーザーは、Word/Excel/PowerPoint 2007 ファイル形式用 Microsoft Office 互換機能パックをダウンロードしてインストールすることによって、生成されたドキュメントを開いたり、編集および保存したりできるようになります。この互換機能パックによって、Word 2007、Excel 2007、および PowerPoint 2007 形式のドキュメントを Office 2000、Office XP、または Office 2003 ユーザーと共有することができます。

まとめ

Open XML 形式によって、サーバー側ソリューションの可能性がさらに広がります。サーバーに Microsoft Office アプリケーションをインストールしなくても、ドキュメントを作成および操作できます。また、この形式によって、組織では LOB データを示すレポートを提供することができます。

Open XML オブジェクト モデルを使用すると, .NET Framework に基づくアプリケーションで、プログラムによって Open XML ドキュメント パッケージおよびドキュメント パーツを作成および操作するプロセスが容易になります。

このドキュメントでは、Open XML オブジェクト モデルと ASP.NET 2.0 を使用して、サーバー側の Word 2007 ドキュメント生成ソリューションを構築する方法を示しました。同様に、Open XML オブジェクト モデルと共に、SpreadsheetML を使用してレポートを Excel にエクスポートしたり、PresentationML を使用して PowerPoint プレゼンテーションを生成するプロセスを自動化したりすることができます。

謝辞

この記事の執筆にご協力くださった Doug Mahugh 氏、Wouter van Vugt 氏、および Frank Rice 氏に感謝いたします。

追加情報

詳細については、以下のリソースを参照してください。