Access (VBA)

Access VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 10全般 : Access 2021)
処理実行後にlaccdbファイルが残ってしまう
投稿日時: 23/04/03 09:40:52
投稿者: miyagi07

操作用accdbのフォームを開いたとき、データベース用accdbのテーブルをコンボボックスの値集合ソースに設定したいです。
ADOでデータベース用accdbに接続してレコードセットを取得し、そのレコードセットをコンボボックスの値に設定するコードを書いてみました。処理自体は問題なく実行されるのですが、操作用accdbのフォームを開いている間データベース用のlaccdbが消えずに残ってしまいます。
データベース用accdbは複数人での共有を想定しているため、Form_Openの実行後はlaccdbファイルが残らないようにしたいです。
laccdbファイルを残さない方法があれば教えていただけないでしょうか。
 
以下に書いたコードを記載します。
 
------
Private Sub Form_Open(Cancel As Integer)
 
Dim Cn As ADODB.Connection
Dim Rs As ADODB.Recordset
Dim DBSQL As String
 
On Error GoTo Err_Exit
 
Set Cn = New ADODB.Connection
 
Cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" _
            & "Data Source=" & DBPath & ";" _
            & "Jet OLEDB:Database Password=" & DBPassword & ";"
 
Set Rs = New ADODB.Recordset
 
DBSQL = "SELECT 顧客番号 FROM T_顧客一覧 ORDER BY 顧客番号 ASC"
 
Rs.Open DBSQL, Cn, adOpenKeyset, adLockOptimistic
 
Me.cmb顧客番号.RowSourceType = "Table/Query"
Set Me.cmb顧客番号.Recordset = Rs
 
Set Rs = Nothing: Close
Set Cn = Nothing: Close
 
Exit Sub
 
Err_Exit:
 
***エラー処理***
 
End Sub

回答
投稿日時: 23/04/03 12:46:03
投稿者: taitani
投稿者のウェブサイトに移動

以下サイトが参考になるかもしれません。
https://himmel-ellipse.com/16791.html

投稿日時: 23/04/03 13:53:10
投稿者: miyagi07

ご回答ありがとうございます。
ご紹介いただいた記事を参考に該当のWindowsUpdateファイルのアンインストール、Officeのオンライン修復を行いましたが問題が解決しませんでした。
データベース用accdbのテーブルから操作用accdbのテーブルにレコードを追加する処理は実行後laccdbファイルが残らないため、コンボボックスの値集合ソースの設定の処理のみlaccdbファイルが残ってしまうようなのですが…。

回答
投稿日時: 23/04/03 14:23:44
投稿者: taitani
投稿者のウェブサイトに移動

うーむ、考えられるとしたら、誰かが開いている状態のまま何らかのセッションエラーで残ってしまうとか。
関係ないかもですが、下記のコードより、Open はされていますが、Close がないためとか?
 
すみません、私の会社の環境では、再現できませんでした。
追加で、以下の MS 公式サイトの確認をお願いします。
 
https://learn.microsoft.com/ja-jp/office/troubleshoot/access/lock-files-introduction#automatic-lock-file-creation-and-deletion

投稿日時: 23/04/03 15:08:53
投稿者: miyagi07

データベース用accdbは共有フォルダに置いていますが、まだ開発中のため、操作用データベース用共にAccessを操作しているのは私だけです。
コンボボックスがあるフォームを閉じると残っているlaccdbファイルも消えますが、フォームを開いている時間が長くなることが想定されるため、やはりForm_Openの実行後はlaccdbを消したいです。
他のaccdbファイルでも同様のコードを書いていますが、そちらでもコンボボックスの値集合ソースの設定でlaccdbが残ってしまいます。
また、NothingとCloseを行を分けて記述してみましたが、結果は変わりませんでした。
 
データベース用accdbのテーブルを操作用accdbのコンボボックスの値集合ソースに設定する他のコードの書き方があれば教えていただけないでしょうか。
諸事情があって、できればVBAで解決したいです。

回答
投稿日時: 23/04/03 15:18:47
投稿者: taitani
投稿者のウェブサイトに移動

Access では、データベースへの接続が終了するまで、ロックファイル(laccdb)が作成されます。
そのため、コードでレコードセットを取得する場合、接続が終了するまでロックファイルが作成されたままになります。
 
ロックファイルを回避する方法としては、フォームが開かれたときにコンボボックスの行ソースタイプを「値のリスト」として設定し、その後、コンボボックスのリストに値を追加する方法があります。
 
以下は、コンボボックスに値を追加するコード例です。

