11

使用 PowerShell 批次設定 Excel 保護密碼

 3 years ago
source link: https://blog.darkthread.net/blog/pretect-excel-with-ps/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
使用 PowerShell 批次設定 Excel 保護密碼-黑暗執行緒

專案遇到為 Excel (.xlsx) 設定讀取密碼的需求。OpenXML SDK 提供的工作表保護功能,只僅限於防止內容被修改,無法做到輸入密碼才能開啟。有不少 Excel 商業元件可以彌補這個缺口,授權費用約三五百塊美金,並不算貴。但由於其他的需求我用 ClosedXML 或 OpenXML SDK 都可滿足,不值得單為這個功能採購元件,加上預計作業會在使用者的個人電腦執行,肯定有安裝 Excel,而且桌面環境,不像在網站或跑排程呼叫 Excel 有遇到一堆妖怪。 (延伸閱讀:呼叫Excel的程式無法以排程方式執行「以排程方式呼叫Word/Excel注意事項」補充包) 評估後決定這次就用 PowerShell 實做批次加密 Excel 檔。

PowerShell 可以建立 COM+ 物件,加上是弱型別語言,操作起來比 C# 還容易,程式碼比預期簡單很多,用到一則之前介紹過的技巧 - Read-Host -AsSecureString 輸入密碼字串(參考:淺談 PowerShell 中的密碼字串加密處理)。這類與權限管控有關的密碼,我偏好請使用者現場輸入,不使用設定檔或批次參數,如此可做到只有當事人一個人知道,全程沒在畫面出現也不會留下軌跡。

還有個小眉角是我設定 $excel.Visible = $true,讓使用者看到 Excel 逐一開檔處理的過程,讓進度更透明一些,這還有另一項好處,若 .xlsx 原本有設讀取密碼,Excel 會彈出對話框等使用者輸入密碼再繼續。

完整程式範例如下:

Param(
    [parameter(Mandatory=$true)][string]
    $excelPath
)
$ErrorActionPreference = "STOP"
$excelPaths = @()
if ($excelPath.EndsWith(".xlsx")) {
    if (Test-Path $excelPath) {
        $excelPath += $excelPath
    }
}
else {
    $excelPaths += @((Get-ChildItem -Path $excelPath -Filter "*.xlsx").FullName)
}
if ($excelPaths.Length -eq 0) {
    Write-Error "未找到 Excel 檔案 - $excelPath"
    Exit
}
function decodeSecureString($secString) {
    $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($secString)
    return [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
}
$pwdSecStr = Read-Host "請輸入 Excel 加密密碼" -AsSecureString 
$pwdConfirmSecStr = Read-Host "請再輸一次密碼" -AsSecureString 
$passwd = decodeSecureString($pwdSecStr)
if ($passwd -ne (decodeSecureString($pwdConfirmSecStr))) {
    Write-Error "密碼不符"
    Exit
}

try 
{
    $excel = New-Object -ComObject Excel.Application
    $excel.Visible = $true # 顯示 UI,若原本就有密碼會提示使用者輸入
    $excelPaths | ForEach-Object {
        Write-Host "加密 $_..."
        $excel.WorkBooks.Open($_) | Out-Null
        $excel.ActiveWorkbook.Password = $passwd
        $excel.ActiveWorkbook.Save()
        $excel.ActiveWorkBook.Close()
    }
}
finally 
{
    $excel.Quit()
}

執行畫面:

產生的 Excel 檔開啟時會彈出密碼輸入視窗,成功!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK