こんにちは!Access VBAの世界へようこそ。
ここまで踏み込んで勉強しようとしているあなたなら、きっと「もっとファイルを軽くしたい」「外部のSQL Serverとスムーズに連携させたい」といった、実務でのリアルな壁にぶつかっていることでしょう。
大丈夫、安心してください。今回は、Access VBAの真骨頂である「DAO」と、外部データベース接続の王様である「ADO」のそれぞれの強みを組み合わせた、「ハイブリッド設計」の極意を伝授します。
ここをクリアすれば、あなたの作るAccessアプリは見違えるほど高速化し、プロ顔負けの堅牢なシステムに生まれ変わりますよ。それでは、一緒に紐解いていきましょう!
—
1. なぜ「DAO」と「ADO」を使い分ける必要があるのか?
Access VBAでデータベースを操作する際、必ず耳にするのが DAO (Data Access Objects) と ADO (ActiveX Data Objects) です。
初学者のうちは「どっちを使えばいいの?」と迷いがちですが、プロの現場での答えはシンプルです。
- DAOの得意分野:
Accessの「ローカル環境(今自分が開いているファイルの中)」にあるテーブル操作。とにかく爆速です。
- ADOの得意分野:
SQL ServerやOracleなど、外部の「サーバー型データベース」との通信。接続の安定性と、高度なSQL(トランザクション含む)の実行に長けています。
💡 現場の黄金律:「適材適所のハイブリッド」
大量のデータ加工や一時的な計算を、いきなり外部のSQL Server上でやろうとすると、ネットワークの往復(オーバーヘッド)が発生して処理が重くなります。
そこで、今回のテーマであるハイブリッド設計の出番です。
1. 【DAOで高速処理】 外部からデータを軽く持ってくるか、Access内のローカル一時テーブル上で、ガリガリと高速にデータを加工・集計する。
2. 【ADOで書き戻し】 最終的に綺麗に整った結果だけを、ADOを使ってSQL Serverへ一気にドカンと書き戻す。
このデータフローをマスターすれば、処理スピードが何倍にも跳ね上がります!
—
2. アーキテクチャの全体像(データフロー)
まずは、今回目指す仕組みを頭の中にイメージしましょう。
[ 外部SQL Server ]
▲
│ (1) ADOでデータを取得
▼
[ Access ローカル一時テーブル ]
│
│ (2) DAOで高速なレコード走査・加工
▼
[ 加工済みローカル一時テーブル ]
│
│ (3) ADOでSQL Serverへトランザクション書込
▼
[ 外部SQL Server (最終結果) ]
「一時テーブルなんて使わなくてもクエリで一発では?」と思うかもしれませんが、複雑な業務ロジックや条件分岐が絡む場合、VBAとDAOを組み合わせた一時テーブルでの逐次処理の方が、後々のメンテナンス性で圧倒的に有利な場面が多いのです。
—
3. 実装コード:ハイブリッド設計の全貌
それでは、開発現場でそのままコピペして使える実践的なコードを公開します。
今回は、「ローカルの一時テーブルでデータを整え、SQL Serverのマスターテーブルへトランザクション付きで一括書き込みを行う」シナリオを想定しています。
Option Compare Database
Option Explicit
‘ ==============================================================================
‘ 【メイン処理】DAOとADOを融合させたハイブリッド・データローダー
‘ ==============================================================================
Public Sub ExecuteHybridProcess()
‘ エラーハンドリングの準備(実務では必須です!)
On Error GoTo ErrorHandler
Dim db As DAO.Database
Dim rsLocal As DAO.Recordset
Dim conn As Object // ADO Connection
Dim cmd As Object // ADO Command
Dim strConn As String
Dim lngCount As Long
Set db = CurrentDb
lngCount = 0
‘ ————————————————————————–
‘ STEP 1: DAOによるローカル一時テーブルの高速読み込み
‘ ————————————————————————–
‘ ※あらかじめ「tmp_WorkData」というローカルテーブルがAccess内にある前提です
Set rsLocal = db.OpenRecordset(“SELECT FROM tmp_WorkData WHERE ProcessedFlag = False”, dbOpenDynaset)
If rsLocal.EOF Then
MsgBox “処理対象のデータが存在しません。”, vbInformation, “通知”
GoTo CleanUp
End If
‘ ————————————————————————–
‘ STEP 2: ADOによる外部SQL Serverへの接続確立
‘ ————————————————————————–
Set conn = CreateObject(“ADODB.Connection”)
‘ SQL Serverへの接続文字列(環境に合わせて書き換えてください)
strConn = “Provider=SQLOLEDB;Server=YOUR_SERVER_NAME;Database=YOUR_DB_NAME;Uid=YOUR_USER;Pwd=YOUR_PASSWORD;”
conn.ConnectionTimeout = 30
conn.Open strConn
‘ ————————————————————————–
Id: ‘ STEP 3: トランザクションを開始して安全に書き戻し
‘ ————————————————————————–
conn.BeginTrans
Do Until rsLocal.EOF
‘ — ここでDAOを使ったローカル側のデータ加工・参照ができる(高速!) —
Dim targetId As Long
Dim targetValue As String
targetId = rsLocal!ID
targetValue = rsLocal!ItemName & ” (Processed)”
‘ ADOコマンドを使ってSQL Serverへ書き込み
Dim sql As String
sql = “INSERT INTO Remote_MasterTable (RecordID, ItemName, CreatedAt) VALUES (?, ?, ?)”
Set cmd = CreateObject(“ADODB.Command”)
Set cmd.ActiveConnection = conn
cmd.CommandText = sql
‘ パラメータクエリでSQLインジェクション対策と型安全性を担保
cmd.Parameters.Append cmd.CreateParameter(“ID”, 3, 1, , targetId) // 3 = adInteger
cmd.Parameters.Append cmd.CreateParameter(“Name”, 200, 1, 255, targetValue) // 200 = adVarChar
cmd.Parameters.Append cmd.CreateParameter(“Date”, 135, 1, , Now) // 135 = adDateTime
cmd.Execute
‘ 処理済みフラグをローカル側(DAO)で更新
rsLocal.Edit
rsLocal!ProcessedFlag = True
rsLocal.Update
lngCount = lngCount + 1
rsLocal.MoveNext
Loop
‘ すべて成功したらコミット
conn.CommitTrans
MsgBox lngCount & ” 件のデータをSQL Serverへ正常に同期しました!”, vbInformation, “処理成功”
CleanUp:
‘ ————————————————————————–
‘ STEP 4: 確実なオブジェクトの解放(メモリリーク防止)
‘ ————————————————————————–
On Error Resume Next
If Not rsLocal Is Nothing Then rsLocal.Close: Set rsLocal = Nothing
If Not db Is Nothing Then Set db = Nothing
If Not conn Is Nothing Then
If conn.State = 1 Then conn.Close
Set conn = Nothing
End If
Exit Sub
ErrorHandler:
‘ 異常発生時はトランザクションをロールバックして変更をなかったことにする
If Not conn Is Nothing Then
If conn.State = 1 Then conn.TransactCount > 0 Then conn.RollbackTrans
End If
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “エラー”
Resume CleanUp
End Sub
—
4. コードの深掘りと「陥りやすい罠」の回避策
上記のコードには、プロのエンジニアが現場で必ず組み込むべき「生き残りの知恵」が詰まっています。いくつか重要なポイントを解説します。
① オブジェクトの解放(メモリ管理)をサボらない
Access VBAにおいて、`Recordset` や `Connection` を開きっぱなしにするのは、メモリのガソリンタンクに火種を放り込むようなものです。必ず `Set … = Nothing` で綺麗にメモリから消去しましょう。
特に、ループ内で `Command` オブジェクトを生成・破棄する際は、ループのスコープとメモリの肥大化に注意が必要です。
② トランザクション(`BeginTrans` / `CommitTrans` / `RollbackTrans`)の重要性
外部DBへの書き込み途中で、ネットワークが切れたり、データに不備があったりしてエラーが起きたとき、中途半端なデータがDBに残ると大惨事になります。
ADOのトランザクションを使うことで、「すべて成功するか、すべて無かったことにするか」の安全地帯(ACID特性)を確保できます。
③ パラメータクエリ(`CreateParameter`)の徹底
SQLの文字列を `sql = “INSERT INTO … VALUES (” & targetId & “, ‘” & targetValue & “‘)” ` のように直接結合して書くのは絶対にNGです(SQLインジェクションや、シングルクォーテーションのエスケープ漏れによる構文エラーの原因になります)。
ADOのパラメータオブジェクトを使い、型を明示して安全に値を渡しましょう。
—
5. おわりに:ここをクリアすれば、もう怖くない!
お疲れ様でした!DAOとADOのハイブリッド設計、そのコンセプトと実装のイメージは掴めましたでしょうか?
- ローカルの快適な操作には「DAO」
- 外部サーバーとの堅牢な通信には「ADO」
この2つを適材適所で使い分けられるようになると、Accessは単なる「オフィスの便利ツール」から、「堅牢で高速な業務システムのフロントエンド」へと劇的に進化します。
最初は難しく感じるかもしれませんが、エラー処理やトランザクションの型を一度自分のテンプレートにしてしまえば、どんな巨大な案件でも怖くありません。
ここをクリアしたあなたなら、もうAccess VBAの初学者卒業です。ぜひ、実際の業務データで試してみてくださいね!応援しています!
