Open XML SDK 2.0 を使用して Word 2010 ドキュメントから目次を取得する

Office Visual How To

概要:  ドキュメントを Microsoft Word に読み込むことなく、Open XML SDK 2.0 の厳密に型指定されたクラスを使用して、Word ドキュメントから目次を含む XXML ブロックを取得します。

適用対象: Excel 2010 | Office 2007 | Office 2010 | Open XML | PowerPoint 2010 | VBA | Word 2010

公開:  2010 年 11 月

提供元: Ken Getz、MCW Technologies, LLC (英語)

概要

Open XML ファイル形式を使用すると、Word ドキュメントから内容のブロックを取得できます。Open XML SDK 2.0 で追加される厳密に型指定されたクラスを使用すると、Open XML ファイル形式に簡単にアクセスできます。SDK を使用すると、特に、目次を含む XML のブロックを取得する作業が簡単になります。この Visual How To に含まれるコード サンプルでは、SDK を使用してこの目標を実現する方法を説明します。

コード化する

この Visual How To に付属するサンプルには、Word 2007 または Word 2010 ドキュメントの目次を含む XML ブロックを取得するために必要なコートが含まれます。Word には、目次を挿入する複数の方法が用意されています。そのような方法の一部だけが、この Visual How To で示されているコードが正しく操作できる適切な内部 XML 構造を生成します。詳細については、「手順」セクションを参照してください。以下ではコードを詳細に見ていきます。ドキュメントの目次はドキュメントの作成者が (Word のユーザー インターフェイスを使用して) 目次を明示的に作成した場合にのみ存在すること、および目次はドキュメント内の参照が記述されている XML のブロックで構成されることに注意してください。サンプル コードを使用して目次を取得すると、プロシージャからは、元のドキュメントの情報の XML ブロックを含む TOC という名前の XML エレメントが返されます。目次を取得した結果の解釈は、開発者 (およびアプリケーション) が行う必要があります。

参照のセットアップ

Open XML SDK 2.0 のコードを使用するには、プロジェクトにいくつかの参照を追加する必要があります。サンプル プロジェクトには既にこれらの参照が含まれていますが、独自のコードでは次のアセンブリを明示的に参照する必要があります。

  • WindowsBase - 作成するプロジェクトの種類によっては、この参照がユーザーのために設定されている場合があります。

  • DocumentFormat.OpenXml - Open XML SDK 2.0 によってインストールされます。

また、次の例で示すように、using および Imports ステートメントをコード ファイルの先頭に追加する必要があります。

Imports DocumentFormat.OpenXml
Imports DocumentFormat.OpenXml.Packaging
Imports DocumentFormat.OpenXml.Wordprocessing
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

プロシージャの確認

WDRetrieveTOC プロシージャは、目次を取得するドキュメントの名前を示すパラメーター (string) を 1 つだけ受け取ります。このプロシージャが返す XElement インスタンスに含まれる TOC という名前のエレメントには、目次が XML エレメントとして格納されています (または、目次が存在しない場合は Null 参照)。

Public Function WDRetrieveTOC(ByVal fileName As String) As XElement
public static XElement WDRetrieveTOC(string fileName)

プロシージャは、指定されたドキュメントを調べて、特別な目次エレメントを探します。目次エレメントが存在する場合は、それを TOC という名前のエレメント内にラップして返します。プロシージャを呼び出すには、コード例で示されているように、パラメーターの値を渡します。サンプル コードを実行する前に、デモ用に目次を含む C:\temp\TOC.docx という名前のドキュメントを用意しておく必要があります。

Dim result = WDRetrieveTOC("C:\Temp\TOC.docx")
Console.WriteLine(result.Value)
var result = WDRetrieveTOC(@"C:\temp\toc.docx");
Console.WriteLine(result.Value.ToString());

ドキュメントへのアクセス

最初に、プロシージャが終了する前に返す TOC という名前の変数を作成します。

Dim TOC As XElement = Nothing
' Code removed here…
Return TOC
XElement TOC = null;
// Code removed here…
return TOC;

