今回まとめておくのは、下図のシステム構成のうち、①~③のBios→Windows指定時間起動、Windows→Excel指定時間起動、Excel→VBAの各プログラム指定時間起動の部分。

BIOSのAPMによるWindows指定時間起動
Windowsを指定時間に起動させるには、Windows上で設定するのではなく、BIOSによる設定が必要となる。メーカーが違っていたり、年代が違えば設定画面は異なると思うが、私が使用している10年以上前のPCのマザーボード(ASUS:P7P55D-E EVO)の設定(スクリーンショット不可のため画像は取説引用)ではAPM:Advanced Power Managementによって行う。
具体的な手順としては、まず、PC起動時に「Del」キーを押すことで、BIOSを起動。BIOS画面にて、Powerのタブを選択し、「APM Configuration」を選択。

「Power On By RTC Alarm」をEnabledにすると、RTC Alarm Date(Days) とSystem Timeが設定可能となる。RTC Alarm Date(Days) を「Every Day」、System Timeを「08:30:00」に設定。市場開場日のみ起動したいものの、BIOSではそこまで細かい設定ができないため、ここでは、毎日8:30にWindowsを起動させるように設定する。

タスクスケジューラによるExcelファイルの指定時間起動
指定時間に指定のExcelファイルを開くために、Windowsの標準機能として内蔵されているタスクスケジューラを利用する。タスクスケジューラでは起動する曜日を指定できるが、祝日を除くことはできない。そのため、タスクスケジューラもWindowsと同様、毎日起動することとし、Excelにて、市場開場日のみ各プログラムが起動するように設定する。タスクスケジューラの具体的な設定手順は下記のとおり。
まず、「Windowsの検索」若しくは「Windowsスタート>Windows 管理ツール>タスクスケジューラ」によってタスクスケジューラアプリを開く。タスクスケジューラが開かれるため、既存のタスクと分けるために、「タスクスケジューラライブラリを右クリック>新しいフォルダー」で「System_Trade」フォルダを作成する。

「System_Tradeフォルダを右クリック>タスクの作成」で、名前「Auto_Start」を入力。

「トリガータブをクリック>新規」で、新しいトリガー画面が開かれる。「毎日」を設定し、開始日時2022/1/27 8:40を設定(日付は翌日以降を設定)し、「OK」をクリック。

タスクの作成画面に戻るため、「操作タブをクリック>新規」で、「新しい操作」画面が表示する。プログラム/スクリプトは「”C:\Program Files\Microsoft Office\root\Office16\EXCEL.EXE”」を参照し、引数の追加は「指定のExcelファイルパス名」を入力(ファイルパス名 /eを入力することで、Excelの起動画面を省略して起動)し、「OK」をクリック。

タスクの作成画面に戻るため、「OK」をクリックすることで、System_Tradeフォルダの中にAuto_Startのタスクが生成される。テストする場合は、Auto_Startを右クリックし、「実行する」をクリックすれば、指定のExcelファイルが開かれるかテスト可能。

