こんにちは!日々のExcel業務、本当にお疲れ様です。
「マクロの記録」を卒業して、いざ自分でコードを書き始めたものの、大量のデータを扱うようになった途端、画面がフリーズしたかのように処理が遅くなって絶望したことはありませんか?
「1行ずつセルを読んで処理していたら、コーヒーを飲み干しても終わらない……」
そんな壁にぶつかったあなたへ。今日は、Excel VBAのパフォーマンスを劇的に引き上げる「Variant型配列へのRange転送」の極意を伝授します。
ここをクリアすれば、あなたのVBAスキルは「初級者」から一気に「実務で頼れるエンジニア」へとシフトします。優しく、そして本質的なところまでしっかりと解説していきますね。
—
1. なぜセルへのアクセスは遅いのか?(VBA最大のボトルネック)
Excel VBAでやってはいけない最大のタブー、それは「ワークシートとVBAの間で何度も往復すること」です。
例えば、1万行のデータがあるとします。
次のようなコードを書いたことはありませんか?
‘ 【やってはいけないアンチパターン】
Dim i As Long
For i = 1 To 10000
‘ セルを1つずつ見に行っている(=激遅の原因)
Debug.Print Range(“A” & i).Value
Next i
Excelの画面(ワークシート)とVBAの世界は、実は「別の国」のようなものです。このコードは、わざわざ1万回も「国境を越えて」データのやり取りをしている状態です。これでは処理が重くなって当然ですよね。
解決策:データを「一網打尽」にするメモリ上の配列
この問題を解決するのが、「Rangeを一気にVariant型の配列へ放り込む」というテクニックです。
‘ 【爆速のベストプラクティス】
Dim データの入れ物 As Variant
‘ 1万行のデータを、一瞬でメモリ上の配列へコピー!
データの入れ物 = Range(“A1:A10000”).Value
これだけで、国境の往復はたった「1回」になります。あとはメモリ上(VBAの世界)で超高速にデータを料理し、必要なら一気にセルへ書き戻せばいいのです。
—
2. 知られざる真実:`.Value` と `.Value2` の決定的な違い
さて、ここで今回のテーマの核心である Valueプロパティ と Value2プロパティ の違いについてお話しします。
「え、どっちもセルの値を取るんでしょ?」と思った方、ここがプログラミングの分かれ道です。
- `.Value`:
Excel独自の「データ型」を律儀に再現しようとします。特に、セルに「通貨(¥)」や「日付」の書式が設定されていると、VBA側でそれを自動的に「Currency型」や「Date型」に変換しようと裏で頑張ります。
- `.Value2`:
余計な装飾(書式情報)を一切気にせず、セルに入っている「純粋な中身(生データ)」だけを高速に引っこ抜きます。
速度とトラブル回避の観点からの結論
実務において、大量のデータを配列に格納する際は、特別な理由がない限り`.Value2`を使うべきです。
なぜなら、`Value`が裏で行う「書式の解釈と型変換」は無駄なオーバーヘッド(処理の負荷)であり、時には予期せぬ型の不一致エラーを引き起こす原因にもなるからです。
—
3. 実践!Value2とVariant配列を使った超高速データ処理
それでは、実際に現場でそのまま使えるサンプルコードを見てみましょう。
今回は、A列にある大量の数値データに「1.1を掛け合わせる(10%アップさせる)」という処理を、配列を使って爆速で実行してみます。
Sub HighSpeedProcessSample()
Dim ws As Worksheet
Set ws = ActiveSheet
Dim startTime As Double
startTime = Timer ‘ 処理時間計測用
‘ 1. データの最終行を取得
Dim lastRow As Long
lastRow = ws.Cells(ws.Rows.Count, “A”).End(xlUp).Row
If lastRow < 1 Then Exit Sub ' 2. 範囲を一気にVariant型配列へ格納(Value2を使用!) ' ※注意:1列だけでも、配列は必ず「2次元配列」として取り込まれます(例: 10000行 × 1列) Dim rawData As Variant rawData = ws.Range(ws.Cells(1, 1), ws.Cells(lastRow, 1)).Value2 ' 3. メモリ上で高速ループ処理 Dim i As Long For i = 1 To UBound(rawData, 1) ' 空白セルでない場合のみ計算 If Not IsEmpty(rawData(i, 1)) Then ' 数値であることを確認して計算 If IsNumeric(rawData(i, 1)) Then rawData(i, 1) = rawData(i, 1) 1.1 End If End If Next i ' 4. 処理済みの配列を一気にワークシートへ書き戻す ws.Range(ws.Cells(1, 2), ws.Cells(lastRow, 2)).Value2 = rawData MsgBox "処理が完了しました! 実行時間: " & Format(Timer - startTime, "0.00秒") & "秒", vbInformation End Sub
コードのポイント解説
- `Dim rawData As Variant`: 配列を受け取る変数は、必ずVariant型で宣言してください。「`String`型」や「`Long`型」で宣言すると、配列を代入した瞬間にエラーになります。
- `UBound(rawData, 1)`: 2次元配列の「行の最大数」を取得しています。これによって、データ量が変わっても柔軟に対応できる堅牢なコードになります。
- 書き戻しも一瞬: 計算が終わった配列を、そのまま右側のセル範囲(B列)に代入しています。1行ずつ書き込む必要はもうありません。
—
4. 陥りやすい罠とエラー回避の知恵
ここで、初学者が必ずと言っていいほどハマる「落とし穴」を2つご紹介します。
落とし穴①:1セルだけを指定したときの挙動
もし `Range(“A1”).Value2` のように、たった1つのセルをVariant配列の変数に入れようとすると、配列ではなく「単体の値(スカラー値)」として格納されます。
そのため、`UBound`関数を使おうとした瞬間に「配列ではありません」というエラー(実行エラー 13: 型が一致しません)が発生します。
対策:複数行・複数列を扱うことが確実なデータ範囲に対してのみ、この一括配列処理を適用するようにしましょう。
落とし穴②:2次元配列のインデックスの方向
Excelから取得したVariant配列は、基本的に `(行, 列)` の2次元 になります。
1列だけのデータであっても `rawData(i, 1)` のように指定する必要がある点(「, 1」を忘れないこと)に注意してください。
—
まとめ:ここをクリアすればVBAの基本はバッチリ!
いかがでしたでしょうか?
1. セルとVBAの往復(1行ずつの処理)は百害あって一利なし
2. 大量データは `.Value2` を使ってVariant型配列に一網打尽にする
3. メモリ上で計算し、最後にドカンとシートへ書き戻す
この3つの原則(パラダイムシフト)をマスターするだけで、あなたの書くマクロは見違えるほど高速になり、実務で「おっ、できるな!」と一目置かれる存在になるはずです。
ここをクリアできれば、Excel VBAの基本構造やパフォーマンスの考え方はもうバッチリです。ぜひ明日からの業務で試してみてくださいね。あなたのVBAライフがより快適なものになることを応援しています!
