- ベストアンサー
エクセルVBA フォーム上でOnkeyがうまく出来ない
エクセルVBAでプログラムをしています。 Application.Onkeyでショートカットを指定したいのですがフォーム上ではうまく指定できません。 フォーム上での指定は不可能なんでしょうか? ショートカットを認識するケース 標準モジュールに Sub test2() MsgBox "test2" End Sub Sub Auto_Open() Application.OnKey "{b}", "test2" End Sub としてシート上で「b」を押した場合はうまくいきます。 ショートカットを認識しないケース 標準モジュールに Sub test() MsgBox "test" End Sub UserForm1フォームに Private Sub UserForm_Initialize() Application.OnKey "{a}", "test" End Sub としてフォームをロード(表示)して「a」を押しても何もおきません。 またフォームが表示されている状態で「b」を押しても何もおきません。 上記のコードはテストで作ったものなのでこれ以外はフォームを開く文以外何も書いておりませんので他との兼ね合いではないと思います。 どうすれば思ったとおりの動作になるのでしょうか? そもそもOnkeyはユーザフォームがアクティブのときは動かないのでしょうか? 動かない場合、フォームがアクティブなときのみフォームごとに違う関数を呼ぶショートカットを作る方法はありませんでしょうか? (コントロールごとにkey_downイベントで確認する方法はコントロールの数が各100個ほどあるのと、フォームが10個以上あるため出来ればやりたくありません。) 環境はwinXP、excel2003です。 よろしくお願いいたします。
- みんなの回答 (7)
- 専門家の回答
質問者が選んだベストアンサー
こんにちは。 > keypressまたはkeydownイベントを使用するしか方法はないのでしょうか。 基本的にはそのとおりです。 > 1000回書くのはナンセンスだと思い何か言い方法が無いか探している状況です。 VB とか Access のように Userform に KeyPreview プロパティーがあれば 話は簡単なのですが、残念ながら Excel にはありません。 # 何故 Access にあって、Excel には KeyPreview がないん # でしょうね。。^^; 解決法としては、クラスモジュールを使うことになります。下記参考 URL に記事があります。一度クラスを書いてしまえば、コントロール数が増え ても減ってもコードの修正は非常に容易です。 Visual Basic 中学校 http://homepage1.nifty.com/rucio/main/main.htm 第30回 同じコードを2度書くな http://homepage1.nifty.com/rucio/main/shokyu/jugyou30.htm その他の方法としては、 ・SetWindowsHookEx api でキーボードフックする ・RegisterHotKey api でホットキーを設定する などでも実現可能ですが、難易度は高めです。
その他の回答 (6)
- lark_0925
- ベストアンサー率63% (37/58)
本格的にするなら、クラス化して、イベントまで作らなければなりませんが、今回のコードはそこまで詰めていません。 当該ユーザーフォームのモジュールに '=========================================================== Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long) Private Declare Function GetAsyncKeyState Lib _ "User32.dll" (ByVal vKey As Long) As Long Private e_l As Boolean '=========================================================== Private Sub UserForm_Activate() e_l = False Do Until e_l = True Sleep 100 DoEvents If key_code(66) Then '{b}が押された? ' 実際には、ここに{b}が押されたときの処理を記述する ' または、ここで別のプロシジャーを呼び出す Range("a1").Value = Range("a1").Value & "b" ' ここではセルA1にbを繋げている End If Loop End Sub '=========================================================== Function key_code(key As Long) As Boolean ' keyの値は、コントロールのKeyDownイベントのKeycodeと同値 Dim inkey As Long key_code = False inkey = GetAsyncKeyState(key) If inkey <> 0 Then key_code = True End If End Function '=========================================================== Private Sub UserForm_Terminate() e_l = True End Sub
- cj_mover
- ベストアンサー率76% (292/381)
ああ、すみません。 #4ですが、読み落としというか、錯誤があって頓珍漢な回答(?)でした。 #3さんのご回答に私が上書きするような話はありません。 いくつか考えついたのはありますが、どれもダミーのコントロールにフォーカスを置く方法ばかりでした。 大変失礼しました。
- cj_mover
- ベストアンサー率76% (292/381)
こんにちは 詳細はよくわかりませんが、 ご要望はこういうことではないでしょうか? Private Sub UserForm_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger) If KeyAscii = 98 Then Application.Run "test2" End Sub 私自身、滅多に使わないイベントですから、詳しい訳ではありませんが、 このイベントがある以上は、 ―OnKey が優先される―ことはないだろうな、とは思います。 ※フォームはModal表示、コントロールにフォーカスを置かない状態で確認済。
- end-u
- ベストアンサー率79% (496/625)
Formヘルプの[Microsoft Forms オブジェクト モデルの全体像] を見てもらったらわかるかもしれませんが、 ExcelとMicrosoft Formsは、言わば別Applicationなので、 FormがActiveになっている時はExcel.ApplicationのOnkeyメソッドは機能しません。 [Alt]キーとの組み合わせで良ければ、[Accelerator プロパティ]を調べてみてはいかがでしょう。 ダミーでもいいので、CommandButton を追加し、そのボタンに[Accelerator プロパティ]を設定します。 Me.CommandButton1.Accelerator = "A" などとコードでも設定できますが、[プロパティウィンドウ]でも可。 [Alt]キー+[設定したキー]で、その CommandButton_Click イベントが実行できます。 その CommandButton はUserFormの非表示エリアに置いて、TabStopをFalseにしておけば あまり気にならないでしょう。 その場合はクリックイベントの最後に他のコントロールにSetFocusするようにしておいたほうがいいです。
- marbin
- ベストアンサー率27% (636/2290)
#1です。 あと、ユーザーフォームにフォーカスがあると 起動しないようです。 シートにフォーカスを移してからキーを打つと 起動します。
お礼
ご回答ありがとうございます。 現在作っているプログラムはユーザがシートにフォーカスを当てる瞬間がまったくありません。 フォームがアクティブなときにいつでもショートカットキーを使用するいい方法はないでしょうか? よろしくお願いいたします。
- marbin
- ベストアンサー率27% (636/2290)
全角/半角 の違いでは? 半角に切り替えたらどうなりますか?
お礼
ご回答ありがとうございます。 テキストボックスなどのコントロールは一切ありませんので常に半角です。 あえて全角にして見ましたがうまくいきません。
お礼
ご回答ありがとうございます。 keypressまたはkeydownイベントを使用するしか方法はないのでしょうか。 質問にも書きましたが本番環境には、ボタンやテキストボックスなどコントロールがざっと1000以上(システム全体で)あります。 1000回書くのはナンセンスだと思い何か言い方法が無いか探している状況です。