Powershell 写入 .XLSX正在损坏文件



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

Excel 无法打开文件"abcd.xlsx,因为文件格式或文件 扩展无效。验证文件是否未损坏 并且文件扩展名与文件格式匹配。

下面是脚本:

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编写的相同问题的任何其他示例。谢谢。

导致此问题的原因是 Xls 的格式与 Xlsx 不同。 版本 2007 之前的旧 Excel 使用二进制格式。2007 Office引入了Xslx使用的称为Office Open Xml的新格式。

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

并且文件扩展名与文件格式匹配。

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

无论如何,要以正确的格式工作,请使用正确的版本值。这对XLS来说是-4143,对Xlsx来说是51。此外,Get-ChildItem返回 FileInfo 对象的集合,文件扩展名位于扩展名属性中。这样

# 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)

使用 com 对象有时在 excel 中太复杂了。我推荐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;
}
}
}

最新更新