VBAのループ回数を減らす書き方|lastRow・SpecialCells・配列一括処理の使い方

VBAで数千行のデータを処理するとき、ループの回数を意識せずに書くと処理が遅くなったり、無駄な繰り返しが大量に発生したりします。少しの工夫でループ回数を減らすだけで、処理速度が数倍になることもあります。

この記事では、ループ回数を減らすための3つのアプローチ(最終行の限定・SpecialCellsの活用・配列への一括読み込み)を具体例で解説します。

最終行を取得してループ範囲を絞るには?

固定の行数でループするコードは、データが少ない場合に無駄なループが大量発生します。

' 改善前:1000行固定で回す(データが100行でも900回無駄)
For i = 2 To 1000
    If Cells(i, 1).Value <> "" Then
        Cells(i, 2).Value = "済"
    End If
Next i
' 改善後:A列の最終行まで限定する
Dim i As Long
Dim lastRow As Long
lastRow = Cells(Rows.Count, 1).End(xlUp).Row

For i = 2 To lastRow
    If Cells(i, 1).Value <> "" Then
        Cells(i, 2).Value = "済"
    End If
Next i

Cells(Rows.Count, 1).End(xlUp).Row でA列の最終行番号を取得し、そこまでしかループしないようにします。データが増減しても自動的に対応できます。

SpecialCellsとFor Eachで対象セルだけを処理するには?

さらに効率化したい場合は、SpecialCells で「値が入っているセルだけ」を取り出してループする方法があります。

Dim rng As Range
Dim c As Range

Set rng = Range("A2:A1000").SpecialCells(xlCellTypeConstants)

For Each c In rng
    c.Offset(0, 1).Value = "済"
Next c

SpecialCells(xlCellTypeConstants) は値が入っているセルだけを範囲として返します。空白セルを完全にスキップするため、ループ回数が大幅に減ります。

For Each は数値カウンターではなく「存在する対象」を1つずつ取り出して処理する構文です。対象が明確なときにコードが読みやすく、エラーも出にくい書き方です。

配列に一括読み込みして処理するには?

処理速度を最大限に上げたい場合は、セル範囲を一度配列に読み込み、配列内で処理してからまとめて書き戻す方法が最も効果的です。

Dim data As Variant
Dim i As Long

' セル範囲を配列に一括読み込み
data = Range("A2:A1000").Value

' 配列内で処理する(Excelシートへのアクセスなし)
For i = 1 To UBound(data, 1)
    If data(i, 1) <> "" Then
        data(i, 1) = "済"
    End If
Next i

' 処理結果をまとめてシートに書き戻す
Range("A2:A1000").Value = data

ポイントは次の3つです。

  • Variant 型の変数はあらゆるデータを格納できる柔軟な型で、セル範囲を二次元配列として受け取れる
  • data(行, 列) の形で各セルに相当する値にアクセスする(例:data(1, 1) は1行目1列目)
  • UBound(data, 1) で配列の行数(ループの終端)を取得する

Excelシートとのやりとり(読み書き)を最初と最後の1回ずつに抑えることで、数千行の処理でも圧倒的に高速になります。

まとめ

  • lastRow = Cells(Rows.Count, 1).End(xlUp).Row でループ範囲をデータが存在する行だけに絞る
  • SpecialCells(xlCellTypeConstants)For Each で値が入っているセルだけを対象にする
  • 配列に一括読み込み → 配列内で処理 → まとめて書き戻すの流れが最も高速
  • 固定行数のループは「データが少ない状況での無駄なループ」の原因になりやすい
  • ループ回数の削減は処理速度だけでなくコードの可読性向上にもつながる

よくある質問

SpecialCellsで対象セルが1つもない場合にエラーになりますか?

なります。SpecialCells は対象セルが存在しないとエラーになるため、On Error Resume Next でエラーを回避するか、事前にデータの有無を確認する処理を入れておくと安全です。

配列を使う方法はどのくらい速くなりますか?

1行ずつセルに書き込む方法と比べて、数百〜数千倍速くなるケースもあります。特に1万行を超えるような大量データを扱う場合に効果が顕著です。

ForとFor Eachはどう使い分けますか?

繰り返す回数が決まっているときや行番号で制御したいときは For i = 開始 To 終了、セル・シートなどのコレクションの各要素を処理するときは For Each が適しています。

配列の二次元インデックス(data(i, 1))の意味が分かりません。

セル範囲を配列に取り込むと「行×列」の二次元配列になります。data(i, 1) は「i行目の1列目」を意味します。A列だけを読み込んだ場合、列インデックスは常に1になります。

Application.ScreenUpdatingと組み合わせるとさらに速くなりますか?

はい。配列処理と Application.ScreenUpdating = False を組み合わせると、画面の再描画も止まるためさらに高速になります。処理後に True に戻すことを忘れないようにしましょう。


動画で学びたい方へ

「記事を読んでも、実際に自分で書けるか不安…」という方には、動画で基礎からじっくり学べる講座がおすすめです。

VBAが初めての方を前提に、つまずきやすいポイントを先回りして解説しています。サンプル動画は無料でご覧いただけます。

動画で学ぶExcelマクロ|JIMOVEオンラインスクール

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール