goo blog サービス終了のお知らせ 

道草日記

通勤幾星霜…寄り道回り道の日記です。

EXCELのVBAで使うSendKeys

2008-11-29 | VBA

ExcelでVBAでマクロを組む場合、SendKeysを使うとキー入力がシミュレートできるので、重宝する。しかし、意外と知られていない問題点がある。

(SendKeysについてはこのOffice TANAKA氏のページが参考になる。)

●コピー・ペーストについて
まず以下のマクロをVBエディターで標準モジュールに入力する。

Sub SKtest()
  SendKeys "^c{RIGHT}^v" ,True
End Sub
 

 エクセルで、文字が入力されているセルを選択してから、このマクロを実行すると、
 ① Ctrl + C
 ② [→]キー
 ③ Ctrl + V
の順にキー入力がシミュレートされ、右側のセルに貼り付けが行われる。
 しかし、マクロを「 SendKeys "^v" ,True 」とだけ記入し、①と②を手動で行い、マクロで実行しようとすると貼り付けが動かない。
 つまり、マクロ側でコピーしたクリップボードの内容でないと貼り付けができない。

●waitオプションとSleep関数について

 Sendkeysは相手を確認しないまま、ただキー入力を送り出すだけの仕組みだ。そのため、ダイアログボックスを呼び出して複雑な処理をさせるような場合、受け取るシステム側がSendkeysのキー入力に追いつけなくなり、誤作動を起こすことがある。そのような場合、waitオプションをTrueに指定すると、キーストロークが渡るまで処理を中断させることできする。
 waitオプションを省略した場合は、デフォルトでFalseになる。

    Sendkeys "(文字列)",True

 ただし、キーが受信されたかを確認しているだけで、その結果の「システム側の処理が終わったかどうか」は確認していないので、誤作動の余地は残る。
 その場合、API関数のSleepで、システム側の処理に時間を与えることで、改善する場合もある。

'標準モジュールの冒頭で宣言
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Sub Sample()
    Sendkeys "(文字列)" ,True
    Sleep(10) 'マクロの処理を指定時間だけ停止。1000で1秒
End Sub

●デバッグ中の誤作動

 開発中にVBエディターでブレークポイントを設定しながらデバッグしていると、Sendkeysが誤作動を起こすことがある。
 これは、ブレークポイントで停止すると、システムのフォーカスはエクセルのシートからVBエディターに移っているので、Sendkeysのキー入力がVBエディターの編集画面に送られることによる。このため、Sendkeysは、単体で十分テストしてから組み込む必要がある。

 これ以外でも意図せずにシステムのフォーカスが移動することは多い。Sendkeysは相手を確認しないまま、ただキー入力を送り出すだけの仕組みなので、誤作動を完全に排除することはできない。このため、やむを得ない場合に限り利用し、できる限り短時間に終了するようにすべきだ。


●ダイアログの表示について

  SendKeys "%fu" ,True

 このマクロは、メニューの「ファイル(F)」→「ページ設定(U)」を開くショートカットキー(Alt + f → u )のキー入力をシミュレートする。実行すると、一気にページ設定ダイアログが開く。
 最後のTrueは、処理が終わるまで、他のマクロを実行しないための指示。

 しかし、SendKeysが行えるのはダイアログを表示するまでで、たとえば
  SendKeys "%fuz" ,True
などとしても、「用紙サイズ(Z)」を操作することはできない。
これは、他のダイアログでも同じ模様。

●機能キーによるフォーカス移動

そこで、{RIGHT}、{TAB}、{HOME}などの機能キーを使う。(一覧はOffice TANAKA氏のページで)

下記では、ページ設定ダイアログで下余白を1.5mmに設定している。

    SendKeys "%fu", True                           ' ページ設定ダイアログ開く
    SendKeys "{RIGHT}", True                     ' 右カーソルで「余白」のタブへ
    SendKeys "{TAB}{TAB}", True                ' 下余白へ移動
    SendKeys "{DOWN}{DOWN}{HOME}", True  ' 余白を1.5mmにしHOMEキーで決定
    SendKeys "{ENTER}", True                     ' 決定

これは、以下のようにつなげて書いても問題ない。

  SendKeys "%fu{RIGHT}{TAB}{TAB}{DOWN}{DOWN}{HOME}{ENTER}", True

●{ESC}の取扱い

なお、ダイアログによっては{ENTER}だけでは、ダイアログが閉じない。その場合は

    SendKeys "{ESC}", True        ' ESCキーでダイアログを閉じる

しかし、{ESC}処理は長いマクロコードの中で使うと、問題を引き起こすことがある。
タイミングによっては、マクロを停止させるESCキー入力と誤判断され、処理が中断されることがあるのだ。
このため、該当サブルーチン等の中では、前もって、ESCキーのキャンセル処理を受け付けないようにしておく。

    Application.EnableCancelKey = xlDisabled

    Sendkeys ".......",True
    SendKeys "{ESC}", True        ' ESCキーでダイアログを閉じる

 



最新の画像もっと見る

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。