Wordにはグラフィックアイテムとして図形と画像があり、配置方法として行内と非行内(四角、外周、内部、上下、背面、前面)があります。
編集時にはそれぞれ扱い方や操作に違いがあるのですが、VBAでは編集時とはまた別のややこしい違いがあるのです。
InlineShapeとShape/画像と図形
配置が行内ならInlineShapeオブジェクト、非行内ならShapeオブジェクトと思いきや、そうではありません。
図形は行内・非行内ともにShapeです。画像は行内ならInlineShape、非行内ならShapeです。
つまり、Shapeオブジェクトには非行内の画像、行内の図形、非行内の図形が含まれ、InlineShapeオブジェクトは行内の画像となります。
なお、グループは中に画像が含まれていても図形と同じ扱いになります。
Shapeオブジェクトの判別
行内と非行内の判別 : WrapFormat.Type プロパティ
Shape.WrapFormat.Type
プロパティで判別します。行内は wdWrapInline
です。非行内は wdWrapBehind
、wdWrapTopBottom
などになります。
画像と図形の判別 : Type プロパティ
処理によっては図形か画像かで扱い方が違うので判別が必要になります。
Shape.Type
プロパティで判別します。画像は msoPicture
または msoLinkedPicture
です。図形は msoAutoShape
、msoLine
、msoGroup
などになります。
Shape と InlineShape の変換
ShapeとInlineShapeは互いに変換できますが、図形と画像とで変換手段が異なります。
図形の場合、上記の WrapFormat.Type
プロパティの値を変更すればOKです。
画像の場合、InlineShapeはConvertToShape
メソッド、Shapeは ConvertToInlineShape
メソッドで変換します。WrapFormat.Type
プロパティに値を指定してもエラーになります。
'例: Shape.Typeが画像またはグループなら配置を行内に変更する
With ActiveDocument.Shapes(1)
Select Case .Type
Case msoPicture, msoLinkedPicture
.ConvertToInlineShape
Case msoGroup
.WrapFormat.Type = wdWrapInline
End Select
End With
ShapesコレクションとShapeRangeコレクション
Shape オブジェクトをメンバーとするコレクションには、ShapesとShapeRangeの2つがあります。Shapesは文書内、ShapeRangeは範囲内のShapeオブジェクトを扱います。
Shapesコレクション : 文書内のShapeオブジェクトを処理する
Shapesコレクションは文書内の範囲や位置と紐づいていないため、Selection.Shapes
のような使い方はできません。For Each
文で各Shapeオブジェクトにアクセスできます。
'例: 文書内のShapeオブジェクトを処理する
Dim objShp As Shape
For Each objShp In ActiveDocument.Shapes
'各Shapeオブジェクトの処理
'...
Next objShp
ShapeRangeコレクション : 選択しているShapeオブジェクトを処理する
ShapeRange.Count
でShapeメンバーの数を求められます。各Shapeオブジェクトにはインデックスでアクセスできます。選択しているShapeに限らず、指定するRangeに応じて対象を使い分けられます。
'例: 範囲内のShapeオブジェクトを処理する
Dim objShp As Shape
Dim i As Long
With Selection.Range '選択しているShapeの場合
' With ActiveDocument.Content '文書内の全Shapeの場合
For i = 1 To .ShapeRange.Count
Set objShp = .ShapeRange(i)
'各Shapeオブジェクトの処理
'...
Next i
End With
図形・画像を選択するには、オブジェクトを直接選択する方法と、オブジェクト(またはそのアンカー)がある段落を選択する方法があります。
直接選択の場合 : Selection.ShapeRange
Selection.ShapeRange
で、直接選択されたShapeが対象になります。1個以上の非行内Shapeまたは1個の行内Shape(複数選択できないため)を扱えます。
段落選択の場合 : Selection.Range.ShapeRange