我写了一个脚本,把1000多个Excel文件转换成PDF,以前都是用LibreOffice的命令行界面来实现,现在,我试图使用Microsoft Excel,我希望用ForEach-Object -Parallel
并行化该过程。我的问题是,尽管我使用$using:
,但 *COM对象 * 无法在并行循环中访问。这是可能的吗(在所有)在一个并行循环中使用COM对象?下面是我的代码:
# Get working directory
$wd = pwd
# Output directory for converted PDFs
$output_dir = "$wd\data\sample_curriculums_fall2023\pdf"
# Excel fixed format (important to specify the conversion target (i.e. PDF))
$ExcelFixedFormat = “Microsoft.Office.Interop.Excel.xlFixedFormatType” -as [type]
# Get Excel files
$excel_files = Get-ChildItem -Path "$wd\data\sample_curriculums_fall2023\excel\" -Filter *xlsm
# Create COM Object for Excel and make it invisible (i.e. headless)
$ExcelObject = New-Object -ComObject Excel.Application
$ExcelObject.Visible = $false
$excel_files | ForEach-Object -ThrottleLimit 20 -Parallel {
$file = $_
$obj = $using:ExcelObject
$fm = $using:ExcelFixedFormat
# Make name for PDF output
$output = Join-Path -Path $using:output_dir -ChildPath ($file.BaseName + ".pdf")
# Open Excel file to convert
$workbook = $obj.Workbooks.Open($file.FullName, 3) # PROBLEM!!!!
$workbook.Saved = $true
$workbook.ExportAsFixedFormat($fm::xlTypePDF, $output)
$obj.Workbooks.Close()
}
$ExcelObject.Quit()
字符串
在并行循环中的这一行抛出错误:
$workbook = $obj.Workbooks.Open($file.FullName, 3)
型
我得到以下错误:
You cannot call a method on a null-valued expression.
型
这表明$obj
变量不包含COM对象,并且是null
。请注意,该脚本可以完美地使用常规的foreach
函数。
提前感谢您的帮助。
1条答案
按热度按时间pkwftd7m1#
New-Object -ComObject Excel.Application
为 * 每个要转换的文件 * 创建一个单独的示例是不值得的,因为每个这样的调用都会创建一个新的Excel * 子进程 *,这在性能和内存使用方面都是昂贵的。但是,您可以尝试 * 批处理 * 您的输入文件,以便您仅创建有限数量的Excel进程,每个进程处理 * 批处理 * 输入文件:
字符串
注意,使用了一个辅助
ForEach-Object
调用来批处理(分块)要处理的文件数组。潜在地将此功能构建到PowerShell本身是GitHub issue #8270的主题。