Wordにおける表の取り扱い

カテゴリー名: [WordVBAとOLE 基本構成とその操作

2016/10/09

Word文書における表(Table)の取り扱いについて解説。


《このページの目次》


    

1. 概要

 Word文書の構成要素の一つに表(Table)があります。

  表の集合は ActiveDocument.Tables で表現します。

 表の個数(総数)は ActiveDocument.Table.Count で知ることができます。

 最初の表は ActiveDocument.Tables(1) で得られます。

    

(1) とりあえず表を作成する

 CSVデータ、またはタブ区切りデータを表に変換するための ConvertToTable というメソッドがあります。Rangeオブジェクトに対して適用できます。

Set rng = ActiveDocument.Range(0, 36)
rng.ConvertToTable ","

 上の2行は、文字の0番〜36番の範囲(Rangeオブジェクト)を表に変換するものです。

 RangeオブジェクトにはCSVデータが書かれている必要があります。

 タブ区切りデータなら、","vbTab にします。つまり、2行目を
rng.ConvertToTable vbTab とします。

 タブ区切りデータが tbl01.txt というファイルに書かれている場合、それを読み込んで表に変換するマクロを下に掲げます。

    

Sub Macro1()
    With ActiveDocument
        .Content.Delete  ' 本文部分を全クリア
        .Range(0,0).InsertFile .Path & "\tbl01.txt"
        .Content.Style = wdStyleNormal  ' 標準スタイルを適用
        .Content.ConvertToTable vbTab
    End With
End Sub

    

 上のマクロを実行すると、tbl01.txt が読み込まれ、そこに書かれているタブ区切りデータが表に変換されます。

 ConvertToTable というメソッドでは多くのオプションを指定できますが、ここでは説明省略。


    

(2) 表の罫線

 表の罫線を引く方法はいくつかありますが、簡単なやり方としては下のものがあります。

ActiveDocument.Tables(1).Borders.InsideLineStyle = wdLineStyleSingle
ActiveDocument.Tables(1).Borders.OutsideLineStyle = wdLineStyleDouble

 上は、外側罫線を二重線にし、内側罫線を細線にします。

 指定できる罫線の種類は多種あります。下のサイトを参考にして下さい。

WdLineStyle列挙型 (Microsoft.Office.Interop.Word)

 罫線を引くためのマクロを掲げておきます。

 前述の ConvertToTable を利用する表作成の方法に、罫線設定を付け加えるだけのものです。

    

Sub Macro1()
    With ActiveDocument
        .Content.Delete  ' 本文部分を全クリア
        .Range(0,0).InsertFile .Path & "\tbl01.txt"
        .Content.Style = wdStyleNormal  ' 標準スタイルを適用
        .Content.ConvertToTable vbTab
        .Tables(1).Borders.InsideLineStyle = wdLineStyleSingle
        .Tables(1).Borders.OutsideLineStyle = wdLineStyleDouble
    End With
End Sub

    

(3) セルごとに文字の配置を設定する

 表の第1行目は項目名なので均等割り付けにして、整数値に関する欄は右揃えにするというのをやってみます。

 表を細かく分解するとセル(Cell)になります。

 また、表は、横方向に伸びる行(Row)、縦方向に伸びる列(Column)という単位でとらえることができます。

 一つの行(Row)、あるいは一つの列(Column)は、それぞれ複数のセルから構成されているのが一般的です。

    

 表の一番左上のセルは下のように表現できます。

ActiveDocument.Tables(1).Rows(1).Cells(1)
ActiveDocument.Tables(1).Columns(1).Cells(1)
ActiveDocument.Tables(1).Cell(1,1)

 上の3種類の記述は、同じセルオブジェクトを指し示します。
ExcelでいえばA1セルです。

 B1セルは次のようになります。

ActiveDocument.Tables(1).Rows(1).Cells(2)
ActiveDocument.Tables(1).Columns(2).Cells(1)
ActiveDocument.Tables(1).Cell(1,2)

 Cell(1,2) は、第1パラメータが行(Row)、第2パラメータが列(Column)を示します。

    

 セルにおける文字の配置は、段落(Paragraph)の場合と違い Alignmentプロパティを使って行うことができません。

 なので、セルオブジェクトからRangeオブジェクトを取り出して、そのRangeを使って配置を設定します。

 変数 CELLobj にセルオブジェクトが代入されている場合、次のようにします。

CELLobj.Range.ParagraphFormat.Alignment = wdAlignParagraphRight

 上は、セル内の文字を右揃えにします。

 主な配置用の組み込み定数は下のとおり。

定数名 意味
wdAlignParagraphLeft 0 左揃え
wdAlignParagraphCenter 1 中央揃え
wdAlignParagraphRight 2 右揃え
wdAlignParagraphJustify 3 両端揃え
wdAlignParagraphDistribute 4 均等割り付け

    

2. VBAマクロ

 「概要」で述べたことを踏まえて作成したマクロが下のものです。

 タブ区切りデータを読み込んで、それを表に変換し、
 罫線を引いてから、セルの文字配置を調整します。

△ macro03.txt

 1' Wordにおける表の取り扱い
 2Sub Macro1()
 3    Dim CN As Variant
 4    Dim CELLobj As Variant
 5
 6    With ActiveDocument
 7        .Content.Delete  ' 本文部分を全クリア
 8        .Range(0,0).InsertFile .Path & "\tbl01.txt"
 9        .Content.Style = wdStyleNormal  ' 標準スタイルを適用
10        .Content.ConvertToTable vbTab
11        .Tables(1).Borders.InsideLineStyle = wdLineStyleSingle
12        .Tables(1).Borders.OutsideLineStyle = wdLineStyleDouble
13        For Each CN In Array(1, 2, 4)  ' 1列, 2列, 4列を右揃えに
14            For Each CELLobj In .Tables(1).Columns(CN).Cells
15                CELLobj.Range.ParagraphFormat.Alignment = _
16                    wdAlignParagraphRight
17            Next
18        Next
19        For Each CELLobj In .Tables(1).Rows(1).Cells  ' 1行目を均等割付
20            CELLobj.Range.ParagraphFormat.Alignment = _
21                wdAlignParagraphDistribute
22        Next
23    End With
24End Sub

    

 For Each …… In …… Next の構文を何度か使っています。

 これは、配列やコレクションの要素を一つずつたどるのに便利なので使ってみました。

 For Each CN In …… とか、
 For Each CELLobj In …… と書いていますが、
 このような場合、変数 CN, CELLobj は、Variant型か Object型でないとエラーになるようです。

 For Each …… In を使うときは、変数の型宣言が要注意です。

目次に戻る


    

3. OLEを利用するVBScript

 前述のVBAマクロと同じ処理を行うVBScriptは下のようになります。

 組み込み定数があれこれ出てくるので、constants_wd.vbs を読み込む形にしました。

 constants_wd.vbs では約3,200の定数を定義しています。Word2010で定義されているwdで始まる定数は、一通り含まれていると思います。

△ vovWD03.vbs

 1' Wordにおける表の取り扱い
 2Option Explicit
 3Dim FSO, DocPath
 4Dim WDapp, DOCobj, CN, CELLobj
 5Include("constants_wd.vbs")
 6
 7Set FSO = CreateObject("Scripting.FileSystemObject")
 8DocPath = FSO.GetAbsolutePathName("Test01.doc")
 9If (FSO.FileExists(DocPath) = True) Then FSO.DeleteFile(DocPath)
10Set WDapp = CreateObject("Word.Application")  ' Wordの起動
11WDapp.Visible = True  ' Wordを見える状態に
12Set DOCobj = WDapp.Documents.Add()
13With DOCobj
14    .Range(0,0).InsertFile FSO.GetAbsolutePathName("tbl01.txt")
15    .Content.Style = wdStyleNormal  ' 標準スタイルを適用
16    .Content.ConvertToTable vbTab
17    .Tables(1).Borders.InsideLineStyle = wdLineStyleSingle
18    .Tables(1).Borders.OutsideLineStyle = wdLineStyleDouble
19    For Each CN In Array(1, 2, 4)  ' 1列, 2列, 4列を右揃えに
20        For Each CELLobj In .Tables(1).Columns(CN).Cells
21            CELLobj.Range.ParagraphFormat.Alignment = wdAlignParagraphRight
22        Next
23    Next
24    For Each CELLobj In .Tables(1).Rows(1).Cells  ' 1行目を均等割付
25        CELLobj.Range.ParagraphFormat.Alignment = wdAlignParagraphDistribute
26    Next
27End With
28DOCobj.SaveAs DocPath, WdFormatDocument
29WDapp.Quit
30
31Sub Include(ByVal FileName)
32    Dim FSO, FileObj, MyStr
33    Set FSO = CreateObject("Scripting.FileSystemObject") 
34    Set FileObj = FSO.OpenTextFile(FSO.GetAbsolutePathName(FileName))
35    MyStr = FileObj.ReadAll()
36    FileObj.Close
37    Set FSO = Nothing
38    Set FileObj = Nothing
39    ExecuteGlobal MyStr
40End Sub

目次に戻る


    

4. JScript

 先のVBScriptと同じ処理を行うJScriptは次のとおり。

△ vovWD03.js

 1// Wordにおける表の取り扱い
 2var fso, docPath;
 3var WdApp, docObj, cells;
 4var cn, cnAry, i;
 5eval(ReadFile("constants_wd.js"));
 6
 7fso = WScript.CreateObject("Scripting.FileSystemObject");
 8docPath = fso.GetAbsolutePathName("Test01.doc");
 9if (fso.FileExists(docPath))  fso.DeleteFile(docPath);
10WdApp = WScript.CreateObject("Word.Application");  // Wordの起動
11WdApp.Visible = true;  // Wordを見える状態に
12docObj = WdApp.Documents.Add();
13with (docObj) {
14    Range(0,0).InsertFile(fso.GetAbsolutePathName("tbl01.txt"));
15    Content.Style = wdStyleNormal;  // 標準スタイルを適用
16    Content.ConvertToTable("\t");
17    Tables(1).Borders.InsideLineStyle = wdLineStyleSingle;
18    Tables(1).Borders.OutsideLineStyle = wdLineStyleDouble;
19    cnAry = [1, 2, 4];
20    while (cn = cnAry.shift()) {  // 1列, 2列, 4列を右揃えに
21        cells = Tables(1).Columns(cn).Cells;
22        for (i=1; i<=cells.Count; i++) {
23            cells(i).Range.ParagraphFormat.Alignment = wdAlignParagraphRight;
24        }
25    }
26    cells = Tables(1).Rows(1).Cells;
27    for (i=1; i<=cells.Count; i++) {  // 1行目を均等割付
28        cells(i).Range.ParagraphFormat.Alignment = wdAlignParagraphDistribute;
29    }
30}
31docObj.SaveAs(docPath, wdFormatDocument);
32WdApp.Quit();
33
34function ReadFile(filename) {
35    var fso = WScript.CreateObject("Scripting.FileSystemObject");
36    var path = fso.GetAbsolutePathName(filename);
37    var MyStr = null;
38    if (fso.FileExists(path)) {
39        var fobj = fso.OpenTextFile(path, 1);
40        MyStr = fobj.ReadAll();
41        fobj.Close();
42    }
43    return MyStr;
44}

    

 JScriptでは、VBA, VBScriptの For Each と同じように使える構文がないようなので別の形式にしてあります。

 でも、私の知識不足で、もっとスマートなやり方があるのかもしれません。

目次に戻る


    

5. カーソル位置への表の挿入&表そのものの中央揃え

 これまでのサンプルでは文書に一つの表を書き込むケースを取り上げてきました。文書全体を使って表だけを書き込むやり方です。

 しかし、実践では文章の間に表が挿入されているのが普通です。

 そこで、カーソル位置に表を挿入するVBAマクロを掲げておきます。

 表の作成方法は、これまで掲げてきたサンプルと同じです。

 それから、ページ内で表そのものを中央揃えにするマクロも取り上げます。

    

△ macro03b.txt

 1' Wordにおける表の取り扱い・その2
 2Sub Macro1()  ' カーソル位置にタブ区切りファイルを読み込んで表を作成
 3    Dim rs As Integer
 4    Dim rng As Range
 5    Dim tbl As Table
 6    Dim CN As Variant
 7    Dim CELLobj As Variant
 8
 9    With ActiveDocument
10        rs = Selection.Range.Start
11        Set rng = .Range(rs, rs+1)
12        .Range(rs, rs).InsertFile .Path & "\tbl01.txt"
13        Set rng = .Range(rng.Start, rng.End-1)
14        rng.Style = wdStyleNormal  ' 標準スタイルを適用
15        rng.ConvertToTable vbTab
16        Set tbl = rng.Tables(1)
17        tbl.Borders.InsideLineStyle = wdLineStyleSingle
18        tbl.Borders.OutsideLineStyle = wdLineStyleDouble
19        For Each CN In Array(1, 2, 4)  ' 1列, 2列, 4列を右揃えに
20            For Each CELLobj In tbl.Columns(CN).Cells
21                CELLobj.Range.ParagraphFormat.Alignment = _
22                    wdAlignParagraphRight
23            Next
24        Next
25        For Each CELLobj In tbl.Rows(1).Cells  ' 1行目を均等割付
26            CELLobj.Range.ParagraphFormat.Alignment = _
27                wdAlignParagraphDistribute
28        Next
29    End With
30End Sub
31
32Sub Macro2()  ' 選択範囲内の表を中央揃えにする
33    Dim tbl As Variant
34    If Selection.Tables.Count > 0 Then
35        For Each tbl In Selection.Tables
36            tbl.Rows.Alignment = wdAlignRowCenter
37        Next
38    Else
39        MsgBox "選択範囲に表がありません。"
40    End If
41End Sub

    

 InsertFileメソッドでファイルを読み込んだ場合、読み込まれたデータ(表の素材となるタブ区切りデータ)がどこに位置するのか、それが把握できれば後は簡単です。

 ただ、その把握が少し厄介でした。InsertFileの実行に合わせて該当のRangeオブジェクトの大きさが自動的に変化してくれるのではないかと期待したのですが、正確な形では自動変化しないようです。

 結果、サンプルにあるような少しややこしい方法を採りました。一つのやり方として参考にして下さい。

    

 Macro2 の方は、選択範囲内の表を中央揃えにするものです。表をページ内で中央揃えにします。

 選択範囲が表全体をすっぽり含んでいなくても、カーソルが表の中にある状態で Macro2 を実行すると、その表が中央揃えになります。

 Selection.Tables で選択範囲(カーソル位置にかかわる範囲)における表を取り出せることを利用しています。

    

 SetWordMacro.vbs でマクロを組み込んだ場合は、
生成される Test01.doc を開いてから
Control + 8 で Macro1 が実行され、
Control + 9 で Macro2 が実行されます。

目次に戻る


    

6. 補足(CellとParagraph)

 次のマクロ記述で文書の段落(Paragraph)を一つずつたどったとします。

For Each para In ActiveDocument.Paragraphs
    MsgBox para.Range.Text
Next

 上は、段落の文字列テキストを表示するものです。

 表が含まれている文祖で上のマクロを実行すると、表のセルが段落として表示されるのが分かります。

 表の1行(Row)が一つの段落になっているのではなく、一つのセルが一つの段落になっています。

 また、ある段落が表に所属しているかどうかを Informationプロパティで確認できます。

 para.Range.Information(wdWithInTable) が True であれば para が表に所属しており、False だと表に所属していないことを示します。

    

 ただ、表のセルを段落としてたどるのは、やはり避けた方が無難です。

 たとえば、3行×4列の表には12個のセルが含まれますが、
この表を段落でたどると、3×5=15個の段落が含まれる形になります。
なぜか列数が一つ増えます。中身が空っぽの列が加わります。

 「そうした仕様であることを承知のうえで、段落でたどる」という方が便利なケースがないとはいえませんが、普通は表の行(Row)あるいは列(Column)ごとにセルをたどるのが無難です。

    

 あと、一般の文章なら段落の末尾が vbCr という開業コードですが、表のセルの場合は違います。

 vbCr は、アスキーコード(文字に割り当てられた番号)でいうと、13番です。Chr(13) と書くことができます。

 これに対して表のセルの場合は、末尾が Chr(13) & Chr(7) の2桁です。

 para.Range.Text とか cell.Range.Text のようにして文字列テキストを取り出したとき、末尾に上記のようなコードがあるので注意して下さい。

    

 ちなみに、一つの段落またはセルが2行以上になっているケースがあります。

 WordをGUI操作しているとき、リターンキーをたたくと通常の改行ですが、シフトキーを押しながらリターンキーをたたくと「行区切り」となって行がかわります。

 この「行区切り」を行ったときは、Chr(8) が挿入されます。

 Range.Text で文字列テキストを取り出した場合、こうした特殊コードが含まれている可能性があります。

〜 以上 〜