先日、コンボボックスで選んだデータを、もう一つのテキストボックスにも同時入力したい、という要望についてアドバイスを求めたものです。そのときは、コンボとテキストボックスをつなげばいい、と教えてもらいました。
今度は、1つのコンボボックスから、複数のテキストボックスに同時入力したい、という要望についてお尋ねします。競馬の話なんですが、日にちごとにレースのデータを並べて表示した帳票フォームがあります。その中に「天候」というコンボと、レース情報の天候に紐づいた天候というテキストボックスがあります。1日の間に天候は変わっていくので、レースごとに天候を設定したいのですが、一つ一つ設定するのはめんどくさいので、一つ「晴れ」と設定したら、テーブルの全部のレースの天候のところに「晴れ」を入力して保存したいと思ってます。これは更新クエリの出番だと思うのですが、
'Private Sub コンボ353_AfterUpdate()
'UPDATE public_stb_ra_time_shokin_5 INNER JOIN public_stb_ra_tpc_sabun ON public_stb_ra_time_shokin_5.race_id = public_stb_ra_tpc_sabun.race_id SET public_stb_ra_tpc_sabun.suitei_tenko = [Me]![form]![コンボ_353].[value]
'WHERE (((public_stb_ra_time_shokin_5.hizuke)=[Me]![開催日].[value]));
'Me.Refresh
'End Sub
と書いてもうまくできません。それともDAOで回すべきでしょうか? すいませんが教えて下さい。
VBAでクエリを動的に生成し実行する場合、「クエリを実行する」という命令を記述する必要があります。
DoCmd.RunSQL メソッド (Access)
Database.Execute メソッド (DAO)
※クエリ(SQL構文)そのものの正否は見ていません
「フォームに表示されている全データを更新したい」のであれば、フォームのレコードセットを更新していく方法もありだと思います
早速返信していただきありがとうございます。恥ずかしいですけど、アップした画像のようなフォームになっています。親フォームがF_T0指数評価用で、サブフォームが埋め込み47またはF_TP指数です。(サブフォームを指定するときはどっちを書いたらいいものかいつも迷いますが、記憶では埋め込み47を書くのが正しいのではないか、と)。親フォームにあるテキストボックスの[開催日]を見て、テーブルの該当箇所にコンボボックスの選択値=天気を入力しようと思ってます。が、できません。Formが見つかりません、というメッセージが出てきます。よろしくお願いします。
Private Sub コンボ351_AfterUpdate()
Dim SQL As String
SQL = "UPDATE public_stb_ra_time_shokin_5 INNER JOIN public_stb_ra_tpc_sabun ON public_stb_ra_time_shokin_5.race_id = public_stb_ra_tpc_sabun.race_id SET public_stb_ra_tpc_sabun.suitei_tenko = " & [Forms]![F_T0指数表示用]![埋め込み47]![Form]![コンボ351].[Value] & "WHERE (((public_stb_ra_time_shokin_5.hizuke) = " & [Forms]![F_T0指数表示用]![開催日].[Value] & "));"
CurrentDb.Execute SQL
Me.Refresh
End Sub
追伸 それとフォームのレコードセットを更新する方法のほうがよいのかもしれないですが、そっちの理屈はまったくわけがわからないです。
フォームのレコードセットはDAOレコードセットなので、下記あたりを参考に学習してください。
VBA DAO レコードセット 更新 - Google 検索
フォームのレコードセットについては、下記で詳しく解説しています。
フォームの Recordset, RecorsetClone, RecordSet.Clone の違いとは? - hatena chips
コンボ351 というのはサブフォームにあるのですよね。
ならば、hirotonさんが提案されたフォームのレコードセットを更新していく方法がいいと思いますよ。
更新クエリで、サブフォームに記述するコードなら、Me(サブフォーム自身) と Parent(親フォーム) を使えば、
ややこしい参照式を使う必要はないです。
ありがとうございます。フォームのレコードセットを更新していく方法で、見事できました。期待以上です。しかし、Hatenaさんの手にかかれば何でも魔法のように解決しちゃいますね。いつもありがとうございます。書いていただいたレコードセットについての記事も読んで勉強します。
あぁ、コードがめちゃくちゃでしたね。ごめんなさい
hatenaさんが正しいコード例を提示してくださっているのでそちらを参考にしてください
クエリを使うか、レコードセットを操作するかについては、フォームに読み込んだレコードを操作するのであれば、圧倒的にDAOによるレコードセットの操作のほうが楽だと思います
開いたフォームがすでにレコードセットを開いているので、よくあるレコードセットを扱うための魔法の言葉が不要で、
With
ステートメントの活用により余計な変数も不要になるのでフォームのレコードセットを操作する方法はいくつかあります。(hirotonの回答がめちゃくちゃなのも、これらを適当に組み合わせてしまっているからです)
DoCmd
によるフォームの操作ACCESSの機能を使ってフォームを見たまま操作する例です。見たまま、レコードを移動させながら操作するので、
suitei_tenko
もMeからの参照で現在のカレントレコードのフィールドの値を修正しますレコードセットの操作と異なり、レコードが無い場合の操作を行うとエラーが発生するので、それようの対策が必要です
「マクロ」で作る場合の理論をそのままVBAでコードにするとこんな感じでしょう
Me.Recordset
を操作表示しているフォームそのもののレコードを扱います。レコードセットのレコードを移動させると、フォーム上のレコードも移動するので、レコードの移動だけレコードセットを操作して、レコードの編集はフォーム上のコントロールを操作するとかいう訳の分からないコードを組むこともできます。(コードが短くなるだけで大したメリットはない)
Me.RecordsetClone
を操作フォームに読み込まれているレコードセットを直接操作します。ただし、表示中のレコードは移動しません。Meによる参照と、レコードセットからの参照で、参照しているレコードを別々に持つことになります
Me.Recordset.Clone
を操作(コードは省略)
全く同じレコードセットを新しく生成します
新規でレコードセットが生成されるので、常にレコードセットの先頭にカーソルがある状態のレコードセットになります。(
DoCmd.GoToRecord
やMoveFirst
のような、全件を操作するための準備がいらない)新規でレコードセットを生成しているので、閉じる処理(
Close
)が必要フォームとは関係ないレコードセットを操作するので、フォームに反映させる処理(
recalc
/refresh
/requery
)が必要何かを参照する場合は、「コードの実行場所」と「コードの実行場所から見た操作したい相手の場所」を常に意識することが大事です。
すべて無視して、ACCESS本体から見た「
Forms!~
」という記述も可能ですが、hatenaさん指摘のように、「コードの実行場所自身=>Me
」や、「サブフォームからみた親フォーム=>Me.Parent
」、「親フォームから見たサブフォーム=>Me![サブフォーム名].Form
」等の参照方法を覚えるとコードが簡素に記述できますまた、参照に用いる場合の
[]
使い方も覚えましょう。これは、基本的に「名前」を指定するときに用いる記号です。ACCESS本体が持つ機能(キーワード)に使うことはできませんたとえば、「天候」を保存するために用意したフィールド「
suitei_tenko
」を指定する場合に、[suitei_tenko]
等記述します。「フォームに読み込んだそれを参照する」ならのようになります
通常「
Me
」とは、コードを実行したオブジェクトを参照するキーワードで何かの名前ではありません。[Me]
と記述した場合、「Me
」と名前を付けた何か(フィールドとか、テキストボックスとか)を参照する記述となります。そのような「何か」が無ければ参照先が見つからないというエラーが発生しますまた、
[]
は省略可能な記述で、ACCESS上(フォームやレポート等)で記述すると自動で付加されますが、VBAで記述する場合は、なるべく省略したほうがコードがすっきりします「省略できない場合」もあるので、より深い知識が必要になったら調べてみると良いでしょう