VBA.SendKeysでキーボードのロックが外れる現象への対策

  • 1
    Like
  • 0
    Comment

1. 現象

操作の自動化の最終手段であるSendKeysですが、VBAのSendKeysにはバグが存在します。

Misrosoftサポート
[BUG] 複数の SendKeys ステートメントが実行されると NumLock キーがオフになる

リンク先にあるように、VBAでSendeKeysステートメントを使用すると、NumLockなどが外れることがあります。

2. 対策:他のSendKeysを使用する

"Windows Script Host Object Model"の"WshShell"オブジェクト(ProgID:"WScript.Shell")のSendKeysステートメントでは上記の問題は発生しません。

WshShellのSendKeysをラップする

WshShellのSendKeysを使えば良い、といっても参照設定を追加するのも面倒だし、CreateObjectするのも面倒、ということでサブルーチン化したものがこちらです。

Public Sub wshSendKeys(Keys As String, Optional Wait As Boolean = False)
    'メモリ効率より動作速度を優先する場合
    Static wshShell As Object
    If wshShell Is Nothing Then Set wshShell = CreateObject("WScript.Shell")
    Call wshShell.SendKeys(Keys, Wait)
End Sub

毎回CreateObjectすると負荷が大きくなるので、Static宣言+存在判定をしています。
代わりにオブジェクトを破棄する方法が無くなるので、wshShellオブジェクトがメモリに残り続けます。

3. その他

AppActivate

WshShellのAppActivateもVBAのものと動作が異なるので状況によっては使い道があります。

具体的には、
VBAでは該当ウィンドウが存在しないときはエラーとなりますが、WshShellではAppActivateが成功したか、失敗したかがBooleanで戻ってきます。

力技

NumLock/CapsLockのオン・オフを取得する

にあるように、WordのApplicationオブジェクトからNumLockなど状態を取得できます。
これを使って、初期状態を保存しておき、VBA.SendKeys後に元に戻すという事もできなくもないです。

参考