【入門編】【HTA プログレスバー】長時間実行されるスクリプトに「残り時間」を表示する動的 HTML インターフェースの組み込み – VBScript (Visual Basic Scripting Edition)解析バイブル

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

【極限の知見】VBScriptを「道具」から「製品」へ:HTAで実装するプロ仕様のプログレスバー

こんにちは。自動化の世界へようこそ。
あなたが今、もし「VBScriptで大量のファイル操作やデータ処理を自動化したけれど、実行中に画面が止まったままなので、ユーザーから『フリーズしてるんじゃないか?』と不安がられている」という状況に直面しているなら……おめでとうございます。

あなたは今、「単なるスクリプター(書き手)」から「エンジニア(設計者)」へと脱皮する最高の入り口に立っています。

プロの現場では、コードが「正しく動くこと」と同じくらい、「動いている状態をユーザーに正しく伝えること」が重視されます。今回は、VBScript単体では不可能な「リッチなUI(ユーザーインターフェース)」を、HTA(HTML Application)という魔法を使って実装し、残り時間まで表示するプロ仕様のプログレスバーを作る手法を伝授しましょう。

ここをクリアすれば、あなたの作るツールは「怪しい黒い画面のスクリプト」から「信頼される業務アプリケーション」へと進化します。準備はいいですか?

1. なぜ VBScript 単体では「不安」を解消できないのか?

通常の `.vbs` ファイルを実行すると、コンソール画面(コマンドプロンプト)が表示されるか、あるいは完全にバックグラウンドで動作します。

従来のやり方の限界

  • MsgBox の乱用: 処理の節目で `MsgBox` を出すのは簡単ですが、大量のメッセージが出るとユーザーは「OK」を連打する作業を強いられます。これは自動化の目的である「手間を減らす」に反します。
  • 沈黙の恐怖: 長時間の処理中、画面に変化がないと、ユーザーは「プログラムが死んだのか?」「強制終了しても大丈夫か?」と迷い、誤ってタスクマネージャーから殺してしまう……。これが業務トラブルの典型例です。

そこで登場するのが HTA (HTML Application) です。

2. HTA:VBScriptに「魂の器(UI)」を与える

HTAとは、簡単に言えば「HTML/CSSで書かれた見た目に、VBScriptのロジックを流し込んだもの」です。
Windows標準の `mshta.exe` というエンジンが実行するため、特別なインストールは不要。HTMLのタグを使って、ボタン、テキストボックス、そして今回作る「プログレスバー」を自由に配置できます。

構成の考え方

プロ仕様のUIを作るには、以下の3つの要素を分離して考えます。
1. View (見た目): HTMLとCSS(プログレスバーの棒、残り時間のテキスト)
2. Logic (計算): VBScript(進捗率の計算、残り時間の予測、実際の処理)
3. Bridge (接続): HTML要素とVBScriptを繋ぐ `document.getElementById`

3. 実装:残り時間を表示するプログレスバー

それでは、実際に動くコードを見ていきましょう。このコードは、そのまま `.hta` という拡張子で保存して実行できます。

