見出し画像

【BAT】バッチファイルからExcelファイルを読み取って、読み取った情報をもとにスケジュールタスクを作成するツール

ちょっと長いタイトルですが、趣旨としては
 ・バッチファイルからExcelファイルを読み取る。
 ・読み取った情報をバッチファイルへ戻す。
 ・タスクスケジューラーで新規スケジュールタスクを作成する。
の流れをツール化したものです。

使いどころは…
何かの受付台帳(問い合わせ台帳とか)をExcel管理していて、回答期日の1日前にリマインドを出したい!
ToDoリストの対応期日の〇日前にリマインドを出したい!
一度リマインド設定したら、途中でPC電源を落としても大丈夫なツールが欲しい!
ってときに有効です。

バッチファイルだから、ダブルクリックですぐ起動できます。
Excelファイルの読み込み速度もまあまあ高速(許容範囲)でした。

@ECHO OFF

REM -------------------------------
REM ファイルパスを設定
REM -------------------------------
SET Folder=\****\****\****\****\
SET File=サンプル.xlsx

REM -------------------------------
REM カレントフォルダを変更
REM -------------------------------
CD/d C:%Folder%

REM -------------------------------
REM VBSファイル作成
REM -------------------------------
SET vbsFile=vbsFile.vbs
REM Excelオブジェクト設定
ECHO Dim objExcel > %vbsFile%
ECHO Dim objWorkbook >> %vbsFile%
ECHO Dim objSheet >> %vbsFile%
ECHO Set objExcel = CreateObject("Excel.Application") >> %vbsFile%
ECHO Set objWorkbook = objExcel.Workbooks.Open("%Folder%\%File%") >> %vbsFile%
ECHO Set objSheet = objWorkbook.Sheets(1) >> %vbsFile%
REM A2セルを読み取って変数Day1へ代入
ECHO Dim Day1 >> %vbsFile%
ECHO Day1 = objSheet.Range("A2").Value >> %vbsFile%
REM Excelオブジェクト終了
ECHO objWorkbook.Close >> %vbsFile%
ECHO objExcel.Quit >> %vbsFile%
ECHO Set objSheet = Nothing >> %vbsFile%
ECHO Set objWorkSheet = Nothing >> %vbsFile%
ECHO Set objExcel = Nothing >> %vbsFile%
REM 変数Day1の1日前を変数Day2へ代入
ECHO Dim Day2 >> %vbsFile%
ECHO Day2 = DateAdd("d", -1, Day1) >> %vbsFile%
REM 変数Day2が、未来の日付か過去の日付かチェック
ECHO Dim Flag >> %vbsFile%
ECHO Flag="未来" >> %vbsFile%
ECHO If DateDiff("d", Now, Day2) ^< 0 Then >> %vbsFile%
ECHO	Flag="過去" >> %vbsFile%
ECHO ElseIf DateDiff("d", Now, Day2) = 0 Then >> %vbsFile%
ECHO	Flag="現在" >> %vbsFile%
ECHO End If >> %vbsFile%
REM CMDへパラメータを渡すためテキスト出力
ECHO Dim fso >> %vbsFile%
ECHO Dim Fpath >> %vbsFile%
ECHO Set fso = CreateObject("Scripting.FileSystemObject") >> %vbsFile%
ECHO Fpath = fso.getParentFoldername(WScript.ScriptFullName) >> %vbsFile%
ECHO With fso.CreateTextFile(Fpath ^& "\一時ファイル.txt") >> %vbsFile%
ECHO	.WriteLine Day2 ^& "," ^& Day1 ^& "," ^& Flag >> %vbsFile%
ECHO	.Close >> %vbsFile%
ECHO End With >> %vbsFile%
ECHO Set fso = Nothing >> %vbsFile%

REM -------------------------------
REM VBSファイル実行&削除
REM -------------------------------
Cscript %vbsFile%
DEL %vbsFile%

REM -------------------------------
REM テキストファイルを読み込んで変数へ代入&テキストファイル削除
REM -------------------------------
FOR /f "tokens=1,2,3* delims=," %%a IN (一時ファイル.txt) DO (
	SET Remind=%%a
	SET CellA2=%%b
	SET Flag=%%c
	)
DEL 一時ファイル.txt
ECHO 「%File%」を読み込みました。
ECHO 読み取った日付は………………………………………%CellA2%
ECHO リマインド予定日(読み取った日付の前日)は……%Remind%
ECHO 判定結果…………………………………………………%Flag%

IF %Flag% EQU 現在 (
	ECHO リマインド予定日が当日のため、予約設定ができません。
	ECHO 未来の日付となるよう、再選択ください。
	ECHO 処理を中断します。
	PAUSE
	GOTO :EOF
)
IF %Flag% EQU 過去 (
	ECHO リマインド予定日が過去のため、予約設定ができません。
	ECHO 未来の日付となるよう、再選択ください。
	ECHO 処理を中断します。
	PAUSE
	GOTO :EOF
)

REM -------------------------------
REM タスクスケジューラーの設定
REM -------------------------------
:QUESTION
	SET /p Check=リマインド設定(タスクスケジューラーへ登録)しますか? (y/n)
	ECHO %Check%
	IF /i %Check% EQU y GOTO :LABEL1
	IF /I %Check% EQU n GOTO :LABEL2
	ECHO もう一度入力してください
	GOTO :QUESTION
:LABEL1
	Schtasks /create /tn "リマインダーVBS起動" /tr %Folder%\再通知ポップアップ.vbs /sc once /st 9:00 /sd %Remind% /f
	PAUSE
	GOTO :EOF
:LABEL2
	GOTO :EOF

これをメモ帳に貼り付けて、拡張子を「.bat」にして保存。
下記を事前設定のこと。
・文字コードはANSIを指定する。
・フォルダパス(\****\****\****\****\の部分)を使用環境に合わせて変更。
 →読み取りたいExcelが格納されているフォルダ―パス
・ファイルパス(サンプル.xlsxの部分)を使用環境に合わせて変更。
 →読み取りたいExcelのファイル名
・ドライブ名(CD/d C:%Folder%の行の「C:」の部分)を使用環境に合わせ
 て変更。
 →読み取りたいExcelが格納されているドライブ名
・Excelシート上の読取り範囲(objSheet.Range("A2").Valueの部分)を使用
 環境に合わせて変更。
・スケジュールタスクに設定するアクション(下から5行目の「%Folder%\再 
 通知ポップアップ.vbs」の部分)を使用環境に合わせて変更。
 →指定日時になったら起動させたいファイルやスクリプトを指定


以下、コードの補足。
【ファイルパスを設定】の部分
上記コードでは変数Folderに直接パスを記入しています。ただし、バッチファイル自身も同じフォルダに入れておく運用ならば
「SET Folder=%~dp0」に書き換えてもOK。

【カレントフォルダを変更】の部分
会社では、ドライブを複数使い分けているケースも珍しくないと思います。そのため、ドライブ名を確認する意味も込めて、別出しで記載しました。
バッチファイルが動かなかったり強制終了する場合は、このカレントフォルダの設定が合っていない可能性があるので要注意。
CDコマンドでカレントフォルダを確認可能。

【VBSファイルを作成】の部分
コマンドプロンプトから直接Excelを操作できないため、一旦VBSを経由してExcel遠隔操作します。
>および>>で、VBSファイルへ1行づつ書き込みます。
VBS経由でExcelシート上の値をテキストファイルへ出力していますが、これは呼び出し元であるコマンドプロンプト側でString型の戻り値を受け取る方法がないため、一旦テキストファイルへ出力したあとコマンドプロンプト側でそれを読み取る運用とした為です。
 ※VBS作成→VBSからExcel読み取り→VBSで変数をテキスト出力→VBS削除→テキスト読み取り(変数受取り)→テキスト削除
回りくどいですが、バッチファイルで処理する以上は仕方ないかな。Date型変数(日付)の扱いも、全部VBS経由で処理させています。

【VBSファイル実行&削除】の部分
CscriptコマンドでVBSを実行しています。
今回はやってませんが、同様にVBSを経由することでExcelマクロを遠隔起動することも可能です。

【テキストファイルを読み込んで変数へ代入&テキスト削除】の部分
delimsスイッチで指定した「,」で区切られた個々のデータから文字列を切り出して変数にセットします。tokensスイッチの最後が「*」の場合は、残りのトークン全部を受け取ります。
FORコマンドで使用する変数名を%a(BAT内では%%a)とした場合、1番目のトークンが%a(%%a)、2番目が%b(%%b)となるように、連続するアルファベットが自動的に割り当てられます。
今回、3番目のトークン%b(%%b)つまり変数Flagの値を判断基準にして、「現在」または「過去」なら強制終了させることにしました。

【タスクスケジューラの設定】の部分
Schtasksコマンドの/createスイッチでスケジュールタスクを新規作成します。(ここを処理したくてBATファイルで書いた。)
/tnオプションは、スケジュールタスクの名前。
/trオプションは、スケジュールタスクとして実行するコマンドを指定。
上記コードではとりあえず、前回作成したVBSを起動するようにしました。
 【VBS】無限にリマインドしてくれる物忘れ防止ツール(←ダメ人間に嬉しい)|地獄の油揚げ (note.com)
適宜変えてください。
/scオプションは、スケジュール実行のタイプ。onceで1回のみ実行。
/stと/sdオプションで、日時を指定。

【その他】
★設定済みスケジュールを一覧形式で確認
「Schtasks /query /tn "スケジュールタスクの名前" /fo list /v」
★設定済みスケジュールを削除
「Schtasks /delete /tn "スケジュールタスクの名前" /f」


今回、何故わざわざバッチファイルで書いたかというと、最後のタスクスケジューラーへの登録がどうしてもバッチファイルじゃないと処理できなかったから。
(どうやらExcel VBAからタスクスケジューラーの登録処理(Schtasksコマンド)をすると、セキュリティソフトに「トロイの木馬が検出されました」と誤検知される模様…)
Schtasksコマンドの部分だけバッチファイルで処理するのも微妙だったので、いっそ全部バッチで書いちゃえ、ということで作成。

VBSを経由して外部アプリケーションを操作する処理や、テキストファイルを経由して引数を受け取る処理や、対話型のループ処理なんかは、汎用性があって他のツールにも使い回せそうな気がします。

この記事が気に入ったらサポートをしてみませんか?