• ベストアンサー

Accessでチェックしたらサブフォームもチェック

T_マスタテーブル ・ID ・氏名 ・チェック T_サブテーブル ・ID ・住所 ・チェック となっていて、それぞれフォームを作成していて、 F_マスタフォームの中にF_サブフォームが入っています。 (IDでリンク) マスタテーブルに 1001  山田 太朗   というデータがあったとすると サブには 1001 東京都*** と入っているのですが、 サブは1人につき、1件とは限らず、 1001 東京都渋谷区*** 1001 東京都新宿区*** 1001 埼玉県さいたま市*** となっていることもあります。 F_マスタフォームのチェックの「更新後処理」に Private Sub チェック_AfterUpdate() If チェック = True Then [Form]![F_サブフォーム]![チェック] = True Else [Form]![F_サブフォーム]![チェック] = False End If End Sub と入っていて、F_マスタの方にチェックをすればF_サブのほうにもチェックが 入るようにしたいのですが、 1件目しかチェックがされません。 IDが同じもののチェックにはすべてチェックがされるようにするには どのようにかけばいいのでしょうか? 宜しくお願いします。 Ac2000です。

質問者が選んだベストアンサー

  • ベストアンサー
  • yoisho
  • ベストアンサー率64% (331/516)
回答No.4

>でも、サブテーブルから削除の部分ができません。 うーん・・・ ためしに簡単なデータをつくって試してみたところ、こちらでは削除ができたんですけど・・・ サブテーブルにマスタ以外のテーブルと一対多の参照整合があったりするとだめなのかなー? 理由は今のところよくわかりませんが、とりあえずサブクエリーを使った以下のコードではいかがでしょうか? (これならロックがかからないと思いますので、削除できるかもしれません。) DoCmd.RunSQL "DELETE * FROM T_サブテーブル WHERE ID In" _ & " (SELECT ID FROM T_マスタテーブル WHERE チェック=True;) " また何かありましたら、補足でコメント下さい。(土日は不在ですので、ご了承ください。)

KODAMAR
質問者

お礼

おはようございます。 教えていただいた方法で実行することができました! ありがとうございました! 長らくお付き合いいただいてありがとうございました。

その他の回答 (3)

  • yoisho
  • ベストアンサー率64% (331/516)
回答No.3

すみません、説明が足らなかったですね。(失礼いたしました。) 前の回答で例として挙げたのは、クエリーのSQLに記述するのではなく、VBAのコードとして記述する物になります。 DoCmd オブジェクト の RunSQL メソッド を使うと、VBA中でアクションクエリーと同じ処理を行うことができます。(つまり、別途アクションクエリーを増やさなくてもよいということです。詳しくは、それぞれのHELPを確認してみてください。) 具体的なVBAのコードとしては、「DoCmd.RunSQL "SQLステートメント"」 と記述します。 ここで、「SQLステートメント」は、クエリーのSQLビューの内容と同じものです。 (ですから、SQLの構文がよくわからなくても、まずアクションクエリーを作って、そのSQLビューをコピー&ペースト(ただし改行されているところは、半角スペースに置き換えること)してやればOKです。) なお、このSQLの部分は文字列として記述しなければなりませんので、両端に「"」が付いています。 (前回の回答で、そのさらに両端に「()」カッコが付いていましたが、これは不要でした(付いていても問題なく動きますが)ので、すみませんが消しておいてください。) また、~CStr(Me![チェック]) & " WHERE ID = " & CStr(Me![ID])) のように、CStr 関数でフォームコントロールのデータを文字列に変換していたのも、この理由によります。 なお、SQLステートメントは通常かなり長く(文字数が多く)なって、VBAのコードが読みにくくなりますので、スペースとアンダスコアの組み合わせ「 _」(詳しくは「表記規則」のHELPを確認してください)と、文字列結合演算子の「&」を利用して、複数行に分けて記述しています。 例を挙げると、 "INSERT" _ & " INTO" は、 "INSERT INTO" と同じ意味です。 注意ですが、INTO の前の半角スペースは必要で、これが無いと "INSERTINTO" になってしまいます。 余談ですが、複数行に分ける別の方法としては、文字列変数を利用して、 Dim str as String str = "INSERT" str = str & " INTO" str = str & CStr(○×△) str = str & " ・・・・・・・・ DoCmd.RunSQL str のようなやり方もあります。(こっちの方がスマートかな?) ということで、例えばマスタフォームにコマンドボタンを配置して、これをクリックした時にデータを移動するようなやり方なら、具体的なコードは以下のようになります。 Private Sub コマンド_Click() 'フォームのチェックボックスをチェックしただけでは、まだテーブルのデータは更新されていない(T_マスタテーブル の チェックフィールドの値 が True になっていない)ため、強制的に更新 DoCmd.RunCommand acCmdSaveRecord ' T_削除マスタテーブルに、データを追加 DoCmd.RunSQL "INSERT INTO T_削除マスタテーブル ( ID, 氏名 )" _ & " SELECT ID, 氏名 FROM T_マスタテーブル" _ & " WHERE T_マスタテーブル.チェック = True" ' T_削除サブテーブルに、データを追加 DoCmd.RunSQL "INSERT INTO T_削除サブテーブル ( ID, 住所 )" _ & " SELECT T_サブテーブル.ID, T_サブテーブル.住所" _ & " FROM T_マスタテーブル INNER JOIN T_サブテーブル" _ & " ON T_マスタテーブル.ID = T_サブテーブル.ID" _ & " WHERE T_マスタテーブル.チェック = True" ' T_サブテーブルのデータを削除(マスタテーブルと連鎖削除されるなら、不要か?) DoCmd.RunSQL "DELETE T_サブテーブル.*" _ & " FROM T_サブテーブル INNER JOIN T_マスタテーブル" _ & " ON T_サブテーブル.ID = T_マスタテーブル.ID" _ & " WHERE T_マスタテーブル.チェック = True" ' T_マスタテーブルのデータを削除(これを最後に行わないと、どのレコードを移動・削除すればいいのかわからなくなってしまいます。) DoCmd.RunSQL "DELETE * FROM T_マスタテーブル" _ & " WHERE チェック = True" ' T_マスタテーブル のレコードが削除されたため、(マスタフォームに表示するデータが無くなると、連結テキストボックスやチェックボックス等にエラー表示が出てしまうので、)フォームを再クエリー Me.Requery End Sub 私はかなり自己流で Access やってますので、本当はもっと良いやり方があるのかもしれませんけど、とりあえず一例としてご参考まで。 コードの不具合(ちゃんとデバッグしてませんので、どこかにミスがあってそのままでは動かない可能性があります。)や、その他疑問等ありましたら、また補足でご連絡願います。 (土日は不在ですので、お答えが遅れてしまうかもしれませんことをあらかじめご了承ください。)