<!DOCTYPE html>
<html>
<head>
    <title>Professional Progress Monitor</title>
    <meta http-equiv="x-ua-compatible" content="ie=9">
    <hta:application 
        id="oApp"
        applicationname="ProgressApp"
        border="thin"
        caption="yes"
        showintaskbar="yes"
        singleinstance="yes"
        sysmenu="yes"
        windowstate="normal"
    >
    <style>
        body { font-family: "Segoe UI", sans-serif; background: #f4f4f9; padding: 20px; color: #333; }
        .container { width: 100%; }
        h2 { font-size: 1.2em; color: #2c3e50; }
        /* プログレスバーの外枠 */
        #progress-container {
            width: 100%;
            background-color: #e0e0e0;
            border-radius: 5px;
            overflow: hidden;
            margin: 20px 0;
        }
        /* プログレスバーの実体 */
        #progress-bar {
            width: 0%;
            height: 25px;
            background-color: #3498db;
            transition: width 0.1s ease-in-out;
        }
        .status-text { font-size: 0.9em; color: #7f8c8d; }
        .info-box { margin-top: 10px; font-weight: bold; }
        button { 
            padding: 10px 20px; cursor: pointer; 
            background: #2ecc71; color: white; border: none; border-radius: 3px;
        }
        button:hover { background: #27ae60; }
    </style>

    <script language="vbscript">
        ' --- 変数の宣言 ---
        Dim startTime, totalSteps, currentStep
        Dim elapsedTime, estimatedTotalTime, remainingTime

        ' 画面の初期化
        Sub Window_OnLoad
            window.resizeTo 450, 250
        End Sub

        ' メイン処理
        Sub StartProcess()
            ' UIのリセット
            SetProgressBar 0
            document.getElementById("status").innerText = "処理を開始しています..."
            document.getElementById("timer").innerText = "残り時間: 計算中..."
            
            ' 開始時間を記録 (Timer関数は秒単位の浮動小数点)
            startTime = Timer
            
            ' 模擬的な総ステップ数 (実際はファイル数やレコード数)
            totalSteps = 100
            
            ' 実際のループ処理
            For currentStep = 1 To totalSteps
                ' ---------------------------------------------------------
                ' ここに本来やりたい「重い処理」を記述します
                ' ---------------------------------------------------------
                WScript.Sleep 100 ' 0.1秒待機(デモ用)
                ' ---------------------------------------------------------

                ' 進捗の更新処理を呼び出す
                UpdateUI currentStep
            Next

            document.getElementById("status").innerText = "完了しました!"
            document.getElementById("timer").innerText = "残り時間: 0秒"
        End Sub

        ' UIを更新するサブプロシージャ
        Sub UpdateUI(step)
            Dim progressPercent, now
            
            ' 1. 進捗率の計算
            progressPercent = (step / totalSteps) * 100
            
            ' 2. プログレスバーの幅を更新
            document.getElementById("progress-bar").style.width = progressPercent & "%"
            
            ' 3. 残り時間の計算 (ここがエンジニアの腕の見せ所)
            now = Timer
            elapsedTime = now - startTime ' 経過時間
            
            ' 経過時間から、1ステップあたりの時間を割り出し、残り時間を予測する
            ' 式: (経過時間 / 現在の進捗) * 残りの進捗量
            If step > 0 Then
                estimatedTotalTime = elapsedTime / (step / totalSteps)
                remainingTime = estimatedTotalTime - elapsedTime
                
                ' 表示用に整形
                document.getElementById("timer").innerText = "残り時間: 約 " & FormatSeconds(remainingTime)
            End If
            
            document.getElementById("status").innerText = "処理中... (" & step & "/" & totalSteps & ")"
        End Sub

        ' 秒数を「分:秒」形式に変換する関数
        Function FormatSeconds(totalSecs)
            Dim mins, secs
            mins = Int(totalSecs / 60)
            secs = Int(totalSecs Mod 60)
            FormatSeconds = mins & "分" & secs & "秒"
        End Function

        ' プログレスバーを強制リセットする関数
        Sub SetProgressBar(percent)
            document.getElementById("progress-bar").style.width = percent & "%"
        End Sub
    </script>
</head>
<body>

<div class="container">
    <h2>自動化タスク実行</h2>
    
    <div id="progress-container">
        <div id="progress-bar"></div>
    </div>

    <div class="status-text" id="status">待機中...</div>
    <div class="info-box" id="timer">残り時間: --</div>
    
    <br>
    <button onclick="StartProcess()">処理を開始</button>
</div>

</body>
</html>

4. プロの視点:コードの深掘りと「陥りやすい罠」

このコードをただコピペするだけでは、あなたはまだ「初学者」です。伝説的なエンジニアになるために、以下の3つのポイントを理解してください。

① 残り時間の計算アルゴリズム

残り時間の予測には、「経過時間 ÷ 進捗率」という数学的アプローチを使っています。

  • 経過時間 ($E$): `現在時刻 – 開始時刻`
  • 進捗率 ($P$): `現在のステップ / 総ステップ`
  • 推定総時間 ($T_{est}$): $E / P$
  • 残り時間 ($R$): $T_{est} – E$

この計算式により、処理のスピードが変動しても(例えば、ファイルサイズがバラバラでも)、動的に残り時間を予測できます。

② 「シングルスレッド」の呪い(重要!)

ここが最も重要な知見です。HTA(およびVBScript)は基本的にシングルスレッドで動作します。
つまり、「重い計算」をしている間、プログラムの意識は「計算」に集中しており、「画面の書き換え(描画)」に手が回りません。

もし、`UpdateUI` を呼ばずに、巨大な `For` ループだけを回すと、プログレスバーはピクリとも動かず、ウィンドウは「応答なし」になります。
「計算の合間に、UIを更新する時間を意識的に作る」。これが、スクリプトをアプリケーションに変えるための鉄則です。

③ `Timer` 関数の精度

VBScriptの `Timer` 関数は、午前0時からの経過秒数を返します。非常に便利ですが、計算の過程で `Double` 型(浮動小数点)として扱われることを意識してください。精度の高い計算が必要な場合は、型変換に注意しましょう。

5. まとめ:次のステップへ

今回の実装で、あなたは以下のスキルを手に入れました。
1. HTML/CSSによるUIデザインの基礎
2. HTAによるVBScriptの実行環境の拡張
3. 数学的予測を用いた「ユーザー体験(UX)」の向上

「ただ動けばいい」という段階を卒業し、「使う人の不安を取り除く」という視点を持てたなら、あなたの自動化ツールは、同僚やクライアントにとって「なくてはならない信頼できる道具」に変わるはずです。

もしエラーが出たり、もっと複雑なことをしたくなったりしたら、いつでも戻ってきてください。
コードの向こう側にある「設計の美しさ」を、共に追求していきましょう。

ここをクリアすれば、VBScriptの基本はバッチリですよ。さあ、次なる自動化の旅へ!

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