Access (VBA)

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

 
(指定なし : 指定なし)
フォームのレコードソースの設定について
投稿日時: 21/06/24 19:29:36
投稿者: だいふくもち

こちらのコミュニティにはいつも大変お世話になっております。
さっそくですが、ご相談させていただきます。
 
DBに登録した情報を編集する際ですが、以下の流れで編集を行おうと思っております。
(前にこちらのコミュニティで教えていただいたことを参考にしました。ありがとうございます)
 
@登録しているレコードを帳票フォームで一覧で表示する
Aその検索フォームのレコードセレクタで編集したいレコードを選択する
B編集ボタンを押す
Cワークテーブルを作成する
(編集フォームに埋め込まれているサブフォーム分のワークテーブルも作成)
D選択した契約番号と合致するレコードを、本テーブルからワークテーブルへ追加する(サブフォームも)
E編集フォームを開き、作成したワークテーブルをレコードソースとして紐づける(サブフォームも)
F必要な情報をユーザーが編集する
G登録ボタンを押す
Hワークテーブルに保存されたレコードを本テーブルに登録する
 
現在Eの部分を作成しているのですが、
下記のコードを使用しても、レコードソースが空白のままになってしまいます。
 

'検索フォームで選択した契約番号の名称でワークテーブルを作成する
DoCmd.RunSQL "CREATE TABLE T_契約マスタ_" & Me.契約番号 & "(契約番号 TEXT PRIMARY KEY, 請求先 TEXT, 契約名 TEXT)"

'登録編集フォームを開く
DoCmd.OpenForm "F_登録編集", acNormal, , , acFormEdit, acWindowNormal

'登録編集フォームのレコードソースをワークテーブルに設定する
Forms![F_登録編集].RecordSource = "T_契約マスタ_" & Me.契約番号

(編集フォームはレコードソースを空白のままにしております。)
 
エラーも特に出ずに途方に暮れております…
度々申し訳ございませんが、どなたか原因が分かる方がいらっしゃいましたら
教えていただけますと大変助かります。
ここまでお読みいただきありがとうございました!

回答
投稿日時: 21/06/25 09:28:53
投稿者: sk

引用:
Cワークテーブルを作成する
(編集フォームに埋め込まれているサブフォーム分のワークテーブルも作成)

マスターテーブルと(ほぼ)同一の構造を持った、
マスターテーブルとは異なる名前のワークテーブルを
フロントエンドデータベースの方にあらかじめ定義しておきさえすれば、
この手順はなくてもよいのではないでしょうか。
 
引用:
'検索フォームで選択した契約番号の名称でワークテーブルを作成する
DoCmd.RunSQL "CREATE TABLE T_契約マスタ_" & Me.契約番号 & "(契約番号 TEXT PRIMARY KEY, 請求先 TEXT, 契約名 TEXT)"

また、ワークテーブルの名前に[契約番号]の値を含めなければならない
特段の理由がないのであれば、例えば[T_契約マスタ_ワーク]だとか
[TW_契約マスタ]のような名前でもよいはず。
 
引用:
E編集フォームを開き、作成したワークテーブルをレコードソースとして紐づける(サブフォームも)

引用:
'登録編集フォームのレコードソースをワークテーブルに設定する
Forms![F_登録編集].RecordSource = "T_契約マスタ_" & Me.契約番号

ワークテーブルの名前が不変であるならば、[F_登録編集]のデザインを
行なう時点でレコードソースをそのワークテーブルにしておけば充分でしょう。
(その都度レコードソースを変更する必要はない)
 
引用:
D選択した契約番号と合致するレコードを、本テーブルからワークテーブルへ追加する(サブフォームも)

5-1. [F_登録編集]のレコードソースであるワークテーブル(親側)の
     全てのレコードを削除する処理(削除クエリなど)を実行する。
 
5-2. [F_登録編集]に埋め込まれているサブフォームのレコードソースである
     ワークテーブル(子側)の全てのレコードを削除する処理
     (削除クエリなど)を実行する。
 
5-3. マスターテーブル(親側)のレコードのうち、[契約番号]の値が
     [検索フォーム]のカレントレコードの[契約番号]の値に等しいレコードを
     [F_登録編集]のレコードソースであるワークテーブル(親側)に
     追加する処理(追加クエリなど)を実行する。
 
5-4. マスターテーブル(子側)のレコードのうち、[契約番号]の値が
     [検索フォーム]のカレントレコードの[契約番号]の値に等しいレコードを
     [F_登録編集]に埋め込まれているサブフォームのレコードソースである
     ワークテーブル(子側)に追加する処理(追加クエリなど)を実行する。
 
-------------------------------------------------------------------------
 
任意に選択された既存のレコードの編集を行なうに当たって
マスターテーブルのレコードをワークテーブルに複写するなら
上記のような操作手順になるはず。
 
引用:
Hワークテーブルに保存されたレコードを本テーブルに登録する

また、この手順に関してはトランザクション制御が必要となるでしょう。

回答
投稿日時: 21/06/25 10:53:34
投稿者: Suzu

skさんが ほぼ説明してくださっています。
 
