【入門編】QueryDefを用いた「一時テーブル」の動的作成とクリーンアップ処理 – Access VBA解析バイブル

スポンサーリンク

こんにちは! Access VBAでの開発、日々の試行錯誤お疲れ様です。

マクロの記録から一歩踏み出し、「自分でコードを書いてシステムをコントロールしたい!」そう思ってVBAに向き合っているあなたへ。今回は、Access開発において避けて通れない、しかし正しく理解すれば怖くない「QueryDef(クエリ定義)を使った一時テーブルの動的作成とクリーンアップ」についてお話しします。

「レポートを出すために、その場で必要な集計データをサクッと作って、使い終わったら綺麗に片付けたい」
そんな現場の切実な願いをスマートに叶える極意を、優しく、そして本質的なところまでしっかりと解説していきますね。

ここをクリアすれば、あなたのAccess VBAのスキルは確実にワンランク上のステージに到達します。一緒にマスターしていきましょう!

—

1. なぜ「一時テーブル」と「QueryDef」が必要なのか?

Accessで複雑な集計や帳票の出力を行うとき、こんな悩みを持ったことはありませんか?

  • 「フォームの検索結果をそのままレポートに出したいけれど、クエリの条件が複雑すぎてVBAからうまく渡せない……」
  • 「毎回同じ名前のテーブルを作ってデータを流し込んでいるけど、なんか動作が重くなってきたし、たまにエラーで止まる……」

こういう時、あらかじめデザイン画面で「固定のクエリ」を作っておくのも手ですが、ユーザーの操作によって条件が無限に変わる動的な処理では限界があります。

そこで登場するのが、VBAのコード上でクエリの設計図(QueryDef)をその場で組み立て、データを実体化(一時テーブル化)するアプローチです。

「一時テーブル」を扱うときの2大リスク

しかし、これを適当に実装すると、Accessの内部で以下のような悲劇が起きます。
1. ゴースト・テーブルの蓄積: 作ったテーブルの消し忘れにより、データベースのファイルサイズが膨れ上がる。
2. オブジェクトの競合: 「すでにその名前のテーブルが存在します」という恐怖のエラー(多人数で使っているときによく起こります)。

これらを完璧にコントロールするのが、プロのアーキテクトも使う「QueryDefを制した安全なライフサイクル管理」です。

—

2. 【基本概念】オブジェクトの「ライフサイクル」を意識しよう

VBAでデータベースを扱うときは、「開いたら閉じる」「作ったら消す」の片付け(クリーンアップ)が美の基本です。

イメージとしては、こんな感じです。

[VBAの指令]
1. 「こういうデータを作るクエリ」を一時的に定義する (QueryDefの作成)
2. そのクエリを実行して、一時テーブルを実体化する (SELECT INTOなど)
3. レポートや画面でそのテーブルを利用する
4. 【重要】用が済んだら、クエリの定義も、一時テーブルも綺麗に消去する! (クリーンアップ)

この「作りっぱなしにしない」鉄則を守るだけで、Accessの動作不良やファイル破損のリスクを劇的に減らすことができます。

—

3. 実装コード:安全な動的テーブル生成とクリーンアップ

それでは、実際のコードを見てみましょう。
今回は、「特定の条件(例:売上金額が一定以上)のデータを抽出し、その場限りの一時テーブルとして作成してレポートの元データにする」というシナリオです。

開発画面の標準モジュールに、そのままコピペして動かせる実用的なコードを用意しました。

Option Explicit

Public Sub CreateAndCleanTemporaryTable()
‘ 変数の宣言(DAOというAccessのデータベースエンジンを使います)
Dim db As DAO.Database
Dim qdf As DAO.QueryDef
Dim targetTableName As String
Dim queryName As String

‘ テーブル名とクエリ名の定義
targetTableName = “tmp_ReportData”
queryName = “qdef_TemporaryCreate”

Set db = CurrentDb

