Word for WPF
TOC の追加
Word for WPF の操作 > 上級レベルの操作 > TOC の追加

Word for WPF では、テキストと見出しを含む Word ドキュメントに目次(TOC)を追加できます。これらの見出しを使用して TOC を作成します。次のコードは、テキストと見出しを含む Word ドキュメントの TOC を作成します。

次のコードでは、WordUtils というクラスを使用しています。このクラスは、システムの次の場所にある製品サンプル内に置かれています。
Documents\ComponentOne Samples\WPF\WordCreator
これらのクラスを上記の場所からアプリケーションで使用できます。

派生しているWindowクラス内に次のコード行を追加して、乱数を生成し、文字列参照を使用します。

Shared rnd As New Random()
Shared _extension As String = ".rtf"
                        
static Random rnd = new Random();
static string _extension = ".rtf";

次のコードは、テキストとヘッダーを含むWord文書のコンテンツとTOCを作成します。

' ドキュメントを作成します
Dim word = New C1WordDocument()
word.Clear()
word.Info.Title = "Document with Table of Contents"

' タイトルを追加します
Dim titleFont As New Font("Tahoma", 24, RtfFontStyle.Bold)
Dim rcPage As Rect = WordUtils.PageRectangle(word)
Dim rc As Rect = WordUtils.RenderParagraph(word, word.Info.Title, 
              _titleFont, rcPage, rcPage, False)
rc.Y += 12

' ナンセンス文書を作成します
Dim bkmk = New List()
Dim headerFont As New Font("Arial", 14, RtfFontStyle.Bold)
Dim bodyFont As New Font("Times New Roman", 11)
For i As Integer = 0 To 29
        ' i番目のヘッダを作成します(リンク先とアウトラインエントリとして)
        Dim header As String = String.Format("{0}. {1}", i + 1, BuildRandomTitle())
        rc = WordUtils.RenderParagraph(word, header, headerFont, rcPage, rc, True, _
                True)

        ' 後で TOC を構築するためにブックマークを保存します
        Dim pageNumber As Integer = 1
        bkmk.Add(New String() {pageNumber.ToString(), header})

        ' テキストを作成します
        rc.X += 36
        rc.Width -= 36

        For j As Integer = 0 To 3 + (rnd.[Next](20) - 1)
                Dim text As String = BuildRandomParagraph()
                rc = WordUtils.RenderParagraph(word, text, bodyFont, rcPage, rc)
                rc.Y += 6
        Next
        rc.X -= 36
        rc.Width += 36
        rc.Y += 20
Next

' TOC を開始します
word.PageBreak()
' 新しいページで TOC を開始します
rc = WordUtils.RenderParagraph(word, "WPFのコントロール", titleFont, rcPage, rcPage, True)
rc.Y += 12
rc.X += 30
rc.Width -= 40

' TOC をレンダリングします
Dim dottedPen As New C1.WPF.Word.Pen(Colors.Gray, 1.5F)
dottedPen.DashStyle = C1.WPF.Word.DashStyle.Dot
Dim sfRight As New StringFormat()
sfRight.Alignment = HorizontalAlignment.Right
rc.Height = bodyFont.Size * 1.2

For Each entry As String() In bkmk
        ' ブックマーク情報を取得します
        Dim page As String = entry(0)
        Dim header As String = entry(1)

        ' 見出し名とページ番号をレンダリングします
        word.DrawString(header, bodyFont, Colors.Black, rc)
        word.DrawString(page, bodyFont, Colors.Black, rc, sfRight)


        ' 2つをいくつかの点で結びます(点線よりも見やすい)
        Dim dots As String = ". "
        Dim wid = word.MeasureString(dots, bodyFont).Width
        Dim x1 = rc.X + word.MeasureString(header, bodyFont).Width + 8
        Dim x2 = rc.Right - word.MeasureString(page, bodyFont).Width - 8
        Dim x = rc.X
        rc.X = x1
        While rc.X < x2
                word.DrawString(dots, bodyFont, Colors.Gray, rc)
                rc.X += wid
        End While
        rc.X = x

        ' 次のエントリに移動します
        rc = WordUtils.Offset(rc, 0, rc.Height)
        If rc.Bottom > rcPage.Bottom Then
                word.PageBreak()
                rc.Y = rcPage.Y
        End If
Next

