Powershell 写入 .XLSX 正在破坏文件

Powershell Writing to .XLSX is Corrupting the Files

我有一个 Powershell 脚本,它循环遍历文件夹中的 .xslx 文件,密码使用文件名保护它们(目前。)循环遍历和写入 .xls 没有问题,但是当我尝试打开时使用 Powershell 编写后的 .xlsx 文件 - 我收到错误:

Excel cannot open the file 'abcd.xlsx' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file.

这是脚本:

function Release-Ref ($ref) { 
    ([System.Runtime.InteropServices.Marshal]::ReleaseComObject( 
    [System.__ComObject]$ref) -gt 0) 
    [System.GC]::Collect() 
    [System.GC]::WaitForPendingFinalizers()  
    } 

$e = $ErrorActionPreference
$ErrorActionPreference="continue"
foreach ($f in Get-ChildItem "C:"){
    try{
        $ff = $f
        $xlNormal = -4143 
        $s = [System.IO.Path]::GetFileNameWithoutExtension($f)
        $xl = new-object -comobject excel.application 
        $xl.Visible = $False
        $xl.DisplayAlerts = $False   
        $wb = $xl.Workbooks.Open($ff.FullName)
        $wb.sheets(1).columns("A:S").entirecolumn.AutoFit()
        $wb.sheets(1).columns("N").NumberFormat = "0.0%"
        $a = $wb.SaveAs("C:\Out\" + $s + ".xls",$xlNormal,$s) #works
        #$a = $wb.SaveAs("C:\Out\" + $s + ".xlsx",$xlNormal,$s) #doesn't work
        $a = $xl.Quit() 

        $a = Release-Ref($ws) 
        $a = Release-Ref($wb) 
        $a = Release-Ref($xl) 
    }
    catch {
        Write-Output "Exception"
        $ErrorActionPreference=$e;
    }
}

我搜索了其他问题,但找不到从 Powershell 编写的相同问题的任何其他示例。谢谢。

有时使用 excel 使用 com 对象太复杂了。我推荐 import-excel 模块。 Install-Module -Name ImportExcel

那你可以这样做。

function Release-Ref ($ref) { 
    $e = $ErrorActionPreference
    $ErrorActionPreference="continue"

foreach ($f in Get-ChildItem $file){
    try{
        $filePass = gci $f
        $path = split-path $f
        $newFile = $path + "\" + $f.BaseName + "-protected.xlsx"
        $f | Export-excel $newFile -password $filePass -NoNumberConversion * -AutoSize
    }
    catch {
        Write-Output "Exception"
        $ErrorActionPreference=$e;
    }
}
}

问题是因为Xls与Xlsx的格式不同。 2007 版之前的 Excels 使用二进制格式。 2007 Office 引入了 new formats called Office Open Xml,Xslx 使用了它。

Excel 足够聪明,可以检查文件扩展名和文件格式。由于使用新版本的扩展名保存二进制文件会产生冲突,因此错误消息也提示了这种可能性:

and that the file extension matches the format of the file.

为什么 Excel 不直接打开文件?我想这是一种防止无意中打开 Office 文档的安全功能。过去,Office macro viruses 是许多办公室的祸根。主要的感染媒介之一是诱骗用户在没有预防措施的情况下打开文件。与经典病毒不同,宏病毒感染的是应用程序数据(包括默认模板文件)而不是 OS 二进制文件,但这是另一回事了。

无论如何,要以正确的格式工作,请使用 proper version value. That would be -4143 for Xls and 51 for Xlsx. What's more, Get-ChildItem returns a collection of FileInfo objects, and file extension is there in Extension 属性。像这样,

# Define Xls and Xlsx versions
$typeXls = -4143
$typeXls = 51
foreach ($f in Get-ChildItem "C:"){

    try{
    $ff = $f
    ...
   # Select saveas type to match original file extension
   if($f.extension -eq '.xsl') { $fType = $typeXls }
   else if($f.extension -eq '.xslx') { $fType = $typeXlsx }

   $a = $wb.SaveAs("C:\Out\" + $s + $.extension, $fType, $s)