結合セルを擬似的に単一セルのように扱うには?(Tips-1)
VBAの勉強を始めてみて、これまでに気づいたことや、習得したこまごました知識などをメモっておこうと思います。
下の画像のように、A1:C3を結合したセルがあります。
見た目は一つのセルのようですが、実際には9個のセル(A1,B1,C1,A2,B2,C2,A3,B3,C3)が含まれてます。
ここで「テスト」という文字列を変数に格納するためのコードを書いてみようと思うのですが、「テスト」という文字列が入っているのは、実際には結合セルの左上セル(A1セル)のみであり、この結合セルを選択した状態で、For Each ~Nextで処理しようとすると・・・・・・
Sub test()
Dim V As String
For Each C In Selection
V = C.Value
Debug.Print V
Next C
End Sub
「テスト」という文字列が1回と、空白が8回、変数に格納されることになります。(イミディエイトウィンドウで空白が分かるように、ドラッグして選択しています)
結合セルに対しては、結合セルに含まれる全ての単一セルに対してループ処理を行うため、このような結果になります。
さて、これを単一セルのように扱うにはどうしたらいいでしょうか?
VBAには結合セルの範囲を取得する MergeAreaプロパティ というものがあります。
Range("A1").MergeArea
と書けば、A1セルが含まれる結合セル範囲を取得することができます。(先の結合セルであれば、単一セルを9個格納したコレクションとして取得されます)
インデックス番号で表すと下の画像のようになります。
ここで、
Range("A1").MergeArea(1).Address
と書けば、セルA1が含まれる結合セル範囲のインデックス番号1のアドレスを取得します。(返り値は、 $A$1 です)
"A1"の部分が、"B1","C1","A2","B2","C2","A3","B3","C3"に変わろうとも、アドレスを取得するセルはMergeArea(1)のセルなので、返り値はすべて $A$1 になります。
この特性を利用して、次のような条件式を作ってみます。
If 単一セル.Address = 単一セル.MergeArea(1).Address Then
何らかの処理
End If
この、単一セルの箇所に、A1,B1,C1,A2,B2,C2,A3,B3,C3を順に当てはめると、
A1は True で、それ以外は False になります。
Range("A1").Address = Range("A1").MergeArea(1).Address ←True
Range("B1").Address = Range("B1").MergeArea(1).Address ←False
Range("C1").Address = Range("C1").MergeArea(1).Address ←False
Range("A2").Address = Range("A2").MergeArea(1).Address ←False
Range("B2").Address = Range("B2").MergeArea(1).Address ←False
Range("C2").Address = Range("C2").MergeArea(1).Address ←False
Range("A3").Address = Range("A3").MergeArea(1).Address ←False
Range("B3").Address = Range("B3").MergeArea(1).Address ←False
Range("C3").Address = Range("C3").MergeArea(1).Address ←False
つまり、これを利用してセルA1(結合セルの左上)にのみ処理を行う、という条件を作ることができるのです。
For Each ~Next的に書くと次のようになります。
Sub test()
Dim V As String
For Each C In Selection
If C.Address = C.MergeArea(1).Address Then
V = C.Value
Debug.Print V
End If
Next C
End Sub
このコードを実行した結果、「テスト」という文字列が1回、変数に格納されるだけでプログラムが終了します。(イミディエイトウィンドウには、テストという文字列のみ出力されています)
このような条件を組み込めば、結合セルを擬似的に単一セルのように扱うことができますね!