Access (VBA)

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

 
(Windows 7 Professional : Access 2013)
例外データだけフォーム上で登録する方法
投稿日時: 19/01/10 09:26:50
投稿者: hato

お世話になります。
 
全社員のテーブル(TBL1)に、例外の社員を登録しているテーブル(TBL2)を
LEFT JOIN で結合しています。
TBL2の項目は
社員コード、検査1(Yes/No型)、検査2(Yes/No型)
 
フォーム上で社員情報を登録・表示していて、TBL2の検査1、検査2は
チェックボックスを使用しています。
 
TBL2.検査1と2がNULLの場合、チェックボックスが青いYESでもNOでもない
状態になるため、フォームの「レコード移動時」のイベントに
 
    If IsNull(chk検査1) Then
        chk検査1.Value = False
    End If
    If IsNull(chk検査2) Then
        chk検査2.Value = False
    End If
 
と記述しています。
 
このようにすると、チェックボックスが白い未選択状態に
なり、期待通りなのですが1つ問題があります。
TBL2に検査1と検査2が両方Falseのデータも当然登録されるので
結局全社員分のデータが登録されてしまいます。
TBL2はあくまで例外データを管理したいので、チェックがついた
データだけ登録するには、どのような処理をすればうまくいく
でしょうか?
どうぞよろしくお願いします。

回答
投稿日時: 19/01/10 10:14:59
投稿者: Suzu

フォーム云々の前に、
レコードソースである クエリ のレコードがどうあって欲しいか を聞かせて下さい。
 
クエリのSQLは、
SELECT TBL1.*, TBL2.検査1, TBL2.検査2
FROM TBL1 LEFT JOIN TBL2 ON TBL1.社員コード = TBL2.社員コード
こんな FROM句ですか?
 
TBL1
社員コード    社員名
10001    あああ
10002    いいい
10003    ううう
 
TBL2
社員コード    検査1    検査2
10001    No    No
10003    No    No
 
この場合、このSQLを実行した時クエリは
 
社員コード    検査1    検査2
10001    No    No
10002    Null    Null
10003    No    No
 
の様になります。
 
フォームで、Null と、 No の判別がしづらいので
VBAレコード移動時 で、 操作をおこなったった事ですよね?
VBAでもチェックボックスを意図的に変えているのですから
TBL2 に 10002 No No のレコードができちゃうのは当たり前です。
 
回避は、トリプルステート で回避できませんか?
https://www.accessdbstudy.net/entry/20080903/p1
https://www.accessdbstudy.net/entry/20080830/p1
 
そういう意味で無いのであれば
 
チェックがついたデータだけ登録するには、どのような処理をすればうまくいくでしょうか?
 
上記の意図する
・フォームの状態
・TBL1、TBL2 の各レコードの値
を説明してください。
 
 
問答無用で判り易くと言うだけなら
・LEFT/RIGHT JOIN を使用しない
・チェックボックス(Yes/No) ではなく、テキストボックス(数値) を使用する
のどちらかでしょうね。

投稿日時: 19/01/10 13:34:06
投稿者: hato

Suzuさん早速のご回答ありがとうございます。説明不足で申し訳ありませんでした。
 
クエリのSQLは、
まさにそんな感じです。健康診断で何をうけるべきかなどを管理しています。
 
TBL1
社員コード    氏名    性別    生年月日    検査日    眼科    聴力    胃部X線・・・
10001        あああ    1    1997/1/1    2018/6/15    Yes    Yes    Yes
10002        いいい    1    1985/8/9    2018/6/15    Yes    Yes    Yes
10003        ううう    2    1976/4/3    2018/7/19    Yes    Yes    Yes
TBL2
社員コード    免除    別検査
10001        No    Yes
10003        Yes    No
 
Yesの部分はチェックボックスになっています。
胃部X線を何らかの理由で免除、または別検査になっている人をTBL2で
管理しています。
TBL1は毎年新規で作成するのですが、TBL2は同じテーブルを使用します。
免除と別検査がNull、NullやNo、Noの社員は登録しないでおきたいです。
TBL2では1度YesにしたものをNoにすることはありません。
 
教えていただいたトリプルステートをはいにしてみたところ、チェックボックスの
Yes→No は可能ですが
No→YesとNULL→Yes の更新ができませんでした。
 
フォームはクエリをレコードソースにしていて、各コントロールに
連結しています。
チェックボックスを使いたいのですが、NullもNoと同じように白い□にして
YesのときだけTBL2に登録したいです。それを制御するために、VBAで
実現可能でしょうか?
 
長くなってすいません。
よろしくお願いします。

回答
投稿日時: 19/01/11 07:41:21
投稿者: Suzu

すみません。良く考えたらトリプルステートのみでは実現できません。
 
 
TBL2のレコードの あり/なし で 連結後のクエリの Null かどうか が決まります。
 
つまり、一般機能として、チェックボックスの On/Off でレコードの削除が必要となり
一般機能では無理です。
 
行うのであれば、VBAで TBL2 のレコードを削除する必要があります。
チェックボックスの見た目の為に、チェックボックスステートに併せて
 レコードの削除・レコード追加(Yes/No) の制御を行う必要があり、
それは、連結フォームのままでは出来ません。
 
