【Access VBAを掌握する極限の知見】名前の自動修正を制する者は、大規模データ処理を制する
開発プロジェクトの現場で、こんな悪夢を経験したことはないだろうか。
数万件を誇るトランザクションテーブルの生成、あるいは複雑なクエリの動的構築。コード自体は美しく、インデックスも適切に貼られているはずなのに、Accessが突如として沈黙する。CPUファンがうなりを上げ、タスクマネージャーを覗けば、Accessのプロセスが単一コアを100%食いつぶしてフリーズ寸前。
「なぜだ、たかが数万レコードの追加・削除になぜこれほど時間がかかる?」
犯人は、コードの書き方でもSQLの非効率さでもない。Accessのデフォルト機能である「名前の自動修正(Name AutoCorrect)」だ。
今回は、この隠れたパフォーマンスキラーをVBAから完全に手なずけ、巨大なデータ処理を圧倒的なスピードで駆け抜けるための極限の知見を授けよう。
—
1. なぜ「名前の自動修正」は悪魔の機能なのか
Accessには、テーブルのフィールド名やフォームのコントロール名を変更した際、それに依存するクエリ、フォーム、レポートの参照を自動的に書き換えてくれる「親切な」機能がついている。これが「名前の自動修正」だ。
開発初期の小規模なデータベースであれば、確かに便利な機能かもしれない。しかし、これが実務の現場における大規模なテーブル操作・オブジェクト構築の場においては「百害あって一利なし」の諸刃の剣と化す。
パフォーマンス低下のメカニズム
Accessは、テーブルの設計変更やプログラムからのオブジェクト生成・変更を検知するたびに、データベース内の全オブジェクトの依存関係をスキャンし、裏でシリアル化されたログを更新し続ける。
特に、VBAから一時テーブル(マートテーブル)をガンガン作成・削除するようなバッチ処理や、数千件のレコードをループで処理するような場面では、この「自動修正の監視コスト」がボディブローのように効いてくる。結果として、処理時間が通常の数倍から数十倍に膨れ上がるのだ。
プロの開発者であれば、データベースの構造変更の連鎖は、自分自身のコード(DDL)で完全にコントロールすべきである。Accessの「おせっかいな自動修正」にバックグラウンドを汚染される謂れはない。
—
2. 解決策:`Application.GetOption` と `SetOption` による動的制御
この問題に対するアプローチはシンプルだ。「重い処理の直前で機能を無効化し、処理が終わったら即座に元の状態へ復元する」。
ここで登場するのが、Accessのアプリケーション設定を操作する `Application.GetOption` と `Application.SetOption` だ。
このアプローチには、以下の2つの絶対的なメリットがある。
1. 環境依存の排除: 開発者のPCや本番サーバーのAccess設定がどうなっていようと、コード側で強制的に最適な環境を作り出せる。
2. 安全性の確保: 処理の最後(エラー発生時を含む)に必ず元の設定に戻すため、ユーザーの意図しない環境変化を残さない。
—
3. 【プロダクションコード】堅牢性を極めた一括処理モジュール
それでは、実際の現場でそのまま使える、極限まで堅牢性を高めたVBAコードを提示しよう。
エラーハンドリング(`On Error GoTo`)を徹底し、万が一データ処理中に予期せぬエラーが発生してコードが中断した場合でも、必ず「名前の自動修正」の設定が元の状態に復元されるように設計されている点がポイントだ。
Option Compare Database
Option Explicit
‘ =========================================================================
‘ モジュール名: modPerformanceOptimizer
‘ 概要 : 大規模データ処理時のパフォーマンス低下要因を一時的に無効化する
‘ 著作権表記 : Enterprise Architecture Lab
‘ =========================================================================
Public Sub ExecuteHeavyProcessWithHighPerformance()
Dim lngAutoCorrectName As Long
Dim lngAutoCorrectSub As Long
‘ ———————————————————————
タイマー計測開始(デバッグ用)
‘ ———————————————————————
Dim dblStartTime As Double
dblStartTime = Timer
On Error GoTo ErrorHandler
‘ ———————————————————————
‘ 1. 現在の設定値を退避(GetOption)
‘ ———————————————————————
‘ 「名前に自動修正を行う」の設定値を取得 (0: オフ, -1: オン ※バージョンにより異なる)
lngAutoCorrectName = Application.GetOption(“Name AutoCorrect Save”)
‘ 「名前の自動修正ログを記録する」の設定値を取得
lngAutoCorrectSub = Application.GetOption(“Name AutoCorrect Log”)
‘ ———————————————————————
‘ 2. 機能を強制的に無効化(SetOption)
‘ ———————————————————————
Application.SetOption “Name AutoCorrect Save”, 0
Application.SetOption “Name AutoCorrect Log”, 0
‘ (オプション)さらにパフォーマンスを極限まで求める場合は、
‘ 実績のある CurrentDb.Execute を用い、画面描画も停止すると完璧。
DoCmd.Echo False
‘ =====================================================================
‘ 3. 本丸の重い処理(ここに大規模なテーブル操作等を記述)
‘ =====================================================================
MsgBox “ここから負荷の高い一括処理を実行します。”, vbInformation, “処理開始”
‘ — 【実務でのシミュレーション】 —
‘ 例: 一時テーブルの作成と数万件のデータインサート
‘ CurrentDb.Execute “CREATE TABLE T_TempBulk (ID Long, DataText Text(255));”, dbFailOnError
‘ Dim i As Long
‘ For i = 1 to 50000
‘ CurrentDb.Execute “INSERT INTO T_TempBulk VALUES (” & i & “, ‘TestData’);”, dbFailOnError
‘ Next i
‘ ———————————–
‘ ———————————————————————
‘ 4. 正常終了時の設定復元
‘ ———————————————————————
Call RestoreOptions(lngAutoCorrectName, lngAutoCorrectSub)
DoCmd.Echo True
MsgBox “処理が完了しました。実行時間: ” & Format(Timer – dblStartTime, “0.00秒”), vbInformation, “完了”
Exit Sub
ErrorHandler:
‘ ———————————————————————
‘ 5. 異常終了時のフォールバック(設定の確実な復元)
‘ ———————————————————————
DoCmd.Echo True
Call RestoreOptions(lngAutoCorrectName, lngAutoCorrectSub)
MsgBox “予期せぬエラーが発生しました。” & vbCrLf & _
“エラー番号: ” & Err.Number & vbCrLf & _
“エラー内容: ” & Err.Description, vbCritical, “致命的エラー”
End Sub
‘ =========================================================================
‘ 内部プロシージャ: 設定値の復元
‘ =========================================================================
Private Sub RestoreOptions(ByVal optName As Long, ByVal optSub As Long)
On Error Resume Next
Application.SetOption “Name AutoCorrect Save”, optName
Application.SetOption “Name AutoCorrect Log”, optSub
On Error GoTo 0
End Sub
—
4. チーフアーキテクトからの実務アドバイス
このテクニックを現場に導入するにあたり、プロとしていくつかの重要な注意点を申し添えておく。
① オプション名のバージョン差異に注意せよ
`Application.GetOption` / `SetOption` に渡す文字列(例: `”Name AutoCorrect Save”`)は、Accessのバージョン(Access 2010, 2013, 2016, 2019, 365など)や言語環境(日本語版・英語版)によって内部名が微妙に異なる場合がある。
コードを本番展開する前に、対象の環境で一度イミディエイトウィンドウを使い、正しく値が取得・設定できるか必ずテストを行ってほしい。
② データベース自体のプロパティも確認せよ
VBAからのオプション変更は、あくまで「そのセッション(開いているAccessインスタンス)」に対する一時的な設定にすぎない。しかし、大元のACCDBファイル側で「名前の自動修正を行う」にチェックが入っていると、ファイルを開いた瞬間に再び重い処理の呪縛にかかる。
本当に大規模なエンタープライズシステムを構築する場合は、Accessのオプション画面([ファイル] > [オプション] > [現在のデータベース])から、「名前の自動修正」に関するすべてのチェックボックスをあらかじめ永続的に外しておくことが、真のプロフェッショナルな設計思想である。
—
総括
Access VBAは、その手軽さゆえに「とりあえず動くコード」が乱立しがちだ。しかし、データ量が膨らんだ瞬間に破綻するシステムは、システムではなく「爆弾」に他ならない。
今回紹介した `GetOption` / `SetOption` による環境の動的制御は、単なる小手先のテクニックではなく、「リソースのライフサイクルをエンジニアが完全に掌握する」というエンジニアリングの基本姿勢そのものだ。
あなたの書くコードにこの知見を組み込み、遅延に悩むエンドユーザーをあっと言わせる超高速なシステムを構築してほしい。
