#10 "↑"や"↓"キーによる商品明細のフォーカス移動

パソコンレジでは、商品のバーコードを次々と読み込んでいくというのが基本的な流れになります。しかし、例外的な操作をしなければならないケースも多々あります。"数量の入力間違いに気付いた"、"同じ1つの商品のバーコードを連続して読み込んでしまった"など、あとでデータを編集しなければならないことも少なくありません。

そのようなとき、元の仕様のままでも、マウスやTabキー/Shift+Tabキーなどを使えばどこへでも入力欄をジャンプできるのですが、今回のカスタマイズではマウス操作や面倒なキー操作はさせないことを基本としています。そのためここでは、入力済みのデータを変更したいとき、"↑"キーや"↓"キーによって各コントロール間のフォーカスを移動できるようフォームに変更を加えたいと思います。矢印キーであれば、TabキーやShift+Tabキーよりは操作しやすいはずです。

※このフォームでは、コンボボックスにフォーカスが移動すると自動的にドロップダウンするようになっています。もしそのような設定がなければ、このような特別な処理を追加しなくても、"←"や"→"キーで入力欄を前後させることができます。


ここでは、商品明細データを入力する「frm売上伝票入力_sub」フォームにおいて、"↑"・"↓"キーに次のような機能を持たせることにします。
  • ↑・・・・・Shift+Tabキーと同じ動作で、1つ前のコントロールにフォーカスを戻す
  • ↓・・・・・Tabキーと同じ動作で、次のコントロールにフォーカスを移動する

このような矢印キーの押し下げに対して独自の処理を行わせるためには、「キークリック時/KeyDown」イベントプロシージャを使います。このイベントプロシージャを使うことによって、特殊キーも含めたキーの押し下げを検知することができます。また、このイベントはテキストボックスやコンボボックスごとに割り当てることもできますが、似たようなコードをコントロールごとに書いていくのはメンテナンス上あまり良いとはいえません。そこで各コントロールではなく、"フォーム"のキークリック時イベントを使い、すべてのコントロールでの矢印キーの押し下げを一元的に処理するようにします。
  1. あるコントロールで発生したキークリック時イベントはそのコントロール内のイベントなので、フォームというオブジェクトのイベントとしては認識されません。そこで、フォームの「キーイベント取得」プロパティを"はい"に設定変更します。そうすることによって、本来はそれぞれのコントロール内で発生したイベントであっても、フォームオブジェクトのキークリック時イベントとして1ヶ所で受け取れるようになります。

  2. 続いて、実際にフォームのキークリック時イベントプロシージャを記述します。

    Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer)
    'フォームのキークリック時

      If KeyCode = vbKeyUp Then
        '↑キーが押されたとき
        Select Case Me.ActiveControl.Name
          Case "商品コード"
            If Me.NewRecord Then
              Me.Recordset.MoveLast
            End If
            On Error Resume Next
            Me.Recordset.MovePrevious
            Me!販売原価.SetFocus
          Case "商品名"
            Me!商品コード.SetFocus
          Case "数量"
            Me!商品名.SetFocus
          Case "単位区分"
            Me!数量.SetFocus
          Case "販売単価"
            Me!単位区分.SetFocus
          Case "課税区分"
            Me!販売単価.SetFocus
          Case "販売原価"
            Me!課税区分.SetFocus
        End Select

      ElseIf KeyCode = vbKeyDown Then
        '↓キーが押されたとき
        Select Case Me.ActiveControl.Name
          Case "商品コード"
            Me!商品名.SetFocus
          Case "商品名"
            Me!数量.SetFocus
          Case "数量"
            Me!単位区分.SetFocus
          Case "単位区分"
            Me!販売単価.SetFocus
          Case "販売単価"
            Me!課税区分.SetFocus
          Case "課税区分"
            Me!販売原価.SetFocus
          Case "販売原価"
            On Error Resume Next
            Me.Recordset.MoveNext
            Me!商品コード.SetFocus
        End Select

      End If

    End Sub
