【入門編】【ADODB.Recordset 活用】Dictionary を超える柔軟性を持つ「インメモリ・データベース」による複雑なデータ集計 – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク
スポンサーリンク

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の基本はバッチリですよ。
さあ、次なるステップへ進みましょう!

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