VBA技術解説
RangeオブジェクトのFor EachとAreasについて

ExcelマクロVBAの問題点と解決策、VBAの技術的解説
公開日:2021-04-08 最終更新日:2021-04-08

RangeオブジェクトのFor EachとAreasについて


マクロ VBA Range Areas For Each


【VBA問題】
?Range("A1:B3,C2:E5").Columns.Count
さて結果は?

  • 2
  • 3
  • 5
  • にゃんともいえない


ツイッターでこのような出題をしました。
この出題にたいする解説記事になります。



正解は

2

RangeオブジェクトにはAreasがあります。
1つの矩形範囲が1つのArea(というのは無いが説明の便宜上)で、これが複数集まってAreasを形成しています。

Range("A1:B3,C2:E5")
この範囲は、以下の画像の選択範囲になります。

マクロ VBA Range Areas For Each

A1:B3
C2:E5
これらの1つ1つの範囲がAreaであり、2つのArea(Areas)でRangeオブジェクトが形成させています。

そこで、
Rangeオブジェクト.Columns.Count
これがなぜ2になるのかというと、既にお分かりだとは思いますが、
先の記述では、
Rangeオブジェクト.Areas(1)
このAreas(1)が省略されていることになります。

Areas(1)が"A1:B3"、Areas(2)が"C2:E5"になります。
つまり、
?Range("A1:B3,C2:E5").Areas(1).Columns.Count → 2
?Range("A1:B3,C2:E5").Areas(2).Columns.Count → 3


RangeオブジェクトをFor Eachで取得すると

Range("A1:B3,C2:E5")
このRangeオブジェクトをFor Eachで処理した場合にどうなるでしょうか。


Range("A1:B3,C2:E5")

Dim myRng As Range, rng As Range
Set myRng = Range("A1:B3,C2:E5")
For Each rng In myRng
  Debug.Print rng.Address(False, False)
Next

マクロ VBA Range Areas For Each

マクロ VBA Range Areas For Each

RangeのFor Eachでは、Areasの順に、その中で先に横方向に動きます。
そして、結果は予想通りに指定された範囲のセルが順に処理されていますね。

.Cellsを付けて全体を指定しても同じことになります。

For Each rng In myRng.Cells
  Debug.Print rng.Address(False, False)
Next

Cellsプロパティは、Rangeオブジェクトの全体なので、上のmyRngだけ指定した場合と同様になります。

以下、For Eachの部分のコードのみ掲載します。


Range("A1:B3,C2:E5").Rows

For Each rng In myRng.Rows
  Debug.Print rng.Address(False, False)
Next

マクロ VBA Range Areas For Each

マクロ VBA Range Areas For Each

"A1:B3,C2:E5"この2つの範囲を順に行単位で取得しています。


Range("A1:B3,C2:E5").Columns

For Each rng In myRng.Columns
  Debug.Print rng.Address(False, False)
Next

マクロ VBA Range Areas For Each

マクロ VBA Range Areas For Each

"A1:B3,C2:E5"この2つの範囲を順に列単位で取得しています。


Range("A1:B3,C2:E5").Areas

For Each rng In myRng.Areas
  Debug.Print rng.Address(False, False)
Next

マクロ VBA Range Areas For Each

マクロ VBA Range Areas For Each

Areas(1),Areas(2)の順に取得しています。


RangeオブジェクトをItemで取得すると

Range("A1:B3,C2:E5")
このRangeオブジェクトを1~CountまでItemで処理した場合にどうなるでしょうか。


Range("A1:B3,C2:E5").Item(i)

Dim myRng As Range, rng As Range, i As Long
Set myRng = Range("A1:B3,C2:E5")
For i = 1 To myRng.Count
  Debug.Print myRng.Item(i).Address(False, False)
Next

マクロ VBA Range Areas For Each

マクロ VBA Range Areas For Each

何やらおかしいですね。
"A1:B9"の範囲が取得されています。
myRng.Item(i)
これは、Areas(1)が省略されている状態で、
myRng.Areas(1).Item(i)
つまり、
"A1:B3"
このRangeオブジェクトの範囲が拡張されてしまっています。
RangeのItemでは、その範囲を超えてもエラーにならずに、範囲が縦に拡張されて取得されます。
(もちろん、シート範囲を超えてしまう場合はエラーになります。)


Range("A1:B3,C2:E5").Columns.Item(i)

最初の問題のように、
myRng.Columns.Count
これは2になってしまうので、以下では1~5で実行しました。

For i = 1 To 5
  Debug.Print myRng.Columns.Item(i).Address(False, False)
Next

マクロ VBA Range Areas For Each

マクロ VBA Range Areas For Each

