こんにちは!VBAのスキルを次のステージへと引き上げる旅へようこそ。
「マクロの記録」から抜け出し、自分でコードを書けるようになると、今度はこんな壁にぶつかります。
「数万行ある巨大なテキストファイルを読み込むと、処理が異様に遅い……というか、Excelが固まる!」
もしあなたが、ファイルを丸ごと`String`型(文字列)の変数に放り込んだり、`Line Input`で1行ずつ地道に読み込んだりしているなら、ちょっと待ってください。そのやり方、VBAのエンジンにものすごい負荷をかけています。
今回は、巨大なファイルを秒速で読み込み、メモリを極限まで節約する「Byte型配列によるバイナリデータ処理」の世界へご案内します。ここをクリアすれば、あなたのVBAは「おもちゃ」から「プロ仕様の自動化ツール」へと生まれ変わりますよ。
—
1. なぜString型でのファイル読み込みは遅いのか?
まずは、敵(ボトルネック)を知ることから始めましょう。
VBAの`String型`は、内部でUTF-16(1文字=2バイト)という形式で文字を保持しています。さらに、VBAがテキストファイルを通常の文字として読み込もうとすると、OSの文字コード変換(ANSIからUnicodeへの変換など)が裏でこっそり行われます。
これがどういうことか分かりますか?
- メモリの無駄遣い: 1バイトの文字(半角英数など)であっても、強制的に2バイトに拡大してメモリに保持します。
- 変換コストの重さ: ファイルの文字コードとVBA内部の文字コードを行き来するたびに、CPUが余計な計算を強いられます。
数百行程度の小さなファイルなら誤差ですが、数メガバイトを超えるようなログファイルやCSVを相手にした瞬間、Excelはフリーズ寸前になります。
—
2. 救世主「Byte型配列」とバイナリ読み込みの思想
ここで登場するのが、今回の主役である`Byte型配列`です。
`Byte型`とは、その名の通り「1バイト(8ビット)」のデータをそのまま格納するデータ型です。余計な装飾も、文字コードの解釈も一切なし。「そこにあるデータを、ただの数字の塊(バイナリ)として丸ごとメモリにロードする」というアプローチを取ります。
イメージ図で表してみましょう。
【従来のString型(文字として読む)】
ファイル (A) ──> [OSの文字コード変換] ──> 変数 (A = 2バイト) + メモリを大量消費!
【今回のByte型配列(バイナリとして読む)】
ファイル (A) ──> [変換なし・そのまま直行!] ──> 配列(0) = 65 (超高速&省メモリ!)
文字コードの変換という「無駄な仲介人」を排除することで、ファイル読み込みの速度は文字通りケタ違いになります。
—
3. 実践!Byte型配列でファイルを爆速読み込みするコード
百聞は一見にしかず。実際に数メガバイトのファイルを一瞬で読み込むプロのコードをお見せします。
VBAの開発画面(VBE)を開き、標準モジュールに以下のコードを貼り付けてみてください。
Sub ReadFileAsBinary()
Dim filePath As String
Dim fileNum As Integer
Dim fileData() As Byte ‘ ★ここがポイント!Byte型の「動的配列」を用意
Dim lofSize As Long
‘ 読み込むファイルのパス(ご自身の環境に合わせて変更してください)
filePath = ThisWorkbook.Path & “\large_data.txt”
‘ ファイルが存在するかチェック
If Dir(filePath) = “” Then
MsgBox “ファイルが見つかりません。”, vbCritical
Exit Sub
End If
‘ 空いているファイル番号を取得
fileNum = FreeFile
‘ ① バイナリモードでファイルを開く(Binary Access Read)
Open filePath For Binary Access Read As #fileNum
‘ ② ファイルのサイズ(バイト数)を取得する
lofSize = LOF(fileNum)
‘ ③ ファイルサイズに合わせて配列の大きさを一発で確保(リサイズ)
ReDim fileData(0 To lofSize – 1)
‘ ④ 【最重要】ファイル全体を一度にByte型配列へ流し込む!
Get #fileNum, , fileData
Close #fileNum
‘ ⑤ 読み込んだデータの確認(例として最初の10バイトを表示)
Dim i As Long
Dim msg As String
msg = “ファイルの読み込みに成功しました!” & vbCrLf & _
“ファイルサイズ: ” & lofSize & ” バイト” & vbCrLf & _
“— 先頭10バイトの文字コード —” & vbCrLf
For i = 0 To IfMin(9, lofSize – 1)
msg = msg & “[” & i & “]: ” & fileData(i) & ” (” & Chr(fileData(i)) & “)” & vbCrLf
Next i
MsgBox msg, vbInformation, “爆速読み込み完了”
End Sub
‘ 補助関数:小さい方の数値を返す
Function IfMin(a As Long, b As Long) As Long
If a < b Then IfMin = a Else IfMin = b
End Function
コードのここがスゴい!
1. `For Binary Access Read`
ファイルを「文字」ではなく「ただのバイナリ(バイトの連続)」として開くことで、OSに余計な仕事をさせません。
2. `LOF(fileNum)` と `ReDim`
ファイルの正確なサイズを一瞬で取得し、配列の大きさを最初にビシッと決めます。途中でメモリを再確保するオーバーヘッド(無駄な時間)が発生しません。
3. `Get #fileNum, , fileData`
これが魔法の1行です。数メガバイトのファイルであっても、このたった1行でハードディスクからメモリへ「一網打尽」にデータをロードします。ループを回す必要すらありません。
—
4. 陥りやすい罠とエンジニアの知見(エラー対策)
この手法は非常に強力ですが、バイナリを直接扱うがゆえの「注意点」もあります。現場でハマりがちなポイントを先回りして解説しておきます。
罠1:文字コードの壁(Shift-JIS vs UTF-8)
Byte型配列として読み込んだデータは、単なる「数字の並び(Shift-JISならShift-JISのバイトコード)」です。
もし読み込んだファイルがUTF-8(BOMなし)やUnicodeの場合、そのまま`Chr()`関数などで文字に変換しようとすると、文字化けを起こします。
- 対策:
現代のテキストファイルを扱う場合、VBAだけで文字コードの判定やデコードを自作するのは労力がかかります。もし文字列として加工したい場合は、読み込んだByte型配列を一度 `ADODB.Stream` オブジェクトなどに流し込んで文字コードを変換・デコードするのが、実務における定石です。
罠2:配列のインデックスは「0」から始まる
VBAの通常の配列やセル操作は1始まりが多いですが、バイナリ配列は `0` から始まります。ファイルサイズが `100` バイトなら、インデックスは `0` から `99` です。
ループを回すときは `LBound` と `UBound` 関数を使って安全に境界を取得する癖をつけましょう。
For i = LBound(fileData) To UBound(fileData)
‘ 処理
Next i
—
まとめ:ここをクリアすれば、VBAの基本はバッチリ!
今回は、Byte型配列を使ったバイナリ読み込みによる「高速化とメモリ節約術」を解説しました。
- 大規模ファイルを扱うときは、`String型`や行単位の読み込みを疑う。
- `Open … For Binary` と `Byte型配列` を組み合わせて、一気にメモリへロードする。
- データの正体は「バイト(数字)」なので、必要に応じて文字コードのデコードを考慮する。
このアプローチが自然に出てくるようになれば、あなたはもう「VBA初学者」を卒業し、システムの本質を理解したエンジニアの領域に足を踏み入れています。
巨大なデータを軽々とさばく、爽快なVBAライフをぜひ楽しんでください!
