- ベストアンサー
コンボボックス選択後のカーソル制御
- ACCESS2007のデータベースでコンボボックス1から選択後、カーソルをテキストボックス2に制御する方法をVBAで追加する必要があります。
- ACCESS2007のデータベースで、コンボボックス1から選択した後、カーソルがテキストボックス2に移動するようにするためには、VBAで特定の処理を追加する必要があります。
- ACCESS2007のデータベースで、コンボボックス1から選択した後、カーソルをテキストボックス2に移動させるためには、VBAで適切な処理を追加する必要があります。
- みんなの回答 (10)
- 専門家の回答
質問者が選んだベストアンサー
#7です > 必要なら考えてみますが・・・・ コンボボックスがレコード確定位置にあった場合でも、 動作すると思われるものに変更しました。 以下を1度メモ帳にコピーされ、★★★を実際のコンボボックス名に置換した後、 フォームのVBA部分に貼り付け、イベントが割り当てられていることを確認され、 実行してみてください。(確認用のフォームにて) Dim bEnter As Boolean Private Sub Form_Timer() Me.TimerInterval = 0 If (Me.ActiveControl Is Me.★★★) Then Me.★★★.SelStart = 0 End If End Sub Private Sub ★★★_GotFocus() bEnter = True End Sub Private Sub ★★★_KeyDown(KeyCode As Integer, Shift As Integer) On Error Resume Next Select Case KeyCode Case vbKeyReturn bEnter = Not bEnter If (bEnter) Then KeyCode = 0 Me.★★★.Text = Me.★★★.Text End If Case Else bEnter = False End Select End Sub Private Sub ★★★_AfterUpdate() bEnter = True Me.TimerInterval = 10 End Sub 使用しているイベントは、 フォームの「タイマ時」 コンボボックスの「フォーカス取得後」「キークリック時」「更新後処理」 になります。 Enter 1回目では、Enter を無効とし、更新の処理を発生させます。 Text に値を設定すると、一連の更新前/更新後等の処理を実行させることが出来ます。 リストに無いものが入力され、Enter されたら、 「リストにありません」というダイアログは出ませんが、リスト外入力は動きます。 (リスト外入力は動きますが、その処理を記述した一連の流れでは確認してません) (リスト外入力が呼ばれたらメッセージを出す、程度の確認です) その後、値を選ぶための Dropdown 表示になります。 構わず、さらに Enter すると、今度はダイアログも表示されます。 今回 Me.★★★.Text = Me.★★★.Text で発生するエラーは無視しました。(リストに無い時のエラー) その結果が上記の動きとなっています。 エラーを処理するように変更する等、使えるまでにはいろいろあると思います。 ※ 前にも記述していましたが、同じような処理をするコンボボックスが複数あるのなら、 上記処理部分をクラス化すれば、フォームへ記述する部分はスッキリすると思います。 必要であればクラス化の一例は提示できます。
その他の回答 (9)
- piroin654
- ベストアンサー率75% (692/917)
Private Sub コンボボックス1_AfterUpdate() 'データの処理、テキストボックス2へコピぺ Me!テキストボックス2 = Me!コンボボックス1 '先頭の選択 Me!コンボボックス1 = Me!コンボボックス1.ItemData(0) '上記の縛りを解除 Me!コンボボックス1.Undo '一旦どこかにフォーカスを移動 Me!テキストボックス1.SetFocus 'フォーカスを戻す Me!コンボボックス1.SetFocus End Sub
お礼
No.8にて解決いたしました。ここまでありがとうございました。
- DexMachina
- ベストアンサー率73% (1287/1744)
No.2・4のDexMachinaです。 > フィールド移動時の動作はどのように設定されていますでしょうか。 通常はデフォルトの「フィールド全体を選択」ですが、提示コードの 動作確認時はそちらの環境に合わせるため、「フィールドの先頭に 移動」を選択して行いました。 ただ、「Shift+Enter」ではなく「Enterで更新確定」だとすると、 確かに > テキストボックス2へカーソルが遷移してしまい、当初の目的の > コンボボックス1の先頭にカーソルがとどまるということは、実現 > できませんでした。 という動作になります(汗) ※前回のコードは、「Shift+Enterで更新確定(&レコード保存)」 を前提としていました。 このキー操作をした場合は、Enterキー単独時と違ってフィールド 移動が起きないので、結果としてご希望の動作になった(ように 見えた)ため、前回の回答となりました。 (興味がありましたら、前回のコードを記述した後「Shift+Enter」 のキー操作を実行してみてください) ですので、「Enterキーで同時に発生するコントロール移動」を前提 とすると、前回「別コントロールに移動していないか確認して」とした 代わりに、「コンボボックスへの強制移動」を追加すれば、ご希望の 動作になるかと思います。 'コンボボックスの更新後イベント Private Sub コンボボックス1_AfterUpdate() Me.TimerInterval = 10 End Sub 'フォームのタイマイベント Private Sub Form_Timer() Me.TimerInterval = 0 '【コントロールの強制移動】 コンボボックス.SetFocus コンボボックス1.SelLength = 0 コンボボックス1.SelStart = 0 End Sub なお、No.8ご指摘の「レコード移動を伴う」事例については、以下の ようにフォームの更新前イベントを使用することもできます。 (但し、「Alt+↓でリストを表示後、選択を確定せずに、今度はマウス に持ち替えて別レコードや別コントロールをクリック」とした場合でも、 強制的に元のコンボボックスの先頭にカーソルが移動しますが(汗)) ※上記はかなり特殊な操作と考え、シンプルさを優先しました。 'レコードの保存を一時的に禁止するためのフラグ '◆この行は、どのイベント処理のコードよりも前に記述してください◆ Private bHold As Boolean 'コンボボックスの更新後イベント Private Sub コンボボックス1_AfterUpdate() '【レコード移動を制限するためにフラグを立てる】 bHold = True Me.TimerInterval = 10 End Sub 'フォームのタイマイベント Private Sub Form_Timer() Me.TimerInterval = 0 '【レコード移動の制限を解除】 bHold = False コンボボックス1.SetFocus コンボボックス1.SelLength = 0 コンボボックス1.SelStart = 0 End Sub '【フォームの更新前イベント】 Private Sub Form_BeforeUpdate(Cancel As Integer) '【bHoldフラグが立っている場合(=コンボボックス更新直後)】 'レコードの更新を取り消す(=結果、同レコードに留まる) Cancel = bHold End Sub ・・・以上です。
お礼
No.8にて解決いたしました。ここまでありがとうございました。
- 30246kiku
- ベストアンサー率73% (370/504)
#5です > テキストボックス2へフォーカスも移したくない・・・・って場合、 この記述は、その前で記述した > ※ Enter した時には、一度テキストボックス2へフォーカスが移りますが、 > タイマ時でコンボボックス1へフォーカスを戻してます。 に対してのものになります。 3パターンのVBAを記述していましたが、2つ目のVBAでは、 テキストボックス1にフォーカスがある状態で、Enter だけを押下した 1回目、2回目、3回目の状況を記述していました。 > コンボボックス1ではなく、テキストボックス2へ遷移しました。 と > テキストボックス1でEnterを押下したときの動作は、 > 1回目のつぎが3回目でした。 とのことですが、私が動作確認した条件は以下の通りです。 ・「タブ移動順」は以下の順 テキストボックス1 → コンボボックス1 → テキストボックス2 ・全ての「タブストップ」は「はい」 また、コンボボックス1のイベント 「更新後処理」「フォーカス取得後」「キークリック時」「フォーカス喪失時」 の4つが、ちゃんと割り当てられているかデザインで確認してみてください。 (VBA部分をコピー&貼り付け後、イベントに割り当たっていない時が稀にあります) コンボボックス1のプロパティを表示して、該当イベント部分が [イベント プロシージャ] になっていることを確認してみてください。 [イベント プロシージャ] になっていない場合には、 [イベント プロシージャ] に変更後、右横の「・・・」ボタンをクリックして それ用に記述したVBA部分が表示されることを確認してください。 フォームの「タイマ時」もあわせて確認いただければと思います。 補足) 動きを言葉で説明してみると、(3パターンのVBAの真ん中(2つ目)のもの) コンボボックス1にフォーカスが入った時に、bEnter = False としておきます。 コンボボックス1で Enter を押下した時、変数 bEnter の値を反転させます。 キー入力がある間は bEnter = False にしておいて、 Enter の押下で bEnter = Not bEnter にしています。 ということは、bEnter = True となり、 フォーカス喪失時のパラメータ Cancel を True とします。 Cancel = True が設定されると、他へフォーカスが移ることを禁止(拒否)します。 その状態後、フォームのタイマ時で、フォーカスがコンボボックス1にあれば、 SelStart = 0 を設定します。(タイマ時が動くのは、変更した時だけです) 続けて、Enter 以外のキーはいじらないで Enter を押下すると、 bEnter = Not bEnter により、bEnter = False になり フォーカス喪失時の Cancel は False になり、フォーカス移動を禁止しません。 また、Alt+↓で表示している時、↓↑で移動し、Enter ではなく、Tab の場合は フォーカス移動を禁止することなく、テキストボックス2へ遷移するばずです。 その後タイマ時が動きますが、フォーカスがコンボボックス1に無いので何もしません。 なので、2回目が無いという事は、どこかのイベントが動いていない・・・・ と、考えられるのですが。 なお、コンボボックス1をマウス操作で選択した場合には、 フォーカスを移動する処理は動かないので、そのままタイマ時が動くだけです。 お手数ですが、その辺確認していただけないでしょうか。 PS. 3パターンのVBAのうち、1つ目の動作はどうでしたか 実際には、連結フォームでレコード確定の位置にコンボボックスがあったら、 Enter で他にフォーカスが移ってしまうと確定動作が起きた・・・と思うので フォーカスを動かさない方法を2つ目/3つ目で書いていました。 (#5を記述した時にはレコード確定位置には置いていなかった【未確認で想像】) そう思っていたのですが、あの後確認していたら、フォーカスに関係なく Enter なら レコードが確定されてました。(2つ目/3つ目でもタイマ時が動いた時にはもう・・・・) ということで、 コンボボックスがレコード確定位置になければ、1つ目で良さそうな気もします。 (Tabキーでの選択でも、コンボボックス1へ戻ります) コンボボックスがレコード確定位置にあれば、また別の方法を考える必要がある、 ということがわかりました。 必要なら考えてみますが・・・・ 追加) > フィールド移動時の動作はどのように設定されていますでしょうか。 > 私は現在”フィールドの先頭に移動”に設定しています。 基本的にいじってなかったと思うので「フィールド全体を選択」のまま使ってます。 また、操作の主をマウスにしているので、どちらでも違和感が無い様な気がします。 「フィールドの先頭に移動」でも、テキストボックス等についているラベルをクリックすれば全選択(反転表示)されるし・・・ また、操作がキーボード主体で、修正/更新が多いのであれば、移動した時、 全選択(反転表示)されていた方が楽? 逆に、簡単に修正/更新させたくなければ・・・・ この設定は1つのフォームだけではなく、全体になると思うので、 操作面を主(後は見栄えとかも考慮?)に、検討されたらと思います。
- piroin654
- ベストアンサー率75% (692/917)
No3の回答が更新前処理になっていました。 一応、以下に修正。 Private Sub コンボボックス1_AfterUpdate() Me.テキストボックス2 = コンボボックス1 End Sub Private Sub コンボボックス1_Enter() Me.コンボボックス1.Dropdown End Sub Private Sub テキストボックス1_Enter() Me!コンボボックス1 = Me!コンボボックス1.ItemData(0) End Sub 選んだコンボボックスのデータの行き場を テキストボックス2にしています。
補足
皆さま、ご回答ありがとうございます。質問者のbicbicayaです。 皆さまの、ACCESS2007のオプションの詳細設定では、 フィールド移動時の動作はどのように設定されていますでしょうか。 私は現在”フィールドの先頭に移動”に設定しています。 この設定を変えた方が良い場合は、ご教示いただけますと幸いです。
- 30246kiku
- ベストアンサー率73% (370/504)
ご質問から2週間経っていますが、既に解決されてましたでしょうか。 不要なら、スルーしてください。 ご希望は、コンボボックスを操作した後、 ・フォーカスはコンボボックスから動かない ・表示は反転表示ではなく、カーソルは先頭に という事になりますか? > Accessのバグ…考え付きもしませんでした。 バグがゴロゴロあるとは思ってないので、仕様と考えた方が良いのでは。 (2003/2007でも同じ動きみたいなので) 更新前/更新後/Click 等の一連の処理の後で、コンボボックスの実データを元に、 何列目を表示して・・・云々後処理をしているのでは・・・ なので、その処理前に表示に関して変更しても反映されないのでは・・・と ヘルプには、こんなの書いてないですね。(私の推測なので当然ですが) ・注意書きがないからできると考えるのか、 ・できるとは書いていないと考えるか、 ・できない=バグと考えるか、 ・・・・ できない=バグとするのは、簡単であきらめやすいと思いますが・・・・・・ バグならバグで、代替えがあっても良いように思います。 > キーボード操作では実現が難しいということが分かってすっきりしました。 以下を試してみてください。 フォームの「タイマ時」を利用し、一連の処理+後処理後に処理させます。 Private Sub Form_Timer() Me.TimerInterval = 0 With Me.コンボボックス1 .SetFocus .SelStart = 0 ' .SelLength = 0 End With End Sub Private Sub コンボボックス1_AfterUpdate() Me.TimerInterval = 10 End Sub ※ SelStart を設定すると、SelLength は 0 になるようです。(ヘルプにもあります) ※ Enter した時には、一度テキストボックス2へフォーカスが移りますが、 タイマ時でコンボボックス1へフォーカスを戻してます。 テキストボックス2へフォーカスも移したくない・・・・って場合、 操作方法が若干変わりますが、以下のようなものもあります。(一例) Dim bEnter As Boolean Private Sub Form_Timer() Me.TimerInterval = 0 If (Me.ActiveControl Is Me.コンボボックス1) Then Me.コンボボックス1.SelStart = 0 End If End Sub Private Sub コンボボックス1_GotFocus() bEnter = False End Sub Private Sub コンボボックス1_KeyDown(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case vbKeyReturn bEnter = Not bEnter Case Else bEnter = False End Select End Sub Private Sub コンボボックス1_AfterUpdate() Me.TimerInterval = 10 End Sub Private Sub コンボボックス1_Exit(Cancel As Integer) Cancel = bEnter End Sub ※ テキストボックス1にフォーカスがあるものとして、Enter を押下していくと 1回目:コンボボックス1へフォーカス移動 2回目:コンボボックス1の内容が反転表示 ★★★ 3回目:テキストボックス2へフォーカス移動 ★★★ 部分の操作が追加されます コンボボックス1で Enter を1回余分に押下しないと次に行きません。 ただ、2回目の Enter では、反転表示されるので、修正するには楽と思います。 Enter だけを見ているので、Tabキー等での移動は自由に行えます。 いやいや、★★★部分はいらない・・・であれば、以下のように改造してみるとか Dim bEnter As Boolean Dim bEdit As Boolean Private Sub Form_Timer() Me.TimerInterval = 0 If (Me.ActiveControl Is Me.コンボボックス1) Then Me.コンボボックス1.SelStart = 0 bEdit = False End If End Sub Private Sub コンボボックス1_GotFocus() bEnter = False bEdit = False End Sub Private Sub コンボボックス1_KeyDown(KeyCode As Integer, Shift As Integer) Select Case KeyCode Case vbKeyReturn bEnter = Not bEnter Case Else bEnter = False End Select End Sub Private Sub コンボボックス1_AfterUpdate() bEdit = True Me.TimerInterval = 10 End Sub Private Sub コンボボックス1_Exit(Cancel As Integer) If (bEdit) Then Cancel = bEnter bEdit = False End Sub ※ 同じような処理をするコンボボックスが複数あるのなら、 上記処理部分をクラス化すれば、フォームへ記述する部分はスッキリすると思います。 ※※ 上記VBAでは、確認した際のコンボボックス名は英文字でしたが、 回答するにあたりメモ帳で置換しています。 そのまま動くのかは・・・ ※ コンボボックス選択=レコード確定はいかがなものかと思いますが
補足
30246kiku様、有難うございます。 テキストボックス2へフォーカスも移したくない・・・・って場合、 操作方法が若干変わりますが、以下のようなものもあります。(一例) を記述しましたが、コンボボックス1ではなく、テキストボックス2へ遷移しました。 テキストボックス1でEnterを押下したときの動作は、 1回目のつぎが3回目でした。
- DexMachina
- ベストアンサー率73% (1287/1744)
No.2のDexMachinaです。 > 普段Altボタン→Enterで確定という操作をしている 実はショートカット キーはあまり覚えていないのですが(汗)、 ひょっとして上記は「Shift + Enter」(=レコード保存)の 打ち間違いということでよろしいでしょうか。 http://office.microsoft.com/ja-jp/access-help/HP010091394.aspx (本文冒頭の右側にある「+すべて表示」をクリック後、 ブラウザ上の検索機能(Ctrl+F)で「Enter + Shift」で 検索) ともあれ、「Enter+α」で入力を確定させているとなると、 SendKeysでは確かに対応はできなさそうです(汗) 暫く考えた結果、別の方法を思いつきましたので、 併せてご紹介してみます。 なお、本来なら質問文でbicbicayaさんご自身が提示 されたように、更新後イベントで「SelStart+SelLength」 で対応するのが正しいはずの事例です。 それが、バグと思われる状況から使えないための「やむを 得ない回避策」ですので、残念ながらこれも手放しで お勧めできるものではありません(汗) ※戸惑われないよう、念のために触れておきますが、 No.3の方の回答は、今回のご質問の目的を取れて いないのではないかと思います。 'コンボボックス1の更新後イベント Private Sub コンボボックス1_AfterUpdate() 'フォームのタイマ時イベントを起動させるため、 'タイマ間隔を設定(ミリセカンド(ms)単位) Me.TimerInterval = 10 End Sub 'フォームのタイマ時イベント Private Sub Form_Timer() 'タイマ時イベントの無限ループを避けるための処理 Me.TimerInterval = 0 '別コントロールに移動していないか確認して処理実行 '(タイマなのでタイムラグを考慮) If Me.ActiveControl.Name = "コンボボックス1" Then コンボボックス1.SelLength = 0 コンボボックス1.SelStart = 0 '値の選択と同時にレコード保存をする場合は '以下も有効にします(=先頭の「'」を削除) 'RunCommand acCmdSaveRecord End If End Sub ・・・以上です。 懸念点としては、コード上のコメントにも書きましたが、 タイムラグの発生があることから、何らかの弊害を発生 する危険があることと、既にタイマ時イベントを使用して いる場合には、それとの整合を取らなければならない、 といったことが考えられます(汗)
補足
DexMachina様、有難うございます。 ご指摘の通り、 > 普段Altボタン→Enterで確定という操作をしている 実はショートカット キーはあまり覚えていないのですが(汗)、 ひょっとして上記は「Shift + Enter」(=レコード保存)の 打ち間違いということでよろしいでしょうか。 http://office.microsoft.com/ja-jp/access-help/HP010091394.aspx (本文冒頭の右側にある「+すべて表示」をクリック後、 ブラウザ上の検索機能(Ctrl+F)で「Enter + Shift」で 検索) の部分は 1)Alt+↓でプルダウン 2)↓で値を選択 3)Enterで確定 の入力ミスでした。申し訳ございません。 'コンボボックス1の更新後イベント 'フォームのタイマ時イベント を記述し試してみたのですが、テキストボックス2へカーソルが遷移してしまい、当初の目的のコンボボックス1の先頭にカーソルがとどまるということは、実現できませんでした。
- piroin654
- ベストアンサー率75% (692/917)
>リストの最初の選択肢しか選べなくなってしまいました。 単純にコンボボックスの項目を選択した後に 何をするのか何も書いていないので、単に コンボボックスを最初の項目に戻すだけの イベントを回答しただけです。 コンボボックスのどれかの項目を選択したら その項目の値をどうしたいのかによって 質問のイベントの記述箇所は変わって来ます。 たとえば、 Private Sub コンボボックス1_BeforeUpdate(Cancel As Integer) Me.テキストボックス2 = コンボボックス1 テキストボックス1.SetFocus End Sub Private Sub テキストボックス1_Enter() Me!コンボボックス1 = Me!コンボボックス1.ItemData(0) End Sub のようにすれば、コンボボックスで選択した値が テキストボックス2に表示され、 テキストボックス1にフォーカスが 移動したときにコンボボックス1の表示が最初の 項目に移動します。 Me!コンボボックス1.ItemData(0) はどこの時点でも設定できます。 質問の、 Private Sub コンボボックス1_AfterUpdate() テキストボックス1.SetFocus コンボボックス1.SetFocus With Me!コンボボックス1 .SelStart = 0 .SelLength = 0 End With End Sub では、 テキストボックス1.SetFocus で、 テキストボックス1にフォーカスを 移動していますが、テキストボックス2 はここではどのような扱いになっている のか何も書いてないのですが、一応 コンボボックスの値をテキストボックス2 に入れるように、テキストボックス1に フォーカスを戻すようにしています。
補足
piroin654様、お忙しいところ有難うございます。 テキストボックス1、コンボボックス1、テキストボックス2が上から順に並んでいます。 コンボボックス1にのみ、右端に下向きの青矢印が付いている状態です。 青矢印で表示される選択肢を、コンボボックス1に表示(入力)したいと思っています。
- DexMachina
- ベストアンサー率73% (1287/1744)
正直なところ、お勧めしかねる手段ではあるのですが(汗)(*1)、一応、 下記で概ね(*2)ご希望通りと思われる動作になることを確認しました: Private Sub コンボボックス1_AfterUpdate() 'F2キーで末尾にカーソルを移動後、 'Homeキーで先頭に移動 SendKeys "{F2}{Home}", False End Sub *1: SendKeys(キー送信)は、ユーザーのキーボード操作を模したものの ため、動作に不安定なところがあります。 (一時的にキーボード操作を受け付けなくなったりするのと同じような イメージ?) また、ユーザーがShiftキーなどを押しっぱなしにしていた場合は、「F2」 を送信するはずが「Shift+F2」になってしまいます。 *2: ドロップダウンリストからのマウスによる選択時は、ご希望の動作に なりますが、キーボードから手入力した場合は、次のコントロールに 移動するのに、Enterキー(またはTabキー)の入力が1回余計に 必要になってしまいます。 (更新が確定された時点で、同コンボボックスの先頭にカーソル が移動させられてしまう、と) ・・・bicbicayaさんが提示されたコードでご希望の動作にならないのは、 Accessのバグ(もしくはいわゆる「仕様」?)かもしれません(汗) (更新前後のSelStart等の値を、Debug.Printで確認してみましたが、 値としては更新されているのに反して、画面上はそうなっていない、 という状況でした) ※コード上に「Debug.Print Me.Name」等と記述すると、Ctrl+Gで表示 される「 イミディエイト ウィンドウ」に、「Me.Name」の内容等が 記録されます。 (既にご存知でしたらご容赦のほど・・・)
お礼
ありがとうございました。
補足
DexMachinaさん、ありがとうございました! Accessのバグ…考え付きもしませんでした。 Debug.Printでの確認方法も、勉強になりました。ありがとうございました。 上記コードで動作確認をしましたところ、ドロップダウンリストからのマウスによる選択時には希望通り動作しました。ただ、普段Altボタン→Enterで確定という操作をしているため、フォーム上で最も若いタブ順序のテキストボックスへカーソルが移動し、希望通りの動作にはなりませんでした。 キーボード操作では実現が難しいということが分かってすっきりしました。 どうも有り難うございました。
- piroin654
- ベストアンサー率75% (692/917)
i以下ではどうですか。 Private Sub コンボボックス1_AfterUpdate() Me!テキストボックス1.SetFocus Me!コンボボックス1 = Me!コンボボックス1.ItemData(0) End Sub
お礼
ありがとうございました。 リストの最初の選択肢しか選べなくなってしまいました。
お礼
ありがとうございました。素晴らしい回答者様に出会えて感謝します。
補足
30246kikuさま タブ移動順、タブストップ、イベントプロシージャの割り当てを確認し、 Private Sub ★★★_KeyDown(KeyCode As Integer, Shift As Integer) On Error Resume Next Select Case KeyCode Case vbKeyReturn bEnter = Not bEnter If (bEnter) Then KeyCode = 0 Me.★★★.Text = Me.★★★.Text End If Case Else bEnter = False End Select End Sub の記述に変更したところついに!!★★★の先頭にカーソルが動いてくれました!!!ここまで粘り強く引っ張って下さり、本当にありがとうございました。 なお、フィールド全体を選択/フィールドの先頭に移動のどちらでも、同様の動作を確認できました。 本当に、本当に、ありがとうございました。