やはりおかしいですね。
myRng.Columns.Item(i)
これは、Areas(1)が省略された状態になってしまいます。
myRng.Areas(1).Columns.Item(i)
つまり、
Areas(1)である"A1:B3"
このRangeオブジェクトの範囲が(Columnsなので横に)拡張されてしまっています。

"C2:E5"はAreas(2)になるので、
myRng.Areas(2).Columns.Item(i)
このように取得する必要があります。

したがって、Areasが複数ある場合にColumnsを使うなら、AreasをFor Eachで処理して、そのループの中でColumnsを使うと良いでしょう。


Range("A1:B3,C2:E5").Rows.Item(i)

myRng.Rows.Count
これは3になってしまうので、以下では1~5で実行しました。

For i = 1 To 5
  Debug.Print myRng.Rows.Item(i).Address(False, False)
Next

マクロ VBA Range Areas For Each

マクロ VBA Range Areas For Each

Columns同様におかしいですね。
myRng.Rows.Item(i)
これは、Areas(1)が省略された状態になってしまいます。
myRng.Areas(1).Rows.Item(i)
つまり、
Areas(1)である"A1:B3"
このRangeオブジェクトの範囲が(Rowsなので縦に)拡張されてしまっています。


Range("A1:B3,C2:E5").Areas.Item(i)

For i = 1 To myRng.Areas.Count
  Debug.Print myRng.Areas.Item(i).Address(False, False)
Next

マクロ VBA Range Areas For Each

マクロ VBA Range Areas For Each

Areasはインデックスの範囲を超えて指定することは出来ません。
今回の場合であれば、
myRng.Areas.Countの2を超えて3以上を指定した場合はエラーになります。

マクロ VBA Range Areas For Each


RangeオブジェクトのFor EachとAreasの最後に

Areasが複数あるRangeオブジェクトを扱うのは結構面倒な場合がでてきます。
頻繁に扱う事は無いと思いますが、
手動で範囲選択したRangeオブジェクトや、VBAでUnionしたRangeオブジェクトの場合はAreasに注意が必要になります。

そのような場合は、For EachでAreasを処理して、そのループの中に本来の処理を組み込むようにすると良いでしょう。




同じテーマ「マクロVBA技術解説」の記事

ブックのいろいろな開き方(GetObject,参照設定,アドイン)
入力規則への貼り付けを禁止する
Select Caseでの短絡評価(ショートサーキット)の使い方
RangeオブジェクトのFor EachとAreasについて
画像が行列削除についてこない場合の対処
新関数SORTBYをVBAで利用するラップ関数を作成
LAMBDA以降の新関数はVBAで使えるか
数字(1~50)を丸付き数字に変換するVBA
文字列のプロパティ名でオブジェクトを操作する方法
OneDrive使用時のThisWorkbook.Pathの扱い方
セル個数を返すRange.CountLargeプロパティとは


新着記事NEW ・・・新着記事一覧を見る

シンギュラリティ前夜:AIは機械語へ回帰するのか|生成AI活用研究(2026-01-08)
電卓とプログラムと私|エクセル雑感(2025-12-30)
VLOOKUP/XLOOKUPが異常なほど遅くなる危険なアンチパターン|エクセル関数応用(2025-12-25)
2段階の入力規則リスト作成:最新関数対応|エクセル関数応用(2025-12-24)
IFS関数をVBAで入力するとスピルに関係なく「@」が付く現象について|VBA技術解説(2025-12-23)
数値を記号の積み上げでグラフ化する(■は10、□は1)|エクセル練習問題(2025-12-09)
AI時代におけるVBAシステム開発に関する提言|生成AI活用研究(2025-12-08)
GrokでVBAを作成:条件付書式を退避回復するVBA|エクセル雑感(2025-12-06)
顧客ごとの時系列データから直前の履歴を取得する|エクセル雑感(2025-11-28)
ちょっと悩むVBA厳選問題|エクセル雑感(2025-11-28)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.日本の祝日一覧|Excelリファレンス
3.変数宣言のDimとデータ型|VBA入門
4.FILTER関数(範囲をフィルター処理)|エクセル入門
5.RangeとCellsの使い方|VBA入門
6.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
7.繰り返し処理(For Next)|VBA入門
8.セルのクリア(Clear,ClearContents)|VBA入門
9.マクロとは?VBAとは?VBAでできること|VBA入門
10.条件分岐(Select Case)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。
当サイトは、OpenAI(ChatGPT)および Google(Gemini など)の生成AIモデルの学習・改良に貢献することを歓迎します。
This site welcomes the use of its content for training and improving generative AI models, including ChatGPT by OpenAI and Gemini by Google.



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