【備忘録】VBAのSendKeysでNumLockが勝手に切り替わる問題と対処法

Office Tips

皆さん、こんにちは!
上越市を拠点にし、「FA設備・装置開発」と「画像処理」に強い会社、NSIです!
私達は豊富な経験と専門知識で、各種業界の自動化・システム化のお手伝いをしています。

すっかり春らしい気温になり、桜もちょうど見頃ですね。
4月から新生活が始まった方は、少しずつ慣れてきた頃ではないでしょうか?
たまにはひと息つきながら、今月を乗り切っていきましょう!

今回は、先日ハマった出来事を備忘録としてまとめます。
同じような状況の方に、この記事が役に立てば幸いです。

SendKeysの落とし穴

先日、VBAで「保存時にセルの入力チェックを行い、不備があればそのセルを編集状態にする」という処理を作っていました。不備があったセルの内容をまるごと削除するのは簡単ですが、それだとまた打ち直すのが面倒…。というわけで、セルをそのまま編集状態にして修正してもらうことにしました。

セルを編集状態にするには「ダブルクリック」か「F2キー」を押すのが一般的です。
今回はVBAで処理するので、「Application.SendKeys “{F2}”」という処理を記述して実行してみたところ…。

ここでまさかの落とし穴。
なぜかNumLockが勝手に切り替わるという謎の現象が発生してしまいました。

なぜNumLockが切り替わるのか?

結論から言うと、Application.SendKeysがNumLockの状態に干渉してしまうことが原因です。

SendKeys は、VBAからキー入力を擬似的に送信する機能ですが、このとき NumLock・CapsLock・ScrollLock などのトグルキーの状態は保存されません。そのため、F2キーを送信した際に、「NumLockがオフの状態でキーが押された」と誤って解釈されてしまい、NumLockの状態が勝手に変わってしまうことがあります。
※トグルキー … 押す度にON/OFFの状態を切り替えることができるキー(NumLock、CapsLockなど)のこと。

NumLockの切替を回避する方法

ズバリ、「SendKeysを使わない」というのがベストですが、どうしてもセルを編集状態にしたい場合もありますよね。Qiitaより(@nukie_53)様の記事を参考にして試したところ、NumLockが切り替わらずにF2キーの動作を再現できる方法が分かったのでご紹介します。

出典:
ソースコードはQiitaより(@nukie_53)様の記事を参考にさせて頂きました。
VBA.SendKeysでキーボードのロックが外れる現象への対策

まず、元のコードはこちら(ThisWorkbook 内に記載):

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    Dim target As Range
    
    ' 対象のセル:B4
    Set target = Range("B4")
    
    ' 数値かどうか確認
    If Not IsNumeric(target.Value) Then
        ' 数値以外なら、セルを選択状態にする
        MsgBox "セル B4 の値が数値ではありません。修正してください。", vbExclamation
        target.Select
        Application.SendKeys "{F2}"
        
        '保存はキャンセル
        Cancel = True
    End If
End Sub

Application.SendKeys を使用しているため、NumLockの状態が切り替わってしまいます。

続いて修正版:

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    Dim target As Range
    
    ' 対象のセル:B4
    Set target = Range("B4")
    
    ' 数値かどうか確認
    If Not IsNumeric(target.Value) Then
        ' 数値以外なら、セルを選択状態にする
        MsgBox "セル B4 の値が数値ではありません。修正してください。", vbExclamation
        target.Select
        wshSendKeys "{F2}"
        
        '保存はキャンセル
        Cancel = True
    End If
End Sub

' ------------------------------------------------------------
' 以下のコードは、Qiita @nukie_53 様の記事より引用しています。
' 出典:https://qiita.com/nukie_53/items/f069a1e48cddca0024c2

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

WScript.Shell の SendKeys をラップすることで、NumLock が切り替わる問題が発生しなくなります。修正内容としては、wshSendKeys というラップ関数を追加し、Application.SendKeys を wshSendKeys に置き換えるだけです。

修正版を実行してみましょう!

NumLockが発生しなくなりましたね。

最後に

今回は SendKeysを実行したときにNumLockが切り替わる現象と、その回避方法 についてご紹介しました。SendKeys 自体は便利な機能ですが、今回のように思わぬ落とし穴があることもあるため、使用には注意が必要です。

ここまで読んでいただき、ありがとうございました。
ご質問・ご要望・ご相談などは、下記お問い合わせフォームからお気軽にご連絡ください。
http://www.net-nsi.co.jp/toiawase.html

べんぞうくん
べんぞうくん

この記事が役に立ったらGoodボタンを押してね~

タイトルとURLをコピーしました