ExcelのVBAで3択クイズを作っていて、ユーザーフォーム上で解答選択支が表示されている
コマンドボタンが3つあって、
そのどれかをクリックすると正解か不正解の表示が出る仕組みのプログラムを作ったのですが、
スムーズに選択できるようキーボードでコマンドボタンを押せるようにしたいのです。

左キーを押すとコマンドボタン1、上キーを押すとコマンドボタン2、右キーを押すとコマンドボタン3
が反応するといった感じにしたいのです。

いろんなサイトを見て回ったのですがAPIのGetAsyncKeyStateという関数を使うというところまでは
分かったのですが素人なものでそこから先を何を記述すべきか分からなくて困っています。
いろいろためしたものの反応がしなくて分からないです。
なにかいい方法はありませんか?

このQ&Aに関連する最新のQ&A

A 回答 (5件)

#2です。


xl2000とxl2010で確認しております。他のバージョンは分かりませんが別の理由だと思います。
然るべきモジュールに置かれたのか、他のルーチンと同居させたのか等が分かりませんのでお返事のしようはないですが、GetAsyncKeyStateの使い方の一例を紹介させていただいたのみですので、スルーして下さって結構です。
    • good
    • 0

再掲:


>他のコントロールを置かなきゃならないなら,そちらのコントロールもフォーカスを持たないようにするか,またはフォーカスを持つ(可能性のある)コントロールのkeyDownイベントに同じ仕込みをしておくこと


意味が分からなくてスルーしてたのなら,そこを聞くべきだったのではありませんか?
次の通り追加します

Private Sub CommandButton1_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
 If KeyCode = 39 Then CommandButton1_Click
 If KeyCode = 38 Then CommandButton2_Click
 If KeyCode = 37 Then CommandButton3_Click
End Sub

Private Sub CommandButton2_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
 If KeyCode = 39 Then CommandButton1_Click
 If KeyCode = 38 Then CommandButton2_Click
 If KeyCode = 37 Then CommandButton3_Click
End Sub

Private Sub CommandButton3_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
 If KeyCode = 39 Then CommandButton1_Click
 If KeyCode = 38 Then CommandButton2_Click
 If KeyCode = 37 Then CommandButton3_Click
End Sub

Private Sub CommandButton4_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
 If KeyCode = 39 Then CommandButton1_Click
 If KeyCode = 38 Then CommandButton2_Click
 If KeyCode = 37 Then CommandButton3_Click
End Sub
    • good
    • 0
この回答へのお礼

回答ありがとうございました。
無事に理想どうりに動きました。

お礼日時:2012/01/05 19:15

1問目とか2問目と言われても,ナンのことか(アナタのエクセルがどうなっているのか)さっぱり判りません。


具体的なハウツーの回答が必要でしたら,もっとエクセルの(ユーザーフォームの)姿をキチンと情報提供するよう頑張って説明してみてください。



断片的な情報から推測できることとしては恐らく
>黒枠が動くだけ

回答で説明した
・他のコントロールがない
という条件が満たされていない,

若しくは
・プロパティパネルで設定する
という準備を怠っている

と考えられます。


もしご自分で作成した(作成中の)モノの説明ができないようでしたら,次のように作成すれば回答1で出来ますので作り直してください。
1.設問ごとにユーザーフォームを作成する
2.ユーザーフォームごとにコマンドボタン1,2,3を配置する
3.ユーザーフォームごとに各ボタンのプロパティを正しく設定する
4.ユーザーフォームごとにマクロを登録する

この回答への補足

英単語の3択でsheets1はコマンドボタンが1つあって、それを押すと全20問で問題がランダムに
出るユーザーフォームが出てくる仕組みです。
sheets2は問題の属性データと問題元データがあります。
問題元データはsheets1のコマンドボタンを押すたびにランダムに変わるようになっています。


sheet3は名詞の単語が1551個収録、sheets4は形容詞の単語が792個収録、sheets5は動詞の単語が
1059個収録、sheets6は副詞の単語が61個収録といった構成です。


userform1には問題数表示と問題文のラベルと4つのコマンドボタンが設置してあり3つは問題の回答選択支としてのボタンで
残りの1つは次の問題へと進むためのボタンです。