‘ ==========================================
‘ STEP 1: 競合を防ぐため、既存の残骸を確実に削除
‘ ==========================================
On Error Resume Next
‘ すでに同名のクエリ定義があれば削除
db.QueryDefs.Delete queryName
‘ すでに同名の一時テーブルがあれば削除
DoCmd.DeleteObject acTable, targetTableName
On Error GoTo 0 ‘ エラートラップを通常に戻す

‘ ==========================================
‘ STEP 2: 動的なSQLを使ってQueryDefを生成
‘ ==========================================
‘ ※ここでは例として、T_Sales(売上テーブル)から抽出するSQLを組み立てます
Dim sqlText As String
sqlText = “SELECT SalesDate, CustomerName, Amount ” & _
“INTO ” & targetTableName & ” ” & _
“FROM T_Sales ” & _
“WHERE Amount >= 10000;” ‘ 例:1万円以上のデータを抽出

‘ QueryDefオブジェクトを作成してデータベースに登録
Set qdf = db.CreateQueryDef(queryName, sqlText)

‘ ==========================================
‘ STEP 3: クエリを実行して一時テーブルを実体化
‘ ==========================================
qdf.Execute dbFailOnError

MsgBox “一時テーブル [” & targetTableName & “] の作成に成功しました!”, vbInformation, “処理完了”

‘ ==========================================
‘ STEP 4: クリーンアップ(メモリ解放と後片付け)
‘ ==========================================
‘ 1. 使い終わったQueryDefの設計図を削除(ゴミを残さない!)
db.QueryDefs.Delete queryName

‘ 2. オブジェクト変数を解放してメモリをキレイに
Set qdf = Nothing
Set db = Nothing

Exit Sub

Error_Handler:
‘ エラーハンドリング(万が一の時のための安全装置)
MsgBox “エラーが発生しました: ” & Err.Description, vbCritical, “異常終了”

‘ エラー時でもメモリの解放は忘れない
If Not qdf is Nothing Then
db.QueryDefs.Delete queryName
Set qdf = Nothing
End If
Set db = Nothing
End Sub

—

4. コードのポイント解説(ここが重要!)

初学者のうちにつまづきやすいポイントを、先輩エンジニアの視点で解説します。

① `On Error Resume Next` の正しい使い方

コードの最初で、あえてエラーを無視する設定を入れています。
これは、「前回、異常終了したせいで同名のテーブルやクエリが残っていた場合、削除命令でエラーになるのを防ぐため」です。「あれば消す、なければ何もしない」という安全な初期化処理の常套手段です。

② `INTO` 句による一時テーブルの動的生成

SQL文の中にある `INTO targetTableName` という記述に注目してください。
これは、「SELECTした結果を、新しくテーブルとして作り出しなさい」というAccess(Jet/ACEエンジン)特有の強力な構文です。これを使うことで、VBAから一瞬で物理的なデータセットを作り出すことができます。

③ 徹底的なクリーンアップ(お片付け)

処理の最後で、`db.QueryDefs.Delete queryName` を実行しています。
実は、`db.CreateQueryDef` で作ったクエリは、放っておくとAccessの裏側のシステム領域に残り続けます。 これが溜まるとクエリの領域が圧迫され、パフォーマンス低下の原因になります。「用事が済んだらその場の設計図はシュレッダーにかける」、これがプロの作法です。

—

5. まとめ:ここをクリアすれば、Access VBAは怖くない!

いかがでしたでしょうか?
今回解説した「QueryDefを用いた動的テーブルの生成とクリーンアップ」の流れは、少し難しく感じるかもしれませんが、「作る・実行する・片付ける」という一連のライフサイクルを意識するだけで、驚くほど安定したシステムが作れるようになります。

  • データをその場で作る必要性
  • 同名オブジェクトによる競合の回避
  • 使い終わった後のクエリ定義の削除

この3つさえ押さえておけば、もうマクロの記録の限界に悩む必要はありません。あなたの思い通りのデータベース制御が自由自在です。

「ここをもっとこうしたい」「こんなエラーが出るんだけど」といった疑問があれば、いつでもまた扉を叩いてくださいね。
あなたのAccess開発ライフが、実り多いものになることを応援しています!

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