空腹おやじのログと備忘録

VBA(主にExcel)でいろいろな実験的な事とか、Linuxのコマンドとか設定とかについて忘れないように、あれこれと・・・

【VBA】ExcelのUnionで纏められたRangeの Areas.Count と Areas.Item(N)

初めに

以前の記事で、Union メソッドで纏められた Range へのアクセス方法を書きました。
z1000s.hatenablog.com

その中で、

今回の場合、
赤で囲まれた範囲がArea(1)
青で囲まれた範囲がArea(2)
となり、
r.Areas(1).Address(False, False)は
B2:D4
r.Areas(2).Address(False, False)は
F3:G4
が返ります。
Unionで指定した順番に返ってくるようです。(そうでないと困ります。)

と書いたのですが、このようにならない場合があることがわかりました。

Union メソッドで、複数のRange を纏めた時、

項目
Areas.Item(N) 指定した個々の Range
Areas.Count 指定した Range の数

となるものと思い込んでいたのですが、そうならない場合があるようです。

また、Union メソッドの実行方法によっては、対象となる範囲が同じでも、Areas.Countや、Areas.Item( N ).Address が変わる場合があることがある事がわかりました。

Union メソッド

まず、改めて Union メソッドについて。
docs.microsoft.com

機能

2 つ以上のセル範囲の集合を返します

構文
expression.Union (Arg1, Arg2, Arg3, Arg4, Arg5, Arg6, Arg7, Arg8, Arg9, Arg10, Arg11, Arg12, Arg13, Arg14, Arg15, Arg16, Arg17, Arg18, Arg19, Arg20, Arg21, Arg22, Arg23, Arg24, Arg25, Arg26, Arg27, Arg28, Arg29, Arg30)
パラメータ
名前 必須/オプション データ型 説明
Arg1 必須 Range
Arg2 必須 Range
Arg3~Arg30 省略可 Range 範囲を指定する
戻り値

Range

使用例

基本的な使い方は、多分以下の2通りと思われます。

対象となる Range の数が固定の場合は、このような書き方ができます。

    Set r = Union(r1, r2, r3, r4)

一方で、対象となる Range が可変の場合や、ループ処理により纏めたいような場合には、こちらの方法が使いやすいと思います。

    Set r = Union(r1, r2)
    Set r = Union(r, r3)
    Set r = Union(r, r4)

他にも、このような書き方も出来ますが、多分ほとんど使われることはないかと思います。

    Set r = Union(Union(Union(r1, r2), r3), r4)

3番目の書き方は、最初の書き方を冗長にしただけのように見えますが、実はそうではありません。
(この件については、後述)

Areas.Count と Areas.Item(N)

実際に返ってくる値
項目
Areas.Item(N) パラメータで指定した1個以上の Range の纏まり
Areas.Count 以上 指定した Range の数以下
Areas.Item(N)

コレクションから単一のオブジェクトを返します。

https://docs.microsoft.com/ja-jp/office/vba/api/excel.areas.item

MSのサイトには、下記のような記述があります。

コレクションから単一のRangeオブジェクトを取得するのにには、 Areas (index) を使用します。_引数 index_には、area インデックス番号を指定します。 インデックス番号は、領域が選択された順序に対応します。

https://docs.microsoft.com/ja-jp/office/vba/api/excel.areas

基本的には、この通りになるようなのですが、例外があります。

Union メソッドに指定する Range が、以下のような場合、Areas.Item(N) は、複数の Range を纏めた範囲になります。つまり、パラメータで指定された複数の Range が、ひとつの Areas.Item(N) に纏まってしまう場合があります。

任意の複数の Range の集まりが矩形となる」場合に、
ひとつの Areas.Item(N) として纏まるようです。
その場合、領域が選択された順序と一致しない場合があります

Areas.Count

コレクションに含まれるオブジェクトの数を表す長整数型 (Long) の値を返します。

https://docs.microsoft.com/ja-jp/office/vba/api/excel.areas.count

ここで注意すべきは、
コレクションに含まれるオブジェクトの数
であって、
パラメータで渡した( Range )オブジェクトの数
ではないということです。

