写出来在PowerShell中更好的方法

我有一个PowerShell脚本读入一个CSV,然后附加到Excel工作表。 它运行得非常缓慢。 我已经search,似乎这是使用COM写入Excel的限制。 我发现加速的一些build议是写出整个范围,而不是逐个单元格。 不过,我需要格式化单元格,写入范围时似乎不可能这样做。 任何build议如何优化下面的代码将是受欢迎的。 我没有select使用数据库。

$csvPath = "Z:\script_test\" $outputFile = "Z:\script_test\exceltest.xlsx" foreach($csvFile in Get-ChildItem $csvPath -Filter "STATS*.txt" ){ $csvFilePath = [io.path]::combine($csvPath, $csvFile) $rawcsvData = Import-Csv -Delimiter ";" -Path $csvFilePath $Excel = New-Object -ComObject excel.application $Excel.visible = $false $workbook = $Excel.workbooks.Open($outputFile) $ExcelWorkSheet = $Excel.WorkSheets.item("2016") $ExcelWorkSheet.activate() $excel.cells.item(1,1) = “PEX” $excel.cells.item(1,2) = “RUN DATE” $excel.cells.item(1,3) = “EXECS” $excel.cells.item(1,4) = “CPU AV.” $excel.cells.item(1,5) = “CPU HI.” $excel.cells.item(1,6) = “CPU TOT.” $excel.cells.item(1,7) = “#VALUE!” $excel.cells.item(1,8) = “ELAPS AV.” $excel.cells.item(1,9) = “ELAPSE HI.” $excel.cells.item(1,10) = “ELAPSE TOT” $i = $ExcelWorkSheet.UsedRange.rows.count + 1 foreach($rawcsv in $rawcsvData) { $RUNDATE = $rawcsv.“RUN DATE ”.replace("--1","") $EXECS = $rawcsv."EXECS ".replace("?","") $CPUAV = $rawcsv.“CPU AV. ”.replace("-",":") $CPUHI = $rawcsv.“CPU HI. ”.replace("-",":") $CPUTOT = $rawcsv.“CPU TOT. ”.replace("-",":") $ELAPSEAV = $rawcsv.“ELAPSE AV.”.replace("-",":") $ELAPSEHI = $rawcsv.“ELAPSE HI.”.replace("-",":") $ELPASETOT = $rawcsv.“ELPASE TOT”.replace("-",":") Write-Output("working" + $i) $excel.cells.item($i,1) = $rawcsv."PEX " $excel.cells.item($i,2) = $RUNDATE $excel.cells.item($i,2).NumberFormat = “yyyy/mm/dd” $excel.cells.item($i,3) = $EXECS $excel.cells.item($i,4) = $CPUAV $excel.cells.item($i,4).NumberFormat = “hh:mm:ss.00” $excel.cells.item($i,5) = $CPUHI $excel.cells.item($i,5).NumberFormat = “hh:mm:ss.00” $excel.cells.item($i,6) = $CPUTOT $excel.cells.item($i,6).NumberFormat = “hh:mm:ss.00” $excel.cells.item($i,7) = “=((HOUR(F"+$i+")*3600)+(MINUTE(F"+$i+")*60)+SECOND(F"+$i+"))*21” $excel.cells.item($i,8) = $ELAPSEAV $excel.cells.item($i,8).NumberFormat = “hh:mm:ss.00” $excel.cells.item($i,9) = $ELAPSEHI $excel.cells.item($i,9).NumberFormat = “hh:mm:ss.00” $excel.cells.item($i,10) = $ELPASETOT $excel.cells.item($i,10).NumberFormat = “hh:mm:ss.00” $i++ } $ExcelWorkSheet.UsedRange.RemoveDuplicates() #$workbook.saveas($outputFile) $workbook.save() $Excel.Quit() Remove-Variable -Name excel [gc]::collect() [gc]::WaitForPendingFinalizers() Move-Item -Path $csvFilePath -Destination "Z:\script_test\used files" } 

慢的部分是关于COM对象的性能。 不幸的是,如果你继续使用COM对象的话,你将无法将其加速。

回到过去,我有一些与Excel相关的项目,我发现一些使用外部DLL的很棒的模块,你可以看看它: PSExcel

最好的部分是你不需要安装Excel,就像使用COM对象一样。

有一个Powershell cmdlet可以安装,名为Export-XLSX,与本地Export-CSV非常类似: https : //gallery.technet.microsoft.com/office/Export-XLSX-PowerShell-f2f0c035

这里的文档非常好,但是这里有一个如何使用它的例子:

 # 1. Define path of Export-XLSX.ps1 script: $ExportXLSX = "C:\YourFilePath\Export-XLSX\Export-XLSX.ps1" # 2. Call script same as any other function by preceding filename with a period (.$ExportXLSX) and following it with parameters: Get-ChildItem $env:windir | Select-Object Mode,LastWriteTime,Length,Name | .$ExportXLSX -Path 'c:\temp\PSExcel.xlsx' -WorkSheetName 'Files' 

更新:与其他答案中提供的完整PSExcel模块相比,我更喜欢PSExcel模块。 在我的testing中,速度方面的performance几乎相同,但PSExcel模块似乎创build了更小的文件。

例如,使用上面的windows目录列表,在我的机器上使用Export-XLSX.ps1输出一个53KB的文件。 但是,PSExcel模块输出一个7KB的文件。 鉴于其易用性,我会去用它。