ここでは、イベントプロシージャの「KeyCode」引数を参照することによってどんなキーが押されたかを判断します。"↑"キーの場合はそれを組み込み定数「vbKeyUp」と比較することによって判別します。"↓"キーの場合は同じく「vbKeyDown」です。

また、押された矢印キーの種類によって次のフォーカス移動先を決定するわけですが、それにはどのコントロールでそのキーが押されたかを取得する必要があります。それが「ActiveControl.Name」という記述です。これによって"現在アクティブになっているコントロールの名前"を得ることができます。

このように、現在アクティブなコントロール名および押されたキーに応じて全体の処理を分岐させています。なお、ここでは「税抜金額」などの使用不可のコントロールに関しては処理する必要はありません。


またここでは特に、「商品コード」および「販売原価」コントロールでのキー操作に注意しなければなりません。
  • 「商品コード」で"↑"キーが押されたら"前レコード"の「販売原価」にフォーカスを移動
  • 「販売原価」で"↓"キーが押されたら"次レコード"の「商品コード」にフォーカスを移動
というように、レコード移動もいっしょに行わなければならないからです。VBAでのレコード移動にはいくつかの方法がありますが、ここではフォームのRecordsetオブジェクトのメソッドによるレコード移動を使っています。この処理の場合、次レコードがない状態(カレントレコードが最終レコードのとき)でMoveNextメソッドを実行したり、先頭レコードの状態でMovePreviousメソッドを実行したりするとエラーが発生する場合があります。それに備えて、ここではOn Error Resume Nextでエラーを無視するようにしています(厳密にはOn Error GoToでエラー処理した方がよいかもしれません)。また、新規レコードを入力中の状態でMovePreviousメソッドを実行すると、そのレコードがまだ保存されていないせいか、2つ前のレコードにジャンプしてしまいます。そのためここでは、NewRecordプロパティで新規レコードがどうかをチェックし、そうであればMoveLastメソッドでいったん最終レコードに移動させることによって(実際にはレコード移動はせずにレコードが保存される結果となる)、そういった誤動作を回避しています。

フォームビュー
                          ("↑"と"↓"キーで行ったり来たりします)
フォームビュー


またこの応用として、"↑"キーが押されたときの処理で、「数量」テキストボックスのCase節を次のように書き換えることもできます。こうすることによって、「数量」欄にカーソルがある状態で"↑"キーを押したとき、1つ前のレコードの「数量」欄に簡単にジャンプできますので、直前に入力した商品の数量だけ変更したい場合に大変操作性がよくなります。

  If KeyCode = vbKeyUp Then
    '↑キーが押されたとき
    Select Case Me.ActiveControl.Name
      Case "商品コード"
        If Me.NewRecord Then
          Me.Recordset.MoveLast
        End If
        On Error Resume Next
        Me.Recordset.MovePrevious
        Me!販売原価.SetFocus
      Case "商品名"
        Me!商品コード.SetFocus
      Case "数量"
        If Me.NewRecord Then
          Me.Recordset.MoveLast
        End If
        On Error Resume Next
        Me.Recordset.MovePrevious
      Case "単位区分"
        Me!数量.SetFocus
      Case "販売単価"
        Me!単位区分.SetFocus
      Case "課税区分"
        Me!販売単価.SetFocus
      Case "販売原価"
        Me!課税区分.SetFocus
    End Select

※実際のユーザー操作においては、矢印キーで他の欄に移動できるまではよいのですが、その自由度によって思わぬ結果を招くこともあります。たとえば、「販売単価」欄にカーソルがある状態でJANコードを読み込んでしまったようなときです。この場合、パソコンは素直にそれを金額入力と判断して、「\4,999,999,900,001」といった値が入力されてしまいます。こういったことを避けるためには、「単位」や「単価」、「原価」などのコントロールを編集不可の状態に設定したり、あるいはVBAでより細かな入力チェックを行ったりといった、より細かい対処が必要となるでしょう。
| Index | Prev | Next |

 

Copyright © T'sWare All rights reserved