カテゴリー名: [WordVBAとOLE 基本構成とその操作]
Word文書における表(Table)の取り扱いについて解説。
Word文書の構成要素の一つに表(Table)があります。
表の集合は ActiveDocument.Tables
で表現します。
表の個数(総数)は ActiveDocument.Table.Count
で知ることができます。
最初の表は ActiveDocument.Tables(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 というメソッドでは多くのオプションを指定できますが、ここでは説明省略。
表の罫線を引く方法はいくつかありますが、簡単なやり方としては下のものがあります。
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
表の第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 | 均等割り付け |
「概要」で述べたことを踏まえて作成したマクロが下のものです。
タブ区切りデータを読み込んで、それを表に変換し、
罫線を引いてから、セルの文字配置を調整します。
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
を使うときは、変数の型宣言が要注意です。
前述のVBAマクロと同じ処理を行うVBScriptは下のようになります。
組み込み定数があれこれ出てくるので、constants_wd.vbs を読み込む形にしました。
constants_wd.vbs では約3,200の定数を定義しています。Word2010で定義されているwdで始まる定数は、一通り含まれていると思います。
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
先のVBScriptと同じ処理を行うJScriptは次のとおり。
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
と同じように使える構文がないようなので別の形式にしてあります。
でも、私の知識不足で、もっとスマートなやり方があるのかもしれません。
これまでのサンプルでは文書に一つの表を書き込むケースを取り上げてきました。文書全体を使って表だけを書き込むやり方です。
しかし、実践では文章の間に表が挿入されているのが普通です。
そこで、カーソル位置に表を挿入するVBAマクロを掲げておきます。
表の作成方法は、これまで掲げてきたサンプルと同じです。
それから、ページ内で表そのものを中央揃えにするマクロも取り上げます。
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 が実行されます。
次のマクロ記述で文書の段落(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
で文字列テキストを取り出した場合、こうした特殊コードが含まれている可能性があります。
〜 以上 〜