セルが結合されているか調べる方法を解説します。
MergeCellsプロパティとMergeAreaプロパティを組み合わせて判定します。
セルが結合されているか判定する - MergeCells
セルが結合されているか判定するには、
RangeオブジェクトのMergeCellsプロパティを参照します。
例えばA1:C3の3×3セル範囲が結合されているときは、
以下のコードはいずれもTrueとして処理されます。
If Range("A1").MergeCells = True Then If Range("C3").MergeCells = True Then If Range("A1:C3").MergeCells = True Then
上記の通りセル結合の範囲に含まれるセルであれば
単独セルでもセル範囲でもTrueとなります。
なお、A1:A5のように結合セルと単独セルが混在する範囲を指定した場合は、
MergeCellsプロパティは「Null」を返します。
セル結合を判定する基本となるプロパティですので、
まずはこのMergeCellsプロパティを覚えてください。
結合セルの先頭(左上)セルを判定する - MergeArea
結合されたセルの値を取得/代入する場合は、
結合範囲の先頭のセルのValueプロパティを参照する必要があります。
Range("A1:C3").Value ' ← 結合セルだったとしても3×3の配列になってしまう Range("A1").Value ' ← これで結合セルの値を取得できる
しかし上記のMergeCellsプロパティでは、
セル結合の先頭セルでも内部セルでもどちらもTrueとなってしまいます。
対象のセルが結合範囲の先頭セルかどうかは、
MergeAreaプロパティを使用して以下のコードで判定します。
' 結合セルの先頭セルか判定 If 処理セル.MergeArea.Cells(1).Address = 処理セル.Address _ And 処理セル.MergeCells = True Then
MergeAreaプロパティは結合エリアをRangeオブジェクトとして取得します。
例えばA1:C3セルが結合されているときに、
MergeAreaプロパティは以下のような値になります。
' 結合アドレスを取得 MsgBox Range("A1").MergeArea.Address ' $A$1:$C$3 MsgBox Range("B2").MergeArea.Address ' $A$1:$C$3 MsgBox Range("C3").MergeArea.Address ' $A$1:$C$3 MsgBox Range("A1:C3").MergeArea.Address ' エラー
MergeCellsの時と違い、複数セルから実行すると必ずエラーになります。
単独セル専用のプロパティだと思ってください。
MergeAreaプロパティはRangeオブジェクトを取得してくれますので、
MergeArea.Cells(1)とすればその先頭セルを取得できます。
あとは対象セルとMergeArea先頭セルのAddressが等しいかで、
対象のセルが結合範囲の先頭セルかどうかを判定することができます。
ただし注意が必要なのが、MergeAreaは結合されていないセルにも実行でき、
その際は単独セル(自分自身)を取得してしまう点です。
MsgBox Range("A1").MergeArea.Address ' 結合されていなければ$A$1が返る
この時はMergeArea.Cells(1)、MergeArea、親セルがすべて同じものですので、
' 結合セルの先頭セルか判定 If 処理セル.MergeArea.Cells(1).Address = 処理セル.Address _ And 処理セル.MergeCells = True Then
このように「MergeCellsがTrue」であることも条件に加えてください。
セル範囲が1つの結合セルか判定する
セル範囲が1つの結合セルかを判定するには以下のコードを用います。
If セル範囲.Cells(1, 1).MergeArea.Address = セル範囲.Address Then
セル範囲のMergeAreaとセル範囲自体のAddressを比較したコードですね。
先ほど「MergeAreaは単独セル専用プロパティ」とした通り、
一旦単独セルにしてからMergeAreaをとる必要がある点に注意してください。
セル範囲.MergeArea ' ← これはエラーになる セル範囲.Cells(1).MergeArea ' ← これでOK
セル結合の各種判定を汎用関数化する
上記の通り、セル結合の判定は一発では判定できず、
MergeCells、MergeAreaプロパティを併用する必要があります。
セル結合をよく扱う場合はいちいちこのコードを書くのは面倒なので、
以下のように汎用関数を作っておくと便利です。
' 結合セル判定 Function Is結合先頭セル(判定セル As Range) As Boolean Is結合先頭セル = (判定セル.MergeCells And 判定セル.Address = 判定セル.MergeArea.Cells(1, 1).Address) End Function Function Is結合内部セル(判定セル As Range) As Boolean Is結合内部セル = (判定セル.MergeCells And 判定セル.Address <> 判定セル.MergeArea.Cells(1, 1).Address) End Function Function Is結合セル全体(判定エリア As Range) As Boolean Is結合セル全体 = (判定エリア.MergeCells And 判定エリア.Address = 判定エリア.Cells(1, 1).MergeArea.Address) End Function
各関数の中身は上記で解説したコードそのままですね。
これらの汎用関数を作っておくと、
以下のようなコードを読みやすく簡単に書くことができます。
選択範囲内の結合セルの値を操作
Dim 処理セル As Range For Each 処理セル In Selection.Cells If Is結合先頭セル(処理セル) Then ' ここに各セルへの処理 Debug.Print 処理セル.Value End If Next
選択範囲内のすべてのセルの値を操作
Dim 処理セル As Range For Each 処理セル In Selection.Cells If Is結合内部セル(処理セル) = False Then ' ここに各セルへの処理 Debug.Print 処理セル.Value End If Next
上記二つのコードの違いは「非結合セルを処理するかどうか」ですが、
これが読んでもわかるコードになっているのが素晴らしいですね。
両者の判定をMergeCells/MergeAreaを組み合わせて判定するとなると、
書くのも読むのも大変なのは想像がつくと思います。
選択範囲がちょうど1つの結合セルか判定
If Is結合セル全体(Selection) = False Then MsgBox "対象は1つだけ選択してください。" Exit Sub End If
例えばマクロの実行条件が「一つのセルを選択して実行」だったとき、
セル結合されていると判定を書くのがちょっと大変です。
そんなときこの汎用関数があれば一発で書けるため、
Excel帳票に対するマクロを書く場合は重宝します。
このように、「簡単だけど書くのが面倒なコード」は、
関数化が簡単な割にメリットが大きいです。
汎用関数集を作っている方は、ぜひそのメンバーに加えてあげてください。
汎用関数集の作り方・使い方についてはこちらをどうぞ。
www.limecode.jp