我正在尝试使用以下powershell脚本将多个Excel文件(xls)转换为csv:
$excel = new-object -ComObject "Excel.Application"
$excel.DisplayAlerts=$True
$excel.Visible =$false
foreach ($file in get-childitem $src_dir) {
$wb = $excel.Workbooks.Open($file.FullName)
$wb.SaveAs($dst_dir + $file.Name + ".csv", 6)# 6 -> csv
$wb.Close($True)
}
$excel.Quit()
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)
原则上这有效,例如我得到了csv文件。但是,对于一些文件(每次运行不同),我得到一个例外:
Exception calling "SaveAs" with "2" argument(s): "Microsoft Office Excel cannot access the file 'C:\Users\...\AppData\Local\Temp'. ...
此外,我收到一个消息框,询问我是否要将更改保存到源xls。
一旦我调用SaveAs,$ wb就会引用新文件。那么如何保存或放弃对源文件的更改?为什么这只发生在几个文件中?这个脚本还有其他问题吗?
更新
我将输入文件(大约200)任意划分(即不知道组的大小)为10组,并在自己的运行中处理每个组。这样做有点不方便。
提前致谢
答案 0 :(得分:4)
尝试移动代码以启动并退出excel INSIDE你的循环。
是的,它的速度较慢,但它会鼓励Excel在每次操作之间清理临时文件。
它不会像你想象的那么慢,因为即使在你退出几秒钟之后,Windows和COM也足够聪明地将Excel保留在内存中,以便下次创建Excel对象时它会快速发生,完全适合这种情况。
答案 1 :(得分:0)
也许你可以实现一个等待一段时间的计时器?或者您在脚本运行时查看目录内部,然后在每个周期后删除临时文件(一次xls文件转换)。
答案 2 :(得分:0)
我相信您可以使用$wb.Close($False)
代替$wb.Close($True)
来避免询问是否要保存的消息框。这是我正常使用的,我没有得到任何消息框。
答案 3 :(得分:0)
我更新的带有计时器的脚本 - 可能不是确切的答案,但可以帮助寻找脚本的人:
$excel = new-object -ComObject "Excel.Application"
$excel.DisplayAlerts=$True
$excel.Visible =$false
$src_dir='D:\folderwithxlsx\'
$dst_dir='D:\folderwithcsv\'
Get-ChildItem $src_dir -Filter *.xlsx |
Foreach-Object{
'processing '+$_.FullName
$wb = $excel.Workbooks.Open($_.FullName)
$dst_file=$dst_dir + $_.BaseName + ".csv"
$wb.SaveAs($dst_file, 6)# 6 -> csv
'saved '+$dst_file
$wb.Close($True)
Start-Sleep -Seconds 2
}
$excel.Quit()
[void][System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel)