現在自分は、ふらっとステーション・とつかというコミュニティカフェのネット広報を担当しています(といっても、やってることは、イベント情報をGoogleカレンダーに取り込んでるだけです)。
ふらっとステーション・とつかの広報誌、わくわくだよりは、2016/06/01時点ではWordで作られており、このWordの中から表をOLEオブジェクトを使って読み取り、GoogleカレンダーのCSV形式に変換、Googleカレンダーにインポートしています。
で、この会報誌、ときどきフォーマットが変わっており、先々月からOLEエラーが発生して読めなかったので、そのときの体験談からこの記事を書きました。
なお、この問題に対応したソースコードは、Githubに上がっています。まあ、Word形式のふらっとステーション・とつかわくわくだよりは公開されていないので、読んでもなんの役にも立たないのですが、どういう感じに使うのかの参考にでも。
なお、自分は個人的な好み(ごく簡易的なGUIがあり、OLEも呼べる)から、UWSCをOLEをいじるために使ってますが、VBAでも大体同じですので、適宜読み替えると良いかと思います。
ごくごく簡単に表を読む場合
WordのOLEオブジェクトを使って表を読む場合、DocumentオブジェクトのTablesコレクション(内のTableオブジェクト)を使います。
例えば以下のような表だと
1 | 2 | 3 |
---|---|---|
日付 | 曜日 | イベント内容 |
日付 | 曜日 | イベント内容 |
日付 | 曜日 | イベント内容 |
・・ | ・・ | ・・・・・・ |
・・ | ・・ | ・・・・・・ |
・・ | ・・ | ・・・・・・ |
・・ | ・・ | ・・・・・・ |
以下のような感じになります
DIM doc
doc = // ドキュメントオブジェクトが入る
FOR i = 1 TO doc.tables.count
DIM table = doc.tables[i]
FOR l = 1 TO table.rows.count
DIM date = table.rows[l].cells[1].range.text
DIM week = table.rows[l].cells[2].range.text
DIM detail = table.rows[l].cells[3].range.text
・・・
NEXT
NEXT
ドキュメントのTablesコレクションからTableオブジェクトを取り出し、その中のRowsコレクションから各行を示すRowオブジェクトを取り出して逐一処理していくという感じですね。
どこかの列が結合された表を読む場合
ただし、このやり方は、表の中でどこかの列が結合されているときに使うことができません(エラーが発生します)。つまり、以下のような表だとアウトと言うことです
1 | 2 | 3 |
---|---|---|
日 | 曜日 | イベント内容 |
付 | 曜日 | イベント内容 |
日 | 曜日 | イベント内容 |
付 | 曜日 | イベント内容 |
・・ | ・・ | ・・・・・・ |
・・ | ・・ | ・・・・・・ |
・・ | ・・ | ・・・・・・ |
Qiita記法にはspanを設定する記法がないため、少しわかりづらいですが、1列目の「日付」は、2行が結合されていると思ってください。
こうなると、TableオブジェクトのRowsコレクションにアクセスしようとした時点で、OLEエラーが発生します。
ではどうするかというと、TableオブジェクトのRangeプロパティを使用します。
DIM doc
doc = // ドキュメントオブジェクトが入る
FOR i = 1 TO doc.tables.count
DIM table = doc.tables[i]
FOR l = 1 TO table.range.cells.count
DIM date = table.range.cells[1].range.text
DIM week = table.range.cells[2].range.text
DIM detail = table.range.cells[3].range.text
・・・
NEXT
NEXT
ドキュメントのTablesコレクションからTableオブジェクトを取り出し、その中のRangeオブジェクトにあるCellsコレクションから、各セルを示すCellオブジェクトを取り出して逐一処理していくという感じです。
セルのColumnIndexを知りたい場合
では今見ようとしているセルが、テーブル上の何番目の列に位置するのかというのを確認するにはどうすればいいでしょうか。
それは、CellオブジェクトのColumnIndexプロパティを使用します。
table.range.cells[1].columnindex // 上に書いた表の通りであれば1
table.range.cells[2].columnindex // 上に書いた表の通りであれば2
table.range.cells[3].columnindex // 上に書いた表の通りであれば3
table.range.cells[4].columnindex // 上に書いた表の通りであれば2
table.range.cells[5].columnindex // 上に書いた表の通りであれば3
table.range.cells[6].columnindex // 上に書いた表の通りであれば1
ということで、table.range.cells[n].range.text
とtable.range.cells[1].columnindex
を使えば、とりあえず表の走査には困らなさそうです。