和風スパゲティのレシピ

日本語でコーディングするExcelVBA

図形の前面/背面を設定・変更する - ZOrder

図形の重なり順(前面・背面)を設定・変更する方法を解説します。

ShapeオブジェクトのZOrderメソッドを実行します。

図形を最前面/最背面/ひとつ前面/ひとつ背面に移動する

基本コード

Dim 対象図形 As Shape
Set 対象図形 = Worksheets("○○").Shapes("Rectangle 1")

' 最前面に移動
対象図形.ZOrder msoBringToFront

' 最背面に移動
対象図形.ZOrder msoSendToBack

' ひとつ前面に移動
対象図形.ZOrder msoBringForward

' ひとつ背面に移動
対象図形.ZOrder msoSendBackward

解説

ShapeオブジェクトのZOrderメソッドを実行すると、
図形(画像やグラフを含む)の重なり順を変更することができます。

実行内容を指定する第2引数の各値は以下の通りです。

定数 実行内容
msoBringToFront 0 最前面に
msoSendToBack 1 最背面に
msoBringForward 2 ひとつ前面に
msoSendBackward 3 ひとつ背面に
msoBringInFrontOfText 4 テキストの前面に(Word限定)
msoSendBehindText 5 テキストの背面に(Word限定)

余談ですが前面と背面で違う動詞が使われている定数で、
前面には「持ってくる:Bring」、背面には「送る:Send」が使われています。

選択した図形(Selection)に実行したい場合

選択した図形(図形を選択時のSelection)のデータ型は、
ShapeオブジェクトではなくDrawingObjectオブジェクトになっています。

DrawingObjectからShape型のメソッドを実行したい場合は、
ShapeRangeプロパティをかませて実行してください。

' 最前面に移動
Selection.ShapeRange.ZOrder msoBringToFront

' 最背面に移動
Selection.ShapeRange.ZOrder msoSendToBack

' ひとつ前面に移動
Selection.ShapeRange.ZOrder msoBringForward

' ひとつ背面に移動
Selection.ShapeRange.ZOrder msoSendBackward

 
なお、ShapeRangeはShapeと同一のメソッドを持っているだけで、
Shape型ではありません。(その名の通りShapeRange型です)

よってShape型変数に入れることはできませんのでご注意ください。

Dim 対象図形 As Shape
Set 対象図形 = Selection.ShapeRange
    ' ↑これは「型が一致しません」エラー

Dim 対象図形 As ShapeRange
Set 対象図形 = Selection.ShapeRange
    ' ↑これはOK

図形の重なり順を調べる - ZOrderPosition

図形の重なり順を調べるには、
ShapeオブジェクトのZOrderPositionプロパティを調べます。

Dim 図形A As Shape
Set 図形A = Worksheets("○○").Shapes("Rectangle 1")

Dim 図形B As Shape
Set 図形B = Worksheets("○○").Shapes("Rectangle 2")

If 図形A.ZOrderPosition > 図形B.ZOrderPosition Then
    MsgBox "図形Aの方が前面にあります。"
Else
    MsgBox "図形Bの方が前面にあります。"
End If

 
すべての図形・画像・グラフにはZOrderPositionが設定されており、
最背面を1として、最前面まで整数値が連番で振られています。

二つの図形のどちらが前にあるかを判定するには、
どちらのZOrderPositionが大きい値かを判定してください。


なお、現在まったく重なっていない図形であっても、
すべての図形には重なり順(ZOrderPosition)が連番設定されています。

図形を移動して重ねた際にどちらが全面かは決まっていますからね。


よって、図形同士のどちらが前/背面にあるかは簡単に判定できますが、
「今重なっている図形の中で最前面かどうか」は簡単に判定できません。

そうなると「今重なっているかどうか」を判定する必要が出てきますが、
それもかなり大変なコーディング(+要件定義)が必要になります。


一応、「特定のセル範囲内にある図形内で最前面のもの」であれば、
図形が配置された左上セル「TopLeftCell」を使って書けますのでご参考ください。

Sub 特定のセル範囲内にある画像の中で最前面の画像を取得する()

    Dim rngセル範囲 As Range
    Set rngセル範囲 = Range("C3:E5")

    ' 全シェイプをループして最前面シェイプを検索
    Dim 最前面シェイプ As Shape
    Dim 最前面ZOrderP As Long
    Dim シェイプ As Shape
    For Each シェイプ In Worksheets("○○").Shapes

        ' シェイプの左上セルが対象セル範囲内にあるか判定
        If Not Intersect(シェイプ.TopLeftCell, rngセル範囲) Is Nothing Then

            ' 現在の最前面シェイプより前のシェイプがあれば更新
            If 最前面シェイプ Is Nothing Then
                Set 最前面シェイプ = シェイプ
            ElseIf 最前面シェイプ.ZOrderPosition < シェイプ.ZOrderPosition Then
                Set 最前面シェイプ = シェイプ
            End If
        
        End If
        
    Next '全シェイプをループして最前面シェイプを検索

    MsgBox "最前面の図形名:" & 最前面シェイプ.Name

End Sub