一時的に、フォームのレコードソースからクエリを切り離し非連結フォームとした後、
TBL2 のレコード操作を行う必要があります。
 
・チェックボックスは予めトリプルステート・非連結コントロールとする
・チェックボックスの更新後処理にて
  1. フォームのレコードソース空白化
  2. チェックボックスの値 及び 変更前の値 により TBL2 の当該 社員コードのレコードに対し
     追加・削除・値の変更 の条件分岐処理
  3. レコードソースを元に戻す
     (再クエリと同じ処理になるのでカレントレコード位置が先頭となす
     必要ならレコード位置の移動処理)
 
の様な形になります。
 
本当にチェックボックスをトリプルステートで表示する事が必須なのであれば
上記の様な事を行うより、TBL1 と TBL2 を 1テーブルにした方が現実的と思います。

回答
投稿日時: 19/01/11 13:06:21
投稿者: hatena
投稿者のウェブサイトに移動

テーブル設計から見直した方がいいのではないかと思います。
 
現状は2つのテーブルは一対一の関係になっています。
一対一の関係のでーたは一つのテーブルにまとめるというのが、データベース設計のセオリーです。
 
ただ、今回のテーブルは正規化できません。正規化するなら、下記のような設計になります。
 
社員のテーブル(TBL1)は現状のまま。
TBL2は下記のような設計にします。
 
社員コード
検査名  テキスト型
検査結果 Yes/No型
 
「社員コード」と「検査名」で複数フィールド主キーに設定。
 
TBL1 と TBL2 は、一対多の関係になります。
これから入力フォームを作成する場合は、メイン/サブフォーム形式のフォームにするのが一般的です。
リレーションシップを設定して、ウィザードで作成するとメイン/サブフォーム形式のフォームになります。

回答
投稿日時: 19/01/11 16:39:28
投稿者: Suzu

あーーー ごめんなさい。。
 
先に提示したサイトに YES/NO型 のフィールドに対し、NULL を設定する事ができません。
 
とありますね。
 
そのフィールドに連結したチェックボックスでは、
コントロールソースとなる YES/NO型がNULLを保持できないのでトリプルステートが使ない様ですね。
 
 

引用:
教えていただいたトリプルステートをはいにしてみたところ、チェックボックスの
Yes→No は可能ですが
No→YesとNULL→Yes の更新ができませんでした。

 
あれ?使えました?手元Access無くて確認できません・
 
 
なぜ、Nullである必要があるのでしょう?
ユーザーは、Null/YES/NO をきちんと使い分ける事ができるのでしょうか?
 
ただ単に、見た目の話なら、やめた方が無難。
 3つの値を明示的に切り替えたいのであれば、数値型フィールドにすべきでしょう。
 
技術的な興味でトリプルステート状態を保持したいなら、先のレスの通り。
 
 
 
私の
引用:
TBL1 と TBL2 を 1テーブルに
と hatenaさんの
引用:
今回のテーブルは正規化できません。
は同じ事を言っています。
 
TBL
------------------
社員コード
氏名
性別
生年月日
検査日
視力
聴力
胃部X線
胃部X線免除(YES/NO)
胃部X線別検査(YES/NO)
  :
------------------
 
の様な、テーブルにするという事。
 
TBL2 と同じ内容は
 
SELECT TBL.氏名コード, TBL.[胃部X線免除] AS 免除, TBL.[胃部X線別検査] AS 別検査
FROM TBL
WHERE (TBL.[胃部X線免除] = TBL.[胃部X線別検査])= TRUE
 
とでもすれば良いのでは?

回答
投稿日時: 19/01/11 20:21:24
投稿者: hatena
投稿者のウェブサイトに移動

あー、私の前回の回答はスルーしてください。
 
最初の質問しかみてませんでした。
 
投稿日時: 19/01/10 13:34:06 の投稿をみると、
 

引用:
胃部X線を何らかの理由で免除、または別検査になっている人をTBL2で
管理しています。
TBL1は毎年新規で作成するのですが、TBL2は同じテーブルを使用します。

 
の設計がおかしいように思います。
 
TBL1 は、社員データと検査データに分割すべきかと。
検査データは毎年更新されるのなら、年度フィールドを追加する。
いちいち毎年新規作成するのはデータベースの設計としてはNGです。
で、免除情報は社員に属するデータで毎年更新しないので、社員データの方に持たせる。
 
社員マスター
------------------
社員コード 主キー
氏名
性別
生年月日
胃部X線免除(YES/NO)
胃部X線別検査(YES/NO)
 
検査データ
------------------------
社員ID   主キー
検査年度  主キー
検査日
眼科
聴力
胃部X線
 
こんな感じにするのがデータベース設計としては正解かと。

投稿日時: 19/01/15 09:45:15
投稿者: hato

Suzuさん、hatenaさんご回答ありがとうございます。
 
毎年テーブル作成をするというのがそもそもの問題だったのですね。
いろいろとアドバイスいただきありがとうございます。
 
テーブルを社員と検査受診に分けてやってみました。
元データのクエリも毎年年度を変えるだけですし、
チェックボックスの白い未選択状態の問題もうまくいきました。
 
本当にお世話になりました。
ありがとうございました。