' 保存するストリームを取得します
Dim dlg = New SaveFileDialog()
dlg.FileName = "Sample document"
dlg.DefaultExt = ".docx"
dlg.Filter = WordUtils.GetFileFilter(_extension)
Dim dr = dlg.ShowDialog()
If Not dr.HasValue OrElse Not dr.Value Then
        Return
End If

' 文書を保存します
Using stream = dlg.OpenFile()
        word.Save(stream, If(dlg.FileName.ToLower().EndsWith(".docx"), 
_FileFormat.OpenXml, FileFormat.Rtf))
End Using
MessageBox.Show("Word Document saved to " + dlg.SafeFileName)
// ドキュメントを作成しますvar word = new C1WordDocument();
word.Clear();
word.Info.Title = "Document with Table of Contents";

// タイトルを追加しますFont titleFont = new Font("Tahoma", 24, RtfFontStyle.Bold);
Rect rcPage = WordUtils.PageRectangle(word);
Rect rc = WordUtils.RenderParagraph(word, word.Info.Title, titleFont, rcPage, rcPage, false);
rc.Y += 12;

// ナンセンス文書を作成しますvar bkmk = new List();
Font headerFont = new Font("Arial", 14, RtfFontStyle.Bold);
Font bodyFont = new Font("Times New Roman", 11);
for (int i = 0; i < 30; i++)
{
    // i番目のヘッダを作成します(リンク先とアウトラインエントリとして)

    string header = string.Format("{0}. {1}", i + 1, BuildRandomTitle());
    rc = WordUtils.RenderParagraph(word, header, headerFont, rcPage, rc, true, true);

     // 後で TOC を構築するためにブックマークを保存します
     int pageNumber = 1;
     bkmk.Add(new string[] { pageNumber.ToString(), header });

     // テキストを作成します
     rc.X += 36;
     rc.Width -= 36;

     for (int j = 0; j < 3 + rnd.Next(20); j++)
     {
          string text = BuildRandomParagraph();
          rc = WordUtils.RenderParagraph(word, text, bodyFont, rcPage, rc);
          rc.Y += 6;
      }
      rc.X -= 36;
      rc.Width += 36;
      rc.Y += 20;
}

// TOC を開始します
word.PageBreak();                  

// 新しいページで TOC を開始します
rc = WordUtils.RenderParagraph(word, "WPFのコントロール", titleFont, rcPage, rcPage, true);
rc.Y += 12;
rc.X += 30;
rc.Width -= 40;

// TOC をレンダリングします
C1.WPF.Word.Pen dottedPen = new C1.WPF.Word.Pen(Colors.Gray, 1.5f);
dottedPen.DashStyle = C1.WPF.Word.DashStyle.Dot;
StringFormat sfRight = new StringFormat();
sfRight.Alignment = HorizontalAlignment.Right;
rc.Height = bodyFont.Size * 1.2;

foreach (string[] entry in bkmk)
{
     // ブックマーク情報を取得します
     string page = entry[0];
     string header = entry[1];

      // 見出し名とページ番号をレンダリングします
      word.DrawString(header, bodyFont, Colors.Black, rc);
      word.DrawString(page, bodyFont, Colors.Black, rc, sfRight);


      // 2つをいくつかの点で結びます(点線よりも見やすい)
      string dots = ". ";
      var wid = word.MeasureString(dots, bodyFont).Width;
      var x1 = rc.X + word.MeasureString(header, bodyFont).Width + 8;
      var x2 = rc.Right - word.MeasureString(page, bodyFont).Width - 8;
      var x = rc.X;
      for (rc.X = x1; rc.X < x2; rc.X += wid)
      {
           word.DrawString(dots, bodyFont, Colors.Gray, rc);
      }
      rc.X = x;

      // 次のエントリに移動します

      rc = WordUtils.Offset(rc, 0, rc.Height);
      if (rc.Bottom > rcPage.Bottom)
      {
           word.PageBreak();
           rc.Y = rcPage.Y;
      }
}
            
// 保存するストリームを取得します
var dlg = new SaveFileDialog();
dlg.FileName = "Sample document";
dlg.DefaultExt = ".docx";
dlg.Filter = WordUtils.GetFileFilter(_extension);
var dr = dlg.ShowDialog();
if (!dr.HasValue || !dr.Value)
{
     return;
}

// ドキュメントを保存します
using (var stream = dlg.OpenFile())
{
     word.Save(stream, dlg.FileName.ToLower().EndsWith(".docx") ? FileFormat.OpenXml : FileFormat.Rtf);
}
MessageBox.Show("Word Document saved to " + dlg.SafeFileName);