各プログラムの指定時間起動
Excel起動後、市場休業日であればExcel保存終了してシャットダウン、市場開場日であれば、自動的に各プログラムが起動するように設定する。
'user32のMessageBoxTimeoutA関数使用のための宣言(64bit版:PtrSafe付)
Private Declare PtrSafe Function MessageBoxTimeoutA Lib "user32" ( _
ByVal hWnd As Long, _
ByVal lpText As String, _
ByVal lpCaption As String, _
ByVal uType As Long, _
ByVal wLanguageId As Long, _
ByVal dwMilliseconds As Long) As Long
Sub Auto_Open()
'8:30にパソコン起動
'8:40にExcel起動
'初期設定
Call InitialSetup
'プログラム自動起動モードか作業モードか選択してプログラム動作を変更する
Dim ReturnMessage As Integer
ReturnMessage = MessageBoxTimeoutA(0&, "プログラム自動起動モードで起動?", "【60秒後にプログラム自動起動】", vbYesNo, 0&, 60000)
If ReturnMessage = vbNo Then
'<作業モード>
Exit Sub
Else
'<プログラム自動起動モード>
'Holidayを定義
Dim Holiday As Range
Set Holiday = Worksheets("Market Closed").Range("B:B"). _
Find(Date, LookAt:=xlWhole)
'休業日ではない、かつ、土日ではない⇒市場開場、それ以外⇒市場休業
If Holiday Is Nothing And Weekday(Date, 2) <= 5 Then
'<市場開場>
'8:45にkabuStation起動
Application.OnTime EarliestTime:=TimeValue("08:45:00"), Procedure:="StartKabuStation"
'8:50にトークン取得
Application.OnTime EarliestTime:=TimeValue("08:50:00"), Procedure:="GetToken"
'8:53に銘柄登録
Application.OnTime EarliestTime:=TimeValue("08:53:00"), Procedure:="Register"
'8:56に一営業日前の取引データ抹消
Application.OnTime EarliestTime:=TimeValue("08:56:00"), Procedure:="DataReset"
'8:59~12:29~リアルタイムデータ取得
Application.OnTime EarliestTime:=TimeValue("08:59:00"), Procedure:="RealTimeRecord"
Application.OnTime EarliestTime:=TimeValue("12:29:00"), Procedure:="RealTimeRecord"
'15:06にkabuStation終了(RealTimeRecord終了を15:30まで待つ)
Application.OnTime EarliestTime:=TimeValue("15:06:00"), Procedure:="CloseKabuStation", LatestTime:=TimeValue("15:30:00")
'15:09にkabuStation起動(RealTimeRecord終了を15:30まで待つ)
Application.OnTime EarliestTime:=TimeValue("15:09:00"), Procedure:="StartKabuStation", LatestTime:=TimeValue("15:30:00")
'15:12にトークン取得(RestartkabuStation終了を15:30まで待つ)
Application.OnTime EarliestTime:=TimeValue("15:12:00"), Procedure:="GetToken", LatestTime:=TimeValue("15:30:00")
'15:15に本日の日足データを取得(GetToken終了を15:30まで待つ)
Application.OnTime EarliestTime:=TimeValue("15:15:00"), Procedure:="GetDaily", LatestTime:=TimeValue("15:30:00")
'18:15に本日の分足データを取得(GetDaily終了を19:00まで待つ)
Application.OnTime EarliestTime:=TimeValue("18:15:00"), Procedure:="GetOHLC", LatestTime:=TimeValue("19:00:00")
'23:00にシャットダウン(GetOHLC終了を23:59まで待つ)
Application.OnTime EarliestTime:=TimeValue("23:00:00"), Procedure:="Auto_ShutDown", LatestTime:=TimeValue("23:59:59")
Else
'<市場休業>
'シャットダウン
Call Auto_ShutDown
End If
End If
End Sub
Sub Auto_ShutDown()
Dim WSH As New WshShell
ThisWorkbook.Save
WSH.Run "shutdown -s -f -t 10", 0, False
Application.Quit
ThisWorkbook.Close
End SubAuto_OpenによるExcel起動後のプログラム実行
Excel起動後に実行するプログラムとする方法として、Auto_OpenとWorkbook_Openの2つがある。
- 標準モジュールのプロシージャー名をAuto_Openとして、その中にVBAのコードを記述する。
- ブックモジュール「ThisWorkbook」のプロシージャー名Workbook_Openとして、その中にVBAのコードを記述する。
Sub Auto_Open()
***エクセル起動時のVBAコード記述***
End Sub2つの方法の違いとして、「VBAのWordkbooks.Openで他ファイルを起動した場合、Auto_Openの内容は実行されない」、「Workbook_Openが作成されている場合、Wordkbook_Open→Auto_Openの順で実行される」といったものがある。今回はタスクスケジューラによってExcelを開くため、どちらの方法でも可能。ここでは、個人的な好みとして、他プログラムを全て標準モジュールで作成していることから、それと合わせてAuto_Openを使う。
MessageBoxTimeoutAによるプログラム自動起動モードと作業モードの使い分け
Auto_Openを使う場合、Excel起動時、毎回プログラムが起動される。プログラムを改修する場合、自動起動して欲しくないので、プログラム自動起動モードで起動するか、作業モードで起動するか選択できるようにする。また、作業モードで起動しないのであれば、自動的にプログラム自動起動モードで起動するように設定する。
これを実現するために、何も選択しなければ自動的に閉じるWindowsAPIのMessageBoxTimeoutAを使用して、モードの使い分けを行う。MessageBoxTimeoutAを使用するために、subの前で宣言(32bit版の場合は不要だが、64bit版の場合はFunctionの前にPtrSafeの記述が必要)。
'user32のMessageBoxTimeoutA関数使用のための宣言(64bit版:PtrSafe付)
Private Declare PtrSafe Function MessageBoxTimeoutA Lib "user32" ( _
ByVal hWnd As Long, _
ByVal lpText As String, _
ByVal lpCaption As String, _
ByVal uType As Long, _
ByVal wLanguageId As Long, _
ByVal dwMilliseconds As Long) As LongExcel起動時に「プログラム自動起動モード」で起動するかどうか確認するMessageBoxを表示し、選択によってモードを使い分ける。
- 「はい」を選択 or 60秒間何も選択しない→「プログラム自動起動モード」で起動
- 「いいえ」を選択→「作業モード」で起動
'プログラム自動起動モードか作業モードか選択してプログラム動作を変更する
Dim ReturnMessage As Integer
ReturnMessage = MessageBoxTimeoutA(0&, "プログラム自動起動モードで起動?", "【60秒後にプログラム自動起動】", vbYesNo, 0&, 60000)
If ReturnMessage = vbNo Then
'<作業モード>
ReturnMessage = MessageBoxTimeoutA(0&, "作業モードで起動", "【5秒後に自動表示消去】", vbInformation, 0&, 5000)
Else
'<プログラム自動起動モード>
***プログラム自動起動時のVBAコード記述***
Endif
MessageBoxTimeoutAのパラメータ、タイプ、戻り値はMicrosoft BuildのMsgBox関数等のドキュメントを参考にまとめた。なお、hwnd、wLanguageIdについては0&以外にする必要はない(0&は長整数型(Long型)の0を表す。wLanguageIdについては、0の場合、システム上のデフォルト言語となる)。また、vb~の定数は組み込み定数と呼ばれるもので、プログラム上は定数=値となるため、定数名と値どちらを使用しても良い。
| パラメータ | 説明 |
| hwnd | Windowsにおけるメッセージボックスのハンドル(識別子) |
| IpText | メッセージ ボックスに表示されるテキスト |
| IpCaption | メッセージ ボックスに表示されるタイトル |
| uType | メッセージ ボックスの内容と動作を指定 |
| wLanguageId | メッセージボックスに表示される言語 |
| dwMilliseconds | ユーザーの応答を待機する時間 (ミリ秒) |
| 定数 | 値 | 内容 |
| vbOKOnly | 0 | [OK] ボタンのみを表示 |
| vbOKCancel | 1 | [OK] ボタンと [キャンセル] ボタンを表示 |
| vbAbortRetryIgnore | 2 | [中止]、[再試行]、[無視] の各ボタンを表示 |
| vbYesNoCancel | 3 | [はい]、[いいえ]、[キャンセル] の各ボタンを表示 |
| vbYesNo | 4 | [はい] ボタンと [いいえ] ボタンを表示 |
| vbRetryCancel | 5 | [再試行] ボタンと [キャンセル] ボタンを表示 |
| vbCritical | 16 | [重大なメッセージ] アイコンを表示 |
| vbQuestion | 32 | [警告クエリ] アイコンを表示 |
| vbExclamation | 48 | [警告メッセージ] アイコンを表示 |
| vbInformation | 64 | [情報メッセージ] アイコンを表示 |
| 定数 | 値 | 内容 |
| vbOK | 1 | OK |
| vbCancel | 2 | キャンセル |
| vbAbort | 3 | 中止 |
| vbRetry | 4 | 再試行 |
| vbIgnore | 5 | 無視 |
| vbYes | 6 | はい |
| vbNo | 7 | いいえ |
| 自動的に閉じる | 32000 | 自動的に閉じる |
市場開場日と市場休業日の判定
土日以外の休業日を設定するため、「Market Closed」のシートを作成し、JPXのHP(営業時間・休業日一覧 | 日本取引所グループ (jpx.co.jp))から2022 年休業日一覧をB2セルへコピペ。

