AccessVBAで、リンクテーブルのリンク先は TableDef オブジェクトの Connect プロパティで取得できる。
Debug.Print CurrentDb.TableDefs("T_在庫").Connect
とすればよい。(「;DATABASE=C:\temp\在庫管理.accdb」が返る)
なので、
With CurrentDb.TableDefs("T_在庫")
Debug.Print .Connect
End With
としてもいけそうだが、これはエラーになる。
CurrentDb
を変数に入れて、
Dim db As Object
Set db = CurrentDb
With db.TableDefs("T_在庫")
Debug.Print .Connect
End With
とすればエラーにならない。
なぜ?
AI先生(ChatGPT)に聞いてみた。
ChatGPT 曰く、
あなたの2つのコードの違いは、CurrentDb
の扱い方にあります。
1つ目のコード(エラーなし)
Dim db As Object
Set db = CurrentDb
With db.TableDefs(table_name)
Debug.Print .Connect
End With
このコードでは、CurrentDb
を db
という変数に 一度代入して から db.TableDefs(table_name)
にアクセスしています。
2つ目のコード(エラー発生)
With CurrentDb.TableDefs(table_name)
Debug.Print .Connect
End With
このコードでは、CurrentDb
を 直接参照 しています。
なぜ2つ目のコードがエラーになるのか?
CurrentDb
は 関数 であり、その呼び出しごとに 新しい Database オブジェクトを返す 仕様になっています。
つまり、With CurrentDb.TableDefs(table_name)
の CurrentDb
が評価されるたびに別のオブジェクトが作られる 可能性があります。
このため:
-
CurrentDb.TableDefs(table_name)
が 一時的なオブジェクト となり、 -
With
のスコープの中でDebug.Print .Connect
を実行する際に、 -
元の
CurrentDb
オブジェクトが破棄されている可能性があるため、エラーが発生する ことがあります。
解決策
-
CurrentDb
を変数に代入して使う(1つ目のコードのようにする)Dim db As Object Set db = CurrentDb With db.TableDefs(table_name) Debug.Print .Connect End With
これにより、同じ
Database
オブジェクトを一貫して使用 できます。 -
CurrentDb
の戻り値を一時変数に格納With (CurrentDb) Debug.Print .TableDefs(table_name).Connect End With
ただし、この方法は Access VBA では
With
ステートメントで括弧を使えないため不可。 -
CurrentDb
を都度明示的に呼び出すDebug.Print CurrentDb.TableDefs(table_name).Connect
これは
With
を使わないのでCurrentDb
の一時オブジェクトの影響を受けません。
結論
-
CurrentDb
は 呼び出すたびに新しいオブジェクトを生成する ため、With CurrentDb
を使うとスコープの途中でオブジェクトが消える可能性がある。 - 回避策として、一度変数に代入して使うのが安全。
→ 1つ目のコードが正しい書き方!
ということらしいです。
CurrentDb
は変数に入れましょうというお話でした。