上記のコードは、ドキュメント内のテキストの見出しにブックマークを追加します。次に、これらのブックマークを使用して TOC を生成します。

上記のコードでは、BuildRandomParagraphとBuildRandomTitleの2つのメソッドを使用しています。これらのメソッドには、次のコードのように指定された形式で文字列の配列およびreturn文字列がふくまれています。同様に、独自のメソッドや文字列値を作成することもできます。

Private Shared Function BuildRandomTitle() As String
    Dim a1 As String() = "Learning|Explaining|Mastering|Forgetting|Examining|Understanding|Applying|Using|Destroying".Split("|"C)
    Dim a2 As String() = "Music|Tennis|Golf|Zen|Diving|Modern Art|Gardening|Architecture|Mathematics|Investments|.NET|Java".Split("|"C)
    Dim a3 As String() = "Quickly|Painlessly|The Hard Way|Slowly|Painfully|With Panache".Split("|"C)
    Return String.Format("{0} {1} {2}", a1(rnd.[Next](a1.Length - 1)), a2(rnd.[Next](a2.Length - 1)), a3(rnd.[Next](a3.Length - 1)))
End Function

Private Shared Function BuildRandomParagraph() As String
    Dim sb As New StringBuilder()
    For i As Integer = 0 To 5 + (rnd.[Next](10) - 1)
          sb.AppendFormat(BuildRandomSentence())
    Next
    Return sb.ToString()
End Function

Private Shared Function BuildRandomSentence() As String
    Dim a1 As String() = "Artists|Movie stars|Musicians|Politicians|Computer programmers|Modern thinkers|Gardeners|Experts|Some people|Hockey players".Split("|"C)
    Dim a2 As String() = "know|seem to think about|care about|often discuss|dream about|hate|love|despise|respect|long for|pay attention to|embrace".Split("|"C)
    Dim a3 As String() = "the movies|chicken soup|tea|many things|sushi|my car|deep thoughs|tasteless jokes|vaporware|cell phones|hot dogs|ballgames".Split("|"C)
    Dim a4 As String() = "incessantly|too much|easily|without reason|rapidly|sadly|randomly|vigorously|more than usual|with enthusiasm|shamelessly|on Tuesdays".Split("|"C)
    Return String.Format("{0} {1} {2} {3}. ", a1(rnd.[Next](a1.Length - 1)), a2(rnd.[Next](a2.Length - 1)), a3(rnd.[Next](a3.Length - 1)), a4(rnd.[Next](a4.Length - 1)))
End Function
static string BuildRandomTitle() {
  string[] a1 = "Learning|Explaining|Mastering|Forgetting|Examining|Understanding|Applying|Using|Destroying".Split('|');
  string[] a2 = "Music|Tennis|Golf|Zen|Diving|Modern Art|Gardening|Architecture|Mathematics|Investments|.NET|Java".Split('|');
  string[] a3 = "Quickly|Painlessly|The Hard Way|Slowly|Painfully|With Panache".Split('|');
  return string.Format("{0} {1} {2}", a1[rnd.Next(a1.Length - 1)], a2[rnd.Next(a2.Length - 1)], a3[rnd.Next(a3.Length - 1)]);
}

static string BuildRandomParagraph() {
  StringBuilder sb = new StringBuilder();
  for (int i = 0; i < 5 + rnd.Next(10); i++) {
    sb.AppendFormat(BuildRandomSentence());
  }
  return sb.ToString();
}

static string BuildRandomSentence() {
  string[] a1 = "Artists|Movie stars|Musicians|Politicians|Computer programmers|Modern thinkers|Gardeners|Experts|Some people|Hockey players".Split('|');
  string[] a2 = "know|seem to think about|care about|often discuss|dream about|hate|love|despise|respect|long for|pay attention to|embrace".Split('|');
  string[] a3 = "the movies|chicken soup|tea|many things|sushi|my car|deep thoughs|tasteless jokes|vaporware|cell phones|hot dogs|ballgames".Split('|');
  string[] a4 = "incessantly|too much|easily|without reason|rapidly|sadly|randomly|vigorously|more than usual|with enthusiasm|shamelessly|on Tuesdays".Split('|');
  return string.Format("{0} {1} {2} {3}. ", a1[rnd.Next(a1.Length - 1)], a2[rnd.Next(a2.Length - 1)], a3[rnd.Next(a3.Length - 1)], a4[rnd.Next(a4.Length - 1)]);
}

上記のコードの出力は、次の図のようになります。