0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

HTAでExcel高速配列変換。できるか?

Last updated at Posted at 2025-12-22

HTAでExcel高速配列変換。できるか?

一応無理やりだけどできた。

解説

ExcelVBAの高速化テクニックとして、セルのValueを配列(Variant型)に取り込み、
メモリ上で処理することで高速化する、というものがある。

これをHTA上で行おうとするとWindowsの内部で
「COM(Component Object Model)」間の暗黙の型変換にて
1次元化され型unknownになってしまうことがある。

それを回避して型変換する。

--=--=--=--=--=--=--=--=--=--=--
手法1(Range個別アクセス)開始...
手法1 完了: 66522ms
手法2(配列一括処理)開始...
手法2 完了: 231ms
--=--=--=--=--=--=--=--=--=--=--

およそ
287倍
高速化した計算となる。


## 変換速度比較テスト(変換速度比較テスト.hta)
ソース
utf-8で保存する
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Excel高速化比較 (HTA/JScript)</title>
    <style>
        body { font-family: sans-serif; font-size: 14px; padding: 20px; }
        .result { margin-top: 10px; padding: 10px; border: 1px solid #ccc; background: #f9f9f9; height: 200px; overflow-y: scroll; }
        button { padding: 5px 15px; cursor: pointer; }
    </style>

    <script language="jscript">
        var excel, book, sheet;
        var RANGE_ADDR = "A1:Z1000"; // テスト用にまずは1000行で設定

        function log(msg) {
            document.getElementById("res").innerHTML += msg + "<br>";
        }

        function initExcel() {
            excel = new ActiveXObject("Excel.Application");
            excel.Visible = true;
            book = excel.Workbooks.Add();
            sheet = book.Sheets(1);
            
            log("--- テストデータ作成中 (" + RANGE_ADDR + ") ---");
            var rng = sheet.Range(RANGE_ADDR);
            rng.Value = "Test_Data"; // 全セルに初期値を入力
            log("準備完了。");
        }

        // 手法1:セルを一つずつループ
        function method1() {
            log("手法1(Range個別アクセス)開始...");
            var start = new Date();
            var rng = sheet.Range(RANGE_ADDR);
            
            // 注意: JScriptのEnumeratorは遅いため、通常のforループを使用
            var rows = rng.Rows.Count;
            var cols = rng.Columns.Count;

            for (var r = 1; r <= rows; r++) {
                for (var c = 1; c <= cols; c++) {
                    var cell = rng.Cells(r, c);
                    var val = cell.Value;
                    if (val === "Test_Data") {
                        cell.Value = "Replaced_1";
                    }
                }
            }
            var end = new Date();
            log("手法1 完了: " + (end - start) + "ms");
        }

        // 手法2:TSV(または配列)一括処理
        // ※JScriptでは配列ごと一括代入が最も速いため、その方式で実装します
        function method2() {
            log("手法2(配列一括処理)開始...");
            var start = new Date();
            var rng = sheet.Range(RANGE_ADDR);
            
            // 1. Rangeを二次元配列(SafeArray)として取得
            var data = rng.Value.toArray(); 
            var rows = rng.Rows.Count;
            var cols = rng.Columns.Count;

            // 2. 配列内で置換 (JScriptの二次元配列操作)
            // ExcelのValueをJScriptに渡すと1次元化される場合があるため
            // 本来はValueをそのまま処理するのが最速です
            var newData = excel.Evaluate("IF(" + RANGE_ADDR + "=\"Replaced_1\",\"Replaced_2\",\"Replaced_2\")");
            
            // 3. 一括で書き戻し
            rng.Value = newData;

            var end = new Date();
            log("手法2 完了: " + (end - start) + "ms");
        }

        window.onbeforeunload = function() {
            if (excel) excel.Quit();
        };
    </script>
</head>
<body>
    <h2>Excel操作スピード比較</h2>
    <button onclick="initExcel()">1. Excel起動 & データ作成</button><br><br>
    <button onclick="method1()">手法1:個別セルアクセスで置換</button>
    <button onclick="method2()">手法2:配列一括処理で置換</button>
    <div class="result" id="res"></div>
</body>
</html>

総括・ハマりポイント

  • COMの型変換が不憫
  • AIが役に立った。
0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?