Powershell Excel 找到价值更好的性能替代方案
Powershell Excel find value better performance alternative
我必须使用 COM 对象在 excel 中完成一个循环(除了随 POSH 5 安装的模块外,环境中不允许使用其他模块)。
在每个循环中,我必须通过工作sheet(从变量列表)查找一组特定的值,并根据它提取和附加数据。
我的问题不是完成它那么多,而是我每次在每项工作中执行 Find Value2 时都会受到性能影响sheet。
随着未来预期工作列表的大量增加sheets,以及只有越来越多的列需要解析和在未来处理的旧列表,我怎样才能使它更顺畅和更快。
我目前做的是:
$Exl = New-Object -ComObject "Excel.Application"
$Exl.Visible = $false
$Exl.DisplayAlerts = $false
$WB = $Exl.Workbooks.Open($excel)
Foreach ($name in $names) {
$ws = $WB.worksheets | where {$_.name -like "*$name*"}
$range = $ws.Range("C:C")
$findstuff = $range.find($item)
$stuffrow = $findstuff.row
$stuffcolumn = $findstuff.column
}
这最后一部分需要很多时间,每增加一个 sheet 和更多的列,我只会看到它在增长,这可能需要 10-20 分钟
可以做些什么来优化它?
附带说明:虽然我只需要一行和一列结果,但在查找值时也存在一个小问题,它只显示第一个结果。如果将来可能需要多行多列 where value2 = $variable 怎么办? (虽然那不那么重要,我问过它是否相关)
只要使用管道,性能就会受到影响。不要使用 where 对象,而是尝试这样的事情(使用 if 语句):
foreach ($name in $names) {
$ws = if ($WB.worksheets.name -like "*$name*")
$range = Range("C:C")
$findstuff = $range.find($item)
$stuffrow = $findstuff.row
$stuffcolumn = $findstuff.column
}
请注意,您的行可能有 *where {$_.name -like "*$names*"}*
部分的拼写错误。也许它应该读作 *where {$_.name -like "*$name*"}*
?
我从我拥有的以下书签中找到了我的基础:http://community.idera.com/powershell/powershell_com_featured_blogs/b/tobias/posts/speeding-up-your-scripts
所以我找到了一个非常简单的答案....它在某种程度上同时非常明显和非常不直观。
在定义 $range 变量时将管道添加到 select 只有你需要的东西。
而不是:
$range = $ws.Range("C:C")
做:
$range = $ws.Range("C:C") | Select Row, text, value2, column
为什么这不直观?
1) 通常管道会使事情变得更慢,特别是如果你推很多来过滤一些
2) 人们会期望,特别是因为它通过 COM 对象,因为它实际上是在设置变量而不是仅仅定义时运行操作。但这不是这里发生的事情。当您设置变量时,它会在定义变量后运行,并在变量被调用的那一刻收集数据[我对此进行了测试,只看到了那个特定时期的资源使用情况],并在第一次变量调用后保存数据。 (这很奇怪)
我必须使用 COM 对象在 excel 中完成一个循环(除了随 POSH 5 安装的模块外,环境中不允许使用其他模块)。
在每个循环中,我必须通过工作sheet(从变量列表)查找一组特定的值,并根据它提取和附加数据。
我的问题不是完成它那么多,而是我每次在每项工作中执行 Find Value2 时都会受到性能影响sheet。
随着未来预期工作列表的大量增加sheets,以及只有越来越多的列需要解析和在未来处理的旧列表,我怎样才能使它更顺畅和更快。
我目前做的是:
$Exl = New-Object -ComObject "Excel.Application"
$Exl.Visible = $false
$Exl.DisplayAlerts = $false
$WB = $Exl.Workbooks.Open($excel)
Foreach ($name in $names) {
$ws = $WB.worksheets | where {$_.name -like "*$name*"}
$range = $ws.Range("C:C")
$findstuff = $range.find($item)
$stuffrow = $findstuff.row
$stuffcolumn = $findstuff.column
}
这最后一部分需要很多时间,每增加一个 sheet 和更多的列,我只会看到它在增长,这可能需要 10-20 分钟
可以做些什么来优化它?
附带说明:虽然我只需要一行和一列结果,但在查找值时也存在一个小问题,它只显示第一个结果。如果将来可能需要多行多列 where value2 = $variable 怎么办? (虽然那不那么重要,我问过它是否相关)
只要使用管道,性能就会受到影响。不要使用 where 对象,而是尝试这样的事情(使用 if 语句):
foreach ($name in $names) {
$ws = if ($WB.worksheets.name -like "*$name*")
$range = Range("C:C")
$findstuff = $range.find($item)
$stuffrow = $findstuff.row
$stuffcolumn = $findstuff.column
}
请注意,您的行可能有 *where {$_.name -like "*$names*"}*
部分的拼写错误。也许它应该读作 *where {$_.name -like "*$name*"}*
?
我从我拥有的以下书签中找到了我的基础:http://community.idera.com/powershell/powershell_com_featured_blogs/b/tobias/posts/speeding-up-your-scripts
所以我找到了一个非常简单的答案....它在某种程度上同时非常明显和非常不直观。
在定义 $range 变量时将管道添加到 select 只有你需要的东西。
而不是:
$range = $ws.Range("C:C")
做:
$range = $ws.Range("C:C") | Select Row, text, value2, column
为什么这不直观?
1) 通常管道会使事情变得更慢,特别是如果你推很多来过滤一些
2) 人们会期望,特别是因为它通过 COM 对象,因为它实际上是在设置变量而不是仅仅定义时运行操作。但这不是这里发生的事情。当您设置变量时,它会在定义变量后运行,并在变量被调用的那一刻收集数据[我对此进行了测试,只看到了那个特定时期的资源使用情况],并在第一次变量调用后保存数据。 (这很奇怪)