Excelシートの関数とは異なり、本日の日付を返すのはDate関数。Find関数にて、Market ClosedシートのB列から本日の日付と完全一致(LookAt:=xlWhole)する日付を探し、あれば本日の日付、なければNothingを返す。
本日の日付が市場休業日ではない(Holiday Is Nothing)かつ、土日ではない(weekday関数では、月曜から順に1から7の数字を返し、それが5以下)場合、市場開場日とみなし、各プログラムを起動する。市場休業日の場合は、Excelを閉じて、PCをWindowsをシャットダウンする。
'Holidayを定義
Dim Holiday As Range
Set Holiday = Worksheets("Market Closed").Range("B:B"). _
Find(Date, LookAt:=xlWhole)
'休業日ではない、かつ、土日ではない⇒市場開場、それ以外⇒市場休業
If Holiday Is Nothing And Weekday(Date, 2) <= 5 Then
'<市場開場>
***市場開場時のVBAコード記述***
Else
'<市場休業>
'シャットダウン
Call Auto_ShutDown
EndifAuto_ShutDownプロシージャ(ExcelとWindowsのシャットダウン)
Excelの終了とWindowsのシャットダウンはAuto_ShutDownプロシージャを作成して行う。内容としては、まずはExcelファイルを保存(Thisworkbook.save)。その後、アプリケーションを強制終了(- f)して、Windowsを10秒後(-t 10)にシャットダウン(shutdown -s)するように設定。なお、シャットダウン時、ウインドウ表示せず(WScript.ShellのrunメソッドWindowStyle:0)、シャットダウンの終了を待たない(WScript.ShellのrunメソッドWaitOnReturn:False)ものとする。
10秒後にシャットダウンするようにしたうえで、ワークブックを閉じて(ThisWorkbook.Close)、Excelを終了(Application.Quit)する。Application.Quitは一連のスクリプト実行後にExcelを終了するものであるため、Application.Quit→ThisWorkbook.Closeの順番が正しい(逆の場合、ワークブックは閉じるが、Excelは終了しない)。
Sub Auto_ShutDown()
Dim WSH As New WshShell
ThisWorkbook.Save
WSH.Run "shutdown -s -f -t 10", 0, False
Application.Quit
ThisWorkbook.Close
End Sub本コードでは、WshShellの参照設定(「VBA画面>ツールメニュー>参照設定>「Windows Script Host Object Model」にチェック>OK」)を行い、WshShellオブジェクトを利用してシャットダウンを行っている。参照設定することで、WSH as New WshShellという形でWshShellオブジェクトを定義可能となる。一方、参照設定しない場合、Dim WSH as Objectでオブジェクト定義後、Set objWshShell = WScript.CreateObject(“WScript.Shell”)という形でWshShellオブジェクトを定義可能。参照設定することの利点として、コード記述時に入力候補が表示されるようになること、コードがシンプルに記述できるようになることの利点があるため、WshShellの参照設定を行っている。
Application.Ontimeによる各プログラムの指定時間起動
各プログラムの起動はApplication.Ontimeによって行う。EarliestTime:=○○により設定された時間に、Procedure:=△△により指定されたプロシージャを起動する。各プロシージャ(InitialSetup含む)の詳細は、今後の記事にまとめる。
'8:45にkabuStation起動
Application.OnTime EarliestTime:=TimeValue("08:45:00"), Procedure:="StartKabuStation"
'8:50にトークン取得
Application.OnTime EarliestTime:=TimeValue("08:50:00"), Procedure:="GetToken"
'8:53に銘柄登録
Application.OnTime EarliestTime:=TimeValue("08:53:00"), Procedure:="Register"
'8:56に一営業日前の取引データ抹消
Application.OnTime EarliestTime:=TimeValue("08:56:00"), Procedure:="DataReset"
'8:59~12:29~リアルタイムデータ取得
Application.OnTime EarliestTime:=TimeValue("08:59:00"), Procedure:="RealTimeRecord"
Application.OnTime EarliestTime:=TimeValue("12:29:00"), Procedure:="RealTimeRecord"
'15:06にkabuStation終了(RealTimeRecord終了を15:30まで待つ)
Application.OnTime EarliestTime:=TimeValue("15:06:00"), Procedure:="CloseKabuStation", LatestTime:=TimeValue("15:30:00")
'15:09にkabuStation起動(RealTimeRecord終了を15:30まで待つ)
Application.OnTime EarliestTime:=TimeValue("15:09:00"), Procedure:="StartKabuStation", LatestTime:=TimeValue("15:30:00")
'15:12にトークン取得(RestartkabuStation終了を15:30まで待つ)
Application.OnTime EarliestTime:=TimeValue("15:12:00"), Procedure:="GetToken", LatestTime:=TimeValue("15:30:00")
'15:15に本日の日足データを取得(GetToken終了を15:30まで待つ)
Application.OnTime EarliestTime:=TimeValue("15:15:00"), Procedure:="GetDaily", LatestTime:=TimeValue("15:30:00")
'18:15に本日の分足データを取得(GetDaily終了を19:00まで待つ)
Application.OnTime EarliestTime:=TimeValue("18:15:00"), Procedure:="GetOHLC", LatestTime:=TimeValue("19:00:00")
'23:00にシャットダウン(GetOHLC終了を23:59まで待つ)
Application.OnTime EarliestTime:=TimeValue("23:00:00"), Procedure:="Auto_ShutDown", LatestTime:=TimeValue("23:59:59")コンテンツの有効化とドキュメント検査機能の非表示設定
今回まとめたExcel VBAによる各プログラムの指定時間起動を行うには、xlsmファイル起動時、マクロを実行するために必要となる「コンテンツの有効化」と「ドキュメント検査機能では削除できない個人情報がドキュメントに含まれていることがありますので、ご注意ください。」の非表示設定が必要。いずれもセキュリティ確保のために用意された警告文であるものの…警告文が出ないように設定する。
いずれもExcel>ファイル>オプション>トラストセンター>トラストセンターの設定の中で行う。「コンテンツの有効化」の非表示設定は、マクロの設定の中で、「VBAマクロを有効にする」。「ドキュメント検査機能」の非表示設定は、プライバシーオプションの中で、「ファイルを保存するときにファイルのプロパティから個人情報を削除する」のチェックを外す。

