(空欄)を先頭に持ってくるようにするために、[年月日] Is Null AS N というフィールドを追加
ORDER BY 2, 1 DESC;
の数字は何列目かを指定しています。下記と同じ意味になります。 ORDER BY [年月日] Is Null, Format(Format([年月日],"yyyy/mm"),"&;""(空欄)""") DESC;
フィールドの式が長いときは簡略化できるので便利です。
cbo年月の更新後処理のイベントプロシージャ
Private Sub cbo年月_AfterUpdate()
If Nz(Me.cbo年月) = "" Then
Me.Filter = ""
Me.FilterOn = False
ElseIf Me.cbo年月 = "(空欄)" Then
Me.Filter = "年月日 Is Null"
Me.FilterOn = True
Else
Me.Filter = "年月日>=#" & Me!cbo年月 & "# AND 年月日<#" & _
DateAdd("m", 1, Me!cbo年月) & "#"
Me.FilterOn = True
End If
End Sub
★降順にしていたものを昇順としたが、その他の問題は解決。
【値集合ソース】
SELECT DISTINCT "(空欄)" AS 年月
FROM T_案件
WHERE (((T_案件.年月) Is Null))
UNION SELECT DISTINCT T_案件.年月
FROM T_案件
WHERE (((T_案件.年月) Is Not Null));
Private Sub txt日付_AfterUpdate()
If IsDate(Me.txt日付.Value) Then
Me.Filter = "日付=#" & Me.txt日付.Value & "#"
Me.FilterOn = True
If Me.Recordset.RecordCount = 0 Then
Me.日付.DefaultValue = "=#" & Me.txt日付.Value & "#"
Me.AllowAdditions = True
End If
Me.項目1.SetFocus
End If
End Sub
フォームの挿入後処理のイベントプロシージャを下記のように記述します。
Private Sub Form_AfterInsert()
Me.AllowAdditions = False
End Sub
SELECT "(すべて)" AS 年月
FROM T_案件
UNION SELECT 年月
FROM T_案件;
'年月選択 更新後処理
Private Sub cbo年月_AfterUpdate()
If Me.cbo年月 = "" Then
Me.Filter = ""
Me.FilterOn = True
Else
Me.Filter = "年月=" & Me.cbo年月
Me.FilterOn = True
End If
End Sub
複数の選択肢に情報をつなげる方法 Microsoft Access 掲示板 - zawazawa
で提示されているテーブルと同じものかな?
だとしたら、データベース設計のセオリーとしては、正規化しましょう、ということになりますね。
正規化については、下記のページの「4.正規化」の項目を読んで学習してください。
もう一度学ぶMS-Access
具体的には下記のようにテーブルを分割します。
●T会社
会社ID 主キー
会社名
会社備考
・・・
●T商品
商品ID 主キー
商品名
単価
・・・
●T取扱商品
会社ID 主キー
商品ID 主キー
複数のフィールドに主キーを設定する方法は下記を参照。
複数のフィールドの組み合わせで重複がないようにする - hatena chips
リレーションシップで、同じ名前のフィールド同士結合しておきます。
リレーションシップの設定と効果 - もう一度学ぶMS-Access
T会社とT取扱商品を結合したクエリをレコードソースとする帳票フォームを作成します。
T商品をレコードソースとする単票フォームに、上記のフォームをサブフォームとして埋め込みます。
サブフォームのリンク親フィールド、リンク子フィールドは「会社ID」と設定します(リレーションシップの結合にあわせて自動で設定される場合もあり)
このフォームから、商品を見ながら、扱っている会社名のリストもサブフォームで見れます。また、サブフォームで取り扱い会社を追加することもできます。
逆に、
T商品とT取扱商品を結合したクエリをレコードソースとする帳票フォームを作成します。
T会社をレコードソースとする単票フォームに、上記のフォームをサブフォームとして埋め込みます。
サブフォームのリンク親フィールド、リンク子フィールドは「商品ID」と設定します。
このフォームからは、会社情報を見ながら、扱っている商品のリストもサブフォームで見れます。また、サブフォームで取り扱い商品を追加することもできます。
このような設計にしておけば、取り扱い商品や取り扱い会社の数に制限なくいくらでも追加できます。
現状のテーブル名と、そこに含まれるフィールド名、主キーフィールド、を提示してもらえますか。
教えていただいた方法でうまくいきました!色々方法がありますね。ありがとうございます。
うまくいきました!""の使い方がまだよく理解できておらず、助かりました。ありがとうございます。
としては、いかがでしょうか。
ID, パスワードが一致したらフォームを開く - hatena chips
上記で紹介したものてすね。
とりあえずサンプルを作成してみました。下記のリンクからダウンロードできます。
参考にしてください。
FrmRogIn2.zip
エラーはどのような間違いをしているのかを教えてくれる大事なものなのでエラーの内容も提示しましょう
見た感じ間違いがあるように見えませんが、よくあるパターンとしては会社IDがテキスト型であるとか
そもそもクエリ上でやりたいのなら「T会社」テーブルを2回入れてしまうのが良いです
クエリデザインでテーブルの表示から「T会社」を2回選ぶと、一つ目は「T会社」、二つ目は「T会社_1」となります
「T商品」の「会社1」と「T会社」の「会社ID」、「T商品」の「会社2」と「T会社_1」の「会社ID」を紐づけて上げれば
備考1:[T会社].[会社ID]
備考2:[T会社_1].[会社ID]
で望みの結果になります
自分なら、だと
メニュー画面で「出勤簿」「運転日報」それぞれのボタンを用意して入力フォームを開いたときに規定値を弄るとか、ですかね
どのコードでエラーはでますか。
当方のサンプルでの実験では問題なく実行できました。
アドバイスありがとうございます。
テストしてみましたがエラーのままでした。
マクロで以下のプロシージャの実行
オートナンバー型初期化("TEST3","ID")
※前後これ以外の処理はありません。
テーブルTEST3に定義しているフィールド名IDは以下の設定になっています。
データ型オートナンバー型
フィールドサイズ 長整数型
新規レコードの値 インクリメント
インデックス いいえ
文字配置 標準
ローカル変数のSQLは以下のようになっていました。
"Alter Table [TEST3] Alter Column [ID] Counter(1,1)"
連投すみません
新しいファイルでやり直したら問題なくできました
原因はわかりませんが、できなかったファイルでは
レイアウトビュー レポートビューで、一切レコードが表示されていませんでした
なにかのプロパティをいじってしまったのでしょうか?
正常なものと見比べましたがどこに違いがあるかわかりませんでした
何度も印刷プレビューとデザインビューを切り替えていると
”印刷時縮小 はい”で入力したレコードが表示される場合があるようですが
印刷するとレコードは表示されていませんでした
またすべてのレコードに余計な空白行が挿入されています
データ数が多くて処理が重く感じた時点で、インデックスを付けることを検討するということでもいいです。
インデックスとは、百科事典・学術書などの最後についている索引のようなものと考えればいいでしょう。
それが、あると検索や抽出が高速になります。
内容確認しました!とても勉強になりました。
「抽出条件でインデックスが無効になる場合」につきましては、また新しい知識なので勉強したいと思います。インデックスもいまいち理解できていなかったので貴重なお話をありがとうございます。
すみません…コンボボックスを左寄せ設定したら解決できました。(右寄せ設定になっていたわけではないので、原因は結局不明ですが…)お騒がせしました
とても丁寧な解説、本当にありがとうございます。じっくり読み解きたいと思います。心から感謝申し上げます。
フィールドを同じにする場合、下記のようなフィールド構成にする。
開始時刻 日付/時刻型
終了時刻 日付/時刻型
運転日報 Yes/No型
レポートの設計は、
出勤簿も運転日報も 開始時刻、終了時刻 をコントロールソースにすればよい。
ラベルの標題を出勤簿なら、出勤時間、退勤時間 に、
運転日報なら、開始点呼時間、終了点呼時間 にすればよい。
出勤簿と運転日報のレイアウトが同じでラベルの標題だけが違うのなら、
ラベルをテキストボックスに変換して、コントロールソースを下記のようにすれば一つのレポートでどちらでも使えます。
=IIf([運転日報],"開始点呼時間","出勤時間")
=IIf([運転日報],"終了点呼時間","退勤時間")
入力フォームは、フォームヘッダーにコンボボックスかラジオボタンを配置しておいて、運転日報か出勤簿か選択できるようにして、「運転日報」フィールドに対してフィルターをかけて対象レコードを表示するようにする。
あるいは、メイン/サブフォーム形式にしてもいいでしょう。
ラベルはレポートの同様にテキストボックスにすればいいでしょう。
自分なら上記のような設計にします。
サンプルの解説
テーブル T_案件 に 日付/時刻型の「年月日」フィールドがある。
「年月日」は未入力(NUll)のレコードもある。
上記のテーブルから帳票フォームを作成する。
フォームヘッダーにコンボボックスを「cbo年月」を配置する。
値集合ソース
テーブルに未入力のレコードが存在するのでユニオンクエリにする必要はなかったです。
Format([年月日],"yyyy/mm")
で年月日を年月に変換、さらに
Format(・・・,"&;""(空欄)""")
をかぶせることで、Nullを(空欄)に変換。(空欄)を先頭に持ってくるようにするために、
[年月日] Is Null AS N
というフィールドを追加ORDER BY 2, 1 DESC;
の数字は何列目かを指定しています。下記と同じ意味になります。
ORDER BY [年月日] Is Null, Format(Format([年月日],"yyyy/mm"),"&;""(空欄)""") DESC;
フィールドの式が長いときは簡略化できるので便利です。
cbo年月の更新後処理のイベントプロシージャ
cbo年月 が未選択の時は全件表示、
"(空欄)"を選択したときは年月日が空欄のレコードを抽出、
年月を選択したときは、その年月のレコードを抽出。
年月でフィルターをかける時、
Me.Filter = "Format([日付],"yyyy/mm")='" & Me!cbo年月 & "'"
とした方がコードは短くなるが、インデックスが無効になるので、処理を軽くしたい場合は上のコードのように年月日フィールドに直接条件を設定するようにしたほうがよい。
詳細は下記参照。
抽出条件でインデックスが無効になる場合 - hatena chips
レポートレイアウトのテクニックになるのかもしれませんが
出勤簿の提出があったとき
レポートには出勤時間や退勤時間レベルフィールドを配置したものにしますが
運転日報で入力したレコードに関してはその項目に値がないので
フラグでいずれかのフィールドを表示させるとかでしょうか?
簡単なサンプルを作成してみました。
下記のリンクでダウンロードできます。
案件管理.zip
何度も連投してしまい、申し訳ありません。自己解決する度、お答えする手間をかけないようにと思って都度都度投稿してしまっておりました…
現状のファイルをお送りしたい気持ちは山々なのですが、難しい状況です。
お言葉、ありがとうございます。
今回の件は、下記で解決とすることにしました。
大変お騒がせしました。
★降順にしていたものを昇順としたが、その他の問題は解決。
【値集合ソース】
SELECT DISTINCT "(空欄)" AS 年月
FROM T_案件
WHERE (((T_案件.年月) Is Null))
UNION SELECT DISTINCT T_案件.年月
FROM T_案件
WHERE (((T_案件.年月) Is Not Null));
【VBA】すみません・・修正しました。
Private Sub cbo年月_AfterUpdate()
If Me.cbo年月 = "(空欄)" Then
Me.Filter = "年月 Is Null"
Me.FilterOn = True
Else
Me.Filter = "年月 ='" & Me!cbo年月 & "'"
Me.FilterOn = True
End If
End Sub
★残り問題点
①(空欄)が選択肢の一番下に表示されるのを一番上に持ってきたい
②選択肢の中に空のものがあるのを表示しないようにしたい。
現状のファイルを送信フォームから送ってもらった方が速そうです。
修正しました!
しかし、まだ問題点が残っています。
①年月がなぜか選べなくなった。(選択すると表示されるレコードが0になる)
②(空欄)の選択肢を一番上に持ってくる方法がわからない。
【VBA】
Private Sub cbo年月_AfterUpdate()
If Me.cbo年月 = "(空欄)" Then
Me.Filter = ""
Me.FilterOn = True
Else
Me.Filter = "年月=" & Me.cbo年月
Me.FilterOn = True
End If
End Sub
【値集合ソース】
SELECT DISTINCT "(空欄)" AS 年月
FROM T_案件
WHERE (((T_案件.年月) Is Null))
UNION SELECT DISTINCT 年月
FROM T_案件
ORDER BY 年月 DESC;
★下記のVBAにすると、きちんと絞り込み表示ができます。
Private Sub cbo年月_Click()
DoCmd.SetFilter "", "[年月] Like [Forms]![F_案件]![cbo年月]", ""
End Sub
いろいろ方法はありますが、一例を紹介しておきます。
フォームウィザードで入力したいテーブルをもとに単票フォームを作成します。
フォームプロパティを下記のように設定します。
「日付」のテキストボックスの「使用可能」は「いいえ」にします。
フォームヘッダーにテキストボックスを配置して下記のように設定します。
txt日付 の更新後処理のイベントプロシージャを下記のように記述します。
フォームの挿入後処理のイベントプロシージャを下記のように記述します。
以上です。
同じでも、分けても、どちらでもOKです。
労基などに提出する統一された出勤簿が同じ欄なら同じで、異なる欄なら別に、というように用途に合わせて使いやすいように設計すればいいでしょう。
テーブルを分けない場合
開始点呼時間 終了点呼時間 と
出勤時間 退勤時間 を
それぞれ同じフィールドにするということですか?
とりあえずコードは下記に修正してみてください。
修正前のコードだとテーブル名やフィールド名に空白や記号が含まれるとエラーになる場合がありますので、その対策を追加しました。
それてもエラーになるなら、この関数を呼び出す前後のコードを提示してください。
上記は、値集合ソースとvbaに入力しているものです。
詳しいご解説ありがとうございます。コントロールソースを指定しておりませんでした。大変お手数をおかけいたしました。うまくいきました!ありがとうございます。
下記作成しましたが、何を選択してもなにも表示されない状態になりました。
また、コンボボックス内に空白の選択肢ができてしまいます。
SELECT "(すべて)" AS 年月
FROM T_案件
UNION SELECT 年月
FROM T_案件;
'年月選択 更新後処理
Private Sub cbo年月_AfterUpdate()
If Me.cbo年月 = "" Then
Me.Filter = ""
Me.FilterOn = True
Else
Me.Filter = "年月=" & Me.cbo年月
Me.FilterOn = True
End If
End Sub
「cbo種類」はフォーム上のコントロールの名前で、コントロールソース名とは別ですか?
カウントに使えるフィールドはレコードソースのフィールドなので、cbo種類のコントロールソース名を指定してあげてください
条件判断についても実際のデータに対して行うので、コンボボックスで目に見える表示と連結列が異なる場合は連結列の値で条件判断をしてあげる必要があります。「特別」や「通常」が直接テーブルに保存される値ならそのままで大丈夫です
追加で試された「
=Count(IIf([txt価格]="1,000",1))
」は「=Count(IIf([価格]=1000,1))
」のような形なら動くと思いますあ・・わかりました、
上記SQLをcbo年月に入れて、下記をVBAに入れています。
これが、②に対応できていないんですね・・もう少し考えてみます。
Private Sub cbo年月_Click()
DoCmd.SetFilter "", "[年月] Like [Forms]![F_案件]![cbo年月]", ""
End Sub
テキストボックスに上記式を入れたのですが、「#エラー」と表示されます。
ためしに「=Count(IIf([txt価格]="1,000",1))」など、他のフィールドでも試してみたのですが、「#エラー」と出ました…。何か原因になりうるものがありますでしょうか。
こちらの件、ずっと解決できず課題になっていました。
下記sqlを作ったのですが、うまくいきません…なぜでしょうか…
①元のデータが降順にならない。
②すべてが表示されない。
SELECT DISTINCT T_案件.年月
FROM T_案件
ORDER BY T_案件.年月 DESC
UNION
SELECT "(すべて)" AS 案件NO FROM T_案件;
ありがとうございます!のちほど試してみます!
どのように表示したいですか?
フォームで見えてる分だけで集計したいならCount()関数で
Count()関数は、指定したフィールドの「Null」のデータをカウントしないのでIIf()関数を使って数えたいものだけデータを出力するようにすればそれぞれで件数を出すことはできます
ex)
大変参考になりました。クエリの件も、見直してみたいと思います。ありがとうございました。
人それぞれの考え方があると思いますが、私は結合するフィールド同士は同じ名前にしています。
クエリにするとき、通常は、一対多の関係のテーブルを結合しますが、クエリに表示させるのは、多側のフィールドにします。
それを両方表示させたり、* で全フィールドを表示させたりすると、同じ名前のフィールドが存在するので、コントロールソースなどで参照するとエラーになります。
ですので、両方表示させることがないように設計すれば問題ないです。
もし、両方表示させる必要がある場合(通常はないですが)は、片方のフィールドに別名を付ければ問題ないです。
ということなら、hirotontさんも言われてますか、そもそも分ける必要がないと思います。
その統一された書式でテーブルを作成して(両方に必要なフィールドをすべて持たせる)、そこに入力していけばいいのでは。
あとは、運転日報かどうかを識別するフィールド(Yes/No型)を追加して、運転日報のみ必要な時に、そのフィールドで抽出をかければいいだけです。