Excel VBAでIEを操作して電車の運行情報をしゃべらせるマクロその3
はじめに
今回もきのうの続きです。
きのう、ソースコートの全体を載せたので、順番をかんがえながら説明をしていきます。
まずは下準備
マクロの本題にはいるまえに「おまじない」が2つ必要です。
このマクロでは参照設定が必要です
参照設定が必要なライブラリは2つあります。
Microsoft Internet Controls Microsoft HTML Object Library
この2つはExcel VBAでIEをあつかうにはかならず必要になってくるライブラリを参照する設定です。
VBE上で「ツール」→「参照設定」とたどっていってください。
ひらいたダイアログでMicrosoft Internet Controls
とMicrosoft HTML Object Library
にチェックをいれて、「OK」をクリックしてください。そうすると、設定が完了します。
この2つを参照設定することによって、VBE上でプロパティやメソッドの候補がでてきたり、Excel VBAでIEを操作したり、HTML文書(HTMLDocumentオブジェクト)を取得・操作することができるようになります。
マクロ内で使用するWindows API関数を宣言します
#If VBA7 Then Private Declare PtrSafe Function GetInputState Lib _ "user32" () As LongPtr #Else Private Declare Function GetInputState Lib _ "user32" () As Long #End If #If VBA7 Then Private Declare PtrSafe Sub Sleep Lib "kernel32" _ (ByVal ms As LongPtr) #Else Private Declare Sub Sleep Lib "kernel32" _ (ByVal ms As Long) #End If
Windows API関数は、Windowsの機能をVBAなどのプログラミング言語からよびだすための関数であり、プログラムの先頭で宣言してからつかいます。
ここではGetInputState
関数とSleep
関数を宣言しています。
HTML文書を取得するファンクション・プロシージャF_GetHTMLDoc
のなかで、ExcelでIEを操作する際につかいます。
具体的なつかいかたはあとで説明します。
API関数を宣言するにはDeclare
ステートメントをつかいます。
Function GetInputState
とSub Sleep
はよびだす関数名を表記しています。
Lib "user32"
とLib "kernel32"
と、関数をふくむライブラリ(DLL)名を表記しています。
ふつう、32ビット版のExcelをつかっている場合は、
Private Declare Function GetInputState Lib "user32" () _ As Long Private Declare Sub Sleep Lib "kernel32" (ByVal ms As Long)
という表記です。
しかし、ここでは32ビット版と64ビット版の両方のExcelに対応する表記方法をつかっています。
64ビット版のExcelの場合は、
Private Declare PtrSafe Function GetInputState Lib _ "user32" () As LongPtr Private Declare PtrSafe Sub Sleep Lib "kernel32" _ (ByVal ms As LongPtr)
になります。
32ビット版との宣言方法の違いは、Declare
のあとにPtrSafe
をつけること、32ビット版のLong
型は64ビット版ではLongPtr
型で宣言すること、です。
32ビット版のExcelと64ビット版のExcelの場合のきりかえのためにVBA7
という「条件付きコンパイル定数」と#If〜〜〜Then〜〜〜#Else
ディレクティブをつかいます。
#If VBA7 Then ' 64ビット版のWindows API関数の宣言 #Else ' 32ビット版のWindows API関数の宣言 #End If
64ビット版のExcelのVBAのバージョンは「7」で、32ビット版のExcelのバージョンは「6」ですので、それを利用して場合分けをしています。
ちなみに、とくに理由がなければOSがWindows 10などの64ビットOSだとしても、Excelは32ビットにしておいたほうがいいと思います。
32ビット版Excelと64ビット版Excelの実質的なちがいは32ビット版のアドインが使えるかどうかだけであとは違いがありません。
ほとんど違いがなくて、万が一のときにアドインを使うかどうかということなので、使いたいときにアドインを使えないとこまるので、32ビット版Excelのほうがいいと思います。
64ビット版Excelでこの宣言をおこなうと、32ビット版の宣言の部分が赤字で表記されます。
わたしの環境は32ビット版Excelなので、赤字表記にはなりません。
しかし、赤字で表記されるからといって、エラーが発生するわけではありませんので、安心して使うことができます。
メインプロシージャについて
メインプロシージャは、この画像の「運行情報取得マクロ自動起動」ボタンに登録する、このマクロの主要なプロシージャです。
メインプロシージャは、一定の時間間隔でExcelに電車の運行情報をしゃべらせるマクロです。
ソースコード
Public Sub S_SpeakTrainInfo() Dim TargetTime As Date TargetTime = Now + TimeValue("1:00:00") Call S_SpeakTrainInfo_Core Application.OnTime TargetTime, "S_SpeakTrainInfo" End Sub
解説
このプロシージャでは、肝心の機能の「Excelに電車の運行情報をしゃべらせる」機能については、サブプロシージャを呼び出すだけです。
ここでは、一定の時間間隔でサブプロシージャをくりかえし呼び出すだけになってて、面倒な「Excelに電車の運行情報をしゃべらせる」機能はサブプロシージャまかせになってます。
まずは日付型の変数TargetTime
を宣言して、この変数に処理をくりかえす時間間隔を格納します。
Now
は現在の日付・時刻を取得する関数です。
TimeValue
は引数に文字列で表示された時刻の日付型のデータ、TimeValue("1:00:00")
の場合は1時間という日付型のデータを返します。
TargetTime = Now + TimeValue("1:00:00")
で、変数に現在から1時間後の時刻を格納します。
Call S_SpeakTrainInfo_Core
は、このプログラムのコア(中核)となる「Excelに電車の運行情報をしゃべらせる」サブプロシージャを呼び出して実行します。
Application.OnTime
メソッドは、指定した時間TargetTiime
に指定したプロシージャS_SpeakTrainInfo
をよびだします。
一定間隔で自動的に「Excelに電車の運行情報をしゃべらせる」にはすこしだけ工夫が必要です。
メインプロシージャをよびだした瞬間からかならず1時間後の時刻を取得して、1時間後に再度メインプロシージャそのものを呼び出します(再帰的呼び出し)。
これは意識的に無限ループをつくっていることになります。
1時間ごとにメインプロシージャを呼び出すことを無限にくりかえします。
ふつうの場合、無限ループはよくないプログラムの例としてよく出されますが、この場合はあえて無限にくりかえす(1時間ごとにサブプロシージャを呼び出す)プログラムなので、例外的に悪くはないプログラムです。
しかし、このままでは永遠におわらないプログラムであることはたしかです。
でも、カンタンにこのプログラムを終了する方法があります。
Excelそのものを終了しましょう。
そうすることでリセットされ、このプログラムの実行はなかったことになります。
おわりに
今回は、参照設定とWindows API関数の宣言、メインプロシージャの解説をしました。
VBAらしいことは、Application.OnTime
メソッドくらいでしたね。
どんなプログラムでもそうだと思いますが、ある程度の目的をもったプログラムは、かならず前処理が必要になってきます。
その前処理と本題のプロシージャはきりはなしてることが普通だとおもいます。
次回は本題のプロシージャに入っていきたいとおもいます。