Excel 2007 起開始推 XLSX 格式取代傳統 XLS,距今快 15 年了,XLS 大軍仍野火燒不盡,春風吹又生。一般使用者不太會知道二者差別,但也不至於刻意選 XLS 檔,現在仍在流傳的 XLS 檔很多是代代相傳,後人開啟更新後按儲存,沒人想過要換格式,就這麼一直活下去;又或者在建新文件時用舊 XLS 當範本,另存新檔時沿用 XLS 格式,老蚌生珠,香火不絕。

使用者通常不在意工作表存 XLS 或 XLSX,反正 Excel 都能開能存。但對系統來說,格式不統一必有額外成本,系統為求單純可限制只吃 XLSX (開檔再另存兩個動作幾秒鐘搞定的舉手之勞,使用者多半樂意配合),一方面也有助早日消滅舊格式,為推動世界前進盡一份心力。(你瞧,這世界不就因 IE 消失變得更美好?)

不過,懶人如我,手工轉存三份 XLS 便超過容忍上限,一個批次轉檔任務催生了「黑暗版 XLS 轉 XLSX 批次轉換工具」。

開發這個 PowerShell 小工具會用到以下知識:

憑著之前的知識與經驗,輕鬆秒殺:

Param(
    [parameter(Mandatory=$true, ValueFromRemainingArguments=$true)]
    [string]
    $excelPaths, 
    [parameter(ValueFromPipelineByPropertyName=$true)]
    [switch][bool]
    $replace
)
$ErrorActionPreference = "STOP"
try 
{
    $excel = New-Object -ComObject Excel.Application
    $excel.Visible = $true # 顯示 UI,方便使用者了解處理進度、輸入密碼等
    Get-Item $excelPaths | ForEach-Object {
        $path = $_.FullName
        Write-Host "開啟 $path..."
        try {
            $excel.WorkBooks.Open($path) | Out-Null
            $savePath = $path.Replace(".xls", ".xlsx")
            # xlsx => xlOpenXMLWorkbook = 51
            $excel.ActiveWorkbook.SaveAs($savePath, 51)
            $excel.ActiveWorkBook.Close()
            if ($replace) {
                Remove-Item $path                
            }
        }
        catch {
            Write-Host "發生錯誤 - $path" -ForegroundColor Red
        }
    }
}
finally 
{
    $excel.Quit()
}

使用範例:

Convert-Xls2Xlsx.ps1 D:\Foo\*.xls -Replace
Convert-Xls2Xlsx.ps1 D:\Foo\*.xls D:\Bar\*.xls ~\Documents\Work\*.xls

學習程式的過程,隨著知識與經驗積累,程式會愈寫愈輕鬆,這種倒吃甘蔗的爽快與成就感,是 Coding 讓人愈陷愈深無法自拔的原因之一吧!

Example of converting .xls to .xlsx with PowerShell.


Comments

# by A reader far away

In fact, still using old format of XLS may harm businesses. If you have interest, check these BBC news how COVID data got lost due to old XLS format used in British government agency. https://www.bbc.com/news/technology-54423988

# by Jeffrey

to A reader far away, 哈,去年也有讀到這則新聞,謝謝分享精彩實例。

# by mouse

請問有doc 轉成 docx的嗎? 謝謝!!

# by 學習的人

不好意思想請問您,因為是完全新手想問我的作法是用記事本後面改.ps1 但執行後發現出現下面的文字... Cmdlet 新文字文件.ps1 在命令管線位置 1 請提供下列參數的值: excelPaths: 想請問該怎麼做呢? 真的非常謝謝您!!!!

# by Jeffrey

to 學習的人,PowerShell 提示你漏了 excelPaths 這個必要參數,在冒號後方填入 D:\your-path\your-excel.xlsx 按 Enter,或執行時輸入 ".\新文字文件.ps1 D:\your-path\your-excel.xlsx" 直接附上參數都可以。

# by s

大大的程式有些小缺點 只能對有xls的資料夾做轉檔 遇上子資料夾內的xls檔案就無法了,只能一直切換資料夾 有辦法做出小改版嗎?

# by Jeffrey

to s,程式不用改,外面套一層指令,列舉所有子資料夾當成路徑參數傳入就好了,例如: Get-ChildItem -Path D:\XXX -Directory -Recurse | ForEach-Object { & .\Convert-Xls2Xlsx.ps1 "$($_.FullName)\*.xls" }

Post a comment