m-eye blog

ノンプログラマによるVBAとPythonの学習記録

Excel VBAでIEを操作して電車の運行情報をしゃべらせるマクロその3

f:id:m-eye:20181006130806p:plain

 

はじめに

今回もきのうの続きです。

www.m-eye.net

きのう、ソースコートの全体を載せたので、順番をかんがえながら説明をしていきます。

 

まずは下準備

マクロの本題にはいるまえに「おまじない」が2つ必要です。

 

このマクロでは参照設定が必要です

参照設定が必要なライブラリは2つあります。

Microsoft Internet Controls
Microsoft HTML Object Library

この2つはExcel VBAでIEをあつかうにはかならず必要になってくるライブラリを参照する設定です。

VBE上で「ツール」→「参照設定」とたどっていってください。

ひらいたダイアログでMicrosoft Internet ControlsMicrosoft HTML Object Libraryにチェックをいれて、「OK」をクリックしてください。そうすると、設定が完了します。

f:id:m-eye:20181031211031p:plain

この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 GetInputStateSub 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なので、赤字表記にはなりません。

しかし、赤字で表記されるからといって、エラーが発生するわけではありませんので、安心して使うことができます。

 

メインプロシージャについて

f:id:m-eye:20181101194536p:plain

メインプロシージャは、この画像の「運行情報取得マクロ自動起動」ボタンに登録する、このマクロの主要なプロシージャです。

メインプロシージャは、一定の時間間隔で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メソッドくらいでしたね。

どんなプログラムでもそうだと思いますが、ある程度の目的をもったプログラムは、かならず前処理が必要になってきます。

その前処理と本題のプロシージャはきりはなしてることが普通だとおもいます。

次回は本題のプロシージャに入っていきたいとおもいます。

 

Copyright 2018 m-eye blog All Rights Reserved.