【実務・中級編】【初心者向け】DateCreatedプロパティを利用した「本日生成された提出ファイル」のみを自動ピックアップするVBS – VBScript (Visual Basic Scripting Edition)解析バイブル

スポンサーリンク
スポンサーリンク

【極限の自動化】VBScriptによる「本日分ファイル」抽出の真髄: DateCreated を使いこなす堅牢な設計思想

「今日作成されたファイルだけをコピーして、別のフォルダにまとめておく」

業務自動化の初歩として、誰もが一度は挑戦するテーマだ。しかし、多くの開発者がここで「動けばいい」というレベルの、極めて脆弱なスクリプトを書き、数週間後に「なぜかファイルが抽出されない」というクレームを受けて頭を抱えることになる。

なぜ、彼らのスクリプトは失敗するのか?
それは、プログラミングにおける「時間」の概念と、オブジェクトの「ライフサイクル」に対する理解が決定的に不足しているからだ。

本稿では、単なるコピペ用のコードを提供するのではない。プロフェッショナルとして、バグを未然に防ぎ、保守性の高い「プロダクション・レベル」のスクリプトを設計するための思考プロセスを伝授する。

1. 初心者が陥る「致命的な設計ミス」

まず、典型的な失敗例を見てみよう。多くの初心者は、以下のようなロジックを組んでしまう。

' --- 典型的な失敗例 (Anti-Pattern) ---
If file.DateCreated = Date Then
    ' コピー処理
End If

このコードを見た瞬間、私は溜息が出る。なぜなら、この条件式が真(True)になることは、ほぼあり得ないからだ。

なぜ失敗するのか?

VBScriptにおける `Date` 関数は、「日付(YYYY/MM/DD 00:00:00)」を返す。一方で、`file.DateCreated` プロパティは、「作成日時(YYYY/MM/DD HH:mm:ss)」という、秒単位までの詳細な情報を保持している。

「2023/10/27 10:30:00」と「2023/10/27 00:00:00」を比較して、一致すると判定できるだろうか? 答えは No だ。

プロフェッショナルは、比較を行う前に「粒度(Granularity)」を合わせる。日付のみを抽出するのか、範囲を指定するのか。この設計判断が、システムの信頼性を左右する。

2. 堅牢な設計のための3つの鉄則

実務で通用するスクリプトを書くためには、以下の3点を遵守しなければならない。

① 時間の比較における「粒度」の制御

前述の通り、日付比較を行う際は、時間の情報を切り捨てるか、あるいは「今日の開始時刻」から「明日の開始時刻」までの範囲指定を行う必要がある。

② リソースの適切なライフサイクル管理

`FileSystemObject` (FSO) はCOMオブジェクトだ。ループの中で何度も生成したり、使い終わった後に適切に解放(`Set obj = Nothing`)しなかったりする行為は、メモリリークや予期せぬファイルロックの原因となる。オブジェクトは「一度生成し、使い回し、最後に確実に破棄する」のが鉄則だ。

③ エラーハンドリングの徹底

ファイル操作は、常に「不確実性」と隣り合わせだ。

  • 対象フォルダが存在しない。
  • ファイルが他のプロセスによって使用中(ロックされている)である。
  • 書き込み権限がない。

これらを無視したスクリプトは、エラーが発生した瞬間に「沈黙」するか、あるいは「暴走」する。

3. プロダクション・コードの実装例

それでは、上記の教訓をすべて反映した、実務レベルのコードを提示する。このコードは、単に動くだけでなく、エラーに強く、設定変更にも容易に対応できる設計になっている。

' ==========================================================================
' Script Name: DailyFilePicker.vbs
' Description: 本日作成されたファイルを抽出し、指定フォルダへコピーする
' Author: Chief Architect
' ==========================================================================

Option Explicit ' 変数の強制宣言(バグ防止の必須設定)

' --- 設定セクション (Configuration) ---
' 実際の実務では、これらを外部のINIファイルやDBから読み込むように設計するのが理想的だ
Const SRC_DIR = "C:\Work\Input"      ' 監視対象フォルダ
Const DEST_DIR = "C:\Work\Output"    ' コピー先フォルダ

' --- メインルーチン ---
Main

Sub Main()
    Dim fso, srcFolder, destFolder
    Dim file, targetDate
    Dim successCount, errorCount

    ' 1. オブジェクトの初期化
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    ' 2. 事前チェック:フォルダの存在確認
    If Not fso.FolderExists(SRC_DIR) Then
        MsgBox "エラー: ソースフォルダが見つかりません: " & SRC_DIR, vbCritical
        Exit Sub
    End If

    If Not fso.FolderExists(DEST_DIR) Then
        ' コピー先がなければ作成する(堅牢な設計)
        On Error Resume Next
        fso.CreateFolder(DEST_DIR)
        If Err.Number <> 0 Then
            MsgBox "エラー: コピー先フォルダの作成に失敗しました: " & Err.Description, vbCritical
            Exit Sub
        End If
        On Error GoTo 0
    End If

    ' 3. 比較用日付の準備(時刻を切り捨てた「今日」の基準)
    ' DateValue関数により、時刻情報を除外した日付型として扱う
    targetDate = Date()

    Set srcFolder = fso.GetFolder(SRC_DIR)
    successCount = 0
    errorCount = 0

    WScript.Echo "処理を開始します..."

    ' 4. ファイルループ処理
    For Each file In srcFolder.Files
        ' エラーハンドリング:個別のファイル操作でスクリプト全体を止めない
        On Error Resume Next
        
        ' 【重要】DateValueを用いて、ファイルの作成日(DateCreated)から時刻を排除して比較
        If DateValue(file.DateCreated) = targetDate Then
            
            ' コピー実行(既存ファイルがある場合は上書き: True)
            file.Copy DEST_DIR & "\" & file.Name, True
            
            If Err.Number = 0 Then
                successCount = successCount + 1
            Else
                WScript.Echo "警告: ファイルのコピーに失敗しました (" & file.Name & "): " & Err.Description
                errorCount = errorCount + 1
                Err.Clear
            End If
        End If
        
        On Error GoTo 0
    Next

    ' 5. 後処理と結果報告
    WScript.Echo "----------------------------------------"
    WScript.Echo "処理完了。"
    WScript.Echo "成功: " & successCount & " 件"
    If errorCount > 0 Then
        WScript.Echo "失敗: " & errorCount & " 件"
    End If
    WScript.Echo "----------------------------------------"

    ' オブジェクトの解放(メモリ管理の極意)
    Set srcFolder = Nothing
    Set fso = Nothing
End Sub

4. アーキテクトの視点:さらに高みを目指すために

このスクリプトは、実務における「第一段階」として非常に優秀だ。しかし、さらに大規模なシステムや、より高度な自動化を目指すなら、以下のステップを検討すべきである。

「作成日時」か「更新日時」か

今回のテーマは `DateCreated`(作成日時)だった。しかし、業務フローによっては「ファイルは昨日作られたが、中身を今日更新した」というケースがある。その場合、`DateLastModified` プロパティを使用すべきだ。要件定義の段階で、「何をもって『本日分』と定義するか」を明確にすること。これがエンジニアの仕事だ。

ログ出力の自動化

`WScript.Echo` は人間が画面を見るためのものだ。バッチ処理としてスケジュール実行(タスクスケジューラ)する場合、結果は画面には見えない。結果をテキストファイルやデータベースに記録する「ロギング機構」を組み込むことで、初めて「運用に耐えうるシステム」へと昇華する。

パフォーマンスの考慮

もし対象フォルダに数万個のファイルが存在する場合、FSOによるループは低速になる可能性がある。その場合は、OSレベルのコマンド(`Robocopy` など)を `WshShell.Run` で呼び出す手法を検討せよ。VBScriptは「司令塔」として使い、重い作業は「専門の道具」に任せる。これが、真の効率化エンジニアの引き際だ。

結びに代えて

自動化とは、単に「楽をするための道具」ではない。「人間が、より価値のある、創造的な仕事に集中するための環境を作る行為」である。

今日学んだ「粒度の管理」「リソースの解放」「エラーへの備え」を意識するだけで、君の書くコードの品質は、一般的なプログラマーの域を遥かに超え、プロフェッショナルの領域へと到達するだろう。

健闘を祈る。

タイトルとURLをコピーしました