KODAMAR
質問者

お礼

すいません、下記標記に誤りがあって修正したらできました。 でも、サブテーブルから削除の部分が 「指定されたテーブルから削除できませんでした。」 と出て、できません。 (マスタテーブルから削除はできました。) 宜しくお願いします。

KODAMAR
質問者

補足

再度回答ありがとうございます。 教えていただいた通りにコードをかいてみました。 -------------------- Private Sub コマンド8_Click() DoCmd.RunCommand acCmdSaveRecord 'T_削除マスタテーブルにデータを追加 DoCmd.RunSQL "INSERT into T_削除マスタテーブル (ID,氏名)" _ & " SELECT ID, 氏名 FROM T_マスタテーブル" _ & " WHERE T_マスタテーブル.チェック = True" 'T_削除サブテーブルに、データを追加 DoCmd.RunSQL "INSERT INTO T_削除サブテーブル (ID, 住所)" _ & " FROM T_サブテーブル.ID, T_サブテーブル.住所" _ & " FROM T_マスタテーブル INNER JOIN T_サブテーブル" _ & " ON T_マスタテーブル.ID = T_サブテーブル.ID" _ & " WHERE T_マスタテーブル.チェック = True" 'T_サブテーブルのデータを削除 DoCmd.RunSQL "DELETE T_サブテーブル.*" _ & " FROM T_サブテーブル INNER JOIN T_マスタテーブル" _ & " ON T_サブテーブル.ID = T_マスタテーブル.ID" _ & " WHERE T_マスタテーブル.チェック = True" 'マスタテーブルのデータを削除 DoCmd.RunSQL "DELETE * FROM T_マスタテーブル" _ & " WHERE チェック = True" 'マスタテーブルのデータが削除されたあとのエラー表示回避 Me.Requery End Sub -------------------- としたんですが、 T_削除マスタテーブルへの追加はスムーズに行われているようで、 きちんと処理が正常にできましたが、 その次のところでエラーらしく、 -------------------- 実行時エラー '3134'; INSERT INTO ステートメントの構文エラーです。 -------------------- とでてしまいます。 これはどのようにしたらいいのでしょうか? 再度回答していただけるとありがたいです。 宜しくお願いします。

  • yoisho
  • ベストアンサー率64% (331/516)
回答No.2

