我有一个脚本,可以在单个 Excel 实例中打开一组 Excel 工作簿并更新连接和数据透视缓存。最终用户报告说,他们通常并行打开所有工作簿并刷新连接(而不是像脚本那样“串行”)。看起来使用 PowerShell 并行处理是可能的,但到目前为止我无法使用脚本块和
Start-Job
方法打开 Excel 工作簿。所发生的只是 Excel 实例启动并且作业永远运行而没有完成,并且没有打开工作簿。
迄今为止最大的努力:
$filePath = "C:\testpath"
#Array: FileName, SaveAs
$files = @()
$files += , @("tst1.xlsx", $false)
$files += , @("tst2.xlsx", $false)
Write-output "$(Get-Date -Format yyyy-MM-dd.hh:mm:ss): Starting loop"
$x1 = New-Object -ComObject "Excel.Application"
$x1.Visible = $true
ForEach($file in $files) {
# Define what each job does
$ScriptBlock = {
param([Object[]]$x1,
[string]$filePath,
[array]$file)
$wb = $x1.workbooks.Open("$filePath\$($file[0])")
ForEach ($cache in $wb.PivotCaches()) {
#Refresh this cache
$cache.Refresh()
}
}
# Execute the jobs in parallel
Start-Job $ScriptBlock -ArgumentList $x1,
$filePath,
$file
}
Get-Job
# Wait for it all to complete
While (Get-Job -State "Running") {
# Pause for 10 seconds
Start-Sleep 10
}
# Getting the information back from the jobs
Get-Job | Receive-Job
Write-output "$(Get-Date -Format yyyy-MM-dd.hh:mm:ss):Loop complete"
所有这些都可以在没有并行处理的情况下正常工作:
$filePath = "C:\testpath"
#Array: FileName, SaveAs
$files = @()
$files += , @("tst1.xlsx", $false)
$files += , @("tst2.xlsx", $false)
Write-output "$(Get-Date -Format yyyy-MM-dd.hh:mm:ss): Starting loop"
$x1 = New-Object -ComObject "Excel.Application"
$x1.Visible = $true
ForEach($file in $files) {
$wb = $x1.workbooks.Open("$filePath\$($file[0])")
ForEach ($cache in $wb.PivotCaches()) {
#Refresh this cache
$cache.Refresh()
}
}
有关如何让 Excel 在脚本块中启动工作簿的线索?我在
$wb = $x1.workbooks.Open("$filePath\$($file[0])")
上添加了代码中断,代码不会停止,它只是永远运行。这是返回的输出:
身份证 | 姓名 | PS作业类型名称 | 状态 | 有更多数据 | 地点 | 命令 |
---|---|---|---|---|---|---|
1 | 工作1 | 后台作业 | 跑步 | 正确 | 本地主机 | ... |
3 | 工作3 | 后台作业 | 跑步 | 正确 | 本地主机 | ... |
1 | 工作1 | 后台作业 | 跑步 | 正确 | 本地主机 | ... |
3 | 工作3 | 后台作业 | 跑步 | 正确 | 本地主机 | ... |
我希望这就是您所寻找的:
#Define the Filepath
$filePath = "C:\testpath\"
#Define the Files
$files = @("tst1.xlsx", "tst2.xlsx")
#Clear the workbootPaths Array
$workbookPaths = @()
foreach ($file in $files) {
#Create an PSobject that hold the filepath and the state (state is alway $false)
$wbary = New-Object -TypeName psobject -Property @{
Filepath = $filepath + $file
State = $false
}
#Add the PSObject to the $workbookpaths array
$workbookPaths += $wbary
}
# Define the Job
$scriptBlock = {
param(
[string]$filePath,
[string]$workbookPath
)
$x1 = New-Object -ComObject Excel.Application
$x1.Visible = $true
$wb = $x1.Workbooks.Open($workbookPath)
foreach ($cache in $wb.PivotCaches()) {
$cache.Refresh()
}
}
Write-output "$(Get-Date -Format yyyy-MM-dd.hh:mm:ss): Starting loop"
#Than start the job for each file
ForEach ($file in $workbookPaths) {
Start-Job -ScriptBlock $scriptBlock -ArgumentList $filePath, $file.Filepath
}
Get-Job
# Wait for it all to complete
While (Get-Job -State "Running") {
# Pause for 1 seconds
Start-Sleep 1
}
# Getting the information back from the jobs
Get-Job | Receive-Job
Write-output "$(Get-Date -Format yyyy-MM-dd.hh:mm:ss): Loop complete"