SharePoint 2010 Word Automation Services での開発

概要:   Word Automation Services を使用して、サーバー側でさまざまな形式のドキュメントをさまざまな形式のドキュメントに変換する方法について説明します。Open XML SDK を使用すると、目次の更新、改ページ位置の修正など、困難な作業を遂行できます。

最終更新日: 2015年3月9日

適用対象: Business Connectivity Services | Office 2010 | Open XML | SharePoint Designer 2010 | SharePoint Foundation 2010 | SharePoint Online | SharePoint Server 2010 | Visual Studio | Word Autmomation Services

この記事の内容
ドキュメント形式を変更する Word Automation Services の使用
Word Automation Services の 1 つのシナリオ
Word Automation Services の機能
Word Automation Services の構成
Word Automation Services アプリケーションの構築
変換状態の監視
変換に失敗したドキュメントの特定
変換後の元ファイルの削除
Open XML SDK との統合
まとめ
その他の技術情報

提供元:    Eric White、Microsoft Corporation | Tristan Davis、Microsoft Corporation | Zeyad Rajabi、Microsoft Corporation

目次

  • ドキュメント形式を変更する Word Automation Services の使用

  • Word Automation Services の 1 つのシナリオ

  • Word Automation Services の機能

  • Word Automation Services アプリケーションの構築

  • 変換状態の監視

  • 変換に失敗したドキュメントの特定

  • 変換後の元ファイルの削除

  • Open XML SDK との統合

  • まとめ

  • その他の技術情報

クリックしてコードを取得  ダウンロード コード (英語)

ドキュメント形式を変更する Word Automation Services の使用

Open XML SDK 2.0 for Microsoft Office へようこそ を使用する場合、いくつかの困難な作業があります。たとえば、改ページ位置の修正、ほかのドキュメント形式 (PDF など) への変換があります。また、目次、フィールドなど、ドキュメント内の動的コンテンツの更新も困難な作業です。Word Automation Services は、このようなシナリオで役に立つ場合がある SharePoint 2010 の新しい機能です。これは共有サービスであり、これを使用して、サーバー側でドキュメントをほかの形式に無人で変換できます。また、その他の重要な機能もいくつか提供されます。これは最初からサーバーで動作するように設計されており、信頼性の高い予測可能な方法で多くのドキュメントを処理できます。

Word Automation Services を使用して、Open XML WordprocessingML からほかのドキュメント形式への変換ができます。たとえば、複数のドキュメントを PDF 形式に変換し、プリンターにスプールしたり電子メールで顧客に送信したりできます。また、ほかのドキュメント形式 (HTML、Word 97-2003 バイナリ ドキュメントなど) から Open XML ワープロ ドキュメントへの変換もできます。

ドキュメント変換機能に加えて、Word Automation Services が提供するその他の重要な機能領域があります。たとえば、ドキュメント内のフィールド コードを更新したり、標準のスタイルを適用した段落に altChunk コンテンツを変換したりする機能です。これらの作業は、Open XML SDK 2.0 を使用すると、実行が困難になる場合があります。ただし、Word Automation Services を使用してこれらの作業を実行することは簡単です。これまで、クライアント アプリケーションでは、このような作業を実行するのに Word Automation Services が使用されていました。ただし、この方法は問題のあるものでした。Word クライアントは、ドキュメントを対話式で作成することに最も適したアプリケーションであり、サーバーでの大量処理を目的として設計されたものではありません。このような作業を実行すると、Word は、エラーを報告するダイアログ ボックスを表示する場合があります。Word クライアントをサーバーで自動化する場合、このダイアログ ボックスに応答するユーザーがいないため、プロセスが突然停止する可能性があります。Word の自動化に関連付けられる問題については、サポート技術情報の記事「Office のサーバーサイド オートメーションについて」を参照してください。

Word Automation Services の 1 つのシナリオ

このシナリオでは、サーバーでのドキュメント処理を自動化するために Word Automation Services をどのように使用できるかについて説明します。

  • ある専門家が、特定の規則に従ったいくつかの Word テンプレート ドキュメントを作成します。専門家はコンテンツ コントロールを使用してテンプレート ドキュメントに構造を与えることができます。これにより、ユーザーの操作性が向上し、ドキュメント生成プロセスの中でデータを置き換える必要のある、テンプレート ドキュメント内の場所を決定するための信頼性の高いプログラム的な方法が提供されます。このテンプレート ドキュメントは、通常、SharePoint ドキュメント ライブラリに格納されます。

  • テンプレート ドキュメントをデータと共に結合し、一連の Open XML WordprocessingML (DOCX) ドキュメントを生成するプログラムをサーバーで実行します。このプログラムは、サーバーでのドキュメントの生成を目的として設計された Open XML SDK 2.0 for Microsoft Office へようこそ を使用して適切に記述されています。このドキュメントは、SharePoint ドキュメント ライブラリに配置されます。

  • 一連のドキュメントを生成した後に、それらのドキュメントを自動で印刷できます。また、それらのドキュメントを WordprocessingML ドキュメントとして電子メールで一連のユーザーに送信したり、それらのドキュメントを WordprocessingML から必要な形式に変換した後に PDF、XPS、または MHTML ドキュメントとして電子メールで一連のユーザーに送信したりできます。

  • 変換の一環として、目次など、フィールドを更新するように Word Automation Services に指示できます。

