こんにちは! Access VBAの開発現場で、日々頭を悩ませていませんか?
「マクロの記録」から一歩抜け出して、本格的なVBAを書こうとしたとき、誰もが一度はぶ壁にぶつかります。それが「存在しないテーブルにアクセスしてしまい、コードが突然停止するエラー」です。
例えば、ユーザーが誤って必要なテーブルを削除してしまったり、集計用のテンポラリ(一時)テーブルがまだ作られていなかったりする状態でプログラムを走らせると、Accessは容赦なく黄色いエラー画面(実行時エラー)を突きつけてきます。
今回は、そんな「想定外の欠損」にしなやかに対応し、エラーを未然に防ぐための防御的プログラミングの極意を伝授します。ここをクリアすれば、あなたの書くAccess VBAは見違えるほどプロ仕様にレベルアップしますよ。ぜひ最後までついてきてくださいね!
—
1. なぜ「エラー」でプログラムが止まってしまうのか?
初学者がやりがちなのが、以下のような「いきなり直球アプローチ」です。
‘ 【アンチパターン】いきなりテーブルを開こうとする危険なコード
Sub BadCode()
‘ もし “T_売上集計_Temp” が存在しないと、ここで即座にVBAがクラッシュします!
DoCmd.OpenTable “T_売上集計_Temp”
End Sub
Accessのオブジェクトモデルにおいて、存在しないテーブル名やクエリ名を指定して操作しようとすると、容赦なく「実行時エラー」が発生し、処理が中断されます。
「じゃあ、エラーが起きたら `On Error Resume Next` で無視させればいいや」と思ったそこのあなた!それはプログラミングのタブーです。エラーを闇雲に握りつぶすと、本当に予期せぬ重大なバグまで隠蔽されてしまい、後から原因の分からないモンスターシステムを生み出す原因になります。
エラーが起きる前に、「そもそも、そのテーブルはあるのか?」を確認してから処理を分岐させる。これが、現場で生き残るエンジニアの常識です。
—
2. 救世主登場:`Application.CurrentData.AllTables` とは?
そこで使うのが、今回主役である `Application.CurrentData.AllTables` コレクションです。
これは、Accessのデータベースファイル(ACCDB)の中に存在する、すべてのテーブルの「名簿(コレクション)」を保持しているオブジェクトです。
イメージとしては、会社の全社員名簿のようなものです。名簿の中に「田中さん(目的のテーブル名)」の名前があるかどうかを、あらかじめチェックしてから部屋に入るようなイメージですね。
`AllTables` の基本構造
`AllTables` の中には、テーブル一つ一つが `AccessObject` というパーツとして格納されています。そして、そのパーツには `.Name` というプロパティ(名前)があり、これを使って存在確認ができます。
—
3. 実践!安全にテーブルの有無をチェックするコード
それでは、実際に動かせる実用的なコードを見てみましょう。
今回は、`T_売上集計_Temp` というテーブルが存在するかどうかをチェックし、存在すれば開き、存在しなければ優しくメッセージを出して新規作成(または処理を回避)するプロシージャです。
‘ ===================================================================
‘ プロシージャ名: CheckTableExistsSample
‘ 概要: AllTablesを使用して、安全にテーブルの存在確認と分岐を行う
‘ ===================================================================
Sub CheckTableExistsSample()
Dim targetTableName As String
Dim isExist As Boolean
Dim tbl As AccessObject
‘ チェックしたいテーブル名を設定
targetTableName = “T_売上集計_Temp”
‘ 存在フラグを一旦「False(無い)」で初期化
isExist = False
‘ CurrentData.AllTables をループして、目当てのテーブルがあるか総当たりで確認
For Each tbl In Application.CurrentData.AllTables
‘ テーブル名の大文字小文字を区別せず比較
If StrComp(tbl.Name, targetTableName, vbTextCompare) = 0 Then
isExist = True
Exit For ‘ 見つかったのでループを抜ける(パフォーマンス配慮)
End If
Next tbl
‘ — ここから分岐処理(防御的プログラミングの真骨頂) —
If isExist = True Then
‘ 存在する場合の処理
MsgBox “テーブル ‘” & targetTableName & “‘ が見つかりました。処理を続行します。”, vbInformation, “確認”
‘ 安全にテーブルを開く
DoCmd.OpenTable targetTableName, acViewNormal
Else
‘ 存在しない場合の処理(エラーで止めず、優しく誘導)
MsgBox “テーブル ‘” & targetTableName & “‘ が存在しません。” & vbCrLf & _
“先にデータ作成処理を実行してください。”, vbExclamation, “警告”
‘ ここでテーブルを自動作成するルーチンを呼び出すことも可能!
‘ Call CreateTempTable
End If
End Sub
コードのポイント解説
1. `For Each tbl In Application.CurrentData.AllTables`
データベース内のすべてのテーブルを一つずつ取り出して変数 `tbl` に代入しています。
2. `StrComp(…, vbTextCompare)`
VBAの文字比較関数です。`vbTextCompare` を指定することで、Accessの仕様に合わせて「大文字と小文字を区別しない(例: `t_sales` と `T_SALES` を同じとみなす)」安全な比較を行っています。
3. `Exit For` による高速化
目的のテーブルが見つかった瞬間にループを抜けています。テーブルが100個あっても、最初の数個で見つかれば無駄なループを回さずに済みます。パフォーマンスへの細やかな配慮が、プロのコードの証です。
—
4. 【さらにスマートに】ループを使わないワンライナー判定
「わざわざ `For Each` でループを回すのは面倒くさいな……もっとスマートに書けないの?」
そんな中級者以上のあなたへ。実は、`AllTables` コレクションが持つ `.IsLoaded` などのプロパティや、裏技的なアプローチもありますが、一番確実でスマートなのは、`DCount` 関数や、実は `AllTables` をそのまま名前で引く方法です。
しかし、存在しない名前を直接指定するとそれ自体がエラーになるため、少し工夫が必要です。実はもっとシンプルに、エラートラップ(`On Error`)をピンポイントでその行だけに限定して使うテクニックもあります。
‘ ===================================================================
‘ 発展編: エラーハンドリングを限定的に使ったスマートな判定
‘ ===================================================================
Function IsTableExist_Smart(tableName As String) As Boolean
Dim dummy As String
‘ この1行だけ、一時的にエラーを無視させる
On Error Resume Next
dummy = CurrentData.AllTables(tableName).Name
‘ エラー番号が 0 なら存在し、0以外なら存在しないと判定
If Err.Number = 0 Then
IsTableExist_Smart = True
Else
IsTableExist_Smart = False
End If
‘ すぐにエラー監視を通常に戻す(これ超重要!)
On Error GoTo 0
End Function
この関数を作っておけば、メインの処理では以下のようにスッキリ書くことができます。
Sub MainProcess()
If IsTableExist_Smart(“T_売上集計_Temp”) Then
MsgBox “テーブルはあるので処理します!”
‘ 実際の処理…
Else
MsgBox “テーブルがありません!”
End If
End Sub
`AllTables(tableName)` のように直接コレクションのインデックスに名前を指定し、もし存在しないエラー(Err.Number != 0)が発生したら「無い」と判断する――。オブジェクトモデルの挙動を熟知したエンジニアならではの、非常にエレガントなアプローチです。
—
まとめ:防御的プログラミングで「壊れないAccess」を作ろう
今回は、`Application.CurrentData.AllTables` を活用した、存在しないテーブルへのアクセス回避術を解説しました。
- 「動かす前に確認する(Exist Check)」 という一手間を惜しまないこと。
- エラーを放置するのではなく、想定内の分岐としてプログラムに組み込むこと。
この2つを意識するだけで、あなたの作るAccessアプリの品質は劇的に向上します。「ユーザーがどんな操作をしても絶対にクラッシュしない、優しく頑丈なデータベースシステム」。それを実現するための基礎が、まさにこのテーブル存在チェックなのです。
ここをクリアできれば、Access VBAの基本はもうバッチリです!
自信を持って、次のステップへ進んでいきましょう。あなたの開発ライフを、これからも応援しています!
