和風スパゲティのレシピ

日本語でコーディングするExcelVBA

SendKeysを実行するとNumLockが切り替わる

知らずに落ちると抜け出せなくなるVBAの落とし穴です。

  • マクロを実行時に気づいたらNumLockが外れている
  • 他アプリを操作するマクロの実行時によく発生する

あたりにお悩みの方は、この落とし穴に落ちていないかご確認ください。

発生する罠

Excel(Application)のSendKeysメソッドにはバグらしき挙動があり、
実行時にNumLockキーに干渉することがあります。

  • SendKeysメソッドがNumLockなどのキー設定に干渉されないように、
    各種設定を一旦OFFにしてからキーを送信して、そのあと元の状態に戻す。
  • しかしSendKeysを連続実行した場合は、
    元の状態をひとつ前のSendKeys実行時と誤認してしまう。
  • この時SendKeysが正しく元の状態に戻らない不具合が起きる。

という、もっともらしい説明がMicrosoftからあったようですが、
普通に1回だけ実行したときにも起こるので真偽のほどは定かではありません。

特にテンキーを使用している方は、この挙動の存在を知っておく必要があります。

解決策

Excel(Application)のSendKeysメソッドを使う上では解決策がありません。

この問題に対応する場合は、ApplicationのSendKeysではなく、
WScript.ShellオブジェクトのSendKeysメソッドを使用して下さい。

Application.SendKeys "^s", True

' ↓ 書き換え

Dim wshShell As Object
Set wshShell = CreateObject("WScript.Shell")

wshShell.SendKeys "^s", True

 
SendKeysメソッドを多用する場合、いちいちこのコードを書くのは面倒ですし、
以下のように汎用関数化しておくことをおすすめします。

Sub WshShellオブジェクトのSendKeysを使用してキー操作を送信する()
    
    wshSendKeys "^s", True

End Sub
    
' WshShellのSendKeysを使用する汎用関数
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

 
WshShellオブジェクトのSendKeysメソッドの仕様については、
引数の順番や指定方法はApplication.SendKeysとほぼ同じになります。

詳細についてはこちらの記事をご覧ください。
www.limecode.jp