如何使用powershell将多个xls文件转换为csv?

发布于 2024-11-08 14:31:27 字数 902 浏览 3 评论 0原文

我正在尝试使用以下 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 组,并在其自己的运行中处理每个组。这有效,所以有点不方便。

提前致谢

I'm trying to convert multiple Excel files (xls) to csv using the following powershell script:

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

In principle this works e.g. I get csv files. However, for a few files (varying per run) I get an exception:

Exception calling "SaveAs" with "2" argument(s): "Microsoft Office Excel cannot access the file 'C:\Users\...\AppData\Local\Temp'. ...

Additionally, I get a message box asking if I want to save the changes to the source xls.

Once I call SaveAs, $wb references the new file. So how do I save or discard the changes to the source file? Why does this happen only for a few files? Are there any other problems with this script?

Update

I divided the input files (ca. 200) arbitrarily (i.e. don't know the size of the groups) into 10 groups and processed each group in its own run. That worked so it is somewhat inconvenient.

thanks in advance

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

独自←快乐 2024-11-15 14:31:27

尝试将代码移至循环内以启动和退出 Excel。

是的,这样会比较慢,但它会鼓励 Excel 在每次操作之间清理其临时文件。

它不会像您想象的那么慢,因为 Windows 和 COM 足够智能,即使在您退出几秒钟后,它也能将 Excel 大部分内容保留在内存中,这样下次您创建 Excel 对象时,它就会快速发生,完全适合某些情况像这样。

Try moving the code to launch and quit excel INSIDE your loop.

Yeah, it's slower that way, but it'll encourage Excel to clean up its temp files between each operation.

It won't be as slow as you think because Windows and COM are smart enough to keep Excel mostly in memory even after you quit for a few seconds so that the next time you create an Excel object it'll happen fast, exactly for situations like this.

是你 2024-11-15 14:31:27

也许你可以实现一个计时器来等待一段时间?或者,您可以在脚本运行时查看目录内部,然后在每个周期(一个 xls 文件转换)后删除临时文件。

Maybe you can implement a timer to wait a while? Or you have a look inside the direcotry while you script is running and then remove the temp files after each cycle (one xls file conversion).

死开点丶别碍眼 2024-11-15 14:31:27

我相信您可以使用 $wb.Close($False) 而不是 $wb.Close($True) 来避免消息框询问您是否要保存。这就是我通常使用的,我没有收到任何消息框。

I believe you can avoid the message box asking if you want to save by using $wb.Close($False) instead of $wb.Close($True). That's what I use normally and I don't get any message boxes.

与他有关 2024-11-15 14:31:27

我用计时器更新的脚本 - 可能不是确切的答案,但会帮助寻找脚本的人:

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

My updated script with timer - may not be exact answer but will help someone looking for a script:

$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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文