下にuserform1のcommandbutton1~4までのプログラムを載せます。



Private Sub CommandButton1_Click()
Application.ScreenUpdating = False

If Label4.Caption = "正解!!" Or Label4.Caption = "残念!!" Then
CommandButton4.SetFocus

ElseIf Label5.Caption = "1" Or Label5.Caption = "2" Or Label5.Caption = "3" Or Label5.Caption = "4" Or Label5.Caption = "5" Or Label5.Caption = "6" Then

Label4.Caption = "正解!!"
Sheets("処理").Select
Cells(2, 3) = Cells(2, 3) + 1
Sheets("スタート").Select

CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty

If Label2 = "20" Then
MsgBox "全20問終了しました。"
End If

Else
Sheets("処理").Select
Label4.Caption = "残念!!" & vbCrLf & Cells(Label2 + 1, 16).Value
Sheets("スタート").Select

CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty

If Label2 = "20" Then
MsgBox "全20問終了しました。"
End If
End If
Application.ScreenUpdating = True

CommandButton4.SetFocus

End Sub




Private Sub CommandButton2_Click()
Application.ScreenUpdating = False

If Label4.Caption = "正解!!" Or Label4.Caption = "残念!!" Then
CommandButton4.SetFocus

ElseIf Label5.Caption = "7" Or Label5.Caption = "8" Or Label5.Caption = "13" Or Label5.Caption = "14" Or Label5.Caption = "19" Or Label5.Caption = "20" Then
Label4.Caption = "正解!!"
Sheets("処理").Select
Cells(2.3) = Cells(2, 3) + 1
Sheets("スタート").Select

CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty

If Label2 = "20" Then
MsgBox "全20問終了しました"
End If

Else
Sheets("処理").Select
Label4.Caption = "残念!!" & vbCrLf & Cells(Label2 + 1, 16).Value
Sheets("スタート").Select
CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty



If Label2 = "20" Then
MsgBox "全20問終了しました。"
End If

End If
Application.ScreenUpdating = True

CommandButton4.SetFocus

End Sub


Private Sub commandbutton3_click()
Application.ScreenUpdating = False
If Label4.Caption = "正解!!" Or Label4.Caption = "残念!!" Then
CommandButton4.SetFocus

ElseIf Label5.Caption = "9" Or Label5.Caption = "11" Or Label5.Caption = "15" Or Label5.Caption = "17" Or Label5.Caption = "21" Or Label5.Caption = "23" Then

Label4.Caption = "正解!!"
Sheets("処理").Select
Cells(2, 3) = Cells(2, 3) + 1
Sheets("スタート").Select

CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty

If Label2 = "20" Then
MsgBox "全20問終了しました"
End If

Else
Sheets("処理").Select
Label4.Caption = "残念!!" & vbCrLf & Cells(Label2 + 1, 16).Value
Sheets("スタート").Select
CommandButton1.Caption = Empty
CommandButton2.Caption = Empty
CommandButton3.Caption = Empty


If Label2 = "20" Then
MsgBox "全20問終了しました。"
End If

End If

Application.ScreenUpdating = True

CommandButton4.SetFocus



End Sub





commndbutton4のプログラムも載せます。
全部載せると文字数が足らないので膨大なcaptionの部分は省きます。

Private Sub CommandButton4_Click()
Dim 正解率 As Variant

Application.ScreenUpdating = False
If Left(Label4.Caption, 4) = "正解!!" Or Left(Label4.Caption, 4) = "残念!!" Then

If Label2 = "20" Then
Sheets("処理").Select
正解率 = Cells(2, 3) / 20 * 100
Label4.Caption = "正解率は" & 正解率 & "%でした。"
Sheets("スタート").Select
MsgBox "全20問終了しました。"
Unload Me
Exit Sub
End If

Label2.Caption = Label2 + 1
Sheets("処理").Select

Label4.Caption = Cells(Label2 + 1, 11)
Label5.Caption = Cells(Label2 + 1, 4).Value

省略



