【テクニカル・上級編】Application.GetOptionで「名前の自動修正」機能をVBAから一時的に無効化する – Access VBA解析バイブル

スポンサーリンク

Access VBAを掌握する極限の知見:『名前の自動修正』という名の隠れたパフォーマンス殺人鬼を御する

レガシーシステムの最前線でAccessと向き合ってきたエンジニアであれば、一度は絶望したことがあるはずだ。数万件規模のレコードを伴うテーブルの生成、フィールドの動的追加、あるいはクエリのプログラム的再構築。その瞬間、Accessの内部エンジンは静かに、しかし確実に牙をむく。

原因は「名前の自動修正(Name AutoCorrect)」だ。

オブジェクトの名前を変更した際に関連するフォームやレポートを勝手に書き換えてくれるこの機能は、エンドユーザーにとっては優しさかもしれないが、プログラミングによる一括処理を行う開発者にとっては最悪のパフォーマンス・キラーである。この機能が有効な状態でスキーマ操作を行えば、すべての変更のたびにAccessは全オブジェクトの依存関係をスキャンし、システム資源を食いつぶす。

今回は、この「名前の自動修正」をVBAの `Application.GetOption` および `SetOption` を用いてプログラムの実行中のみ完全に無効化し、限界までパフォーマンスを引き出すアーキテクチャを解説する。

1. 「名前の自動修正」がもたらすアーキテクチャ上の致命傷

Accessの「名前の自動修正」情報は、システムテーブル(`MSysNameMap` 等)に常時保持され、オブジェクトの参照整合性を維持するために監視されている。

これが有効な状態で以下のようなバッチ処理を実行したとする:

  • 一時テーブルの頻繁なCREATE/DROP
  • 大量のフィールド追加・削除
  • 複雑なクエリの動的生成と保存

Accessエンジンは、操作のたびに裏で膨大なメタデータの書き換えと依存関係の検証を行う。これがネットワーク越し(ファイルサーバー上)の環境であれば、トラフィックの増大とファイルロックの競合を引き起こし、処理時間は何倍もの遅延を記録する。

シニアエンジニアとして、「バッチ処理の開始時に自動修正を殺し、終了時に確実に復元する」というライフサイクル管理をコードに組み込むことは、もはや必須の教養である。

2. 実装パターン:`GetOption` と `SetOption` による状態の支配

Accessのオプション値は、GUIから変更するだけでなく、`Application` オブジェクトのメソッドを通じてプログラムから直接制御できる。

ここで重要なのは、「現在の設定値を必ず退避させ、処理の成否(エラーハンドリング)に関わらず確実に元の状態へ復元する」というイミュータブル(不変)な例外処理の原則だ。

以下に、実務でそのまま使える堅牢なモジュールコードを提示する。

高速バッチ処理実行テンプレート(VBA)

Option Compare Database
Option Explicit

‘ =========================================================================
‘ módulo名: modPerformanceOptimizer
‘ 概要 : 大規模スキーマ操作・データ処理時のパフォーマンス極限最適化モジュール
‘ =========================================================================

‘ レジストリ/内部オプションに対応する定数
Private Const C_OPT_AUTOCORRECT_NAME As String = “Name AutoCorrect”
Private Const C_OPT_AUTOCORRECT_TRACK As String = “Track Name AutoCorrect Info”
Private Const C_OPT_AUTOCORRECT_PERFORM As String = “Perform Name AutoCorrect”

Public Sub ExecuteHighPerformanceBatch()
Dim orgTrackName As Boolean
Dim orgPerformAutoCorrect As Boolean

‘ 1. 現在のオプション状態を退避(GetOptionの活用)
On Error GoTo ErrorHandler

orgTrackName = Application.GetOption(C_OPT_AUTOCORRECT_TRACK)
orgPerformAutoCorrect = Application.GetOption(C_OPT_AUTOCORRECT_PERFORM)

‘ 2. 自動修正機能を完全に無効化(パフォーマンス優先モードへの移行)
Application.SetOption C_OPT_AUTOCORRECT_TRACK, False
Application.SetOption C_OPT_AUTOCORRECT_PERFORM, False

‘ データベースの変更を強制的にディスクへ反映させず、メモリ上でトランザクション的に処理
Dim db As DAO.Database
Set db = CurrentDb

‘ トランザクション開始によるI/O極限削減
db.Execute “BEGIN TRANSACTION”, dbFailOnError

‘ =========================================================================
‘ [ここに高負荷なテーブル操作・スキーマ変更処理を記述]
‘ =========================================================================
Call HeavySchemaAndDataOperation(db)

‘ コミット
db.Execute “COMMIT”, dbFailOnError

‘ 3. 正常終了時の復元
Call RestoreOptions(orgTrackName, orgPerformAutoCorrect)

MsgBox “バッチ処理が正常に完了しました。”, vbInformation, “最適化完了”
Exit Sub

ErrorHandler:
‘ 異常終了時も必ずオプションを復元し、トランザクションをロールバック
On Error Resume Next
If Not db Is Nothing Then
db.Execute “ROLLBACK”, dbFailOnError
End If

Call RestoreOptions(orgTrackName, orgPerformAutoCorrect)

MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “致命的エラー”
End Sub

Private Sub HeavySchemaAndDataOperation(ByRef db As DAO.Database)
‘ サンプルとしての重い処理
‘ 例: 一時テーブルの作成と大量インサート
Dim i As Long

‘ ※実際の現場ではここでCREATE TABLEやALTER TABLE、DAO/ADOを用いた一括処理を行う
db.Execute “SELECT INTO tmp_PerformanceTest FROM MSysObjects WHERE 1=0;”, dbFailOnError

For i = 1 to 1000
‘ 高速化されたコンテキスト下でのデータ操作
Next i

db.Execute “DROP TABLE tmp_PerformanceTest;”, dbFailOnError
End Sub

Private Sub RestoreOptions(ByVal trackName As Boolean, ByVal performCorrect As Boolean)
‘ 確実に元の設定を書き戻す
Application.SetOption C_OPT_AUTOCORRECT_TRACK, trackName
Application.SetOption C_OPT_AUTOCORRECT_PERFORM, performCorrect
End Sub

3. チーフアーキテクトが指摘する「見落とされがちな罠」

上記のコードは美しく機能するが、レガシーAccess環境を扱う上では、さらに一歩踏み込んだ知見が必要となる。

① アプリケーションスコープと永続性のリスク

`Application.SetOption` で変更した設定は、そのAccessセッション(インスタンス)全体に影響を与える。もし処理の途中で予期せぬクラッシュが発生し、`RestoreOptions` が呼ばれなかった場合、そのデータベースを開いている間(あるいはAccess終了時まで)、設定が書き換わったままになる。
そのため、必ず `On Error GoTo` による厳格な例外処理と、トランザクションのロールバックをセットで実装しなければならない。

② フロントエンドとバックエンド(BE/FE)の分離構造における注意

マルチユーザー環境において、テーブルを格納している「バックエンド側(BE)」のMDB/ACCDBに対して直接ADO/DAOで接続してスキーマ変更を行う場合、BE側で名前の自動修正が有効になっていると、ネットワークトラフィックとロック競合の原因になる。
可能であれば、スキーマ変更を伴うメンテナンススクリプトを実行する際は、BEファイルを排他制御(Exclusive)モードで開くか、ローカルのテンポラリDB上で処理を完結させるアーキテクチャを採用すべきだ。

③ 開発環境と本番環境のコンフィグレーション管理

「名前の自動修正」は、開発時には便利だが、デプロイ後の本番環境(特にRuntime版)では百害あって一利なしである。インストールスクリプトや初回起動時のVBAブートストラップコードで、レジストリまたはApplicationオプションを監視し、デフォルトで無効化しておくことを強く推奨する。

総括

Access VBAは「おもちゃの言語」と揶揄されることがある。しかし、それは言語の限界ではなく、プラットフォームの挙動を理解せず、デフォルトの甘えに浸ったコードを書き続けた結果に過ぎない。

`Application.GetOption` と `SetOption` を駆使し、Accessエンジンが裏で行っている無駄な自動化の鎖を断ち切る。このアプローチを習得した瞬間から、あなたの書くAccessアプリケーションは、単なる「動くスクリプト」から、過酷な現場を支える堅牢なエンタープライズ・システムへと昇華する。

技術の深淵を覗き、すべてのリソースを支配せよ。

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