我有一个Powershell脚本,该脚本可以循环访问文件夹中的.xslx文件,并且密码使用文件名来保护它们(目前)。循环访问并写入.xls没有问题,但是当我尝试打开.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编写的相同问题的任何其他示例。谢谢。
答案 0 :(得分:1)
使用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;
}
}
}
答案 1 :(得分:1)
由于Xls与Xlsx格式不同而导致问题。 2007版之前的旧版Excel使用二进制格式。 2007 Office引入了Xslx使用的new formats called Office Open Xml。
Excel非常聪明,可以检查文件扩展名和文件格式。由于保存具有新版本扩展名的二进制文件会产生冲突,因此错误消息也暗示了这种可能性:
并且文件扩展名与文件格式匹配。
为什么Excel仍然不打开文件?我猜这是一个安全功能,可以防止意外打开Office文档。过去,Office macro viruses是许多办公室的祸根。一种主要的感染媒介是诱使用户在没有预防措施的情况下打开文件。与经典病毒不同,宏病毒感染的是应用程序数据(包括默认模板文件)而不是操作系统二进制文件,但这是另外一回事了。
无论如何,要使用正确的格式,请使用proper version value。 Xls将为-4143
,Xlsx将为51
。此外,Get-ChildItem
返回一个FileInfo对象的集合,并且文件扩展名位于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)