今、「定食屋の売上」というAccessのデータベースがあります。
その中に「F_注文履歴」というフォームがあり、"カツ丼"や"親子丼"等のメニューが入っております。
このメニューは、手入力も可能なのですが。
別フォームから、情報を取得する仕組みを作りたいのです。
「F_注文履歴」フォーム内の「商品コード」という欄をダブルクリックしますと、「F_メニュー一覧」という別フォームが開くように、イベントプロシージャを設定しました。
そして開きました「F_メニュー一覧」フォームに「かつ丼」「とんかつ定食」等のメニューがありますので。
該当するメニューを選んで「選択」ボタンを押下すると。
そのメニューの情報が「F_注文履歴」フォーム内に記入されるという仕組みなのですが…「実行時エラー'2465':アプリケーション定義またはオブジェクト定義のエラーです。」が、出てきてしまいました。
「デバック」ボタンを押下すると、Visual Basicの画面に飛びます。
以下の「 Forms(Forms("F_メニュー一覧").OpenArgs).Form.txt商品コード.Value = menucode」という箇所で、エラーになっておりました。
---------------
Option Compare Database
Private Sub 選択_Click()
Const sub_choice As String = "選択_click"
Dim menucode As String '商品コード
menucode = Me.txt商品コード.Value
Forms(Forms("F_メニュー一覧").OpenArgs).Form.txt商品コード.Value = menucode
DoCmd.Close acForm, "F_メニュー一覧"
End Sub
---------------
何とかしフォームに記載されております「商品名」「商品コード」「単価」の3つの情報を、「F_注文履歴」フォームの方の「商品名」「商品コード」「単価」の方にズラリと、転記できるようにしたいのです。
イメージとしてはこちらの画像
https://f.hatena.ne.jp/moon-fondu/20200909134933
のような処理になります。
どのようにVBAのコードを修正しましたら、うまく転記処理ができるのか…。
実際のデータ等が入っているAccessのデータべースファイルはこちら
にアップしております。
お力添えいただけますと幸いです。
よろしくお願い致します<m(__)m>
Forms(Forms("F_メニュー一覧").OpenArgs).Form.txt商品コード.Value = menucode
を
Forms(Forms("F_メニュー一覧").OpenArgs).Form.商品コード.Value = menucode
txt商品コードの名前が違っていた、正しくは、商品コードでした。
下記、いつものデバッグ動画です。
https://youtu.be/efi6Tg4_Fns?t=317
>「デバック」ボタンを押下すると、Visual Basicの画面に飛びます。
>以下の「 Forms(Forms("F_メニュー一覧").OpenArgs).Form.txt商品コード.Value = menucode」という箇所で、エラーになっておりました。
エラーの時は、変数が正しく受け渡されているかを確認すると良いと思います。
Forms(Forms("F_メニュー一覧").OpenArgs).Form.txt商品コード.Value = menucode
なので、まずは、
Forms("F_メニュー一覧").OpenArgsが正しく渡っているかを確認するために、
黄色で止まった場所で
(※動画内ではコードをストップさせてしまいましたが止まっている場所でやるほうがいいです)
? Forms("F_メニュー一覧").OpenArgs
F_注文履歴
と、値がわたっていることが確認できます。
あとは、やりたいことが
Forms(呼び出し元親のフォーム名).Form.txt商品コード.Value = menucode
なので、
ア.この文法が合っているか?
イ.フィールド名、オブジェクト名が正しいか?
を確認してみる。
今回は、
txt商品コードの名前が違っていた、正しくは、商品コードでした。
みたいに、デバッグできると思います。
※※と、簡単に書いていますが、本人、動画内でもあたふたしてましたが・・・
https://youtu.be/efi6Tg4_Fns
↑動画の頭から見ると、笑ってしまうと思いますが・・・
デバック時の参考となれば幸いです。
Forms(Forms("F_メニュー一覧").OpenArgs).Form.txt商品コード.Value = menucode
を
Forms(Forms("F_メニュー一覧").OpenArgs).Form.商品コード.Value = menucode
txt商品コードの名前が違っていた、正しくは、商品コードでした。
下記、いつものデバッグ動画です。
https://youtu.be/efi6Tg4_Fns?t=317
>「デバック」ボタンを押下すると、Visual Basicの画面に飛びます。
>以下の「 Forms(Forms("F_メニュー一覧").OpenArgs).Form.txt商品コード.Value = menucode」という箇所で、エラーになっておりました。
エラーの時は、変数が正しく受け渡されているかを確認すると良いと思います。
Forms(Forms("F_メニュー一覧").OpenArgs).Form.txt商品コード.Value = menucode
なので、まずは、
Forms("F_メニュー一覧").OpenArgsが正しく渡っているかを確認するために、
黄色で止まった場所で
(※動画内ではコードをストップさせてしまいましたが止まっている場所でやるほうがいいです)
? Forms("F_メニュー一覧").OpenArgs
F_注文履歴
と、値がわたっていることが確認できます。
あとは、やりたいことが
Forms(呼び出し元親のフォーム名).Form.txt商品コード.Value = menucode
なので、
ア.この文法が合っているか?
イ.フィールド名、オブジェクト名が正しいか?
を確認してみる。
今回は、
txt商品コードの名前が違っていた、正しくは、商品コードでした。
みたいに、デバッグできると思います。
※※と、簡単に書いていますが、本人、動画内でもあたふたしてましたが・・・
https://youtu.be/efi6Tg4_Fns
↑動画の頭から見ると、笑ってしまうと思いますが・・・
デバック時の参考となれば幸いです。
ken3memoさんありがとうございます!確認しますね♪動画も勉強させていただきます!!
オブジェクト名とVBAの記載が不一致だったんですね…うっかりしておりました。
~~~~~~~~~~~~~~~~~~~~~
Option Explicit
Option Compare Database
Private Sub 選択_Click()
Const sub_choice As String = "選択_click"
Dim menucode As String '商品コード
menucode = Me.商品コード.Value
Forms(Forms("F_メニュー一覧").OpenArgs).Form.商品コード.Value = menucode
DoCmd.Close acForm, "F_メニュー一覧"
End Sub
~~~~~~~~~~~~~~~~~~~~~
で、動きました!
ありがとうございます。
ですがすみません、呼び出し元親のフォーム「F_注文一覧」が、なぜ、
Forms("F_メニュー一覧").OpenArgs
で、出てくるのか、まだピンときていない部分がありまして。
ken3memoさんに、
Forms(呼び出し元親のフォーム名).Form.txt商品コード.Value = menucode
と書いていただいたのですが。まだ疑問が残りまして。
OpenArgsプロパティは、本には、
-----------
引数を指定してフォームが開かれたとき、その引数の値を収納します。フォーム側では、このプロパティを参照して、渡された引数を取得します。
-----------
と書かれておりました。
Formsコレクションについては「フォーム名をキーとして、フォームオブジェクトを管理しています」「フォーム名を指定して、特定のフォームオブジェクトを取り出すことができます。」とありました。
Forms("F_メニュー一覧")
では、F_メニュー一覧というフォームオブジェクトを、取り出しているのだと思います。
それが、
Forms("F_メニュー一覧").OpenArgs
と、「.OpenArgs」が後ろに付くと、なぜ呼び出し元親フォームである「F_注文履歴」に、変化したのでしょうか…。
引数を指定して、とありましたが、引数とは今回の場合、どれを指しているのでしょうか。
度々お手数お掛け致しますが、ご教授いただけますと幸いです。
よろしくお願い致します<m(__)m>
ken3memoさんが既に回答されていますが、オブジェクト名が正しくないですね。
「txt商品コード」を「商品コード」にすれば正常に動作すると思います。
以降は質問の直接の回答ではないので余談になりますが・・・
フォームの名前をコード上に直書きするのはよくないですよ。
名前をダブルクオートで直書きするとオブジェクト名を変更したら参照しているすべてのコードを変更しないといけない。
また、他のフォーム上のコントロール名を直接参照するのも極力避けたほうがいい。
他のフォーム上のオブジェクトの詳細に依存した作りはメンテナンス性が下がるしバグの温床になる。
今回のように「txt商品コード」と「商品コード」に違いで動かないとかね。
Forms(Forms("F_メニュー一覧").OpenArgs).Form.txt商品コード.Value = menucode
なぜ自フォームの名前を"F_メニュー一覧"とハードコードしているのに、呼び出し元はOpenArgs渡しなのかなと思う。
いろんなフォームから”F_メニュー一覧”が呼ばれることを想定しているのかもしれないけど、呼び出し元フォームに"txt商品コード"という名前のオブジェクトが存在しなければいけないという縛りができるから、いろんなフォームから呼ばれるには汎用性を犠牲にするし。
本来ならメニュー一覧を呼び出したらフォームが商品コードを返してくれるか、呼ぶときに値をセットする場所を渡してメニュー一覧側でそこにセットしてもらうのがベスト。
とりあえず、”F_メニュー一覧”は”Me.Name”でいいのでは? そうすればフォーム名を変更しても常にMe.Nameのままでいい。
Forms(Forms(Me.Name).OpenArgs).Form.商品コード.Value = menucode
アレ? OpenArgsは自分のプロパティだから、Forms(Me.Name)すら必要ないのでは?
Forms(Me.OpenArgs).Form.商品コード.Value = menucode
でOKですよ。
っていうか、Forms("xxx")がFormオブジェクトを返すので、.Form.も余分ですね。
なので、Forms(Me.OpenArgs).商品コード.Value = menucode、だけで動きますよ。
それから常にモジュールの先頭で「Option Explicit」を宣言したほうがいいですよ。
変数名やオブジェクト名の打ち間違いによる挙動不審で悩まされる時間も減るでしょう。
ごろえもんさん、ありがとうございます。
~~~~~~~~~~~~~~~~~~~~~
Option Explicit
Option Compare Database
Private Sub 選択_Click()
Const sub_choice As String = "選択_click"
Dim menucode As String '商品コード
menucode = Me.商品コード.Value
Forms(Me.OpenArgs).商品コード.Value = menucode
DoCmd.Close acForm, "F_メニュー一覧"
End Sub
~~~~~~~~~~~~~~~~~~~~~
で、動きました!
直書きのリスク、意識してなかったです、確かにそうですよね。
しかしまだ、疑問が残っておりまして。
Forms("F_メニュー一覧").OpenArgs
が「F_注文履歴」になる理由も、未だに理解できていないのですが。
ごろえもんさんが言うForms("xxx")がFormオブジェクトを返す…ここで返される、取り出しているフォームは「F_メニュー一覧」の方かと思います。
「Forms(Me.」の部分だと認識しているのですが。
OpenArgsは自分のプロパティ…であるのでしたら、
Forms(Me.OpenArgs)
は、「F_メニュー一覧」の方から、何かを渡しているのだと思うのですが。
渡し先である「F_注文履歴」のテキストボックスについて、何も記述していないように見えるのですが。
それでも「F_注文履歴」にデータがしっかり入るのは、なぜなのでしょうか…すみません、コードがまだしっかり理解できておらず。
お手隙の時に再度、ご教授いただけますと幸いです。
よろしくお願い致します<m(__)m>
コメントより回答追加
Forms("F_メニュー一覧").OpenArgs
と、「.OpenArgs」が後ろに付くと、なぜ呼び出し元親フォームである「F_注文履歴」に、変化したのでしょうか…。
引数を指定して、とありましたが、引数とは今回の場合、どれを指しているのでしょうか。
ダブルクリック時のコード
OpenFormのパラメーターで渡していると思いますが・・・
Private Sub 商品コード_DblClick(Cancel As Integer)
DoCmd.OpenForm "F_メニュー一覧", , , , , , "F_注文履歴"
End Sub
で開くと、
開かれた一覧の方で
.OpenArgs を参照することで、
渡された"F_注文履歴"を取り出すことができます。
なので、
Forms(Forms("F_メニュー一覧").OpenArgs).Form.商品コード.Value = menucode
は
Forms("F_注文履歴").Form.商品コード.Value = menucode
となり、
無事に親フォーム・呼び出し元のフォームに値をセットできる。
そんな仕組みだと思います。
ダブルクリック(呼び出しもとで、セット先を指示したいので、)
FormOpen時のパラメーターとして、渡してあげる。
渡された方は、
.OpenArgs
で、値を取り出せる。
回答No2のごろえもんさんが書かれていますが、
自分のフォームなので
Forms("F_メニュー一覧").OpenArgs
は
Me.OpenArgs の方が、自分にOpen時に渡されたパラメーターってことで、コードも見やすいかも。
話を戻すと、
DoCmd.OpenForm
これのパラメーターで渡されていると思います。
https://docs.microsoft.com/ja-jp/office/vba/api/access.docmd.openform
OpenArgs 省略可能 バリアント型 文字列式。 この式は、フォームの OpenArgs プロパティを設定するために使用されます。 この設定は、Open イベント プロシージャなどのフォーム モジュールのコードで使用可能です。 OpenArgs プロパティは、マクロや式でも参照できます。
DoCmd.OpenForm "F_メニュー一覧", , , , , , "F_注文履歴"
↑の一番後ろで指定しています。
ken3memoさん、再度ご回答いただきまして、ありがとうございます。
OpenFormのパラメーターというのが理解できていなかったです。
本を読んで復習しました。
Docmd.OpenFormメソッド、
----------------
Docmd.OpenForm フォーム名,[ビュー],[フィルター名],[条件式],[入力モード],[ウィンドウモード],[フォーム引数]
----------------
と、記載がありました。
7つ目なので"F_注文履歴"が[フォーム引数]なのですね。
フォーム引数については、
----------------
フォームを開くときに、任意の値をフォームに渡すことができます。渡された値は、フォーム側でOpenArgsプロパティを使って確認することができます。
----------------
という説明がありました。
開かれたF_メニュー一覧でOpenArgsプロパティを使えば、どのフォームから呼び出されたかわかるのですね。
OpenFormメソッド、OpenArgsプロパティを理解した後で、
-----------------
Forms("F_注文履歴").Form.商品コード.Value = menucode
-----------------
を読みますと、確かに"F_注文履歴"フォームの商品コードの欄に、menucode、すなわちMe.商品コード.Valueの値を代入する、とまでわかりました。
それにより、F_メニュー一覧の商品コードが、F_注文履歴の商品コードに入るわけですね。
ごろえもんさんの、
-----------------
Forms(Me.OpenArgs).Form.商品コード.Value = menucode
-----------------
も、理解できたような気がします。
ありがとうございました。
ken3memoさんありがとうございます!確認しますね♪動画も勉強させていただきます!!
2020/09/19 23:29:56オブジェクト名とVBAの記載が不一致だったんですね…うっかりしておりました。
2020/09/23 14:13:36~~~~~~~~~~~~~~~~~~~~~
Option Explicit
Option Compare Database
Private Sub 選択_Click()
Const sub_choice As String = "選択_click"
Dim menucode As String '商品コード
menucode = Me.商品コード.Value
Forms(Forms("F_メニュー一覧").OpenArgs).Form.商品コード.Value = menucode
DoCmd.Close acForm, "F_メニュー一覧"
End Sub
~~~~~~~~~~~~~~~~~~~~~
で、動きました!
ありがとうございます。
ですがすみません、呼び出し元親のフォーム「F_注文一覧」が、なぜ、
Forms("F_メニュー一覧").OpenArgs
で、出てくるのか、まだピンときていない部分がありまして。
ken3memoさんに、
Forms(呼び出し元親のフォーム名).Form.txt商品コード.Value = menucode
と書いていただいたのですが。まだ疑問が残りまして。
OpenArgsプロパティは、本には、
-----------
引数を指定してフォームが開かれたとき、その引数の値を収納します。フォーム側では、このプロパティを参照して、渡された引数を取得します。
-----------
と書かれておりました。
Formsコレクションについては「フォーム名をキーとして、フォームオブジェクトを管理しています」「フォーム名を指定して、特定のフォームオブジェクトを取り出すことができます。」とありました。
Forms("F_メニュー一覧")
では、F_メニュー一覧というフォームオブジェクトを、取り出しているのだと思います。
それが、
Forms("F_メニュー一覧").OpenArgs
と、「.OpenArgs」が後ろに付くと、なぜ呼び出し元親フォームである「F_注文履歴」に、変化したのでしょうか…。
引数を指定して、とありましたが、引数とは今回の場合、どれを指しているのでしょうか。
度々お手数お掛け致しますが、ご教授いただけますと幸いです。
よろしくお願い致します<m(__)m>