5-1 と 5-2 の順番は 親フォームのレコードソース/子フォームのレコードソース
それぞれのテーブルの リレーションシップ の設定によります。
 
リレーションシップ にて、
参照整合性 を設定し、連鎖更新あり、連鎖削除なし なら
先に 子側のテーブルのデータを消さないといけません。
 
 
トランザクション処理については
 
1) 編集中レコード の 主キー 情報を保存するテーブルを用意します。
  今回は、テーブル名『TW_編集中』とします。
   フィールドは『契約番号』、『ユーザー名』、『日付』
 
2)レコードを選択し、「編集」を押した時点で、
  TW_編集中 に、当該レコードの契約番号が無いかを確認
 
  レコードがあるときは、誰かが編集中 なので、編集できません 旨のメッセージを出し処理中断
  レコードがないときは、
    2)-1:トランザクション処理開始
    2)-2:TW_編集中 に対し 編集したい、契約番号、自身のユーザー名、現在の時刻 のデーを保存
    2)-3:親子のワークテーブルに、当該契約番号のレコードを追加
    2)-4:トランザクション のコミット
 
3)レコード編集後、親子ワークテーブルの内容を 保存用テーブルに保存します。
    3)-1:トランザクション開始
    3)-2:保存用テーブルの 子側の 当該契約番号のデータを削除し、続いて親側のデータ削除
    3)-3:保存用テーブルの 親側の 当該契約番号のデータを追加し、続いて子側にデータを追加
    3)-4:TW_編集中 の、当該契約番号のデータを削除
    3)-5:ここまでで、トランザクションエラーが無ければコミット処理
 
の流れになります。
 
ワークテーブルから、保存テーブル へ 更新でなく、削除/更新 を行うのは、
新規追加 の 場合でも、同じ流れで処理可能であるからです。
 
 
この処理の場合、その他に、システム起動時等に、
当該ユーザーのデータが、TW_編集中 に無いか確認する必要があります。
 
ある場合には、編集処理が終わらない状態でシステムを終了した事になりますので
レコードの確認をさせる旨のメッセージを出し、保存テーブルのデータを確認させます。
 
上記 の メッセージの際に、 ワークテーブルに存在したままのレコードを 表示するか
複数人が、複数の PC にて編集できるようにするか
 
により、TW_編集中 と、ワークテーブルを
フロントエンド/バックエンド どちらに用意するかが決まります。
 
バックエンド(サーバー)に置くと、
 どのパソコンからでも、編集中だった ワークテーブルに保存中のレコードを参照できます
 
フロントエンド(クライアント)に置くと
 編集中だったデータは、破棄されます 旨のメッセージを出すだけに留まります。
  (ワークテーブルは、PCで編集中だった場合、そのPC に保存されており
   別のPCから そのデータを見ることは叶わないため)
 
ただ、、、ワークテーブルをバックエンドに置くと、、
更に考慮すべき事項が増え、処理が面倒になります。 フロントエンドに置くことをお勧めします。
 
 
また、締め処理等の場合には、『TW_編集中』のデータを確認し、
データが無い事を確認し、締め処理を進める必要があります。

投稿日時: 21/06/25 15:17:50
投稿者: だいふくもち

>sk様、Suzu様
初歩的な質問にも関わらず、毎回丁寧にご教授いただき本当にありがとうございます…!
 

引用:
マスターテーブルと(ほぼ)同一の構造を持った、
マスターテーブルとは異なる名前のワークテーブルを
フロントエンドデータベースの方にあらかじめ定義しておきさえすれば、
この手順はなくてもよいのではないでしょうか。

実は、当初はこちらのような構造で作成していたのですが、
ファイルを社内サーバ上に置き、PCを2台用意して同時にファイルを開いて編集してみようとしたところ、
編集のためにワークテーブルに追加したいちばん最初のレコードしか
編集フォームで読み取れないことに焦ってしまいまして…
それなら編集ボタンを押すたびに毎回ワークテーブルを作成、編集フォームを複製すればいいのでは?!
と思いつき進めていたのですが…
 
引用:
フロントエンド(クライアント)に置くと
 編集中だったデータは、破棄されます 旨のメッセージを出すだけに留まります。
  (ワークテーブルは、PCで編集中だった場合、そのPC に保存されており
   別のPCから そのデータを見ることは叶わないため)

こういうことが可能なのですね…
バックエンド側(社内サーバ)に置く方法しか知りませんでしたので、大変勉強になりました。
調べてみると、「Accessのデータベースを分割する」という方法を見つけましたので、
そちらを参考にやってみたいと思います!
 
引用:
また、締め処理等の場合には、『TW_編集中』のデータを確認し、
データが無い事を確認し、締め処理を進める必要があります。

まさに実現しようとしていたところでしたので(請求書の作成)
おかげさまで見落とさずに済みました…!ありがとうございます。
 
また、トランザクション処理に関するアドバイスも本当にありがとうございます!
そのまま処理しようとしていたので、今考えると途中でエラーが起こってしまった場合
面倒な事になってしまいますよね…
 
sk様、Suzu様、重ねてになりますが、
この度は分かりやすく教えていただき本当にありがとうございました!