【技術コラム】ワークテーブル廃止!「ADO切断+ディクショナリ方式」で作る超高速・一覧編集フォームの極意

2026/05/26(更新日:2026/05/26) Accessコラム
タグ:

ファイルサーバー上にバックエンド用のAccessファイル(.accdb)を配置し、複数人でフロントエンドから共有利用するシステムにおいて、

・一覧編集フォームの表示が重い

・スクロールが引っかかる

・Wi-FiやVPN環境で固まる

・ファイル破損やロック競合が頻発する

といった問題に悩まされた経験はないでしょうか。

特に、大量データを扱う「一覧形式の編集フォーム」では、従来の実装方法に限界があります。

今回は、ローカルのワークテーブル(一時テーブル)を一切作成せず、Accessのパフォーマンスを極限まで引き出すアーキテクチャ
「ADO切断+ディクショナリ方式」について、実践的な3つの極意をご紹介します。


1. 従来手法と「超えられない壁」

Accessで一覧編集フォームを作る際、一般的なのは次のような構成です。

1.バックエンドからデータを取得

2.フロントエンド内にワークテーブルを作成

3.そのワークテーブルをフォームへ連結(バインド)

この方式は安全で扱いやすい反面、データ件数が増えると深刻な問題が発生します。

■ ワークテーブル作成が重い

数万件規模になると、ワークテーブル生成処理などによるローカルディスクへの物理書き込みに数十秒かかるケースがあります。

さらに、フロントエンドファイル(.accdb)の肥大化も引き起こします。

■ ネットワーク越しの一覧フォームが遅い

リンクテーブル経由の一覧フォームでは、Access特有の「細かく頻繁に通信する仕様(チャッティ)」が問題になります。

特にWi-FiやVPN環境では、

・スクロール時の引っかかり

・編集時の待ち時間

・画面フリーズ

が発生しやすくなります。


こうした「ディスクI/O」と「ネットワーク通信」の壁を突破するために辿り着いたのが、

「ディスクへ書き込まず、すべてメモリ上で処理する」

というアプローチです。


2. 極意その1:レコードソースを空にして「現物」をバインドする

通常、フォームの「レコードソース」にテーブルやクエリを設定すると、Accessは裏側でバックエンドへ接続し、自動的にデータ管理を行います。

しかし、この「Accessによる自動制御」こそが、速度低下や不要通信の原因になります。

そこで新手法では、フォームの「レコードソース」をあえて空欄にします。

その代わり、VBAからADO(ActiveX Data Objects)を使い、データをメモリ上へ一括取得し、そのRecordsetオブジェクト自体をフォームへ直接渡します。

<サンプルで使用するテーブルのイメージ>

コード例:ADOによる仮想バインド

' ADOでバックエンドファイルからデータを取得
Set rs = New ADODB.Recordset
rs.CursorLocation = adUseClient

rs.Open _
    "SELECT ID, ItemA, ItemB FROM T_SampleData", _
    cn, _
    adOpenStatic, _
    adLockBatchOptimistic

' 【重要】
' バックエンドとの接続を完全に切断
Set rs.ActiveConnection = Nothing
cn.Close

' メモリ上のRecordsetをフォームへ直接バインド
Set Me.Recordset = rs

この方式では、

・ワークテーブル作成不要

・ディスク書き込みゼロ

・通信回数激減

となるため、数万件規模でも高速に表示できます。

スクロールも非常に滑らかで、ローカルデータを扱っているかのような操作感になります。

<フォームの実行結果のイメージ>

 


3. 極意その2:Accessのお節介な「自動保存」を封じる

Accessのフォームには、

行移動時に勝手に保存しようとする

という非常に強力な自動保存仕様があります。

通常、この挙動を完全制御するのはかなり困難です。

しかし今回の構成では、ADO Recordset を「切断状態」にしているため、この問題を根本的に回避できます。

ポイントはこの1行です。

Set rs.ActiveConnection = Nothing

この時点で、フォーム上のデータはバックエンドとの接続を失っています。

つまり、ユーザーが行移動しても、Accessは保存先へ通信できません。

結果として、

・意図しない自動保存を防止

・「保存ボタン押下時のみ更新」という制御が可能

・更新タイミングを100%開発者側で管理可能

になります。

これは、業務システムにおける安全性向上にも非常に効果的です。


4. 極意その3:ディクショナリで「変更履歴」を管理する

Recordset が切断状態である以上、ユーザーが編集した内容は、そのままでは保存されません。

そこで活用するのが、VBAの Scripting.Dictionary です。

このディクショナリに、

・更新データ

・新規データ

・削除対象

を蓄積し、「保存ボタン押下時」にまとめてDBへ反映します。


コード例:変更内容をディクショナリへ記録

Private Sub Form_BeforeUpdate(Cancel As Integer)

    Dim dictKey As String

    ' ID未発番なら新規行
    If IsNull(Me!ID.Value) Then

        ' 仮キーで管理
        dictKey = "NEW_" & Me.CurrentRecord

        dictChanges.Item(dictKey) = Array( _
            Null, _
            Me!ItemA.Value, _
            Me!ItemB.Value, _
            "SAVE" _
        )

    Else

        ' 既存データは実IDで管理
        dictKey = CStr(Me!ID.Value)

        dictChanges.Item(dictKey) = Array( _
            Me!ID.Value, _
            Me!ItemA.Value, _
            Me!ItemB.Value, _
            "SAVE" _
        )

    End If

End Sub

 


■ 新規行と既存行を正確に判定

IsNull(ID) を利用することで、

・未保存の新規行

・既存データの編集

を明確に区別できます。

新規追加後に再編集された場合でも、同じ仮キーへ上書きされるため、状態管理が崩れません。


■ 命令フラグで処理を切り分ける

配列の最後に、

"SAVE"

"DELETE"

などの命令フラグを保持することで、保存時に

・INSERT

・UPDATE

・DELETE

を正確に振り分けられます。


■ ディクショナリは「最終状態」だけを保持できる

Dictionaryは同じキーに対して自動上書きされるため、同一行を何度編集しても、最終状態だけが残ります。

つまり、

・差分管理がシンプル

・メモリ効率が良い

・更新処理を最適化できる

という大きなメリットがあります。


まとめ

「ADO切断」による超高速表示と、
「ディクショナリ」による堅牢な変更管理。

この2つを組み合わせることで、Access最大のボトルネックである

「ワークテーブルへの物理アクセス」

を完全に排除できます。

さらに、ユーザー操作中はデータベースと切断されており、保存時のみ瞬間的に接続するため、

・排他ロック競合の激減

・ファイル破損リスクの低下

・多人数同時利用時の安定性向上

といった副次効果も得られます。

大量データを扱うAccessシステムの高速化や、ファイル共有環境での安定運用を検討されている方は、ぜひ一度このアーキテクチャを試してみてください。

Access開発サポートがわかる、
3つのコンテンツ