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を実行する関数を用意しておくと、何も考えずに済みます。

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ステートメントが呼び出されます。

実行すると、新規のメモ帳に「12345 abc ABC 12345 abc ABC 」とキーボード入力が行われ、カーソルを先頭(左端)に移動します。