Word 2010:InlineShapeオブジェクトの縮尺をまとめて揃え、枠線を付けるマクロ

パワーポイントのスライドをワードの表(テーブル)に整列させて、スライドのサイズを適当にそろえ、枠線を付けるという作業をしている。そのためのマクロ。
できたマクロは極めてシンプルだが、作る途中にたくさん引っかかったので、メモ。
なお、この記事は先に投稿した文章を全面的に書き直したもの。

マクロ

Sub パワポの図のサイズ揃えと枠線付け()
    For Each inShp In ActiveDocument.InlineShapes
        With inShp
            .Line.Visible = 1
            .Line.ForeColor = wdColorAutomatic
            .ScaleHeight = 71
        End With
    Next
End Sub

躓いたところのメモ

そもそも自分が操作したい対象がどういうオブジェクトでどういう階層にあり、そういう操作が許されているのかが全く分からず、ドキュメントを手探りで引きまくってだんだん構造が分かってきた感じ。

Shape と InlineShape の区別

Shapeオブジェクトというものを先に見つけて、「パワーポイントのスライドはWordでは Shapeオブジェクトとして扱うのだ」と思い込んでしまったのが大失敗だった。
パワーポイントのスライドなどは、文書中の「レイアウト」によって、Shape になるか、InlineShape になるかが変わるのである。これを理解するのに数時間かかってしまった。

Activedocument.Shapes.Item(1).Select

とやっても全然スライドの図が選択できない理由がいくら検索しても、何を試しても分からず、途方に暮れたわけだ。今から思えば、そのスライドの図は表のセル内のインライン要素であって、InlineShape なので、Shapes のメソッドで選択できるはずがなかったわけである。

Word2010の「Word 開発者用リファレンス」の「Shape オブジェクト」にはこうある。

オートシェイプ、フリーフォーム、OLE オブジェクト、ActiveX コントロール、図などの描画レイヤーに含まれるオブジェクトを表します。

この「描画レイヤーに含まれる」という記述がキモだった。実際、「InlineShape オブジェクト メンバー」には

文書の文字列レイヤー内のオブジェクトを表します。位置を固定した図形にすることができるのは、図、OLE オブジェクト、または ActiveX コントロールだけです。

と、「文字列レイヤー」と書かれている。
つまり、OLE オブジェクト、ActiveX コントロール、図の3種類は「描画」か「文字列」のどちらのレイヤーにあるかによって、オブジェクトとしての扱いが変わる。
他方、オートシェイプとフリーフォームは、常に Shape オブジェクトになる。Word文書の「レイアウト」操作では、どれも同じように配置操作ができるので、マクロでも同じ扱いになるような気がするが、そうではないというわけだ。
そして、Shape, Shapes と、InlineShape, InlineShapes では、プロパティもメソッドもいろいろ異なっている。例えば、

Activedocument.Shapes.SelectAll    ……できる
Activedocument.InlineShapes.SelectAll ……できない

これも最初分からず苦戦した。Shape と InlineShape の区別が分かっていなかったから、ドキュメントをきちんと読めず、メソッドの有無を確認できなかったのだ。また、選択範囲について、

Selection.InlineShapes.Item(1)  ……できる
Selection.Shapes.Item(1)     ……できない

Selection.ShapeRange(1)     ……できる

という違いがある。Wordマクロの基本だろうと思うが、この辺も躓いたところだ。

ScaleHeight

これも、Shape と InlineShape で同名なのに扱いが異なる例。これは図形の拡大縮小率に関するメソッド・プロパティなのだが、Shape ではメソッド、InlineShape ではプロパティになっている。
Shape の場合、拡大縮小率は小数で指定するが、InlineShapeの場合は百分率で指定するのも違い。

図形の枠線

ドキュメントを眺めて、図形の枠線(輪郭)は Border や Borders だろうと思った。しかし、いろいろやって上手く行かず、どうやら Line と LineFormat らしいことが分かった。

Line.Visible

パワーポイントのスライドをワード文書にコピーすると、最初、スライドには枠線が付いていない。初め、枠線の色を指定すれば枠が付くと思っていたが、上手く行かなかった。
どこが間違っているのか分からず、いろいろやっているうちにオートシェイプで試したら色が付くことに気がつき、LineFormat のプロパティの指定が合っていないことが原因だろうと見当を絞れた。
結局、色を付けるかどうかではなく、可視化するかどうか visible かどうかを指定する必要があったことが分かった。

感想

結局、たったこれだけの自動化のために半日かかってしまった。
いつも思うことだが、マクロを作る時間の方が節約できる時間の総和よりもかなり大きい。
自分の勉強にはなるが、効率面では改善どころか悪化していて本末転倒も甚だしい。素人というか、物わかりが悪い人間の悲哀を感じている。

おまけ:マクロを書く途中で詰まってしまったときのメモ。

当時の混乱が分かるので記念に置いておく。

Word2010 Shape.ScaleHeight はメソッドなのか?
 
具体的には、msoEmbeddedOLEObject に対して働かないようだ。
Word2010 のVBAヘルプには、

Word 開発者用リファレンス
Shape.ScaleHeight メソッド
図形の高さを、指定した係数で拡大または縮小します。

とあり、サンプルコードがある。だが、この中の

s.ScaleHeight 1.75, True

を msoEmbeddedOLEObject に対して実行しようとすると、

実行時エラー'5863':
'ScaleHeight'はメソッドではありません。

というエラーが出る。

msoEmbeddedOLEObject には、Word以外のオフィス製品、例えば ExcelPowerpoint で作った図やグラフなどが含まれる。
したがって、ワード文書にパワーポイントやエクセルの図を貼り付けて、それをマクロで操作しようとすると、上手く行かないということになる(実際それで困っているのだが)。
Word2010のマクロヘルプでは、msoEmbeddedOLEObject もシンプルに操作可能なような記述があるのだが、どうも上手く行かない。そもそも msoEmbeddedOLEObject が Shapes コレクションに含まれていなかったり、Select メソッドで選択できなかったり、SelectAll メソッドでエラーが出たりする。
一番シンプルなのは、

ActiveDocument.Shapes.SelectAll

の一行だけのマクロで

実行時エラー'70':
書き込みできません。

というエラーが出る。msoEmbeddedOLEObject の有無でこのエラーの出る・出ないが変わるので、msoEmbeddedOLEObject が関与しているのだろう。
他に困っている人がいるのではないかといろいろ検索するが、似た事例はいくつかあるが、ほとんど見つからない。
環境依存型のバグ(トラブル?)だろうか?

もちろん、そんなことはないわけで完全に自分の誤解なのだが、その誤解にどうしても気づけず、外部に理由を求めようとしているところが興味深い。