End If
Else
MsgBox "解答を選択して下さい!!", vbCritical
End If
Sheets("スタート").Select
Application.ScreenUpdating = True

End Sub

補足日時:2012/01/05 17:39
    • good
    • 0

#1で十分だと思いますが、GetAsyncKeyState APIを使ってやってみました。


参考URLの他、VBAのヘルプの「RaiseEvent ステートメントの使用例」をご参照下さい。
とりあえず動いたという以上の検証は出来ておりません。
また、CommandButton1のところしか記載しておりませんので悪しからず。
☆標準モジュール
Sub test()
UserForm1.Show
End Sub

☆UserForm1モジュール
Private WithEvents watchKey As Class1

Private Sub CommandButton1_Click()
MsgBox "CommandButton1が押されたよ"
End Sub

Private Sub UserForm_Initialize()
Set watchKey = New Class1
End Sub

Private Sub UserForm_Activate()
'これをUserForm_Initializeで実行するとフォームが表示されずはまった...
watchKey.watchTask
End Sub

Private Sub UserForm_Terminate()
watchKey.stopLoop = True
Set watchKey = Nothing
End Sub

Private Sub watchKey_keyPushed(ByVal strKey As String)
'MsgBox strKey & "が押されました"
Select Case strKey
Case "←"
Call CommandButton1_Click
Case "↑"

Case "→"

End Select
End Sub

☆Class1モジュール 中身が分かる名前をつけるのが本来ですが、簡便のため挿入/クラスモジュールでつくお仕着せの名前にしてあります。
Public Event keyPushed(ByVal strKey As String)

