私は仕事でサーバー管理をしているが、作業を行う際にスクリーンショットで証跡を残す必要がある。
Alt+PrintScreenでカレントウインドウをキャプチャ―し、Excelに切り替えてCtrl+Vで張り付ける。
作業終了まで延々とこれを繰り返す。
WinShotのようなツールを使って撮りためた画像を後からマクロで取り込むということも検討したが、あいにくフリーソフトの類は勝手にインストールすることはできず、なんとか楽にする方法は無いかと模索していた。
今日たまたまこれを実現するアイデアが浮かび、実際にコードを書いてみたらうまく動いたので自分用のメモも兼ねてここに記しておこうと思う。
画像サイズや張り付け位置の調整は後からコードに組み込めば良いので、今回のサンプルでは考慮していない。
Declare Function OpenClipboard Lib "user32" (Optional ByVal hwnd As Long = 0) As Long Declare Function CloseClipboard Lib "user32" () As Long Declare Function EmptyClipboard Lib "user32" () As Long Sub AutoCapture() MsgBox "AutoCaptureを開始します。" & vbNewLine & _ "終了するには任意のシートのA1セルにExitと入力してください。", vbInformation Dim CB As Variant Do While True CB = Application.ClipboardFormats If StrConv(ActiveSheet.Cells(1, 1).Value, vbUpperCase) = "EXIT" Then GoTo Quit If CB(1) <> -1 Then For i = 1 To UBound(CB) If CB(i) = xlClipboardFormatBitmap Then ActiveSheet.Paste Destination:=Range("A5").Offset(OffsetY, 0) OffsetY = OffsetY + 10 'クリップボードを空にする。 OpenClipboard EmptyClipboard CloseClipboard End If Next i End If DoEvents Loop Quit: MsgBox "AutoCaptureを停止しました。", vbInformation ActiveSheet.Cells(1, 1).ClearContents End Sub
AutoCaptureを実行するとDo文で無限ループに入り、常時クリップボードの中身を監視する。もし画像が入ってきたらセルに張り付け、その後クリップボードを空にする。そして再び画像が入ってくるまで無限ループする。
マクロを終了する条件は、ActiveSheetのA1セルにexitと入力すること。
無限ループでは、ループの最後に入れているDoEventsが非常に重要で、これが無いとすぐにExcelはフリーズする。
(本当はスリープも挟んだほうが良いかもしれない。)
マクロ実行中もExcelは操作でき、他のマクロの実行もできるようだ(Windows10 Excel2013で検証済)。
余談
マクロ自体のアイデアは1年ほど前からあったのだが、当初はキーフックでPrintScreenが押されたことを検知してイベントで処理できないかと考えていた。
また、無限ループで回したりしたら、同じ画像が無数に張り付いてしまうと思い込んでおり、「さっきと同じ画像かどうか」をどうやって判定させようか悩んでいた。
今日たまたまクリップボードに別のテキストをセットして画像を消したら良いということに気がついてコードを書いたらうまくいったのだが、考えてみればクリップボードの中身を消してしまえば良いわけで、なぜ最初にこれを思いつかなかったのか未だに理解しがたい。
クリップボードを空にする処理は以下のサイトを参考にした。
www7b.biglobe.ne.jp
ちなみに、無限ループを使うことを思いついたのは、この本のおかげ。
Excel VBA アクションゲーム作成入門 Excel 2007/2003/2002 対応
- 作者: 近田伸矢,谷孝一,武藤玄,USA【うさ】,影斬
- 出版社/メーカー: インプレス
- 発売日: 2009/03/06
- メディア: 単行本
- 購入: 7人 クリック: 123回
- この商品を含むブログ (12件) を見る
この本では無限ループではなく、「恒常ループ」と呼んでいる。
ビジネスアプリケーションのプログラミングを習ってきた私にとって無限ループは一種のバグである。終了条件を間違えて無限ループに陥ったコードはアプリのフリーズを引き起こし、強制終了させられる。
しかし、ゲームのように常に動きつづけるプログラムにとって、恒常ループは基本中の基本のようだ。
結局ゲームは作っていないが、頭の片隅に「恒常ループ」というキーワードがあったからこそ、今回のマクロを作ることができた。
やはり何事も経験である。分野の違うことでも少しかじっておくと、そこから広がる世界もあるのだと思った。
2015/11/29追記
改良版を作成したので、こちらの記事もどうぞ。
thom.hateblo.jp