MS Access Tips/Sample and VBA and Blog customize etc...

帳票フォームで表示項目が多いときページ切り替えで その2

以前の記事 帳票フォームで表示項目が多いとき、ページ切り替えで でヘッダーのタブコントロールで詳細のページ切り換えをするフォームを紹介しましたが、そのフォームではキーボードのTab, Enter, 矢印キー で全ての項目を移動できないという欠点がありました。マウスでしか別のページへ移動できない仕様では、ユーザーインタフェイスとしては失格です。

そこで、キーボードでもページをまたいですべてのフィールドに移動できるように、改良しました。

想定では簡単にできそうだと思ったのですが、実際やってみると結構、複雑で大変でした。その顛末も含めてのレポートになります。

難易度:

まず、帳票フォームで表示項目が多いとき、ページ切り替えで のサンプルでは、固定列の最後の項目(氏名)でTabやEnterで移動しようとするとタブ1ページ目の項目 在籍支社 に移動せずに、次レコードへ移動してしまいます。これを 在籍支社 に移動するようにします。

ここで、単純に 氏名 のフォーカス喪失時に 在籍支社 にSetFocusすればいいと考えるのは間違いです。こうすると、氏名 に移動後、Shiftタブで前の項目へ戻ろう、あるいは、マウスクリックで別の項目へ移動しようとしても、無視して、在籍支社へ移動してしまいます。

ならば、キーボードイベントでEnterキーやTabキー押下のとき、移動するようにすればいいように思います。が、しかし、これも問題があります。Accessのフォームでは、入力モードと移動モード(正式名称は分かりませんが)の2つのモードがあります。入力モードでは左右矢印キーでテキストボックス内でカーソルを移動できます。移動モードでは、矢印キーでカレントコントロールやレコードを移動します。モードにより動作が異なりますので、現在、どのモードなのか取得できないと、この方法での実装はできませんが、このモードを取得できる方法を私は知りません(もし、知っている方がみえたらコメントください。)

では、どんな方法で対処するかというと、ダミーのコントロールを配置して、タブオーダーを最後にしておきます。 ダミーのコントロールのフォーカス取得時に希望のコントロールへ移動させるコードを記述します。ダミーのコントロールはコマンドボタンにして、「透明」プロパティを「はい」にして、他のコントロールの背面に隠しておけば、目立ちません。

前回のサンプルのフォームにダミーのコマンドボタンを詳細セクションに配置します。

プロパティ  設定値 
透明 はい
名前 cmdNext0
タブ移動順 3
タブ移動順(タブオーダー)は詳細セクションのコントロールの最後になるようにします。

フォーカス取得時のイベントプロシージャを下記のように記述します。

これで、「氏名」テキストボックスでTabキーやEnterキー等で次の項目に移動しようとすると、タブコントロール内の 在籍支社 に移動します。cmdNext3は、次レコードへ移動するコードも追加します。また、新規レコードの時は、移動しないようにします。

同様にタブコントロールの各ページに、コマンドボタンを配置して、名前を cmdNext1, cmdNext2, cmdNext3 とします。プロパティの設定は上記の cmdNext0 と同様に設定します。イベントプロシージャは下記のよう、次ページの先頭項目へ移動するコードを記述します。

これで動作確認してみると、思惑通り、キーボードで全ての項目を移動して、さらに次のレコードに移動できました。

次に、逆に Shift+Tab、あるいは移動モードの ←キー で前方にも移動できるようにするために、詳細と各ページにcmdPrev0, cmdPrev1, cmdPrev2, cmdPrev3 の3つの透明コマンドボタンを配置して、タブオーダーを 0(先頭)にして、それぞれのフォーカス取得時のイベントプロシージャに下記のコードを記述します。

で、このフォームを開いて動作確認してみると、エラーが出てうまく動作しない。例えば、1ページ目の最後のコントロール「内線」からTabキーで移動しようとすると、
実行時エラー '2110':

コントロール '自宅郵便番号' にフォーカスを移動することはできません。
というエラーが発生する。

ブレークポイントを設定してコードを追ってみると、タブのページを変更すると最初に、先頭のコントロール(cmdPrev1・・・)のフォーカス取得時イベントが発生するためらしい。そこで、また、ページ変更をして、、、、と連鎖的にイベントが発生してしまうのが原因のようだ。

このようにフォーカス移動系のイベントを制御するのはなかなかやっかいです。

いろいろ試行錯誤して、連鎖につながるような不必要な[イベント プロシージャ]を解除してから処理を実行というコードを下記のように追加してなんとかエラー無く思惑通りに動くようになった。(簡単に書いているが、ここまでたどり着くのにかなりの時間を要しました。)

しかし、OnEnter = ""  OnEnter = "[イベント プロシージャ]" がやたら出てきて実に美しくないコードになりました。(サンプルMDBでは「F_社員」がこのコードです。)

そこで、発想を変えて、ダミーコントロールのフォーカス取得時で、必要なときのみ実行するようなロジックにした方がシンプルになるのではと思い、直前のコントロール(PreviousControl)が先頭項目のときのみ発動するようにしてみました。 で、また、いろいろ試行錯誤して最終的に下記のコードになりました。

すこしはすっきりと見通しがよくなったかな?(サンプルMDBでは「F_社員1」のコードです。)

ちなみに、OnEnter(フォーカス取得時) から GotFocus(フォーカス取得後)に変更したのは、OnEnter だとまだエラーが出る場合があり、それならと GotFocus に変更したらエラー無く安定して動作するようになったためです。

これで、全項目、全レコードをキーボードで移動できるようになりました。

しかし、これだけのことでほぼ1日を費やしてしまいました。こんなことなら、詳細にタブコントロールを使わずに、単に各項目の可視プロパティを制御して、表示/非表示 を切り換えた方が楽だったかも・・・・。

サンプルMDB が下記からダウンロードできます。
FrmColumnTabPageKai_07.zip (Access 2007 形式 - 44kb)
FrmColumnTabPageKai.zip (Access 2002-2003 形式 - 27kb)
FrmColumnTabPageKai_2k.zip (Access 2000 形式 - 25kb)

拍手する

Leave a reply






Trackbacks

trackback URL
http://hatenachips.blog34.fc2.com/tb.php/252-0a46bd56
該当の記事は見つかりませんでした。