Range("A1,B2:C2,D4:E6")のような複数領域をもつRangeオブジェクトを、
各セル範囲ごとに分割して取得するAreasプロパティを解説します。
- 複数領域(Areas)をFor Eachでセル範囲ごとに取得する
- Rangeオブジェクトが単一のセル範囲か判定する
- ○番目のエリアを取得する
- Value、Rows、Columnsなどの仕様
- おまけ:Areaオブジェクトはありません
複数領域(Areas)をFor Eachでセル範囲ごとに取得する
RangeオブジェクトのAreasプロパティを使用すると、
Range内の複数セル範囲をひとつずつ分けて取り出すことができます。
Dim 親Range As Range Set 親Range = Range("A1,B2:C2,D4:E6") Dim 各セル範囲 As Range For Each 各セル範囲 In 親Range.Areas Debug.Print 各セル範囲.Address Next
このコードを実行すると、「$A$1」「$B$2:$C$2」「$D$4:$E$10」が表示され、
3つのRangeをエリアごとにループできていることが分かります。
対して、以下のコードのようにAreasをCellsに変えると、
「$A$1,$B$2,$C$2,・・・$E$6」と1セルずつのループになります。
For Each 各セル In 親Range.「Cells」
やりたい処理によってどちらのループにするかを選択してください。
Rangeオブジェクトが単一のセル範囲か判定する
Areasプロパティは「Count」プロパティを持つため、
Rangeオブジェクトがいくつの領域を持つかを調べることができます。
Rangeオブジェクトが単一のセル範囲かどうかを判定するには、
Areas.Countが1かどうかを判定します。
' Rangeが単一範囲の時にのみマクロを実行する If 指定Range.Areas.Count = 1 Then ' ここに実行したい処理 End If
○番目のエリアを取得する
Areasプロパティの引数に数値を指定すると、
○番目のエリアを取得することができます。
例えば第1エリアだけを処理する場合は以下のコードを実行します。
' 第1エリアに対してだけ処理 Dim 処理Range As Range Set 処理Range = 親Range.Areas(1) 処理Range.Value = 1
こちらのコードで個別のエリアを指定して処理できます。
エリア数を超える数値を指定すると、
「インデックスが有効範囲にありません。」
エラーとなりますのでご注意ください。
この仕様に先ほどのCountプロパティを組み合わせると、
For文でも全エリアをループするコードを書くことができます。
Dim 親Range As Range Set 親Range = Range("A1,B2:C2,D4:E6") Dim i As Long Dim 各セル範囲 As Range For i = 1 To 親Range.Areas.Count Set 各セル範囲 = 親Range.Areas(i) ' ここに各セル範囲への処理 Next
ただ全エリアを走査するだけならFor Each文で十分ですが、
エリア番号に関わるループを書く場合はこちらを使用してください。
Value、Rows、Columnsなどの仕様
Range("A1,B2:C2,D4:E6")などのRangeオブジェクトで注意が必要なのが、
Value、Rows、Columnsなどのプロパティの挙動です。
これらは「第1エリア」の状態を取得するよう動くため、
各結果は以下のようになります。
Dim 親Range As Range Set 親Range = Range("A1,B2:C2,D4:E6") 親Range.Value ' ← A1セルの値が入ります。 親Range.Rows.Count ' ← 1 親Range.Columns.Count ' ← 1
つまりこれらのプロパティは、
親Range.Areas(1).Value ' ← A1セルの値が入ります。 親Range.Areas(1).Rows.Count ' ← 1 親Range.Areas(1).Columns.Count ' ← 1
このコードと同等に動くということになります。
逆に「総行数」をカウントするようなプロパティはありませんので、
これを実装する場合は愚直にカウントしていく必要があります。
Dim 親Range As Range Set 親Range = Range("A1,B2:C2,D4:E6") Dim 総行数 As Long: 総行数 = 0 Dim 各セル範囲 As Range For Each 各セル範囲 In 親Range.Areas 総行数 = 総行数 + 各セル範囲.Rows.Count Next
複数領域を持つRangeオブジェクトを処理するときは、
この仕様に注意して使用してください。
おまけ:Areaオブジェクトはありません
Areasプロパティは「各Rangeオブジェクト」を取得するので、
返り値はRange型のプロパティです。
Areasコレクションの中にAreaオブジェクトがあるわけではありません。
' これはエラー(というかそもそも宣言できない) Dim 各エリア As Area For Each 各エリア In 親Range.Areas
一応このことも知っておいてください。