PowerShellからのExcel操作時のApplication.Calculationの設定による速度の違いを測定をしてみた

記事内に広告が含まれています。

Excelマクロでは、無駄な再計算でマクロの実行速度を落とさないために、実行中はApplication.Calculationの自動計算をOFFにするコードを記述することがあります。

PowerShellでこのプロパティを操作したときも、実行速度に影響があるか検証してみました。

検証手順

PowerShellのScript(*.ps1)でExcelに、数値と計算式を10000行3列、設定します。

下記の2パターンをそれぞれ10回テストして、実行時間の平均値を求めます。

パターンNo.検証パターンApplication.Calculation補足数値セル計算式セル
1自動計算
ONの状態
(PowerShellのScript内で未設定)Excelファイルの設定の初期値のままとする。
10000行
(A1~A10000 セル、B1~B10000)
10000行
(C1~C10000セル)
2自動計算OFFの状態xlCalculationManual意図的にPowerShellのScript内で意図的にOFFにする。
処理の最後でONにする。
10000行
(A1~A10000 セル、B1~B10000)
10000行
(C1~C10000セル)

なお、Excelファイルの初期値とは、Excelファイルの下記の部分を「自動」としたケースです。

PowerShellの処理時間については下記のように開始時刻と終了時刻を出力させ、差分の実行時間の平均を求めます。

※下のキャプチャはPowerShellのScriptの作成時のイメージです。

Application.Calculationの再計算を十分に検証するため、PowerShellのScriptは下記の処理順とします。

  1. C列には「=A列+B列」の数式を格納する
  2. A列に値を格納する
  3. B列に値を格納する

下のキャプチャは実行した際にできる、実行結果のExcelファイルのイメージです。

※なお、通常はC列は計算結果が表示されますが、分かりやすさの為、上記のキャプチャは数式を表示しています。

なお、そのほかの条件はPCのスペック等含めて、同じにしています。

想定する結果

自動計算時

C列の数式を入力した際に、A列B列に値はないけど、一度数式が計算される想定です。

また、その後にA列B列の数値が入力された際にも、C列の数式が再計算される想定です。

なので、頻繁に数式を再計算して、処理速度が激遅の予測です。

手動計算時

C列の数式はループ終了時にまとめて再計算される想定です。

なので、おそらく処理速度は早い予測です。

ソースコード

使用したソースコードは下記のとおりです。

$excel.Calculationの部分(24行目、41行目あたり)をコメントアウトしたり、アンコメントしたりして検証します。

# 開始時刻
$startTime = (Get-Date)
Write-Host "StartTime : " $startTime.ToString("HH:mm:ss.fffffff")


$excel = New-Object -ComObject Excel.Application
$book = $null

$excel.Visible = $false
$excel.DisplayAlerts = $false
$excel.ScreenUpdating = $false


$fileName  = "Book1.xlsx"
$filePath = (Convert-Path .) + "/" + $fileName

$book = $excel.Workbooks.Open($filePath)
$sheet = $book.Sheets("Sheet1")

$Calculation = "microsoft.office.interop.excel.XlCalculation" -as [type]


# 自動計算 OFF
$excel.Calculation = $Calculation::xlCalculationManual 

# 負荷をかける処理
for ( $i=1; $i -le 10000; $i++){

    # C列:計算式の入力(A列+B列) ※再計算の確認のため、先に数式を用意しておく
    $formula = "=A" + $i + "+B" + $i
    $sheet.Cells.Item($i,3).Formula = $formula
    
    # A列
    $sheet.Cells.Item($i,1).Value = $i
    # B列
    $sheet.Cells.Item($i,2).Value = $i + 1

}

# 自動計算 ON
$excel.Calculation = $Calculation::xlCalculationAutomatic 

$excel.ScreenUpdating = $true

[void]$book.Save()
[void]$book.Close($false)
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($book)

[void]$excel.Quit()
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)

# 終了時刻
$endTime = (Get-Date)
Write-Host "EndTime : " $endTime.ToString("HH:mm:ss.fffffff")
# 時間差
Write-Host "TimeSpan : " ($endTime - $startTime).ToString("")


Pause

XlCalculation 列挙値

XlCalculationについては3つの値が設定可能ですが、今回は意味の補足に留めておきます。

詳しくはMicrosoftのドキュメントを参照してください。

設定値説明
xlCalculationAutomatic-4105Excel が再計算を制御します。
xlCalculationManual-4135ユーザーが要求すると、計算が完了します。
xlCalculationSemiautomatic2Excel が再計算を制御しますが、テーブル内の変更は無視します。

実行結果(速度測定)

初期設定

数字、数式を格納する対象Excelファイルの計算方法の設定の初期値は「自動」です。

速度測定結果の一覧

速度測定は各々10回実施しました。記事が長くなるためキャプチャは割愛します。

(経過時間の記載の形式は「HH:mm:ss.fffffff」です)

実行回数自動計算ONの状態
(PowerShellのScript内で未設定の場合)
自動計算OFFの状態
(xlCalculationManualを設定の場合)
1回目00:01:57.937978100:01:35.5133327
2回目00:02:17.810970400:01:36.9314456
3回目00:02:39.696252700:01:35.9776432
4回目00:02:15.936311100:01:42.2736822
5回目00:02:38.781281900:01:34.7567951
6回目00:02:23.583721400:01:57.8079433
7回目00:02:36.454648900:01:32.2901524
8回目00:02:39.342481900:01:34.1461086
9回目00:02:35.150241000:01:38.9322428
10回目00:02:27.915906100:01:40.2430028
速度測定一覧

平均値、最小値、最大値は下記のとおりです。

実行回数自動計算ONの状態
(PowerShellのScript内で未設定の場合)
自動計算OFFの状態
(xlCalculationManualを設定の場合)
差異
平均値約00:02:27約00:01:39約49秒スピードアップ
最小値00:01:57.937978100:01:32.2901524約26秒スピードアップ
最大値00:02:39.696252700:01:57.8079433約42秒スピードアップ
平均値、最小・最大値

結論

結果として、処理実行中はxlCalculationManualに設定したほうが、平均値、最大値、最小値とも早い結果となりました。

PowerShellでもApplication.Calculationの設定を意識したほうがよさそうです。

参考情報

下記の環境で作成・実行しております。

No.環境バージョン
1OSWindows10
2PowerShell5.1
環境一覧

以上です。

コメント

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