Private Sub M_CMB_AfterUpdate()
Dim strFilter
If Not IsNull(Me!M_CMB) Then
strFilter = "個人ID=" & Me!M_CMB
End If
Me!F_個人別.Form.Filter = strFilter
Me!F_個人別.Form.FilterOn = True
End Sub
Private Sub M_CMB_AfterUpdate()
[Forms]![基礎情報編集]![M-CMB].Requery
sqlstr="SELECT * " &・・・
Me.F_個人別.Form.RecordSource = sqlStr
Me.F_個人別.Form.Requery
end sub
謎の数字「6」はLen(" And ") + 1で求められる数値です。(「And」の前後に空白スペースが入っています)
条件が複数選ばれると前後の条件を" And "でつなぐことになりますが、そのままコードにするならば、条件追加の時にはすでに条件があるかどうかをチェックするということになります
ex)前提条件を考えた検索条件の追加コードの一部
'-------------------------------------分類---------------------
If Not IsNull(大分類) Then
If myStr <> "" Then myStr = myStr & " And " '初めての条件でなければ" And "でつなぐ
myStr = myStr & "大分類 Like '" & 大分類.Value & "'"
End If
If Not IsNull(中分類) Then
If myStr <> "" Then myStr = myStr & " And " '初めての条件でなければ" And "でつなぐ
myStr = myStr & "中分類 Like '" & 中分類.Value & "'"
End If
If Not IsNull(小分類) Then
If myStr <> "" Then myStr = myStr & " And " '初めての条件でなければ" And "でつなぐ
myStr = myStr & "小分類 Like '" & 小分類.Value & "'"
End If
:
DoCmd.OpenForm "F_周知", , , myStr
:
何回も同じことをしているIfが出てきて手間だし読みにくいですね
そこで、最初かどうかにかかわらず、条件にはすべて先頭に" And "をつけておこう、処理の最後に先頭の" And "を削除するようにしようというのがMid(myStr, 6)です
ACCESSを扱うなら非常に行儀が悪いですね。危惧している通りいろいろ問題が起きます。
まずはしっかりACCESSの作法を覚えるべきで、応用はその上に成り立つものでしょう
フォーム(サブフォーム)に必要とするすべてのデータを表示することができたら、フィルタープロパティを使ってデータの絞り込みができます。
サブフォームにはレコードソースを設定しておいて、親フォームのM_CMBの更新後イベントを次のようにします
たびたびすいません、もう一点。
レコードソースについてなのですが、少し他の人に以前教えていただいたところ、VBAの中で
Private Sub M_CMB_AfterUpdate()
[Forms]![基礎情報編集]![M-CMB].Requery
sqlstr="SELECT * " &・・・
Me.F_個人別.Form.RecordSource = sqlStr
Me.F_個人別.Form.Requery
end sub
で、サブフォームのレコードセットは適当でも、これで書き換わるからいいと教えられました。
確かにこれでサブフォームのレコードセットは書き換わってうまく動作はするのですが・・・
だったら、最初からマクロに書かないで、レコードセットの所に直接書けば動くのでは?、と思い書くと動きませんでした。
こういう場合、このようなやり方は一般的なのでしょうか?
後からこのDBのフォームを見た人は、レコードセットがないと勘違いしてしまいそうで怖いです。
ちなみに、とりあえずの最終形態として考えているは、
個人別サブフォームを帳票フォームにして、
M_CMBを1に切り替えると、
Aさん ○○障害
Aさん ××障害
Aさん △△障害
そして、2に切り替えると、帳票フィールドの行数も動的に変化し
Bさん ××障害
Bさん △△障害
といった形に持って行きたいと思っています。
今は。帳票フォームの行が全部AさんやBさんになっているので、そこからまた頭を使って考えなければなりません(^^;
早々なご対応、誠にありがとうございます。
一番の問題は私自身の知識不足です。
エクセルからのAccessへの移行なので、その辺の知識が完全に欠落しております。
「関数に間違いない変数を渡してるんだから、計算して当然」
という思い込みがありました。
私もレコードセットは疑って、色々試したんですが、とりあえず、クエリ1でいいのかなと思って当てたものの、うまくいかず(エラーのまま)、であれば、SQL分でSelect・・・で書いたものはどうか、と色々試しては見たんですが結果が同じでしたので、そのまま非連結の状態でお渡ししてしまったという経緯です。
やはり、一番望ましいのは、
>リンクフィールドが設定されていないために、自動で再読み込みが発生しないのが原因だと思われます。
これを回避するために、リンクフィールドをきちんと設定してあげて、自動で再読み込みさせるのが理想です。
もしよろしければ教えていただきたいのですが、このような場合、どのようなレコードソースを設定してあげるのがよろしいのでしょうか。
ご教授いただけると助かります。
送信ありがとうございました。
ファイルは私のところにメールで届いています。
自動でダウンロードできるようにはなってません。
ファイルを見てみました。
原因はメインフォームで個人IDを変更したときに、サブフォームで再クエリか再読み込みか再計算をしないと変更が反映されないようです。
コンボボックス「M_CMB」の更新後処理のイベントプロシージャで再読み込みをしたらエラーなく表示されて、更新するとサブフォームの値も更新されました。
下記が修正済みのファイルです。
ZIPファイル
ただ、サブフォームが非連結(レコードソースが空欄)で、リンクフィールドが設定されていないために、自動で再読み込みが発生しないのが原因だと思われます。
通常、サブフォームはテーブルかクエリに連結させて、リンクフィールドを設定すると思います。そうすれば、リンクフィールドを更新すればサブフォームも再読み込みされます。
現状の非連結のサブフォームは、サブフォームにする必然性があるようには思えません。
最終的にどのようなものを考えているのでしょうか。
こんばんわ、ろでますです。
お手数おかけしますm(_ _)m
ファイルの方送付させていただきました・・・
が、この掲示板ではどこでアップしたファイルがダウンロードできるようになっているのでしょう。
手順を間違えたでしょうか(汗
これで、
フォーム名、コンボボックス名に間違いがないとすると、
外から原因を特定するのは難しそうです。
症状の再現できるなるべくシンプルなファイルを、右カラムのファイル送信フォームから送ってもらえませんか。
そうすれば、現物をみて原因を特定できるかもしれません。
>=[Forms]![基礎情報編集]![M_CMB]
>としたときは、正しい個人IDが表示されますか。
テキストボックスの値は真っ白でした・・・
全く値が取れていないようですね・・・。
>=[Parent]![テキストボックス名]
同じく、
「#エラー」
となりました・・・><
VBAとかで細かく値の受け渡し状況を確認する方法とかあれば・・・
=[Forms]![基礎情報編集]![M_CMB]
としたときは、正しい個人IDが表示されますか。
ということなら、このテキストボックスは非表示で配置しておいて、サブフォームのテキストボックスのコントロールソースを下記のように設定してみたらどうなりますか。
=[Parent]![テキストボックス名]
こんにちわ、ろでますです。
フォーム名が間違っているということはないと思います。
一度フォームを組み立てなおしても、同じエラーが出て、かなり困っています。
・メインフォーム名=基礎情報編集
・コンボボックスの名前=M_CMB
・クエリ名=クエリ1
メインフォーム上で
=DLookUp("氏名","クエリ1","個人ID=" & [M_CMB])
では、テキストボックスに「Aさん」が入ってくれますが
サブフォームに
=DLookUp("氏名","クエリ1","個人ID=" & [Forms]![基礎情報編集]![M_CMB])
と入れると
「#エラー」
となります。
何処がおかしいのか、以下の様にしたら、Aさんが取れました。
=DLookUp("氏名","クエリ1","個人ID=" & 1)
同様に以下の様にしたら、Bさんがとれました。
=DLookUp("氏名","クエリ1","個人ID=" & 2)
つまり、Dlookup関数の構文は間違っていないけども、M_CMBの値がちゃんと取れていないようです。
フォーム名等も、式ビルダーを使って、タブキーを押しながら選んでいったので、間違いはないと思います。
すいません、よろしければ、サブフォームに引き渡されているM_CMBの値を見る方法はありませんか。
よろしくお願い申し上げます。
Mid(myStr, 6)
はMid()関数を使った複数の中からいくつかを選ぶときに使うよくある手法ですね。これをそうだと解説しているのはあまり見ない気がします。謎の数字「6」は
Len(" And ") + 1
で求められる数値です。(「And」の前後に空白スペースが入っています)条件が複数選ばれると前後の条件を" And "でつなぐことになりますが、そのままコードにするならば、条件追加の時にはすでに条件があるかどうかをチェックするということになります
ex)前提条件を考えた検索条件の追加コードの一部
何回も同じことをしているIfが出てきて手間だし読みにくいですね
そこで、最初かどうかにかかわらず、条件にはすべて先頭に" And "をつけておこう、処理の最後に先頭の" And "を削除するようにしようというのが
Mid(myStr, 6)
ですいつもご丁寧ありがとうございます。
ヘルプを熟読します。
ありがとうございました。
コードの意味が分からないときは、まずはヘルプを参照しましょう。
OpenForm をクリックしてカーソルを置いてF1キーを押すとヘルプページが表示されます。下記のページです。
DoCmd.OpenForm メソッド (Access) | Microsoft Docs
上記の構文をみると4番目のパラメータ(引数)は WhereCondition です。
この下のほうにそれぞれのパラメータの役割が説明してあります。WhereConditionの説明は下記です。
ちょっと遠回りな説明ですが、抽出条件式を文字列として設定するということです。
Mid(myStr, 6) の部分は、やはりMidにカーソルを置いてF1キーを押してヘルプを表示させます。「キーワード」というページが表示されました。下の方にスクロールしていくと「Mid 関数」というリンクがありますのでそれをクリックします。下記のページか表示されます。(ダイレクトにこのページにいけないところがちょっち使いづらいですね。)
Mid 関数 (Visual Basic for Applications) | Microsoft Docs
これを読めば、Mid(myStr, 6) は myStrに格納されている文字列の6桁目以降を取り出しているとわかります。
上の方のコードで myStr変数に条件式を格納しているのですが、" And 条件式" というように前に不要な" And "が付いているので、それを削除しているのです。
分からないコードがあったらこんな感じで調べてみてください。F1でのヘルプは結構目的のページにたどり着けない場合もあります。その場合は「VBA 分からないコード」というようなキーワードで調べればたいてい解説ページにたどり着けます。
フォーム名が間違っているくらいしかなさそうですが、「基礎情報編集2」はフォーム名で合ってますか?(フォームのプロパティの「標題」ではないですよね?)
前回のテーブルと今回のテーブルの2つがあるなら、
変更があったレコードの抽出は、クエリウィザードの不一致クエリウィザードを使って作成してみてください。
新たに追加されたレコードの抽出は、
今回のテーブルと前回のテーブルを外部結合して、前回の主キーフィールドがNullのレコードを抽出すればいいでしょう。
hatenaさん
お返事ありがとうございます。
もう少し具体的に整理してから、もう一度ここに書き込みします!
まずは、そのようなことができるのかを知りたかったのです。
整理してきます。
素晴らしいです。
同じ宛名印刷システムでもお歳暮用になると上級編なのですね。自力では挫折していたと思います。
まだ半分位しか理解出来ていないので勉強します。
1から10までありがとうございました。
m(_ _)m
提示のコードだと、構文エラーで実行すらできません。実際のコードを提示してください。
「MT_単価」テーブルのフィールド構成、主キー設定、データ例を提示してください。
これはテーブルにデータ化されているモノですか?
そうですよね。私の記憶でもできたような気がしていたのですが、当方の2019で確認したら反映されないので、動作が変わったのかも知れませんね。
他にも、動作が変わっている部分があるような気がします。
例えば、コンボボックスのフォーカス取得時で、自身を再クエリするというコードで以前は問題なかったとおもったのですが、2019だと▼ボタンをクリックしても1回ではリストが開かないという現象が発生しています。
ご確認ありがとうございます。最大で4人に設定する予定でした。
こちらACCESS2013ですが「リスト項目の編集」で既定値を設定すると「規定値」プロパティにちゃんと反映されるようでした。仕様ってことはなさそうです
「複数の担当者が関わっている」とのことですが、最大何人ぐらいの担当者になりますか。
テーブルに担当者1、担当者2、担当者3 というようにフィールドがあるのなら、そのフィールド数分のコンボボックスを作成して、それに重なるようにコンボボックス(またはテキストボックス)を配置して、各コントロールを以前の回答にように設定すればいいかと思いますが、どのあたりがうまくいきませんか。
システムとはどこにあるどのようなデータですか。
それをどのように抽出してますか。
前回のデータと今回のデータとは具体的にどのようなものですか。
前回のテーブルと今回のテーブルの2つのテーブルがあるのですか。
もしそうなら、それぞれのテーブルの名前、フィールド名、主キー設定を提示してください。
以前のレコードと新たに追加されたレコードの区別はどのようにつけるのですか。
今回のテーブルで前回のテーブルにないレコードが新たに追加されたレコードということですか。
具体的にどのような形で表示したいのですか。
前回のデータと今回のデータの両方を表示しますか。
上記の点を含めてもう少し具体的に情報を提供してください。
そのうえで現状はどこまでできていて、どの辺で躓いているか具体的に説明してください。
送付していただいたファイルを改良しました。
下記のリンクからダウンロードできます。
定形外宛名ラベル作成.zip
いろいろ変更しましたので、自身のファイルと比べてどこが変更されたか確認してください。
主な変更点は、
レポートは、
レコードソースのクエリの結合を変更してます(前回の回答の内容)。
テキストボックスの名前がフィールド名と同じものになっていたので、それが原因でエラーとなってましたので、
テキストボックスの名前を変更してます。
フォームでは、VBAを変更しました。
最初の回答の cb受取人ID のフォーカス取得時のイベントプロシージャで再クエリする方法だと、一回のクリックでリストが開かないので、
レコード移動時と、cb発注者IDの更新後処理で再クエリするようにしました。
御親切にありがとうございます。ファイルを送信しました。よろしくおねがいします
いろいろ間違いでご迷惑をおかけしました。
修正部分はそれで問題ないと思います。
レポートのレコードソース用のクエリの結合が間違ってます。
T_発注者 と T_発注者の顧客 は結合しませんのて、結合線を削除してください。
T_受注.受取人ID と T_発注者の顧客.発注者の顧客ID を結合してください。
結合線をダブルクリックして、結合プロパティを表示させて、「T_受注のすべてのレコードと・・・・」というオプションを選択します。結合線が T_受注.受取人ID → T_発注者の顧客.発注者の顧客ID という向きの矢印になります。
同様に、T_受注とT_発注者の結合線も 同じ向きに矢印になるように設定してください。
全体としては結構複雑なものになりますので、もし、差支えなければ右カラムの「ファイル送信フォーム」から現状のファイルを送信してもらえると、ファイルを見ながら具体的におかしいところを指摘できるとおもいます。
細かく説明していただきありがとうございました
レポートがうまくいかなかったので見ていただけませんでしょうか
ただし誤植と思われる個所◆は以下のように変更しています
T_発注者の顧客
発注者の顧客ID 主キー
発注者ID
発注者の顧客 ◆削除
発注者の顧客氏名
発注者の顧客 ◆削除
発注者の顧客住所
T_受注
受注ID 主キー オートナンバー型
受注日 ◆削除
発注者ID (T_発注者 の外部キー)
歳暮用 Yes/No型
受取人欄ID (T_発注者の顧客 の外部キー) ◆欄を削除
受取人選択用のコンボボックス
名前 cb受取人ID
コントロールソース 受取人ID
値集合ソース SELECT * FROM T_発注者の顧客 WHERE 発注者ID=cb発注者ID;
列数 3 ◆変更
列幅 0cm;0cm;1cm ◆変更
差出人欄(受取人欄の誤植ですよね)の氏名テキストボックスのコントロールソースを
=IIf([歳暮用]=True,[発注者の顧客氏名],[発注者氏名])
住所テキストボックスは、
=IIf([歳暮用]=True,[[発注者の顧客住所],[発注者住所]) ◆[が多い
ありがとうございます。難しそうですがチャレンジしてみます
Accessで入力フォームを作成することをお勧めします。
いろいろ方法はありますが、とりあえず2つの方法を提案しておきます。
案1 帳票フォームまたはデータシートフォームで入力する。
見た目は、エクセルと似たものになります。
日付はVBAでフォームの更新前処理で、既定値を入力値に設定すれば、新規レコードへ移動したときに前に入力した日付が既定値として表示されます。
上書きすれば,次からその値が規定値になります。
案2 メイン/サブフォーム形式の入力フォームを使う
非連結のメインフォームに日付入力用のテキストボックスを配置して、
テーブルと連結した帳票フォームをサブフォームとして埋め込みます。
サブフォームコントロールのプロパティを下記のように設定すれば、メインフォームの日付テキストボックスに入力した値がサブフォームに表示され、新規レコードもその日付が規定値となります。
リンク親フィールド 日付テキストボックス名
リンク子フィールド 日付フィールド名
この場合、親フォームで日付を入力するとその日付の入力済みのデータがサブフォームに表示されますので入力済みの日付のデータ修正なども楽になります。
以下、蛇足ですが、Accessはデータベースですので、Excelと同じような発想でテーブルを設計するとたいていうまくいきません。データベースのテーブル設計の原則として「正規化」というものがあります。
テーブル設計をする前に「データベース 正規化」をキーワードにWEB検索して、設計の基本を簡単に理解しておくことをお勧めます。
バグなんですかね?
プロパティに直接書き込みます
ありがとうございました
レポートの設定は下記のようになります。
まず、レコードソース用のクエリを作成します。
クエリで、T_受注、T_発注者、T_発注者の顧客 を追加して、
T_受注の外部キーと他のテーブルの主キーとを結合します。
レポートに必要なフィールドを追加します。
これをレポートのレコードソースにします。
レポート上の差出人欄の氏名テキストボックスのコントロールソースを下記のように設定します。
=IIf([歳暮用]=True,[発注者氏名],"当店の名前")
住所テキストボックスは、
=IIf([歳暮用]=True,[発注者住所],"当店の住所")
差出人欄の氏名テキストボックスのコントロールソースを
=IIf([歳暮用]=True,[発注者の顧客氏名],[発注者氏名])
住所テキストボックスは、
=IIf([歳暮用]=True,[[発注者の顧客住所],[発注者住所])
以上です。
下記のような感じのテーブル設計になると思います。(一例です)
T_発注者
発注者ID 主キー
発注者氏名
発注者住所
T_発注者の顧客
発注者の顧客ID 主キー
発注者ID
発注者の顧客
発注者の顧客氏名
発注者の顧客
発注者の顧客住所
T_受注
受注ID 主キー オートナンバー型
受注日
発注者ID (T_発注者 の外部キー)
歳暮用 Yes/No型
受取人欄ID (T_発注者の顧客 の外部キー)
入力フォームは T_受注 をレコードソースとして作成します。
発注者選択用のコンボボックスを下記のように設定します。
名前 cb発注者ID
コントロールソース 発注者ID
値集合ソース T_発注者
列数 2
列幅 0
これで 氏名 で選択できます。
ちなみに下記の方法を使えば、ID でも 氏名 でも選択できるようにできます。
コードでも名称でも入力できるコンボボックス - hatena chips
「歳暮用」フィールドを配置すると自動でチェックボックスになります。
歳暮用の場合は、「歳暮用」にチェックをいれて、受取人選択用のコンボボックスで受取人を選択します。
受取人選択用のコンボボックスの設定は下記のようにします。
名前 cb受取人ID
コントロールソース 受取人ID
値集合ソース SELECT * FROM T_発注者の顧客 WHERE 発注者ID=cb発注者ID;
列数 2
列幅 0
これも氏名での選択でので、IDでも入力したい場合は上記のリンクを参考にしてください。
cb受取人ID のフォーカス取得時のイベントプロシージャを下記のように記述します。
以上が入力フォームです。
こちらの機能、複数ののフォームで利用しています。よく使う機能なので、教えてもらい本当に助かりました。ちなみに今、1つのレコード(帳票)で上記のコンボボックスを複数配置したいのですがどうしたら良いでしょうか…1つの案件に担当者を複数配置したくて、コンボボックスを複数配置したいのですが方法がわからず苦しんでいます
アドバイス、ありがとうございます!正規化、なかなか難しいですね。日々実践しながら勉強の日々です。
サブフォームのデザインビューで詳細セクションにコマンドボタンを配置して、そのクリック時のイベントプロシージャを下記のように記述すればいいでしょう。(コマンド1 は実際のコマンドボタン名に変更)
「削除しますか?」の確認メッセージを出したくないときは、
そういうことになります。
あるいは、フォームのレコードソースをクエリにして、クエリの演算フィールドに「単価*個数」というような式を設定します。フォームのコントロールソースにはその演算フィールド名を設定します。
レポートのレコードソースも同じクエリにすれば、同様に演算フィールド名をコントロールソースに設定できます。
確認してみましたが「リスト項目の編集」で既定値を設定しても反映されないみたいですね。
仕様なのか、バグなのか?
「標準」タグの方の「規定値」プロパティに「"有"」と設定してください。
おおむね、その理解でいいと思います。
具体的には「正規化」をキーワードでWEB検索してみてください。
厳密な設計方の解説がいろいろ見つかると思います。例えば下記のサイト。
正規化 カテゴリーの記事一覧 - もう一度学ぶMS-Access
完全に理解するのは簡単ではないですが、ざっと読んで雰囲気をつかんでおくいいでしょう。
クエリとフォームとレポートですね。
集計、抽出、データ分析などはクエリ、
データの入力、閲覧はフォーム、
データの出力、印刷はレポート、
というように使い分けます。
もちろんそれぞれを組み合わせより使いやすいものにすることも必要になります。
まずはクエリ、フォーム、レポートの機能を理解することが先決ですね。
それで不足する部分を改善したい、より高度の機能を追加したいというときにVBAとSQLを使用するという感じでしょうか。
フォームでと、コンボボックス、リストボックス、サブフォームの機能を理解して利用するとVBAなくてもかなり高度なことができます。
レポートはグループ化の機能を理解すると、見やすいレイアウトの出力が可能になります。
ご教示ありがとうございました。おかげで助かりました。
また、よろしくお願いいたします。