LoginSignup
0
2

More than 1 year has passed since last update.

【ExcelVBA】セルに対するFor Eachの順番

Last updated at Posted at 2019-07-16

For Eachでセルを処理する

VBAのFor文は2種類あります。

  1. 開始と終了のインデックスを指定するFor カウンタ変数 = 開始 To 終了
  2. 配列やリストの先頭~末尾までを処理するFor Each 要素の変数 In 配列やリスト

インデックスを指定する必要がなければ、記述が簡潔になるので上記2.を推奨したいところです。
そのFor Eachループですが、ワークシート上のセルを処理する場合、知らないと「なんで??」となる挙動があるのでまとめておきます。特に他言語やジャグ配列に馴染みがある人。
…行単位や列単位でループすることのほうが多いと思うので、あんまり必要のない知識かもしれませんが。

サンプルデータ

Range("A1:C2")に対してデータを設定しています。

image.png

サンプルプログラム

サンプルデータの範囲のセルの値をFor Eachで順番に「/」区切りで結合していき、Debug.printで結果をイミディエイトウィンドウに出力します。

' 処理対象の指定方法によってFor Eachの順番が違う
Sub TestOrder()
    Dim area As Range: Set area = Range("A1:C2")

    ' Rangeで読み込み
    Dim str As String: str = ""
    Dim cell As Variant: For Each cell In area
        str = str & IIf(Len(str) > 0, "/", "") & cell.Value
    Next
    Debug.Print "                     Range: " & str
    
    ' 二次元配列で読み込み
    str = ""
    For Each cell In area.Value
        str = str & IIf(Len(str) > 0, "/", "") & cell
    Next
    Debug.Print "          Multidimentional: " & str
    
    ' 配列をtranspose関数で行列を入れ替えるとRangeと同じ順番に
    str = ""
    For Each cell In WorksheetFunction.Transpose(area.Value)
        str = str & IIf(Len(str) > 0, "/", "") & cell
    Next
    Debug.Print "Transpose multidimentional: " & str
End Sub

実行結果

For EachでそのままRangeで指定した場合とサンプルデータの範囲を配列に格納してから指定した場合で、処理するセルの順番が変わります。
Rangeだと行単位、配列に格納した場合だと列単位になります。最初はびっくりする。

                     Range: 陸/海/空/梅/竹/松
          Multidimentional: 陸/梅/海/竹/空/松
Transpose multidimentional: 陸/海/空/梅/竹/松

配列に格納した場合は、(1, 1)(1, 2)(1, 3)…ではなく、(1, 1)(2, 1)(1, 2)…の順番で処理してるなんて、まさか夢にも思わなかったよ。
2次元配列はFor Eachで処理すると、1次元目×2次元目ではなく2次元目×1次元目なんですな…
多分3次元以上の配列も次元の大きい順で処理すると思う。確認してないけど。

配列の中身

セルをVariant型の配列に格納した場合、以下のように格納されます。
1次元目が行、2次元目が列の多次元配列です。
image.png

上記の配列に対して縦横を変換するワークシート関数のTransposeを使うと以下のように変換されます。
2次元目×1次元目で処理するので、Rangeをそのまま指定したときと同じ順番になります。
image.png


感覚的には行×列の方がしっくりきます…
Cellsプロパティの引数もCells(行, 列)だし、第1引数の行×第2引数の列の二重ループのが思い浮かびやすくないですか?

(他言語で)ジャグ配列を使い慣れていると、外側の小さい次元→内側の大きい次元のイメージになる気がするので、覚えとくといいかもです。
JavaでPOI使ってExcel弄るときなんか、getRowはあってもgetColumn的なのがないので、基本が行ベースの処理になりますし。(最新版は知らないけど)
VBAの多次元配列はFor Each使わずにForで2重ループするほうがわかりやすいかも。

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2