まず、ご質問への回答ですが、 フォーム上の連結コントロールの値は、カレントレコードについてしか操作できませんので、サブフォームの1件目にしかチェックが入らないのは、仕方ないことです。 (ためしに、サブフォームの2件目にフォーカスを移動してからメインフォームにチェックを入れれば、サブの2件目にチェックが入るのがわかると思います。) ご希望のことをするには、アクション(更新)クエリーでも使って、[T_サブテーブル]のデータを直接書き換えてしまうのが簡単だと思います。 (多少画面のレスポンスは悪くなりますが、GotoRecordでサブフォームのカレントレコードを順番に移動して全てを処理するよりは、ずっとシンプルです。) 具体的には、以下のようにすればできると思います。 Private Sub チェック_AfterUpdate() DoCmd.RunSQL ("UPDATE T_サブテーブル SET チェック = " & _ CStr(Me![チェック]) & " WHERE ID = " & CStr(Me![ID])) Me![F_サブフォーム]. Refresh End Sub さて確認ですが、KODAMARさんのなさりたいことは、以下でよろしいのでしょうか。 (もし、私の勘違いがありましたらお許しください。) ○[T_マスタテーブル]から、マスターフォームでチェックをしたレコードの“ID”、“氏名”のデータを[T_削除マスタテーブル]へ移動する。 ○さらに、[T_サブテーブル]から、対応する ID のレコードの“ID”、“住所”のデータを[T_削除サブテーブル]へ移動する。 以上で間違いなければ、元のテーブルのチェックフィールドは全て False、削除テーブルは全て True となりますので、いずれのテーブルのチェックフィールドも最終的には必要ないように思います。 (移動処理のために[T_マスタテーブル]のチェックを一時的に利用するなら、これはあっても良いかもしれませんが、(tatezooさんと同じ意見ですが、)少なくとも[T_サブテーブル]のチェックは不要では?) 例えば[T_削除サブテーブル]への追加でしたら、[T_サブテーブル]にチェックフィールドがなくでも、以下の追加クエリー(SQLステートメント)で可能です。 DoCmd.RunSQL ("INSERT INTO T_削除サブテーブル ( ID, 住所 )” & _ “ SELECT T_サブテーブル.ID, T_サブテーブル.住所” & _ “ FROM T_マスタテーブル INNER JOIN T_サブテーブル” & _ “ ON T_マスタテーブル.ID = T_サブテーブル.ID” & _ “ WHERE チェック = True”) 私の勘違いやSQLの疑問などがありましたら、補足でコメントをお願いします。

KODAMAR
質問者

お礼

>○[T_マスタテーブル]から、マスターフォームでチェックをしたレコードの“ID”、“氏名”のデータを[T_削除マスタテーブル]へ移動する。 >○さらに、[T_サブテーブル]から、対応する ID のレコードの“ID”、“住所”のデータを[T_削除サブテーブル]へ移動する。 はい、その通りです! それをやりたいんです。 DoCmd.RunSQL ("INSERT INTO T_削除サブテーブル ( ID, 住所 )” & _ “ SELECT T_サブテーブル.ID, T_サブテーブル.住所” & _ “ FROM T_マスタテーブル INNER JOIN T_サブテーブル” & _ “ ON T_マスタテーブル.ID = T_サブテーブル.ID” & _ “ WHERE チェック = True”) これは追加クエリーの SQLビューで入力すればいいんですか? (間違ってたらごめんなさい。) すると「SQLステートメントが正しくありません」ってでてしまうんですが。。。 宜しくお願いします。

  • tatezoo
  • ベストアンサー率43% (7/16)
回答No.1

提示されたソースですと、マスターテーブルのチェックに完全連動させるように伺えますがそれでよろしいのでしょうか? であれば、サブテーブルにチェックを入れる必要性が無いのではないでしょうか。 サブフォームにマスターフォームのチェックを貼り付ければ良いのではないでしょうか? サブフォームのチェックのコントロールソースに=[Forms]![F_マスタフォーム]![チェック]とすればよいのではないでしょうか? 違っていたら、スイマセン。

KODAMAR
質問者

お礼

もうひとつ追加です。 T_マスタテーブル、T_サブテーブルともに、チェックが入ったものを クエリを利用してT_削除マスタテーブル、T_削除サブテーブルに追加し、 それから削除したいのです。 ですので、リレーションシップを使っての、連鎖削除だと、 T_マスタテーブルの方は追加・削除ともに成功しますが、 T_サブテーブルの方が追加しないまま削除してしまうので、 この方法も的確ではないようなのです。 よいお知恵ありましたらよろしくお願いします。

KODAMAR
質問者

補足

回答ありがとうございます。 >サブフォームのチェックのコントロールソースに=[Forms]![F_マスタフォーム]![チェック]とすればよいのではないでしょうか? これ、私もやってみたりしたのですが、これですと、フォーム上はチェックが入るんですが、テーブルの実際のデータはかわってないんです。 このチェックをもとにいろいろ操作をしたいので、テーブルの方にチェックが 入らないと。。。 #クエリ使えばたぶんできますよね。 #最終手段はクエリを使おうと思ってるんですけど、 #できればテーブルとフォームで済ませたいと思ったりしてます。 #でないとクエリがたくさんになってややこしくなってしまうので。。。

関連するQ&A

専門家に質問してみよう