Private Sub Form_Open(Cancel As Integer)
 
    Dim Cn As ADODB.Connection
    Dim Rs As ADODB.Recordset
    Dim DBSQL As String
    Dim strList As String
    
    On Error GoTo Err_Exit
 
    Set Cn = New ADODB.Connection
    Cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" _
            & "Data Source=" & DBPath & ";" _
            & "Jet OLEDB:Database Password=" & DBPassword & ";"
 
    Set Rs = New ADODB.Recordset
    DBSQL = "SELECT 顧客番号 FROM T_顧客一覧 ORDER BY 顧客番号 ASC"
    Rs.Open DBSQL, Cn, adOpenKeyset, adLockOptimistic
 
    Do While Not Rs.EOF
        strList = strList & Rs!顧客番号 & ";"
        Rs.MoveNext
    Loop
    
    Me.cmb顧客番号.RowSourceType = "Value List"
    Me.cmb顧客番号.RowSource = strList
 
    Rs.Close
    Set Rs = Nothing
    Cn.Close
    Set Cn = Nothing
 
    Exit Sub
 
Err_Exit:
    'エラー処理
 
End Sub

 
このコードでは、レコードセットの値をセミコロンで区切った文字列を作成し、それをコンボボックスのリストとして設定しています。
この方法であれば、データベースの接続を切断することができ、ロックファイルが残らないようになると思います。

回答
投稿日時: 23/04/03 15:23:07
投稿者: sk

引用:
ADOでデータベース用accdbに接続してレコードセットを取得し、
そのレコードセットをコンボボックスの値に設定する

引用:
Set Me.cmb顧客番号.Recordset = Rs

引用:
処理自体は問題なく実行されるのですが、操作用accdbのフォームを
開いている間データベース用のlaccdbが消えずに残ってしまいます。

コンボボックスにレコードセットがバインドされている限り
バックエンドデータベースへの接続も維持されていますので、
仕様通りの動作でしょう。
 
引用:
データベース用accdbは複数人での共有を想定しているため、
Form_Openの実行後はlaccdbファイルが残らないようにしたいです。

なぜ残っていてはいけないのでしょうか。
 
1 人以上のユーザーが何らかの方法によってデータベースファイルを
開けばそのロックファイルが自動作成されるのは Access の仕様であり、
それ自体は何ら問題ないでしょう。

投稿日時: 23/04/03 16:33:32
投稿者: miyagi07

taitani様
ご回答ありがとうございます。
値リストでしたら確かに解決できそうです。
開発しているaccdbの中にコンボボックスに表示される値と取得される値を変えたいものがあるのですが、そちらはデータベースの構成をもう一度考え直そうと思います。
コード参考にさせていただきます。
 
 
sk様
ご回答ありがとうございます。
1つのデータベース用accdbに対して操作用accdbは複数の種類があり、各操作用accdbからデータベース用accdbに接続してデータの更新を行うという形にしたいと考えていました。
なので、誰かがフォームを開いている間、ロックがかかって他の操作用accdbからデータベース用accdbの更新ができない、データを取ってくることができないという事態は避けたいです。

回答
投稿日時: 23/04/03 16:57:44
投稿者: sk

引用:
誰かがフォームを開いている間、ロックがかかって
他の操作用accdbからデータベース用accdbの更新ができない、
データを取ってくることができないという事態は避けたい

バックエンドデータベースを排他モードで開くようなことを
していない限り、その心配は杞憂であるように思います。
 
少なくとも、データベースなりレコードなりのロックが
かかる/かからないといった問題はロックファイルの有無
だけで決まることではありません。
参照中のレコードがユーザーによって編集されたかどうか
なども関係してきます。
 
どうしても気になるのであれば、taitani さんが例示されたように
値リストとして取得するか、もしくはフロントエンド側に
[T_顧客一覧]と同一構造のローカルテーブルを設けておいて
[cmb顧客番号]の値集合ソースとしておき、任意のイベントで
バックエンド側からレコードを複写する処理を実行する仕組みを
実装することになるでしょう。

投稿日時: 23/04/04 10:06:45
投稿者: miyagi07

sk様
 
AccessのロックはExcelのロックとはまた別物なのですね。
今は自分のパソコンでしか確認できないのでlaccdbファイルが作られたときにどういう動作をするのかよく分からないのですが、他のパソコンから確認して問題なくデータベースの更新やデータベースからデータを持ってくることができるようでしたらlaccdbファイルの存在は気にしないようにします。
 
また、ローカルテーブルを設けるという方法も参考にさせていただきます。連結列と表示される列を別にしたい場合、値リストを使用することができないので非常に助かりました。
ご回答ありがとうございました。