次に、WordprocessingDocument.Open メソッドを使用し、読み取り専用アクセスで開くことを指定して (最後の false パラメーター)、ドキュメントを開きます。ドキュメントを開いたら、MainDocumentPart プロパティを使用してメイン ドキュメントに移動し、パーツの Document プロパティを使用してメイン ドキュメント パーツの目次の参照を取得します。その後、この参照を doc という名前の変数に格納します。

Using document = WordprocessingDocument.Open(fileName, False)
  Dim docPart = document.MainDocumentPart
  Dim doc = docPart.Document
  ' Code removed here…
End Using
using (var document = WordprocessingDocument.Open(fileName, false))
{
  var docPart = document.MainDocumentPart;
  var doc = docPart.Document;
  // Code removed here…
}

目次の検索

次に、ドキュメントの子孫を検索し、値が "Table of Contents" である DocPartGallery 型の XML エレメントを探します。コードは、一致した最初のエレメントに対する参照を返します (または、エレメントが存在しない場合は Null 参照)。その後、値を取得する前に、エレメントの Val プロパティの HasValue プロパティを使用して、値が存在することを確認します。

Dim block As OpenXmlElement = _
  doc.Descendants(Of DocPartGallery)().
  Where(Function(b) b.Val.HasValue AndAlso
          (b.Val.Value = "Table of Contents")).FirstOrDefault()
OpenXmlElement block = doc.Descendants<DocPartGallery>().
  Where(b => b.Val.HasValue && 
    (b.Val.Value == "Table of Contents")).FirstOrDefault();

親の検索と戻り値の作成

目次マーカー エレメントが見つかったら、完全な目次情報を含む親 SdtBlock エレメントが見つかるまで、エレメントの階層を上方に移動する必要があります。その後、block 変数が Null 参照になるか、または block 変数の種類が SdtBlock になるまでループして、親ノードを参照するように block 変数を設定します。ループが終了したら、TOC 変数に block 変数の OuterXml プロパティを格納します (コードでは、親エレメントのループの後で block が Null 参照ではないことは検証されません。ドキュメントの形式が正しくないことを示すために、block が Null 出会った場合にのみ例外を生成します)。

If block IsNot Nothing Then
  ' Back up to the enclosing SdtBlock and return that XML.
  Do While (block IsNot Nothing) AndAlso (Not TypeOf block Is SdtBlock)
    block = block.Parent
  Loop
  TOC = New XElement("TOC", block.OuterXml)
End If
if (block != null)
{
  // Back up to the enclosing SdtBlock and return that XML.
  while ((block != null) && (!(block is SdtBlock)))
  {
    block = block.Parent;
  }
  TOC = new XElement("TOC", block.OuterXml);
}

サンプル プロシージャ

次のコード例には、完全なサンプル プロシージャが含まれています。

Public Function WDRetrieveTOC(ByVal fileName As String) As XElement
    Dim TOC As XElement = Nothing

    Using document = WordprocessingDocument.Open(fileName, False)
      Dim docPart = document.MainDocumentPart
      Dim doc = docPart.Document

      Dim block As OpenXmlElement = _
        doc.Descendants(Of DocPartGallery)().
        Where(Function(b) b.Val.HasValue AndAlso
                (b.Val.Value = "Table of Contents")).FirstOrDefault()
      If block IsNot Nothing Then
        ' Back up to the enclosing SdtBlock and return that XML.
        Do While (block IsNot Nothing) AndAlso 
         (Not TypeOf block Is SdtBlock)
          block = block.Parent
        Loop
        TOC = New XElement("TOC", block.OuterXml)
      End If
    End Using
    Return TOC
  End Function
public static XElement WDRetrieveTOC(string fileName)
{
  XElement TOC = null;

  using (var document = WordprocessingDocument.Open(fileName, false))
  {
    var docPart = document.MainDocumentPart;
    var doc = docPart.Document;

    OpenXmlElement block = doc.Descendants<DocPartGallery>().
      Where(b => b.Val.HasValue && 
        (b.Val.Value == "Table of Contents")).FirstOrDefault();

    if (block != null)
    {
      // Back up to the enclosing SdtBlock and return that XML.
      while ((block != null) && (!(block is SdtBlock)))
      {
        block = block.Parent;
      }
      TOC = new XElement("TOC", block.OuterXml);
    }
  }
  return TOC;
}
手順