Private Declare Function GetAsyncKeyState Lib "User32.dll" (ByVal vKey As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Const VK_LEFT = &H25 '[←]
Private Const VK_UP = &H26 '[↑]
Private Const VK_RIGHT = &H27 '[→]

Private myStopFlag As Boolean

Public Sub watchTask()
Do
If GetAsyncKeyState(VK_LEFT) Then
RaiseEvent keyPushed("←")
ElseIf GetAsyncKeyState(VK_UP) Then
RaiseEvent keyPushed("↑")
ElseIf GetAsyncKeyState(VK_RIGHT) Then
RaiseEvent keyPushed("→")
Else

End If
Call Sleep(100)
DoEvents
Loop Until myStopFlag
End Sub

Public Property Let stopLoop(stopFlag As Boolean)
myStopFlag = stopFlag
End Property

参考URL:http://home.att.ne.jp/zeta/gen/excel/c04p07.htm
    • good
    • 0
この回答へのお礼

回答ありがとうございます!
試したのですが、名前が適切ではないとエラーがでてしまいました・・

お礼日時:2012/01/05 15:28

準備:


UserForm1にCommandButton1,2,3を配置してある(他のコントロールは無い)
プロパティパネルで各コマンドボタンのTabStop並びにTakeFocusOnClickをFalseにしておく

手順:
ユーザーフォームのシートに
Private Sub UserForm_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
 If KeyCode = 39 Then CommandButton1_Click
 If KeyCode = 38 Then CommandButton2_Click
 If KeyCode = 37 Then CommandButton3_Click
End Sub

としておく。




#他のコントロールを置かなきゃならないなら,そちらのコントロールもフォーカスを持たないようにするか,またはフォーカスを持つ(可能性のある)コントロールのkeyDownイベントに同じ仕込みをしておくこと
    • good
    • 0
この回答へのお礼

回答ありがとうございます!
早速試して1問目に限れば理想どうりに動いたのですが、2問目からはコマンドボタンに点々の黒枠が
出てしまい方向キーをおしてもクリック動作がせず、黒枠が動くだけになってしまいました・・

お礼日時:2012/01/05 15:26

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qコマンドプロンプトでネットワークドライブ名の変更

コマンドプロンプト画面でコマンドを使用して、ネットワークドライブ名を任意の名前に変更することは出来ますか?
宜しくお願いします。

Aベストアンサー

 こんばんは ^^
 ネットワークドライブ名とは,ドライブ文字のことでしょうか?
 もしそうでしたら,net useコマンドで可能かと思います.

参考URL:http://support.microsoft.com/kb/308582/ja

Qユーザフォームの押下コマンドボタンの区別は?

Excel2007のVBAについて質問します。初心者です。

コマンドボタンが2個あるユーザフォームを表示します。それぞれのボタンが押されると対応する処理をして制御がユーザフォームを表示した直後に戻るようになっています。

このとき、どちらのボタンが押されたのか区別する方法をご教示頂きたくよろしくお願い致します。

Aベストアンサー

「ボタンが押された」なるプロパティはありません。
たとえば回答済みの方法1を応用してみると

標準モジュール
public flg
sub macro1()
 load userform1
 userform1.show
 msgbox flg
end sub


ユーザーフォームのモジュール
private sub commandbutton1_click()
 flg = "button1"
 me.hide
end sub

private sub commandbutton2_click()
 flg = "button2"
 me.hide
end sub

などのようになりますが?

QEIGRPコマンド「network」で使えるのはクラスフルネットワークアドレスのみ?

シスコのルーティングプロトコル、EIGRPコマンド「network」で使えるのはクラスフルネットワークアドレスのみなんでしょうか?EIGRPはRIPやIGRPとは違ってクラスレスなルーティングプロトコルと聞いたんですが・・
もしかして、「network」コマンドが同一AS内のネイバーへのアップデートなのでクラスフルなネットワークアドレスを使用するんでしょうか???

Aベストアンサー

こんばんは
hdddvdさんは勉強熱心ですね。

私の嫌いなEIGRP ですが、もちろん『クラスレス・ルーティング・プロトコル』です。
ネイバーへアップデートするルーティング情報には、きちんと『サブネットマスク』の情報が含まれています。

EIGRP の『network』コマンドは、どのNW がEIGRP のAS に参加するかを定義するパラメータです。
EIGRP ルータの、「どのインターフェースがEIGRP に参加するか」と「どのネットワークにアドバタイズするか」を定義します。

参考URL:http://www.cisco.com/japanese/warp/public/3/jp/service/tac/103/eigrp-toc-j.html

QVBAです。ユーザーホームにコマンドボタンについて

VBAです。ユーザーホームにコマンドボタンについて
画像のように、コマンドボタンの淵に黒枠が出来ているのがあります。
この設定が解る方教えて下さい。
宜しくお願い致します。

Aベストアンサー

> 画像のように、コマンドボタンの淵に黒枠が出来ているのがあります。
> この設定が解る方教えて下さい。

決して難しい質問ではないのですが、
内容がかなり漠然としているため、レスが付きにくくなっていますね。

まず「黒枠」ですが、これは、そのボタンにフォーカスが当たっている、というものです。
(万が一、フォーカスの意味がわからなければ、ググってみてください。)

「この設定が解る」
というのが、
全部のボタンに黒枠を付けるような設定
ということなら、
複数のコントロールに同時にフォーカスを当てることは出来ませんから無理です。

逆に、黒枠が出来てはマズい場合、
(エンターキー や スペースキー 押下で、
意図せずにボタンのクリックイベントが走ってしまう場合などですね。)

「TabStop」「TakeFocusOnClick」プロパティ を False にしてみてください。

それ以外の意味でしたら、誰でもわかるように
詳しく質問を説明してください。

QコマンドでPCのネットワークドライブの書き換え

こんにちは

PC1からコマンドでPC2のネットワークドライブの書き換えが出来るか知りたいです。

同ネットワーク上のPCをshutdownコマンドで落とせるようなので、もしかしたら他のPCのネットワークドライブの書き換えも出来るのではないか?と勝手に思っていますが、知識が乏しい為、出来るか出来ないかすらわかりません。
もし出来るのであれば方法など教えていただければ嬉しいです。
出来ない場合は理由なども教えて下さい。

ネットワーク上のマシンのOSはWindowsXPです。

すみませんがよろしくお願いします。

Aベストアンサー

『ネットワークドライブの書き換え』というのは、具体的にどのような作業を指しているのでしょうか?

QVBAコマンドボタン

Excel2003です。

コマンドボタンで指定したヘルプファイルを開くにはどうしたら良いでしょうか?
C:\help\aaa.chm

Aベストアンサー

こんにちは。

こんなふうにしてみたらいかがですか?

'-------------------------------------------

Private Sub CommandButton1_Click()
  Const FN As String = "C:\help\aaa.chm"
  
  If Dir(FN) = "" Then
    MsgBox "ファイルがありません。", 48
    Exit Sub
  End If
  With CreateObject("Shell.Application")
   .ShellExecute FN
  End With
End Sub

Qコマンドプロンプトからネットワーク切断

お世話になっております。王次郎です。

さて、今回の質問は、
windows7で、ネットワークへの接続と切断を簡単に切り替えたく、
コマンドか、C++関数での 方法を探しています。


(詳細)
当方、パソコンでローカルな作業をする際に、インタネットにつながっていると
不都合な場合がございます。ただし、普段はネットワークに接続して
メール送受信やインタネット接続を行う必要があります。
という訳で、ネットワーク接続のオン・オフを簡単に行いたいと考えてます。
例えば、コマンドプロンプトのコマンドを使って、batファイルにしておく事を考えてます。
もしくは、C++も使えるので、C++関数で簡単にネットワーク接続状態を変えられる関数が
あるとうれしいです。

よろしくお願いします。

Aベストアンサー

下記に具体的な方法が載っています。
http://l.inolv.jp/2013/02/27/disable-and-enable-network-by-comman/
ただし、文字列の区切りが違っています(半角のダブルクオートです)。
無効化(disabled)
netsh interface set interface "ローカル エリア接続" disabled
有効化(enabled)
netsh interface set interface "ローカル エリア接続" enabled
「ローカルエリア接続」の箇所は、「ipconfig /all」で「イーサネット アダプター」の後にかかれています。例えば「イーサネット アダプター イーサネット:」であれば「イーサネット」です。

QEXCELのvisual basicでのコマンドボタンの文字を変えたい

EXCEL2003と2007でvisual basicでのコマンドボタンの枠内の文字を
プロパティ欄でcommandbuttn1を「数字入力」と変えたいのですがどうも旨くいきません。枠内の背景やフォントは自由に変えれるのですが何故なんでしょうか?
よろしくお願いします

Aベストアンサー

オブジェクト名ではなく、Captionプロパティを変更されていますか?

Qコマンドプロンプトを使ってネットワークの一覧を表示

コマンドプロンプトを使ってネットワークの一覧を表示する方法
LAN内のPCやプリンタ、ネットワーク機器のIPアドレスを
調べて一覧にするコマンドプロンプトのコマンドはありませんか?
固定IPかDHCPから割り振られたIPか、わかると更に嬉しいです。

なければそういった機能があるソフトでもいいので
ご紹介頂けると幸いです。

Aベストアンサー

こちら参考に
★lan内のpcをipアドレスで一覧表示したい | OKWave
http://oshiete.goo.ne.jp/qa/5829669.html

QExcelのマクロでコマンドボタンを選択する方法

Excelのマクロでコマンドボタンを選択する方法

マクロの記述でオブジェクトのコマンドボタンのみを選択するにはどうしたらいいでしょうか?
別のマクロが登録されているボタンを削除するのが目的です。
オブジェクトは他にもテキストや直線などがあり、コマンドボタンのみの特定の仕方がわかりません。
シートも複数あり、コマンドボタンもまちまちな名前がついています。

WinXP Excel2000

Aベストアンサー

有無を言わせず削除でよいのですか?

↓参考になると思います。
エクセルのチェックボックスとかについて
http://oshiete.goo.ne.jp/qa/5850376.html

フォームのコマンドボタンは
ActiveSheet.Buttons.Delete

コントロールツールボックスのコマンドボタンは
Nameプロパティを使って
Dim btn As OLEObject
For Each btn In ActiveSheet.OLEObjects
If btn.Name Like "CommandButton*" Then
btn.Delete
End If
Next btn

あるいはprogIDを使って
Dim btn As OLEObject
For Each btn In ActiveSheet.OLEObjects
If btn.progID = "Forms.CommandButton.1" Then
btn.Delete
End If
Next btn

条件があるなら追加してください。


人気Q&Aランキング

おすすめ情報