VBAからキーボードの入力操作を行うには
文字の入力はキーボードを使って行うのが普通です。これを疑似的に行うことが出来るのがSendKeysステートメントです。実際にはキーボード入力を行っていませんが、入力したときと同じ動作をします。
通常のキーボードの入力はアクティブウィンドウに対して行います。SendKeysステートメントも同様で、Excelに限定されず、アクティブウィンドウになっているアプリケーションがキー入力の対象になります。
一つの用途として、VBAで外部アプリケーションを起動もしくはアクティブにして、そのあとにSendKeysステートメントでキーボードのショートカットを入力する、というようなことも可能になります。
Application.SendKeysステートメントではなくWshShellオブジェクトのSendKeysを使う
VBAにはSendKeysが2つあります。VBA標準のApplicationオブジェクトのSendKeysステートメントと、WshShellオブジェクトのSendKeysメソッドです。
SendKeysの使い方は同じですが、後者のWshShellオブジェクトを使う場合はCreateObject関数か参照設定をしておく手間があります。しかし、その手間があってもWshShellオブジェクトのSendKeysメソッドを使うことをお勧めします。
というのも、VBA標準のApplication.SendKeysステートメントには、実行するとNumLockキーがオフになり数値入力ではなく矢印キーなどの扱いになるバグのような挙動になることがあるためです。これは極めて高い頻度で発生します。
もう一度NumLockキーを押すSendKeysステートメントを実行すれば元に戻りますが、元のNumLockキーの状態がオンなのかオフなのか分からないと、もう一度NumLockキーを押すかどうかの判定ができません。元がオンであればオフになってしまいます。
このNumLockバグは、小さいサイズのノートPCのキーボードのようにテンキーが無いのであれば影響はないかもしれませんが、USBで外部キーボードを接続したりすると、そうもいきません。
Win32APIのGetKeyboardState関数を使ってNumLockキーがオン、オフのどちらなのかを判定して、Win32APIのkeybd_event関数でNumLockキーの状態をオフやオフに変更することは出来ますが、はっきり言って面倒です。
実際にSendKeysを使う場面では、単純な文字列を入力するよりも、Ctrlキーなどと一緒にショートカットキーとして入力することの方が圧倒的に多いはずです。その場合は上記のNumLockオンのバグが高確率で発生します。
このように、NumLockのバグに対応しようとするとなかなか大変ですが、解決方法があります。それはWshShellオブジェクトのSendKeysメソッドを利用する方法です。この場合は上記バグは発生しません。使い方も全く同じため、WshShell.SendKeysの利用をお勧めします。
以降で紹介する処理はWshShell.SendKeysの利用する方法で記載しています。
WshShell.SendKeysを関数化する
WshShellは先に書いた通り、CreateObject関数か参照設定をしておく必要があります。
CreateObject関数:
「Set w = CreateObject(“WScript.Shell”)」
WshShellの参照設定:
VBA画面→ツールメニュー→参照設定、を選択し、参照設定ダイアログで「Windows Script Host Object Model」にチェックを付けます。
参照設定はVBAに限定されますが、SendKeysはVBScriptでも実行できますので、CreateObject関数を使う方法で考えると、以下のようにWshShell.SendKeysを実行する関数を用意しておくと、何も考えずに済みます。
1 2 3 4 5 6 7 8 9 10 11 |
Public Sub SendKeys(Keys As String, Optional Wait As Boolean = False) Static w As Object '// WshShellオブジェクト '// WshShellオブジェクトが生成されていない場合 If w Is Nothing Then '// WshShellオブジェクトを生成 Set w = CreateObject("WScript.Shell") End If Call w.SendKeys(Keys, Wait) End Sub |
CreateObject関数は処理に時間が掛かるため、上記SendKeys関数が呼ばれたときにWshShellオブジェクトが生成済みかどうかを判定して、未作成の場合のみ作成するようにします。SendKeys関数を抜けたあともStaticとして変数は保持されますので、2回目以降にSendKeys関数を実行したときはCreateObject関数は実行されません。
上記の関数の名前が「SendKeys」となっていますが、SendKeysステートメントと同じ名前であっても、関数の方が動作します。VBA標準のSendKeysを使いたい場合は「Application.SendKeys」と書けば利用できます。
構文
Sub SendKeys(Keys, [Wait])
Keys | 入力するキーボードのキーを文字列で指定します。 |
Wait省略可 | キーボード操作が終わるまでVBAの次の処理を行うかどうかをBoolean(TrueかFalse)で指定します。Trueの場合はキーボード入力操作が終わるまで待ちます。False(規定値)の場合はキーボード入力操作が終わるのを待たずに次の処理を行います。 |
キーボード入力一覧
キー | 設定値 |
---|---|
a~z | “a” ~ “z” |
A~Z | “A” ~ “Z”(Shiftキーと小文字英字を組み合わせずに大文字をそのまま利用可能) |
0~9 | “0” ~ “9” |
記号キー | “!”、”#” のように””で囲う。ダブルクォーテーション(”1文字は)””””と書く。 |
F1~F16 | {F1} ~ {F16} |
Esc | {ESC} |
Tab | {TAB} |
CapsLock | {CAPSLOCK} |
BackSpace | {BACKSPACE}、{BS}、 {BKSP} のいずれか |
Enter | {ENTER} または ~ |
PrintScreen | {PRTSC} |
ScrollLock | {SCROLLLOCK} |
Break | {BREAK} |
Insert/Ins | {INSERT} または {INS} |
Home | {HOME} |
PageUp | {PGUP} |
Delete/Del | {DELETE} または {DEL} |
End | {END} |
PageDown | {PGDN} |
↑ | {UP} |
↓ | {DOWN} |
← | {LEFT} |
→ | {RIGHT} |
NumLock | {NUMLOCK} |
キー | 設定値 |
---|---|
Shift | + |
Ctrl | ^ |
Alt | % |
テンキーの数字はSendKeysで入力できません。どうしてもテンキーの操作を行いたい場合は、Win32APIのkeybd_event関数を利用してください。
利用例
キーボードの各キーの入力をSendKeysで行う場合、キー入力は文字列として扱うためダブルクォーテーションで囲います。
ショートカットキーとして、Shift(+)、Ctrl(^)、Alt(%)と英数字を組み合わせる場合は、英数字を丸括弧で囲みます。(例:Ctrl + a = “^(a)”)
上記のWshShell.SendKeysを関数化したSendKeys関数があればそちらが呼び出され、無ければVBA標準のSendKeysステートメントが呼び出されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
Sub SendKeysTest() '// メモ帳起動(キーボード入力を行うアプリケーションをアクティブにする) Shell "Notepad.exe", 1 '// 12345 を入力 Call SendKeys("12345 abc ABC ") '// Ctrl + a(全選択) Call SendKeys("^(a)") '// Ctrl + c(コピー) Call SendKeys("^(c)") '// Ctrl + v(貼り付け)×2回 Call SendKeys("^(v)") Call SendKeys("^(v)") '// Home(カーソルを先頭に移動) Call SendKeys("{HOME}") End Sub |
実行すると、新規のメモ帳に「12345 abc ABC 12345 abc ABC 」とキーボード入力が行われ、カーソルを先頭(左端)に移動します。