【入門編】【実務中級者向け】FSOでパースした大量CSVデータをADODB.Recordset(インメモリDB)へロードして高速ソート&グループ化 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク

こんにちは!VBScriptの世界へようこそ。
業務自動化の現場で「Excelを使うほどでもないけれど、数万行のCSVデータをサクッと集計・並び替えしてレポートを出したい」なんて要件に直面したことはありませんか?

「よし、FSO(FileSystemObject)でファイルを読み込んで、配列に入れて…あれ、ソートはどう書くんだっけ?ループがネストして遅すぎる!」
――そんな壁にぶつかった経験があるなら、今回のテーマはまさにあなたのためのものです。

今回は、FSOでパースした大量CSVデータを `ADODB.Recordset`(インメモリDB)へロードし、SQLライクな検索や高速ソート・グループ化を行う極限テクニックを伝授します。ここをクリアすれば、あなたのVBScriptスキルは間違いなく「中級者の壁」を突破し、プロの領域に到達しますよ。

—

なぜ「FSO × ADODB.Recordset」なのか?

VBScriptでCSVを扱う際、次のようなアプローチをとりがちです。

1. 愚直な配列処理: コードが複雑化し、ソートや集計のロジックを自前で書くとパフォーマンスが劇的に低下する。
2. Excelを裏で起動: 圧倒的に重い。デスクトップアプリケーションのバックグラウンド起動はリソースの無駄遣いであり、サーバーサイドでは御法度。

そこで登場するのが、Windowsに標準搭載されている隠れた名優 `ADODB.Recordset` です。
これを使うと、物理的なデータベース(SQL ServerやAccessなど)に接続しなくても、メモリ上に仮想的なデータベーステーブルを作り出すことができます。つまり、FSOで読み込んだCSVデータをメモリ上に放り込み、「SQLの威力(ORDER BYやWHERE句)」をVBScript上で直接利用できるようになるのです。

—

全体像:データ処理のライフサイクル

今回の処理の流れを図解すると、以下のようになります。

[ CSVファイル ]
↓ (FileSystemObjectで1行ずつパース)
[ ADODB.Recordset (インメモリDB) ]
↓ (.Sort で超高速並び替え / SQLフィルタ)
[ 綺麗な集計結果を出力 ]

それでは、実際のコードを見ていきましょう。開発現場でそのままコピペして使えるように、実用的なコメントをみっちり仕込んでおきました。

—

実装コード:インメモリDB駆動型CSV高速プロセッサ

以下のコードをメモ帳などに貼り付け、拡張子を `.vbs` にして保存して実行してみてください(※同一フォルダに `data.csv` という名前の適当なCSVを用意しておいてくださいね)。

‘ ==============================================================================
‘ スクリプト名: MemoryDBCSVProcessor.vbs
‘ 概要: FSOで読み込んだCSVをADODB.Recordset(インメモリDB)に展開し、
‘ 高速ソートとフィルタリングを行う実務向けサンプル
‘ ==============================================================================
Option Explicit

Sub Main()
Dim fso, ts, csvFile
Dim rs
Dim line, fields
Dim targetValue

csvFile = “data.csv” ‘ 処理対象のCSVファイル名

‘ 1. FileSystemObjectの生成
Set fso = CreateObject(“Scripting.FileSystemObject”)

If Not fso.FileExists(csvFile) Then
MsgBox “指定されたCSVファイルが見つかりません: ” & csvFile, vbCritical, “エラー”
Exit Sub
End If

‘ 2. ADODB.Recordset の生成(インメモリDBの土台作り)
Set rs = CreateObject(“ADODB.Recordset”)

‘ テーブルのスキーマ(列定義)を明示的に作成する
‘ 引数: 列名, データ型(200=VarCharなど), 列の最大長
rs.Fields.Append “ID”, 3 ‘ 3 = adInteger (整数)
rs.Fields.Append “Name”, 200, 50 ‘ 200 = adVarChar (文字列, 最大50文字)
rs.Fields.Append “Score”, 3 ‘ 3 = adInteger (整数)

‘ カーソルタイプとロックタイプを指定してオープン
‘ adOpenStatic(3), adLockOptimistic(3) はインメモリ操作の黄金律です
rs.Open

‘ 3. FSOによるCSVファイルの読み込みとRecordsetへの投入
‘ ForReading = 1, Unicode/ANSIの判定は省略してデフォルト(False)で開く
Set ts = fso.OpenTextFile(csvFile, 1, False)

‘ ヘッダー行をスキップ(もしヘッダーがある場合)
If Not ts.AtEndOfStream Then ts.ReadLine

Do While Not ts.AtEndOfStream
line = ts.ReadLine
If Trim(line) <> “” Then
‘ カンマ区切りで配列に分解(単純なCSVを想定)
fields = Split(line, “,”)

‘ レコードの新規追加と値の設定
rs.AddNew
rs.Fields(“ID”).Value = CInt(fields(0))
rs.Fields(“Name”).Value = CStr(fields(1))
rs.Fields(“Score”).Value = CInt(fields(2))
rs.Update
End If
Loop
ts.Close

‘ 4. インメモリDBの真骨頂:【高速ソート】の実行
‘ Scoreの降順(-1)、同点ならIDの昇順(1)で一瞬で並び替え
WScript.Echo “— 【ソート結果】Scoreの降順 —”
rs.Sort = “Score DESC, ID ASC”

‘ 先頭に移動して全件走査
If Not rs.EOF Then rs.MoveFirst

Do Until rs.EOF
WScript.Echo “ID: ” & rs.Fields(“ID”).Value & _
” | Name: ” & rs.Fields(“Name”).Value & _
” | Score: ” & rs.Fields(“Score”).Value
rs.MoveNext
Loop

‘ 5. インメモリDBの真骨頂:【条件フィルター(抽出)】の実行
WScript.Echo vbCrLf & “— 【フィルタ結果】Scoreが80以上のデータ —”
rs.Filter = “Score >= 80”

If Not rs.EOF Then rs.MoveFirst
Do Until rs.EOF
WScript.Echo “抽出 -> Name: ” & rs.Fields(“Name”).Value & ” (Score: ” & rs.Fields(“Score”).Value & “)”
rs.MoveNext
Loop

‘ 6. クリーンアップ(メモリの解放)
rs.Close
Set rs = Nothing
Set ts = Nothing
Set fso = Nothing

WScript.Echo vbCrLf & “すべての処理が正常終了しました。”
End Sub

‘ メイン処理の実行
Main()

—

階層を追って、このコードのキモを解説しましょう。

1. スキーマ(列定義)の重要性

`rs.Fields.Append` を使って、あらかじめデータの型を定義しています。これをサボって適当にVariant型で突っ込むと、後でソートや集計を行ったときに「文字列としてソートされてしまう(例: “100” が “20” より前に来る)」といった致命的なバグを踏みます。型を厳格に定義するのが、プロのエンジニアの作法です。

2. 黄金のオープン定数

`rs.Open` の前段階で、インメモリ上でデータをいじり倒すための準備をしています。
`ADODB.Recordset` は本来データベースサーバーと通信するためのものですが、接続先を指定せずに `.Open` を叩くだけで、完全に独立したメモリ上のテーブルとして機能し始めます。これがめちゃくちゃ高速な理由です。

3. `.Sort` と `.Filter` の圧倒的パワー

自前でバブルソートなどのアルゴリズムを書く必要は一切ありません。
`rs.Sort = “Score DESC, ID ASC”` と一行書くだけで、C++ベースの最適化された高速アルゴリズムがメモリ上でソートを完了させます。さらに `.Filter` プロパティを使えば、SQLの `WHERE` 句と同等の条件抽出がノーコストで行えます。

—

現場でやりがち!陥りやすいエラーと対策

初心者がこの手法に挑んだとき、9割の確率でハマるポイントを先回りして解説しておきます。

エラー①:型不一致 (Type Mismatch)

  • 症状: `rs.AddNew` のタイミングや `Score` の比較時に「型が一致しません」というエラーが出る。
  • 原因: CSVから読み込んだデータは、FSOを通すとすべて文字列(String型)として扱われます。そのため、定義したスキーマが整数型(`3 = adInteger`)であっても、パースした文字列をそのまま突っ込むと怒られる場合があります。
  • 対策: サンプルコードのように `CInt()` や `CLng()`、`CDbl()` を使って、明示的に型変換を行ってから代入してください。

エラー②:マルチバイト文字(日本語)の文字化け

  • 症状: `Name` 列などに日本語を入れたら「?????」になったり、文字化けして例外が発生する。
  • 原因: FSOの `OpenTextFile` はデフォルトでシステム既定の文字コード(Windows環境ならShift-JIS等)で開きますが、CSV自体がUTF-8(BOM付き/無し)である場合、うまく読み込めません。
  • 対策: 本格的な業務システムでは、FSOではなく `ADODB.Stream` オブジェクトを使って文字コード(UTF-8など)を明示的に指定してテキストを読み込むのがベストプラクティスです。

—

先輩エンジニアからのエール

お疲れ様でした!ここまで読み進めたあなたなら、もう「マクロの記録をポチポチ押すだけの初学者」ではありません。
ファイルシステムを自在に操るFSOと、メモリ上でデータを縦横無尽に料理するADODB.Recordsetのコンビネーションは、VBScriptにおける最強の武器の一つです。

「ここをクリアすれば、VBScriptの基本はバッチリですよ!」

社内の定型業務や、ローカルでのデータ前処理バッチなどで、ぜひこのテクニックを役立てて周囲をあっと言わせてください。あなたの自動化ライフがより快適で知的なものになることを応援しています!

タイトルとURLをコピーしました