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 」とキーボード入力が行われ、カーソルを先頭(左端)に移動します。