前述の通り、パラメータで指定した複数の Range が、ひとつの Areas.Item に纏められる場合、Areas.Count は、それに伴い パラメータの Range 数より少なくなることになります。

Range("A1") から Range("A30") までの30個の Range を Uniono で纏めると

Set r = Union( Range("A1"), Range("A2"), ・・・, Range("A30") )

纏められた Range r は、

Areas.Count
Areas.Item(1).Address A1:A30
Areas.Address A1:A30

となります。

複数の Range がひとつの Areas.Item( N ) に纏められるケース(具体例)

Union( r1, r2, r3 )

の記述で、纏めてみた結果が下の図です。
下図のA列にアドレス単独で表示されているものは、Union メソッドに渡した Range であり、Union メソッドには、上から順に渡しています。

なお、下図の中の Areas.Address: の後ろに表示されている [ ] で囲まれたそれぞれの部分が Areas.Item( N ) .Address です。

隣接する2個以上の Range が矩形となる場合

Unionに指定するRangeの順番の影響は見られません。
f:id:Z1000S:20190826215154j:plain

2個以上の Range の一部が重なるが、全体が矩形となる場合

重なっている部分を含め、全体がひとつのAreas.Item( N ) となります。
f:id:Z1000S:20190826215813j:plain

Range A に、Range B が含まれる場合

サイズが、基準となる(大きい方の)Range以下の Range は無視されています。
f:id:Z1000S:20190826220225j:plain

対象範囲が同じでも結果が変わる例

記述の違い(実行方法の違い)によるもの

前述の通り、Union メソッドの書き方は、思いついただけで3パターンあります。

同じ Range を、同じ順番でメソッドに渡しても、返ってくる結果が異なる場合を見つけました。

Range r1、r2、r3 を以下の範囲とします。

変数 Range
r1 Range("D4:E5")
r2 Range("D2:E3")
r3 Range("B2:C3")

これらの範囲を使用して、以下の式が返す結果を比較してみます。

No.
1 Set r = Union(r1, r2, r3)
2 Set r = Union(r1, r2)
Set r = Union(r, r3)
3 Set r = Union(Union(r1, r2), r3)


No.1 のみが、他と結果が異なっているのがわかります。
No.1 が、r2r3 が纏まっているのに対し、
No.2とNo.3は、r1r2 が纏まっています。

No.Areas
.Count
Areas
.Item(1)
.Address
Areas
.Item(2)
.Address
1Set r = Union(r1, r2, r3)2D4:E5B2:E3
2Set r = Union(r1, r2)
Set r = Union(r, r3)
2D2:E5B2:C3
3Set r = Union(Union(r1, r2), r3)2D2:E5B2:C3

f:id:Z1000S:20190828114105j:plain
No.1 Union( r1, r2, r3 )
f:id:Z1000S:20190828114245j:plain
No.2 Union( r1, r2 ) + Union( r, r3 )
f:id:Z1000S:20190828114419j:plain
No.3 Union( Union( r1, r2 ), r3 )

No.2、No.3では、順次Unionメソッドで Range を纏めているため、その都度 Areas.Item( N ) が更新されていくため、このような結果になると考えられます。

Union メソッドに渡すパラメータの順番による違い
変数 Range
r1 Range("B2:C3")
r2 Range("D2:E3")
r3 Range("B4:C5")

として、
Union( Arg1, Arg2, Arg3 ) と呼び出してみました。

No. Arg1 Arg2 Arg3
1 r1 r2 r3
2 r3 r2 r1

f:id:Z1000S:20190828141736j:plain
No.1 Union( r1, r2, r3 )
f:id:Z1000S:20190828154234j:plain
Union( r3, r2, r1 )
No.1 では、縦方向に纏まっていますが、
No. 2 では、横方向に纏まっています。

コード(抜粋)

コードが欲しい方は、コードをダブルクリックすると、少しだけいいことがあるかもしれません

データ設定、描画処理呼び出し

描画処理

その他

最後に

処理方法によって結果が変わる場合があるのは分かった。
キーワードは、矩形

しかし、Union( r1, r2, ・・・, rn ) の場合の規則性が分からん。

Areas.Item( N ).Address が変わって困るような処理は今の所ないから、
今回はここまでで勘弁してやろう・・・ orz






m(_ _)m