この Visual How To に付属するサンプルでは、Word ドキュメントから目次を取得するコードが説明されています。サンプルを使用するには、「関連情報」のリンクから入手できる Open XML SDK 2.0 をインストールする必要があります。また、サンプルでは、Open XML SDK 2.0 のコード例のセットの一部として含まれるコードの変更バージョンも使用します。「関連情報」セクションにはコード例全体へのリンクも含まれますが、コード例をダウンロードしてインストールしなくてもサンプルを使用できます。

Word にはドキュメントに目次を挿入する手段が少なくとも 4 つあります。そのうちの 2 つでは、この Visual How To で示したコードで使用できる内部 XML コードが生成されます。具体的には、次の 2 つの方法を使うと、SdtBlock エレメントで入れ子になった目次が提供されます。

  • 組み込みデザインの使用 - [参照] タブの [目次] グループで [目次] をクリックし、ギャラリの選択肢の中からいずれかの組み込みデザインを選択します (現在は 3 つのオプションがあります)。

  • Office.com エントリの [その他の目次] の使用 — [参照] タブの [目次] グループで [目次] をクリックし、下端の近くの [Office.com…] から [その他の目次] をクリックします。

次の 2 つの方法でも有効な目次がドキュメントに生成されますが、目次が SdtBlock エレメント内に入れ子にならないので、この Visual How To のコードでは使用できません。

  • [目次の挿入] エントリの使用 — [参照] タブの [目次] グループで [目次] をクリックし、下端の近くにある [目次の挿入] をクリックします。

  • フィールドの挿入 オプションの使用 — [挿入] タブの [テキスト] グループで [クイック パーツ] をクリックし、[フィールド] をクリックします。[フィールドの名前] で [TOC] をクリックし、[目次] をクリックして (オプション)、[OK] をクリックします。

これら 2 つのオプションでは独立した目次エレメントが作成され、ドキュメントから目次を抽出するにはさらに複雑なコードが必要になります。Word 2007 より前のバージョンの Word からドキュメントをインポートした場合も、これらのバージョンの Word では目次エレメントで SdtBlock が使用されていないため、やはりこのコードは動作しません。

サンプル コードを理解するには、Open XML SDK 2.0 Productivity Tool for Microsoft Office を使用してドキュメントの内容を調べるのが有効です。このツールは Open XML SDK 2.0 に含まれます。図 1 は、目次を含むサンプル ドキュメントをツールで開いたところです。サンプル コードは、Document パーツの参照を取得し、そのパーツの中で、value:Table of Contents を含む DocumentPartGallery エレメント (w:docPartGallery と呼ばれます) を探します。

図 1. サンプル ドキュメントを開いてエレメントを見つける

サンプル ドキュメントを開いて要素を見つける

サンプルでは、ドキュメントの構造を変更するときに使用できる Open XML SDK 2.0 で提供されているプロパティとメソッドのうちの一部のみが紹介されています。詳細については、Open XML SDK 2.0 生産性ツールに付属するドキュメントを参照してください。アプリケーション ウィンドウの左下隅の [Open XML SDK Documentation] タブをクリックし、目的のクラスを検索します。現在ドキュメントにコード例は含まれませんが、ここで示したサンプルとドキュメントを使用すれば、サンプル アプリケーションを問題なく変更できるはずです。

ビデオ

ビデオを見る

ビデオを見る (英語) | 所要時間: 00:09:53

クリックしてコードを取得

コードを取得する (英語)

関連情報

著者について
Ken Getz 氏は、MCW Technologies のシニア コンサルタント。『ASP.NET Developers Jumpstart』(Addison-Wesley 刊、2002 年)、『 Access Developer's Handbook』(Sybex 刊、2001 年)、および『VBA Developer's Handbook, 2nd Edition』(Sybex 刊、2001 年) の共著者でもあります。