銀河鉄道

【VBA】.Cells と .Range の使い分け目安|数千か数万か

サムネイル
[VBA]Cells or Range
データ件数によって
使い分け

〜3,000件|ws.Range(“AA” & i).Value

' Small loops — readable but slightly slower (safe for few thousands)
' 小規模ループ — 読みやすいがやや遅い(数千件なら実用上OK)
Public Sub FillByRangeReadable(ByVal ws As Worksheet, ByVal lastRow As Long)
	Dim i As Long
	For i = 2 To lastRow
		ws.Range("AA" & i).Value = "ok"
	Next i
End Sub
メリット

参照セルがわかりやすい

数百~数千件なら問題なし

ちょっとしたことなら十分

3,000〜10,000件|前計算してから .Cells(i, j)

' Medium/Large loops — precompute the column index and use Cells
' 中~大規模 — 列番号を前計算しCellsで指定
Public Sub FillByCellsFast(ByVal ws As Worksheet, ByVal lastRow As Long)
	Dim colAA As Long: colAA
    ws.Columns("AA").Column  ' 前計算

	Dim i As Long
	With ws
		For i = 2 To lastRow
			.Cells(i, colAA).Value2 = "ok"
		Next i
	End With
End Sub
メリット

大量ループで早い

10,000件〜|Variant配列で一括入出力

' Fastest pattern — batch read/process/write via Variant arrays
' 最速パターン — Variant配列で一括入出力
Public Sub BatchProcessArray(ByVal ws As Worksheet, ByVal firstRow As Long, ByVal lastRow As Long)
	Dim firstCol As Long
    firstCol = ws.Columns("AA").Column

	Dim rng As Range
	Set rng = ws.Range(ws.Cells(firstRow, firstCol), ws.Cells(lastRow, firstCol))
	
	Dim v As Variant: v = rng.Value2  ' 二次元配列(1-based)
	Dim r As Long
	For r = 1 To UBound(v, 1)
		' 例: 条件によりAA列へラベルを書く
		If Len(v(r, 1)) = 0 Then
			v(r, 1) = "empty->labeled"
		End If
	Next r
	rng.Value2 = v  ' 一括で書き戻し
End Sub
メリット

大量ループで圧倒的に早い

Prefer Cells with precomputed column indices and batch arrays for any loop that might grow.
将来増えうるループは、列番号の前計算+配列一括を書式として統一する

ヘルパー関数を使う場合

' Helper — convert column letter to number (human↔machine bridge)
' ヘルパー — 列文字→列番号(人間↔機械の橋渡し)
Public Function ColIndex(ByVal colLetter As String, Optional ByVal ws As Worksheet) As Long
	If ws Is Nothing Then
		ColIndex = ActiveSheet.Range(colLetter & "1").Column
	Else
		ColIndex = ws.Range(colLetter & "1").Column
	End If
End Function

条件まとめ

規模区分目安の行数推奨方式理由
Small(小)~3,000件Range("A" & i)でもOK体感差ほぼゼロ、書きやすさ重視でいい
Medium(中)3,000〜10,000件Cells(i, col)へ切り替え文字列連結+A1パースの遅延が目立ち始める
Large(大)10,000〜100,000件Cells+配列一括入出力COM境界のオーバーヘッドが支配的になる
Massive(特大)100,000件〜Range.Value2→配列処理→Range.Value2これ以外は実質ムリ。単セル操作は1/100〜1/1000速
規模感実務シナリオ例最適解
〜3,000行単票チェック、軽い抽出可読性優先でRange
〜10,000行1シート単位の集計Cells+列番号変数
〜100,000行日次データ/CSV読込後整形Variant配列でまとめ処理
100,000行超大規模帳票・CSV統合VBA限界。Python/pandasへ委譲を検討

補足:なぜその件数?

  • Range("A" & i)は**1回あたり約10〜20µs(マイクロ秒)**の遅延(※ローカル実測平均)
    10,000回繰り返すと 0.1〜0.2秒の純オーバーヘッドになる
  • Cells(i, col)は数値直指定のため 約1〜2µs 程度
    → 同条件でも 0.01秒未満で完了
  • Variant配列なら、10万件を0.02秒以内で処理できることもある(CPUキャッシュ効率が段違い)

つまり、「文字列連結+Rangeパース」は数千件で限界が見え始める
そこを超えたら、Cells+配列で“まとめて渡す”のが鉄板

詳細のまとめ

  • Cells(row, col)Cells(行, 列)数値指定の低コストAPI。大量ループはこれ一択。
  • Range("A1")連結|Range("列文字 & 行")読みやすいが遅め。数千行程度ならOK。
  • 列番号は前計算|precompute column index
  • 値は配列で一括入出力|batch via Variant arrays

いつCells?いつRange?|When Cells vs Range

  • 可読性優先(小規模)Range("AA" & i)は素直で読みやすい。数百~数千件なら体感問題なし
  • 性能優先(中~大規模)Cells(i, 27)(又はCells(i, colAA))が本命
  • 相対参照が要るときRange("A1:B5").Cells(r, c)相対座標が便利

列番号は“毎回計算しない”|Precompute Column Index

  • ループ内でColumns("AA").Column毎回呼ばない
    • 外で一度だけ求めて変数に保持しよう
  • 列文字を多用したいなら、定数化変換関数で橋渡し(人間→機械)

配列で一括処理|Work in Variant Arrays

  • Range.Value一度だけ読み込み→配列上で処理一括で書き戻し
  • これが最強のボトルネック回避
  • セル単位で往復しない(COM境界の回数削減)

セーフガード|Safety & Hygiene

  • With ws ... End Withオブジェクト参照の重複を減らす
  • ScreenUpdating/Calculation/EnableEventsの制御は長いバッチ処理のときのみ
  • Value2を基本(通貨・日付の自動変換トラップ回避、速度有利)

実務判断の目安|Practical Thresholds

  • ~数千行:Range("AA" & i)でもOK。優雅さ>わずかな速度
  • 数万行~:必ずCells列番号前計算配列一括速度>表記の簡便さ
  • 将来拡張が見込まれる処理は最初から高速系で設計

結論|大量データを扱わないなら読みやすさ優先

もし扱うデータが「数百〜数千行」レベルなら

  • Range("A" & i) でも
  • .Value でも
    関係ない

“あとから見ても意味がわかるか?”
“他の人が読んでも怖がらないか?”

――このほうがずっと大事。

Write for humans first — machines are already fast enough for small worlds.
まず人間のために書こう。小さな世界なら、マシンはもう十分速い。

Referenced Insights & Citations

Vocabulary

| Threshold|しきい値 |
| Overhead|オーバーヘッド |
| Parsing Overhead|パースのオーバーヘッド |
| Batch Processing|一括処理 |
| Batch Write|一括書き込み |
| Variant Array|Variant配列 |
| Performance Bottleneck|性能ボトルネック |
| Precomputation|前計算 |
| COM Boundary|COM境界 |
| Column Index|列インデックス |
| Relative Reference|相対参照 |
| Maintainability|保守性 |

If it feels like “a lot”, you’re already past the point — switch to Cells or arrays.

著者

author
月うさぎ

編集後記:
この記事の内容がベストではないかもしれません。

記事一覧