Open XML SDK 2.0 for Microsoft Office へようこそ を Word Automation Services と共に使用することで、適切に動作し、Word クライアント アプリケーションの自動化を必要としない機能豊富なエンド ツー エンドのソリューションを作成できます。

Word Automation Services の主な利点の 1 つは、ユーザーのニーズに合わせてスケール アウトできることです。Word クライアント アプリケーションとは異なり、複数のプロセッサを使用するようにこれを構成できます。また、必要に応じて、複数のサーバー間で負荷を分散するように構成することもできます。

もう 1 つの主な利点として、Word Automation Services は Word クライアント アプリケーションとの完全な再現性があることです。改ページを含め、ドキュメントのレイアウトは同じです。ドキュメントがサーバーまたはクライアントのどちらで処理されたかは関係ありません。

サポートされる変換元のドキュメント形式

ドキュメントの変換元のドキュメント形式として、次の形式がサポートされます。

  1. Open XML ファイル形式のドキュメント (.docx, .docm, .dotx, .dotm)

  2. Word 97-2003 ドキュメント (.doc, .dot)

  3. リッチテキスト形式のファイル (.rtf)

  4. 単一ファイル Web ページ (.mht, .mhtml)

  5. Word 2003 XML ドキュメント (.xml)

  6. Word XML ドキュメント (.xml)

サポートされる変換先のドキュメント形式

サポートされる変換先のドキュメント形式には、サポートされる変換元のドキュメント形式のすべてと次の形式が含まれます。

  1. Portable Document Format (.pdf)

  2. Open XML Paper Specification (.xps)

Word Automation Services のその他の機能

さまざまな形式でドキュメントの読み込みと保存ができることに加えて、Word Automation Services にはその他の機能が含まれます。

Word Automation Services で目次、引用文献一覧、および索引フィールドの更新を起動できます。これは、ドキュメントを生成するときに重要です。ドキュメントに目次が含まれる場合、ドキュメントを生成した後で、目次が正しく更新されるようにドキュメントの改ページを決定する作業は特に困難です。Word Automation Services は自動でこの作業を簡単に処理します。

Open XML ワープロ ドキュメントには、さまざまなフィールド型を含めることができます。これにより、動的コンテンツをドキュメントに追加できます。Word Automation Services を使用して、すべてのフィールドの再計算を起動できます。たとえば、現在の日付をドキュメントに挿入するフィールド型を含めることができます。フィールドが更新されると、関連付けられたコンテンツも更新されるため、ドキュメントのフィールドの場所で現在の日付が表示されます。

コンテンツ コントロールの強力な使用方法の 1 つは、カスタム XML パーツ内でコンテンツ コントロールを XML 要素にバインドすることです。バインドされたコンテンツ コントロールの詳細と、作業の開始に役立ついくつかのリソースへのリンクについては、記事「Word 2010 および Word 2007 でテンプレートからドキュメント生成システムを作成する」を参照してください。バインドされたコンテンツ コントロールのコンテンツを置き換えるには、カスタム XML パーツ内の XML を置き換えます。メイン ドキュメント パーツを変更する必要はありません。メイン ドキュメント パーツには、バインドされたすべてのコンテンツ コントロールのキャッシュされた値が含まれます。カスタム XML パーツ内の XML を置き換えても、メイン ドキュメント パーツにキャッシュされた値は更新されません。ユーザーがこの生成されたドキュメントを Word クライアントのみを使用して表示することが予想される場合、これは問題になりません。ただし、さらに WordprocessingML マークアップを処理する場合、メイン ドキュメント パーツにキャッシュされた値を更新する必要があります。Word Automation Services は、この処理を行うことができます。

代替フォーマット コンテンツ (altChunk 要素で表される) は、HTML コンテンツを WordprocessingML ドキュメントにインポートするための優れた方法です。代替フォーマット コンテンツの詳細、その使用法、作業の開始に役立つリンクについては、記事「Word 2010 および Word 2007 でテンプレートからドキュメント生成システムを作成する」を参照してください。ただし、altChunk 要素が含まれるドキュメントを開いて保存するまで、ドキュメントには HTML が含まれており、段落、ラン、およびテキスト要素など、一般的な WordprocessingML マークアップは含まれていません。Word Automation Services を使用すると、HTML (または代替コンテンツのその他のフォーム) をインポートし、それを、各種スタイルが適用された使い慣れた WordprocessingML 段落が含まれる WordprocessingML マークアップに変換できます。

また、以前のバージョンの Word で使用された各種形式間で変換を行うこともできます。数千ものユーザーが使用するエンタープライズ クラスのアプリケーションを構築する場合、Word 2007 または Word 2003 を使用して Open XML ドキュメントを編集するユーザーがいる可能性があります。Word 2007 または Word 2003 で使用されるマークアップと機能のみを含むように Open XML ドキュメントを変換できます。

Word Automation Services の制限事項

Word Automation Services には、ドキュメントの印刷機能が組み込まれていません。ただし、WordprocessingML ドキュメントを PDF または XPS に変換して、プリンターにスプールすることが簡単にできます。

よくある質問は、SharePoint Server 2010 を購入してインストールしなくても Word Automation Services を使用できるかということです。Word Automation Services は SharePoint 2010 の機能を利用すると共に、その機能の 1 つになっています。これを使用するには、SharePoint Server 2010 を購入してインストールする必要があります。Word Automation Services は、Standard Edition と Enterprise Edition に含まれます。

Word Automation Services の機能

既定では、Word Automation Services は、スタンドアロンの SharePoint Server 2010 インストールと共にインストールおよび実行されるサービスです。SharePoint 2010 をサーバー ファームで使用する場合、Word Automation Services を明示的に有効にする必要があります。

これを使用するには、そのプログラミング インターフェイスを使用して変換ジョブを開始します。各変換ジョブで、どのファイル、フォルダー、ドキュメント ライブラリに対して変換ジョブを処理するかを指定します。変換ジョブを開始すると、構成に基づいて、指定した数の変換プロセスが各サーバーで開始されます。変換ジョブの開始頻度を指定できますし、変換プロセスごとに、開始する変換の数を指定できます。さらに、Word Automation Services が使用できるメモリの最大比率 (パーセント) も指定できます。

構成設定を使用して、重要なインフラストラクチャの一部である SharePoint サーバーの多くのリソースを消費しないように Word Automation Services を構成できます。使用する必要のある設定は、SharePoint Server をどのように使用するかによって決まります。ドキュメントの変換のみで使用する場合、プロセッサ時間のほとんどを変換サービスで消費できるように設定を構成します。優先順位の低いバックグラウンド変換で変換サービスを使用する場合、それに応じて構成します。

重要なメモ重要

ワーカー プロセスの数をサーバーのプロセッサ数よりも 1 つ少なく設定することをお勧めします。4 つのプロセッサを持つサーバーがある場合、ワーカー プロセスの数を 3 以下に設定します。

サーバー ファーム インストールを実行する場合、ワーカー プロセスの数を、サーバー ファーム内で最も少ないプロセッサを持つサーバーのプロセッサ数よりも 1 つ少なく設定する必要があります。

1 分間の 1 ワーカー プロセスあたりの最大ドキュメント変換数を 90 とするようにシステムを構成することをお勧めします。

変換プロセスを開始するコードを書くことに加えて、変換の進行状況を監視するコードを書くこともできます。このコードを使用して、大規模の変換ジョブが完了したときに、ユーザーに通知したり、通知結果を投稿したりできます。

Word Automation Services では、変換に関する 4 つの追加の側面を構成できます。

  1. サポートされるファイル形式の数を制限できます。

  2. 変換プロセスを再起動するまでにそのプロセスで変換するドキュメントの数を指定できます。無効なドキュメントが原因で Word Automation Services が多くのメモリを消費する可能性があるため、この設定は役に立ちます。プロセスが再起動されるとすべてのメモリは再要求されます。

  3. Word Automation Services がドキュメントの変換を試行する回数を指定できます。既定では、この値は 2 に設定されます。したがって、Word Automation Services がドキュメントの変換を試みて失敗した場合、(その変換ジョブ内で) もう 1 度だけドキュメントの変換が試みられます。

  4. 変換プロセスを監視するまでの経過時間の長さを指定できます。Word Automation Services は変換を監視して変換が停止しないようにするため、この設定は役に立ちます。

Word Automation Services の構成

サーバー ファームをインストールしていない限り、既定では、Word Automation Services は SharePoint Server 2010 にインストールされて開始されます。ただし、開発者は、その構成を変更して開発環境を向上することを望みます。既定では、変換プロセスは 15 分間隔で開始されます。Word Automation Services を使用するコードをテストする場合、この間隔を 1 分に設定することでメリットが得られます。また、Word Automation Services で可能な限り多くのリソースを使用することが望まれるシナリオがあります。このシナリオの場合も、間隔を 1 分に設定することでメリットが得られることがあります。

変換プロセスの間隔を 1 分に調整するには

  1. SharePoint 2010 サーバーの全体管理を開始します。

  2. SharePoint 2010 サーバーの全体管理のホーム ページで、[サービス アプリケーションの管理] をクリックします。

  3. サービス アプリケーションの管理ページでは、サービス アプリケーションはアルファベット順に並べ替えられています。ページの下部までスクロールし、[Word Automation Services] をクリックします。サーバー ファームをインストールする場合に、Word Automation Services が手動でインストールされていると、サービス名として入力したものがこのページに表示されます。

  4. Word Automation Services の管理ページで、変換スループットのフィールドを、必要な変換ジョブの開始頻度に構成します。

  5. また、開発者として、変換プロセスの数を設定したり、1 ワーカー プロセスあたりの変換数を調整したりすることが必要になる場合もあります。変換プロセスの開始頻度を調整し、ほかの 2 つの値を調整しないで、多くのドキュメントの変換を試みる場合、変換プロセスの効率が大幅に低下します。これらの最適な数値は、SharePoint Server 2010 を実行するコンピューターの能力を考慮して設定する必要があります。

  6. ページの下部までスクロールし、[OK] をクリックします。

Word Automation Services アプリケーションの構築

Word Automation Services は、SharePoint Server 2010 のサービスなので、SharePoint Server 上で直接実行されるアプリケーション内でのみ使用できます。アプリケーションは、ファーム ソリューションとして構築する必要があります。Word Automation Services はサンドボックス ソリューションから使用できません。

Word Automation Services を使用すると、クライアント アプリケーションで使用できる Web サービスを簡単に書くことができます。

ただし、Word Automation Services を使用するコードの作成方法を示す最も簡単な方法は、コンソール アプリケーションを構築することです。コンソール アプリケーションは、クライアント コンピューターではなく SharePoint Server で構築し、実行する必要があります。変換ジョブの開始と監視を行うコードは、Web パーツ、ワークフロー、またはイベント ハンドラーに対して書くコードと同じです。コンソール アプリケーションから Word Automation Services を使用する方法を示すことで、Web パーツ、イベント ハンドラー、またはワークフローの複雑性を追加することなく API について説明することができます。

重要なメモ重要

次のサンプル アプリケーションでは、5 秒おきに状態についてクエリを実行するように Sleep(Int32) が呼び出されています。これは、運用サーバーに展開するコードを書く場合、最適な方法ではありません。代わりに、Delay アクティビティを含むワークフローを書くことをお勧めします。

アプリケーションを構築するには

  1. Microsoft Visual Studio 2010 を起動します。

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

  3. [新しいプロジェクト] ダイアログ ボックスの [最近使用したテンプレート] ウィンドウで、[Visual C#] を展開して、[Windows] をクリックします。

  4. [最近使用したテンプレート] ウィンドウの右側で、[コンソール アプリケーション] をクリックします。

  5. 既定では、Visual Studio によって, .NET Framework 4 を対象とするプロジェクトが作成されます。ただし、ここでは .NET Framework 3.5 を対象とする必要があります。[ファイルを開く] ダイアログ ボックスの上部にあるリストから、[.NET Framework 3.5] を選択します。

  6. [名前] ボックスに、プロジェクトに使用する名前を入力します。たとえば、 「FirstWordAutomationServicesApplication」と入力します。

  7. [場所] ボックスに、プロジェクトを保存する場所を入力します。

    図 1. [新しいプロジェクト] ダイアログ ボックスでのソリューションの作成

    [新しいプロジェクト] ボックスでのソリューションの作成

  8. [OK] をクリックして、ソリューションを作成します。

  9. 既定では、Visual Studio 2010 によって、x86 CPU を対象とするプロジェクトが作成されます。ただし、SharePoint Server アプリケーションを構築するには、すべての CPU を対象とする必要があります。

  10. Microsoft Visual C# アプリケーションを構築する場合、ソリューション エクスプローラー ウィンドウで、プロジェクトを右クリックし、[プロパティ] をクリックします。

  11. プロジェクト プロパティ ウィンドウで、[ビルド] をクリックします。

  12. [プラットフォーム ターゲット] リストをポイントし、[Any CPU] を選択します。

    図 2. C# コンソール アプリケーションを構築する場合、[Any CPU] を対象とする

    ターゲットを任意の CPU に変更する

  13. Microsoft Visual Basic .NET Framework アプリケーションを構築する場合、プロジェクト プロパティ ウィンドウで、[コンパイル] をクリックします。

    図 3. Visual Basic アプリケーションのコンパイル オプション

    Visual Basic アプリケーションのコンパイル オプション

  14. [詳細コンパイル オプション] をクリックします。

    図 4. [コンパイラの詳細設定] ダイアログ ボックス

    [コンパイラの詳細設定] ダイアログ ボックス

  15. [プラットフォーム ターゲット] リストをポイントし、[Any CPU] をクリックします。

  16. Microsoft.Office.Word.Server アセンブリへの参照を追加するには、[プロジェクト] メニューで、[参照の追加] をクリックして [参照の追加] ダイアログ ボックスを開きます。

  17. [.NET] タブを選択し、Microsoft Office 2010 コンポーネントという名前のコンポーネントを追加します。

    図 5. Microsoft Office 2010 コンポーネントへの参照の追加

    Microsoft Office 2010 コンポーネントへの参照の追加

  18. 次に、Microsoft.SharePoint アセンブリへの参照を追加します。

    図 6. Microsoft SharePoint への参照の追加

    Microsoft SharePoint への参照の追加

次の例では、最も簡単な Word Automation Services アプリケーション用の C# および Visual Basic の完全なリストを提供します。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.Office.Word.Server.Conversions;

class Program
{
    static void Main(string[] args)
    {
        string siteUrl = "http://localhost";
        // If you manually installed Word automation services, then replace the name
        // in the following line with the name that you assigned to the service when
        // you installed it.
        string wordAutomationServiceName = "Word Automation Services";
        using (SPSite spSite = new SPSite(siteUrl))
        {
            ConversionJob job = new ConversionJob(wordAutomationServiceName);
            job.UserToken = spSite.UserToken;
            job.Settings.UpdateFields = true;
            job.Settings.OutputFormat = SaveFormat.PDF;
            job.AddFile(siteUrl + "/Shared%20Documents/Test.docx",
                siteUrl + "/Shared%20Documents/Test.pdf");
            job.Start();
        }
    }
}
Imports Microsoft.SharePoint
Imports Microsoft.Office.Word.Server.Conversions
Module Module1
    Sub Main()
        Dim siteUrl As String = "http://localhost"
        ' If you manually installed Word automation services, then replace the name
        ' in the following line with the name that you assigned to the service when
        ' you installed it.
        Dim wordAutomationServiceName As String = "Word Automation Services"
        Using spSite As SPSite = New SPSite(siteUrl)
            Dim job As ConversionJob = New ConversionJob(wordAutomationServiceName)
            job.UserToken = spSite.UserToken
            job.Settings.UpdateFields = True
            job.Settings.OutputFormat = SaveFormat.PDF
            job.AddFile(siteUrl + "/Shared%20Documents/Test.docx", _
                siteUrl + "/Shared%20Documents/Test.pdf")
            job.Start()
        End Using
    End Sub
End Module

注意

siteUrl に割り当てられた URL を SharePoint サイトの URL で置き換えます。

例をビルドして実行するには

  1. Test.docx という名前の Word ドキュメントを SharePoint サイトの共有ドキュメント フォルダーに追加します。

  2. 例をビルドして実行します。

  3. 変換プロセスの実行を 1 分待機した後、SharePoint サイトの共有ドキュメント フォルダーに移動し、ページを更新します。ドキュメント ライブラリに新しい PDF ドキュメントである Test.pdf が含まれています。

変換状態の監視

多くのシナリオで、変換の状態を監視し、変換プロセスが完了したときにユーザーに通知したり、変換されたドキュメントをさらに別の方法で処理したりする必要があります。ConversionJobStatus クラスを使用して、変換ジョブの状態について Word Automation Services のクエリを実行できます。WordServiceApplicationProxy クラスの名前 (文字列、既定では "Word Automation Services") と変換ジョブ識別子を渡します。変換ジョブ識別子は ConversionJob オブジェクトから取得できます。テナント パーティションを指定する GUID を渡すこともできます。ただし、SharePoint Server ファームが複数テナントとして構成されていない場合は、このパラメーターの引数として Null (Visual Basic では Nothing) を渡すことができます。

ConversionJobStatus オブジェクトのインスタンス化が終了すると、変換ジョブの状態を示すいくつかのプロパティにアクセスできます。最も重要な 3 つのプロパティを次に示します。

ConversionJobStatus のプロパティ

プロパティ

戻り値

Count

現在、変換ジョブ内にあるドキュメントの数。

Succeeded

変換に成功したドキュメントの数。

Failed

変換に失敗したドキュメントの数。

最初の例では、1 つのドキュメントを変換するように指定されていましたが、次の例では、指定したドキュメント ライブラリ内のすべてのドキュメントが変換されます。変換されたすべてのドキュメントを、元のライブラリとは別のドキュメント ライブラリに作成することもできますが、簡単にするために、次の例では、入力と出力のドキュメント ライブラリに同じドキュメント ライブラリが指定されています。さらに、次の例では、出力ドキュメントが既に存在する場合、変換ジョブによってそのドキュメントが上書きされるように指定されています。

ダウンロード コード (英語)

Console.WriteLine("Starting conversion job");
ConversionJob job = new ConversionJob(wordAutomationServiceName);
job.UserToken = spSite.UserToken;
job.Settings.UpdateFields = true;
job.Settings.OutputFormat = SaveFormat.PDF;
job.Settings.OutputSaveBehavior = SaveBehavior.AlwaysOverwrite;
SPList listToConvert = spSite.RootWeb.Lists["Shared Documents"];
job.AddLibrary(listToConvert, listToConvert);
job.Start();
Console.WriteLine("Conversion job started");
ConversionJobStatus status = new ConversionJobStatus(wordAutomationServiceName,
    job.JobId, null);
Console.WriteLine("Number of documents in conversion job: {0}", status.Count);
while (true)
{
    Thread.Sleep(5000);
    status = new ConversionJobStatus(wordAutomationServiceName, job.JobId,
        null);
    if (status.Count == status.Succeeded + status.Failed)
    {
        Console.WriteLine("Completed, Successful: {0}, Failed: {1}",
            status.Succeeded, status.Failed);
        break;
    }
    Console.WriteLine("In progress, Successful: {0}, Failed: {1}",
        status.Succeeded, status.Failed);
}
Console.WriteLine("Starting conversion job")
Dim job As ConversionJob = New ConversionJob(wordAutomationServiceName)
job.UserToken = spSite.UserToken
job.Settings.UpdateFields = True
job.Settings.OutputFormat = SaveFormat.PDF
job.Settings.OutputSaveBehavior = SaveBehavior.AlwaysOverwrite
Dim listToConvert As SPList = spSite.RootWeb.Lists("Shared Documents")
job.AddLibrary(listToConvert, listToConvert)
job.Start()
Console.WriteLine("Conversion job started")
Dim status As ConversionJobStatus = _
    New ConversionJobStatus(wordAutomationServiceName, job.JobId, Nothing)
Console.WriteLine("Number of documents in conversion job: {0}", status.Count)
While True
    Thread.Sleep(5000)
    status = New ConversionJobStatus(wordAutomationServiceName, job.JobId, _
                                     Nothing)
    If status.Count = status.Succeeded + status.Failed Then
        Console.WriteLine("Completed, Successful: {0}, Failed: {1}", _
                          status.Succeeded, status.Failed)
        Exit While
    End If
    Console.WriteLine("In progress, Successful: {0}, Failed: {1}", _
                      status.Succeeded, status.Failed)
End While

この例を実行するには、いくつかの WordprocessingML ドキュメントを共有ドキュメント ライブラリに追加します。この例を実行すると、次のコード スニペットに似た出力が表示されます。

Starting conversion job
Conversion job started
Number of documents in conversion job: 4
In progress, Successful: 0, Failed: 0
In progress, Successful: 0, Failed: 0
Completed, Successful: 4, Failed: 0

変換に失敗したドキュメントの特定

変換に失敗したドキュメントを確認して、ユーザーに通知したり、是正措置 (無効なドキュメントを入力ドキュメント ライブラリから削除するなど) を講じたりする場合があります。ConversionItemInfo() オブジェクトのコレクションを返す GetItems() メソッドを呼び出すことができます。GetItems() メソッドを呼び出す場合、失敗した変換または成功した変換のどちらのコレクションを取得するかを指定するパラメーターを渡します。次の例で、この方法を示します。

ダウンロード コード (英語)

Console.WriteLine("Starting conversion job");
ConversionJob job = new ConversionJob(wordAutomationServiceName);
job.UserToken = spSite.UserToken;
job.Settings.UpdateFields = true;
job.Settings.OutputFormat = SaveFormat.PDF;
job.Settings.OutputSaveBehavior = SaveBehavior.AlwaysOverwrite;
SPList listToConvert = spSite.RootWeb.Lists["Shared Documents"];
job.AddLibrary(listToConvert, listToConvert);
job.Start();
Console.WriteLine("Conversion job started");
ConversionJobStatus status = new ConversionJobStatus(wordAutomationServiceName,
    job.JobId, null);
Console.WriteLine("Number of documents in conversion job: {0}", status.Count);
while (true)
{
    Thread.Sleep(5000);
    status = new ConversionJobStatus(wordAutomationServiceName, job.JobId, null);
    if (status.Count == status.Succeeded + status.Failed)
    {
        Console.WriteLine("Completed, Successful: {0}, Failed: {1}",
            status.Succeeded, status.Failed);
        ReadOnlyCollection<ConversionItemInfo> failedItems =
            status.GetItems(ItemTypes.Failed);
        foreach (var failedItem in failedItems)
            Console.WriteLine("Failed item: Name:{0}", failedItem.InputFile);
        break;
    }
    Console.WriteLine("In progress, Successful: {0}, Failed: {1}", status.Succeeded,
        status.Failed);
}
Console.WriteLine("Starting conversion job")
Dim job As ConversionJob = New ConversionJob(wordAutomationServiceName)
job.UserToken = spSite.UserToken
job.Settings.UpdateFields = True
job.Settings.OutputFormat = SaveFormat.PDF
job.Settings.OutputSaveBehavior = SaveBehavior.AlwaysOverwrite
Dim listToConvert As SPList = spSite.RootWeb.Lists("Shared Documents")
job.AddLibrary(listToConvert, listToConvert)
job.Start()
Console.WriteLine("Conversion job started")
Dim status As ConversionJobStatus = _
    New ConversionJobStatus(wordAutomationServiceName, job.JobId, Nothing)
Console.WriteLine("Number of documents in conversion job: {0}", status.Count)
While True
    Thread.Sleep(5000)
    status = New ConversionJobStatus(wordAutomationServiceName, job.JobId, _
                                     Nothing)
    If status.Count = status.Succeeded + status.Failed Then
        Console.WriteLine("Completed, Successful: {0}, Failed: {1}", _
                          status.Succeeded, status.Failed)
        Dim failedItems As ReadOnlyCollection(Of ConversionItemInfo) = _
            status.GetItems(ItemTypes.Failed)
        For Each failedItem In failedItems
            Console.WriteLine("Failed item: Name:{0}", failedItem.InputFile)
        Next
        Exit While
    End If
    Console.WriteLine("In progress, Successful: {0}, Failed: {1}", _
                      status.Succeeded, status.Failed)
End While

この例を実行するには、無効なドキュメントを作成してドキュメント ライブラリにアップロードします。無効なドキュメントを簡単に作成する方法は、ファイル名に .zip を追加して WordprocessingML ドキュメントの名前を変更することです。次に、メイン ドキュメント パーツ (document.xml とも呼ばれる) を削除します。これは、パッケージの Word フォルダーにあります。.zip 拡張子を削除してファイル名に標準の .docx 拡張子が含まれるようにドキュメントの名前を変更します。

この例を実行すると、次のような出力が生成されます。

Starting conversion job
Conversion job started
Number of documents in conversion job: 5
In progress, Successful: 0, Failed: 0
In progress, Successful: 0, Failed: 0
In progress, Successful: 4, Failed: 0
In progress, Successful: 4, Failed: 0
In progress, Successful: 4, Failed: 0
Completed, Successful: 4, Failed: 1
Failed item: Name:http://intranet.contoso.com/Shared%20Documents/IntentionallyInvalidDocument.docx

変換プロセスを監視するもう 1 つの方法は、SharePoint リストでイベント ハンドラーを使用し、変換されたドキュメントが出力ドキュメント ライブラリにいつ追加されたかを確認することです。

変換後の元ファイルの削除

場合によって、変換後に元のドキュメントの削除が必要になることがあります。次の例で、この方法を示します。

ダウンロード コード (英語)

Console.WriteLine("Starting conversion job");
ConversionJob job = new ConversionJob(wordAutomationServiceName);
job.UserToken = spSite.UserToken;
job.Settings.UpdateFields = true;
job.Settings.OutputFormat = SaveFormat.PDF;
job.Settings.OutputSaveBehavior = SaveBehavior.AlwaysOverwrite;
SPFolder folderToConvert = spSite.RootWeb.GetFolder("Shared Documents");
job.AddFolder(folderToConvert, folderToConvert, false);
job.Start();
Console.WriteLine("Conversion job started");
ConversionJobStatus status = new ConversionJobStatus(wordAutomationServiceName,
    job.JobId, null);
Console.WriteLine("Number of documents in conversion job: {0}", status.Count);
while (true)
{
    Thread.Sleep(5000);
    status = new ConversionJobStatus(wordAutomationServiceName, job.JobId, null);
    if (status.Count == status.Succeeded + status.Failed)
    {
        Console.WriteLine("Completed, Successful: {0}, Failed: {1}",
            status.Succeeded, status.Failed);
        Console.WriteLine("Deleting only items that successfully converted");
        ReadOnlyCollection<ConversionItemInfo> convertedItems =
            status.GetItems(ItemTypes.Succeeded);
        foreach (var convertedItem in convertedItems)
        {
            Console.WriteLine("Deleting item: Name:{0}", convertedItem.InputFile);
            folderToConvert.Files.Delete(convertedItem.InputFile);
        }
        break;
    }
    Console.WriteLine("In progress, Successful: {0}, Failed: {1}",
        status.Succeeded, status.Failed);
}
Console.WriteLine("Starting conversion job")
Dim job As ConversionJob = New ConversionJob(wordAutomationServiceName)
job.UserToken = spSite.UserToken
job.Settings.UpdateFields = True
job.Settings.OutputFormat = SaveFormat.PDF
job.Settings.OutputSaveBehavior = SaveBehavior.AlwaysOverwrite
Dim folderToConvert As SPFolder = spSite.RootWeb.GetFolder("Shared Documents")
job.AddFolder(folderToConvert, folderToConvert, False)
job.Start()
Console.WriteLine("Conversion job started")
Dim status As ConversionJobStatus = _
    New ConversionJobStatus(wordAutomationServiceName, job.JobId, Nothing)
Console.WriteLine("Number of documents in conversion job: {0}", status.Count)
While True
    Thread.Sleep(5000)
    status = New ConversionJobStatus(wordAutomationServiceName, job.JobId, _
                                     Nothing)
    If status.Count = status.Succeeded + status.Failed Then
        Console.WriteLine("Completed, Successful: {0}, Failed: {1}", _
                          status.Succeeded, status.Failed)
        Console.WriteLine("Deleting only items that successfully converted")
        Dim convertedItems As ReadOnlyCollection(Of ConversionItemInfo) = _
            status.GetItems(ItemTypes.Succeeded)
        For Each convertedItem In convertedItems
            Console.WriteLine("Deleting item: Name:{0}", convertedItem.InputFile)
            folderToConvert.Files.Delete(convertedItem.InputFile)
        Next
        Exit While
    End If
    Console.WriteLine("In progress, Successful: {0}, Failed: {1}",
                      status.Succeeded, status.Failed)
End While

Open XML SDK との統合

Word Automation Services の能力は、Open XML SDK 2.0 for Microsoft Office へようこそ と組み合わせて使用する場合に明らかになります。Open XML SDK 2.0 for Microsoft Office へようこそ を使用することで、ドキュメント ライブラリ内のドキュメントをプログラムで変更できます。その後、Open XML SDK を使用することで、Word Automation Services を使用して困難な作業の 1 つを実行できます。一般的なニーズとして、ドキュメントをプログラムで生成し、そのドキュメントの目次を生成または更新することがあります。次に、目次のあるドキュメントについて考えます。

図 7. 目次のあるドキュメント

目次のあるドキュメント

目次に含める必要のあるコンテンツを追加してこのドキュメントを変更すると仮定します。この次の例は、以下の手順をとります。

  1. サイトを開き、Collaborative Application Markup Language (CAML) クエリを使用して Test.docx ドキュメントを取得します。

  2. Open XML SDK 2.0 を使用してドキュメントを開き、Heading 1 のスタイルを適用した新しい段落をドキュメントの先頭に追加します。

  3. 変換ジョブを開始して、Test.docx を TestWithNewToc.docx に変換します。このジョブは変換が完了するまで待機し、変換が正常終了したかどうかを報告します。

ダウンロード コード (英語)

Console.WriteLine("Querying for Test.docx");
SPList list = spSite.RootWeb.Lists["Shared Documents"];
SPQuery query = new SPQuery();
query.ViewFields = @"<FieldRef Name='FileLeafRef' />";
query.Query =
  @"<Where>
      <Eq>
        <FieldRef Name='FileLeafRef' />
        <Value Type='Text'>Test.docx</Value>
      </Eq>
    </Where>";
SPListItemCollection collection = list.GetItems(query);
if (collection.Count != 1)
{
    Console.WriteLine("Test.docx not found");
    Environment.Exit(0);
}
Console.WriteLine("Opening");
SPFile file = collection[0].File;
byte[] byteArray = file.OpenBinary();
using (MemoryStream memStr = new MemoryStream())
{
    memStr.Write(byteArray, 0, byteArray.Length);
    using (WordprocessingDocument wordDoc =
        WordprocessingDocument.Open(memStr, true))
    {
        Document document = wordDoc.MainDocumentPart.Document;
        Paragraph firstParagraph = document.Body.Elements<Paragraph>()
            .FirstOrDefault();
        if (firstParagraph != null)
        {
            Paragraph newParagraph = new Paragraph(
                new ParagraphProperties(
                    new ParagraphStyleId() { Val = "Heading1" }),
                new Run(
                    new Text("About the Author")));
            Paragraph aboutAuthorParagraph = new Paragraph(
                new Run(
                    new Text("Eric White")));
            firstParagraph.Parent.InsertBefore(newParagraph, firstParagraph);
            firstParagraph.Parent.InsertBefore(aboutAuthorParagraph,
                firstParagraph);
        }
    }
    Console.WriteLine("Saving");
    string linkFileName = file.Item["LinkFilename"] as string;
    file.ParentFolder.Files.Add(linkFileName, memStr, true);
}
Console.WriteLine("Starting conversion job");
ConversionJob job = new ConversionJob(wordAutomationServiceName);
job.UserToken = spSite.UserToken;
job.Settings.UpdateFields = true;
job.Settings.OutputFormat = SaveFormat.Document;
job.AddFile(siteUrl + "/Shared%20Documents/Test.docx",
    siteUrl + "/Shared%20Documents/TestWithNewToc.docx");
job.Start();
Console.WriteLine("After starting conversion job");
while (true)
{
    Thread.Sleep(5000);
    Console.WriteLine("Polling...");
    ConversionJobStatus status = new ConversionJobStatus(
        wordAutomationServiceName, job.JobId, null);
    if (status.Count == status.Succeeded + status.Failed)
    {
        Console.WriteLine("Completed, Successful: {0}, Failed: {1}",
            status.Succeeded, status.Failed);
        break;
    }
}
Console.WriteLine("Querying for Test.docx")
Dim list As SPList = spSite.RootWeb.Lists("Shared Documents")
Dim query As SPQuery = New SPQuery()
query.ViewFields = "<FieldRef Name='FileLeafRef' />"
query.Query = ( _
   <Where>
       <Eq>
           <FieldRef Name='FileLeafRef'/>
           <Value Type='Text'>Test.docx</Value>
       </Eq>
   </Where>).ToString()
Dim collection As SPListItemCollection = list.GetItems(query)
If collection.Count <> 1 Then
    Console.WriteLine("Test.docx not found")
    Environment.Exit(0)
End If
Console.WriteLine("Opening")
Dim file As SPFile = collection(0).File
Dim byteArray As Byte() = file.OpenBinary()
Using memStr As MemoryStream = New MemoryStream()
    memStr.Write(byteArray, 0, byteArray.Length)
    Using wordDoc As WordprocessingDocument = _
        WordprocessingDocument.Open(memStr, True)
        Dim document As Document = wordDoc.MainDocumentPart.Document
        Dim firstParagraph As Paragraph = _
            document.Body.Elements(Of Paragraph)().FirstOrDefault()
        If firstParagraph IsNot Nothing Then
            Dim newParagraph As Paragraph = New Paragraph( _
                New ParagraphProperties( _
                    New ParagraphStyleId() With {.Val = "Heading1"}), _
                New Run( _
                    New Text("About the Author")))
            Dim aboutAuthorParagraph As Paragraph = New Paragraph( _
                New Run( _
                    New Text("Eric White")))
            firstParagraph.Parent.InsertBefore(newParagraph, firstParagraph)
            firstParagraph.Parent.InsertBefore(aboutAuthorParagraph, _
                                               firstParagraph)
        End If
    End Using
    Console.WriteLine("Saving")
    Dim linkFileName As String = file.Item("LinkFilename")
    file.ParentFolder.Files.Add(linkFileName, memStr, True)
End Using
Console.WriteLine("Starting conversion job")
Dim job As ConversionJob = New ConversionJob(wordAutomationServiceName)
job.UserToken = spSite.UserToken
job.Settings.UpdateFields = True
job.Settings.OutputFormat = SaveFormat.Document
job.AddFile(siteUrl + "/Shared%20Documents/Test.docx", _
    siteUrl + "/Shared%20Documents/TestWithNewToc.docx")
job.Start()
Console.WriteLine("After starting conversion job")
While True
    Thread.Sleep(5000)
    Console.WriteLine("Polling...")
    Dim status As ConversionJobStatus = New ConversionJobStatus( _
        wordAutomationServiceName, job.JobId, Nothing)
    If status.Count = status.Succeeded + status.Failed Then
        Console.WriteLine("Completed, Successful: {0}, Failed: {1}", _
                          status.Succeeded, status.Failed)
        Exit While
    End If
End While

このセクションの以前に使用したドキュメントに似たドキュメントを使用してこの例を実行すると、図 8 に示された新しいドキュメントが生成されます。

図 8. 目次が更新されたドキュメント

目次が更新されたドキュメント

まとめ

Open XML SDK 2.0 は、サーバー側でドキュメント生成とドキュメント処理を行うシステムを構築するための強力なツールです。ただし、ドキュメントの変換、フィールドの更新、目次の更新など、ドキュメント操作の困難な側面がいくつかあります。Word Automation Services は、ユーザーの要件に合わせてスケール アウトできる高性能のソリューションを使用してこのギャップを埋めます。Open XML SDK 2.0 を Word Automation Services と組み合わせて使用すると、Open XML SDK 2.0 だけを使用する場合は困難な多くのシナリオが実現可能になります。

その他の技術情報

クリックしてコードを取得  ダウンロード コード (英語)