概要
PowerShellスクリプトでのExcel操作方法について
備忘録として記載いたします。
実行環境
windows:Windows11Pro 23H2
Windows PowerShell:5.1.26100.4061
PowerShellのバージョン確認
確認コマンド:$PSVersionTable
PowerShellとWindows PowerShellの違い
下記のサイトが参考になります。
実行ポリシーの確認・変更
現在の実行ポリシーを確認する方法
Get-ExecutionPolicy
Restrictedである場合はスクリプトを実行できない。
管理者権限で実行ポリシーを変更する
Set-ExecutionPolicy RemoteSigned
再度、実行ポリシーを確認して、
RemoteSignedに変更されていることを確認する。
実行ポリシー変更スクリプト
RemoteSignedに変更してスクリプトの実行を可能にしたい場合
@echo off
setlocal
:: PowerShellの現在の実行ポリシーを取得
for /f "tokens=* usebackq" %%i in (`powershell -Command "Get-ExecutionPolicy -Scope LocalMachine"`) do set policy=%%i
echo 現在の実行ポリシーは: %policy%
:: RestrictedならRemoteSignedに変更
if /i "%policy%"=="Restricted" (
echo 実行ポリシーがRestrictedのため、RemoteSignedに変更します(管理者権限が必要)...
:: 管理者権限でPowerShellを起動し、ポリシー変更を実行
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"Start-Process PowerShell -Verb RunAs -ArgumentList '-NoProfile -Command \"Set-ExecutionPolicy RemoteSigned -Scope LocalMachine -Force\"'"
echo 実行ポリシー変更コマンドを管理者権限で実行しました。
echo PowerShellウィンドウが表示され、変更が完了するまで閉じないでください。
) else (
echo 実行ポリシーの変更は不要です。
)
echo Enterキーを押下して画面を閉じてください。
endlocal
pause
Restrictedに変更してスクリプトの実行を禁止にしたい場合
@echo off
setlocal
:: PowerShellの現在の実行ポリシーを取得
for /f "tokens=* usebackq" %%i in (`powershell -Command "Get-ExecutionPolicy -Scope LocalMachine"`) do set policy=%%i
echo 現在の実行ポリシーは: %policy%
:: RemoteSignedならRestrictedならに変更
if /i "%policy%"=="RemoteSigned" (
echo 実行ポリシーがRemoteSignedのため、Restrictedに変更します(管理者権限が必要)...
:: 管理者権限でPowerShellを起動し、ポリシー変更を実行
powershell -NoProfile -ExecutionPolicy Bypass -Command ^
"Start-Process PowerShell -Verb RunAs -ArgumentList '-NoProfile -Command \"Set-ExecutionPolicy Restricted -Scope LocalMachine -Force\"'"
echo 実行ポリシー変更コマンドを管理者権限で実行しました。
echo PowerShellウィンドウが表示され、変更が完了するまで閉じないでください。
) else (
echo 実行ポリシーの変更は不要です。
)
echo Enterキーを押下して画面を閉じてください。
endlocal
pause
注意点
・param はスクリプトの先頭に配置する必要がある。
関数定義の後に param を記述すると、PowerShell がスクリプトの実行時に param を認識できず、
エラーになる。
・スクリプト内に日本語の表記が存在しているとエラーとなる場合がある。
解決策として、ファイルの拡張子を.txtにして
メモ帳を開いて「名前を付けて保存」の選択時に「エンコード」の項目から「UTF-8(BOM 付き)」を選択する。
そして再度拡張子を.ps1にしてスクリプトを実行する。
batファイルの使用
@echo off
powershell -NoProfile -ExecutionPolicy Bypass -File "test.ps1"
iniファイルから取得
[VEHICLE]
train = train
bike = bike
car = car
[BIRTHDAY]
may = may
june = june
july = july
function Get-IniContent {
param (
[string]$filePath
)
# 結果を格納するOrderedハッシュテーブル
$iniData = [ordered]@{}
# ファイル内容を解析
$section = $null # 初期化
switch -regex -file $filePath {
"^\[(.+)\]$" {
$section = $matches[1]
$iniData[$section] = @{}
}
"^(.+?)\s*=\s*(.+)$" {
if ($section) {
$key, $value = $matches[1], $matches[2]
$iniData[$section][$key] = $value
} else {
Write-Error "セクションが未定義のままキーと値にアクセスしています: $($matches[1]) = $($matches[2])"
}
}
}
return $iniData
}
# INIファイルのパスを指定して読み込み
$filePath = "config.ini"
$iniData = Get-IniContent -filePath $filePath
# セクションごとにデータを出力
foreach ($section in $iniData.Keys) {
Write-Host "[$section]"
foreach ($key in $iniData[$section].Keys) {
Write-Host "$key = $($iniData[$section][$key])"
}
Write-Host ""
}
# 指定のセクションのみ出力
foreach ($key in $iniData["BIRTHDAY"].Keys) {
Write-Host "$key = $($iniData["BIRTHDAY"][$key])"
}
チェックボックスの使用
# 必要なアセンブリをロード
Add-Type -AssemblyName System.Windows.Forms
# フォームの作成
$form = New-Object System.Windows.Forms.Form
$form.Text = "項目と教科選択"
$form.Width = 600
$form.Height = 300
# ウィンドウの「×」ボタンが押された際の処理を追加
$form.Add_FormClosing({
param([System.Object]$sender, [System.Windows.Forms.FormClosingEventArgs]$e)
$result = [System.Windows.Forms.MessageBox]::Show(
"スクリプトを終了しますか?",
"確認",
[System.Windows.Forms.MessageBoxButtons]::YesNo,
[System.Windows.Forms.MessageBoxIcon]::Question
)
if ($result -eq [System.Windows.Forms.DialogResult]::Yes) {
Write-Host "スクリプトを終了しました。"
# イベントループを終了
$form.Dispose()
} else {
$e.Cancel = $true # フォームの閉じ動作をキャンセル
}
})
# ラベルの作成
$label = New-Object System.Windows.Forms.Label
$label.Text = "項目を選んでください"
$label.Font = New-Object System.Drawing.Font("Arial", 10)
$label.AutoSize = $true
$label.Location = New-Object System.Drawing.Point(20, 20)
$form.Controls.Add($label)
# チェックボックス1
$checkbox1 = New-Object System.Windows.Forms.CheckBox
$checkbox1.Text = "項目1"
$checkbox1.Location = New-Object System.Drawing.Point(20, 50)
$form.Controls.Add($checkbox1)
# チェックボックス2
$checkbox2 = New-Object System.Windows.Forms.CheckBox
$checkbox2.Text = "項目2"
$checkbox2.Location = New-Object System.Drawing.Point(120, 50)
$form.Controls.Add($checkbox2)
# チェックボックス3
$checkbox3 = New-Object System.Windows.Forms.CheckBox
$checkbox3.Text = "項目3"
$checkbox3.Location = New-Object System.Drawing.Point(220, 50)
$form.Controls.Add($checkbox3)
# ラベルの作成(教科を選んでください)
$subjectlabel = New-Object System.Windows.Forms.Label
$subjectlabel.Text = "教科を選んでください"
$subjectlabel.Font = New-Object System.Drawing.Font("Arial", 10)
$subjectlabel.AutoSize = $true
$subjectlabel.Location = New-Object System.Drawing.Point(20, 80)
$form.Controls.Add($subjectlabel)
# 教科チェックボックス
$SubjectEnglish = New-Object System.Windows.Forms.CheckBox
$SubjectEnglish.Text = "英語"
$SubjectEnglish.Location = New-Object System.Drawing.Point(20, 100)
$form.Controls.Add($SubjectEnglish)
$SubjectMath = New-Object System.Windows.Forms.CheckBox
$SubjectMath.Text = "数学"
$SubjectMath.Location = New-Object System.Drawing.Point(120, 100)
$form.Controls.Add($SubjectMath)
$SubjectPhysics = New-Object System.Windows.Forms.CheckBox
$SubjectPhysics.Text = "物理"
$SubjectPhysics.Location = New-Object System.Drawing.Point(220, 100)
$form.Controls.Add($SubjectPhysics)
# 選択された「項目」と「教科」を格納する変数
$selectedItems = [ref] "未登録"
$subjectItems = [ref] "未登録"
# OKボタン
$okButton = New-Object System.Windows.Forms.Button
$okButton.Text = "OK"
$okButton.Location = New-Object System.Drawing.Point(150, 200)
$okButton.Add_Click({
$selectedItems.Value = ""
$subjectItems.Value = ""
if ($checkbox1.Checked) {$selectedItems.Value += "項目1 "}
if ($checkbox2.Checked) {$selectedItems.Value += "項目2 "}
if ($checkbox3.Checked) {$selectedItems.Value += "項目3 "}
if ($SubjectEnglish.Checked) {$subjectItems.Value += "English"}
if ($SubjectMath.Checked) {$subjectItems.Value += "Math"}
if ($SubjectPhysics.Checked) {$subjectItems.Value += "physics"}
if (-not ($selectedItems.Value -and $subjectItems.Value)) {
[System.Windows.Forms.MessageBox]::Show("項目と教科を最低1つずつ選択してください。", "警告")
return
}
$form.DialogResult = [System.Windows.Forms.DialogResult]::OK
})
$form.Controls.Add($okButton)
# フォームを表示
$result = $form.ShowDialog()
# フォームを閉じた後の選択を10秒間表示
Write-Host "選択された項目: $($selectedItems.Value)"
Write-Host "選択された教科: $($subjectItems.Value)"
if($subjectItems.Value -eq "Math"){
Write-Host "数学を選択しました"
}else{
# ポップアップの表示
[System.Windows.Forms.MessageBox]::Show("すぐに終了します。OKボタンを押下してください。", "警告")
# スクリプトの終了
exit
}
# 10秒間ログを表示する
Start-Sleep -Seconds 10
COMオブジェクトの解放
# COMオブジェクトの作成
$excel = New-Object -ComObject Excel.Application
# 何らかの操作を実行
$excel.Visible = $true
# アプリケーションを終了
$excel.Quit()
# COMオブジェクトの解放
[System.Runtime.InteropServices.Marshal]::ReleaseComObject($excel) | Out-Null
$excel = $null
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
