Dictionaryの限界を超えろ。ADODB.Recordsetによる「インメモリ・データベース」構築術
こんにちは。自動化の世界へようこそ。
ここまで、`Scripting.Dictionary` を使ってデータを管理する方法を学んできたことでしょう。「キー」に対して「値」を紐付ける。この手法は、VBScriptにおけるデータ処理の基本であり、非常に強力な武器です。
しかし、あなたがより複雑な業務——例えば、「売上データから特定のカテゴリだけを抜き出し、さらに金額の高い順に並べ替えたい」といった要望——に直面したとき、Dictionaryは突然、その牙を抜かれたかのように沈黙します。
「Dictionaryでは、データの並べ替え(ソート)ができない……」
「複数の条件でデータを絞り込む(フィルタリング)のが、あまりに面倒だ……」
もしあなたが今、そう感じているなら、おめでとうございます。あなたは「プログラミングの壁」に正しくぶつかりました。その壁の向こう側には、エンジニアとしての視界を一気に広げる、伝説的なテクニックが待っています。
今日は、Dictionaryを超え、メモリ上に仮想のデータベースを構築する魔法のオブジェクト、`ADODB.Recordset` の活用術を伝授しましょう。
なぜ Dictionary では足りないのか?
まずは、私たちが直面している課題を整理しましょう。`Scripting.Dictionary` は非常に高速ですが、あくまで「箱(キー)」と「中身(値)」のペアを管理するためのものです。
| 機能 | Scripting.Dictionary | ADODB.Recordset |
|---|---|---|
| 基本構造 | キーと値のペア | 行と列を持つ「表(テーブル)」 |
| ソート(並べ替え) | 不可能(追加した順になる) | 極めて容易(Sortプロパティ) |
| フィルタリング(抽出) | 自力でループを回して判定が必要 | 極めて容易(Filterプロパティ) |
| 複数列の管理 | 値の中に配列やオブジェクトが必要で複雑 | 列(Field)として直感的に扱える |
Dictionaryで「金額順に並べ替える」作業をしようとすると、一度全てのデータを配列に取り出し、複雑なソートアルゴリズム(バブルソートなど)を自前で実装しなければなりません。これは、初学者が最も挫折しやすいポイントです。
一方で、`ADODB.Recordset` を使えば、まるでSQLを使っているかのように、たった一行の指示でこれらを解決できるのです。
秘技:Disconnected Recordset(非接続型レコードセット)
通常、`ADODB.Recordset` と聞くと、「データベース(AccessやSQL Serverなど)に接続するためのもの」と思うかもしれません。しかし、ここがプロの知恵です。
私たちは、データベースに接続せず、メモリ上だけで完結する「仮想のテーブル」として Recordset を利用します。これを「Disconnected Recordset」と呼びます。これによって、外部環境に依存せず、爆速で高度なデータ操作が可能になるのです。
実践:インメモリ・データベースの構築フロー
以下のコードは、メモリ上に「商品リスト」という仮想のテーブルを作り、データを追加し、ソートとフィルタリングを行う完全なサンプルです。
' ===========================================================================
' テーマ:ADODB.Recordset を用いたインメモリ・データベースの実装
' 目的:Dictionaryでは困難な「ソート」と「フィルタリング」をメモリ上で完結させる
' ===========================================================================
Option Explicit
Dim rs, newRow
Dim strProduct, lngPrice, strCategory
' 1. Recordsetオブジェクトの生成
Set rs = CreateObject("ADODB.Recordset")
' 2. スキーマ(テーブル構造)の定義
' データベースに接続しないため、あらかじめ「列(フィールド)」を定義しておく必要があります。
rs.Fields.Append "ID", 3 ' 3 = adInteger (整数型)
rs.Fields.Append "Name", 200 ' 200 = adVarChar (文字列型)
rs.Fields.Append "Price", 5 ' 5 = adCurrency (通貨型)
rs.Fields.Append "Category", 200 ' 200 = adVarChar (文字列型)
' 3. レコードセットを開く(接続先を指定しないことでメモリ上での動作になる)
' ※ 本来は接続文字列が必要ですが、ここでは空の状態で開きます。
rs.Open
' --- データの投入プロセス ---
' 4. データの追加 (AddNew)
' 毎回「AddNew」を呼び出し、値をセットして「Update」する流れです。
' データ1
rs.AddNew
rs.Fields("ID").Value = 1
rs.Fields("Name").Value = "高級コーヒー豆"
rs.Fields("Price").Value = 2500
rs.Fields("Category").Value = "食品"
rs.Update
' データ2
rs.AddNew
rs.Fields("ID").Value = 2
rs.Fields("Name").Value = "万年筆"
rs.Fields("Price").Value = 12000
rs.Fields("Category").Value = "文具"
rs.Update
' データ3
rs.AddNew
rs.Fields("ID").Value = 3
rs.Fields("Name").Value = "ノート"
rs.Fields("Price").Value = 500
rs.Fields("Category").Value = "文具"
rs.Update
' データ4
rs.AddNew
rs.Fields("ID").Value = 4
rs.Fields("Name").Value = "高級チョコレート"
rs.Fields("Price").Value = 1500
rs.Fields("Category").Value = "食品"
rs.Update
' --- 高度なデータ操作プロセス ---
' 5. 【魔法1】ソート(並べ替え)
' 「Price(価格)を降順(DESC)に並べ替え」
rs.Sort = "Price DESC"
WScript.Echo "--- 【価格の高い順】 ---"
Do Until rs.EOF
WScript.Echo rs.Fields("Name").Value & " : " & rs.Fields("Price").Value & "円"
rs.MoveNext
Loop
' 6. 【魔法2】フィルタリング(絞り込み)
' 「Categoryが '文具' のものだけを抽出」
rs.Filter = "Category = '文具'"
WScript.Echo ""
WScript.Echo "--- 【カテゴリ:文具のみ抽出】 ---"
If rs.EOF Then
WScript.Echo "該当するデータはありません。"
Else
Do Until rs.EOF
WScript.Echo rs.Fields("Name").Value & " (" & rs.Fields("Category").Value & ")"
rs.MoveNext
Loop
End If
' 7. 後始末(オブジェクトの解放)
' ライフサイクル管理はプロの作法です。
rs.Close
Set rs = Nothing
WScript.Echo ""
WScript.Echo "処理が正常に完了しました。"
陥りやすいエラーと、エンジニアの「勘所」
この手法を使いこなすために、いくつか注意すべき点があります。これを知っているかどうかが、現場でのデバッグ時間を左右します。
1. 「Open」を忘れると動かない
Recordsetは、フィールドを定義しただけでは「空の器」に過ぎません。`rs.Open` を呼び出して、初めてメモリ上の作業領域が確保されます。これを行わずに `AddNew` をしようとすると、「オブジェクトが開かれていません」というエラーに襲われることになります。
2. データ型の不一致
`rs.Fields.Append` で定義する型(adInteger, adVarCharなど)は非常に重要です。数値を入れるべき列に文字列を入れようとすると、実行時エラーが発生します。
- `3` は整数 (`adInteger`)
- `200` は文字列 (`adVarChar`)
- `5` は通貨 (`adCurrency`)
これらは、実務では定数として定義して使うのがスマートですが、まずは数字で理解しておけば十分です。
3. オブジェクトのライフサイクル(メモリ管理)
VBScriptは、使い終わったオブジェクトを適切に解放しないと、メモリを食いつぶしたり、後続の処理で予期せぬ挙動を引き起こしたりします。
`Set rs = Nothing`。この一文を、スクリプトの最後に必ず書く癖をつけてください。これは、プロとしての「美しい作法」です。
まとめ:ここをクリアすれば、あなたはもう「単なるマクロ使い」ではない
Dictionaryは「点」の管理です。
ADODB.Recordsetは「面(テーブル)」の管理です。
データを単なる値の集まりとしてではなく、「構造を持ったデータセット」として捉えられるようになったとき、あなたの作る自動化ツールは、劇的に柔軟で、劇的に強力なものへと進化します。
「もっと複雑な条件で集計したい」「大量のデータを高速に処理したい」
そんな欲求が出てきたら、ぜひこの `ADODB.Recordset` を思い出してください。
ここをクリアすれば、VBScriptの基本はバッチリですよ。
さあ、次なるステップへ進みましょう!
