用PowershellparsingExcel文档有没有更快的方法?

我通过PowershellMS Excel文档进行交互。 有大约1000行数据的每个excel文件都有可能。

目前这个脚本似乎读取Excel文件,并写入一个值,以每1.6秒1logging的速度进行屏幕。 乍一看,这似乎非常缓慢。

这是我第一次用Powershell读取Excel文件,这是否是常态? 有没有更快的方式来读取和parsingExcel数据?

这里是脚本输出(为了可读性而修剪)

 PS P:\Powershell\ExcelInterfaceTest> .\WRIRMPTruckInterface.ps1 test.xlsx 3/20/2013 4:46:01 PM --------------------------- 2 078110 3 078108 4 078107 5 078109 <SNIP> 242 078338 243 078344 244 078347 245 078350 3/20/2013 4:48:33 PM --------------------------- PS P:\Powershell\ExcelInterfaceTest> 

这是Powershell脚本:

 ######################################################################################################## # This is a common function I am using which will release excel objects ######################################################################################################## function Release-Ref ($ref) { ([System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$ref) -gt 0) [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers() } ######################################################################################################## # Variables ######################################################################################################## ######################################################################################################## # Creating excel object ######################################################################################################## $objExcel = new-object -comobject excel.application # Set to false to not open the app on screen. $objExcel.Visible = $False ######################################################################################################## # Directory location where we have our excel files ######################################################################################################## $ExcelFilesLocation = "C:/ShippingInterface/" + $args[0] ######################################################################################################## # Open our excel file ######################################################################################################## $UserWorkBook = $objExcel.Workbooks.Open($ExcelFilesLocation) ######################################################################################################## # Here Item(1) refers to sheet 1 of of the workbook. If we want to access sheet 10, we have to modify the code to Item(10) ######################################################################################################## $UserWorksheet = $UserWorkBook.Worksheets.Item(2) ######################################################################################################## # This is counter which will help to iterrate trough the loop. This is simply a row counter # I am starting row count as 2, because the first row in my case is header. So we dont need to read the header data ######################################################################################################## $intRow = 2 $a = Get-Date write-host $a write-host "---------------------------" Do { # Reading the first column of the current row $TicketNumber = $UserWorksheet.Cells.Item($intRow, 1).Value() write-host $intRow " " $TicketNumber $intRow++ } While ($UserWorksheet.Cells.Item($intRow,1).Value() -ne $null) $a = Get-Date write-host $a write-host "---------------------------" ######################################################################################################## # Exiting the excel object ######################################################################################################## $objExcel.Quit() ######################################################################################################## #Release all the objects used above ######################################################################################################## $a = Release-Ref($UserWorksheet) $a = Release-Ref($UserWorkBook) $a = Release-Ref($objExcel) 

如果数据是静态的(没有涉及的公式,只是单元格中的数据),则可以作为ODBC数据源访问电子表格,并对其执行SQL(或至less类似SQL)查询。 看看这个关于设置连接string的参考 (工作簿中的每个工作表都是这个练习的“表格”),并且使用System.Data来查询它,就像你定期的数据库一样(Don Jones写了一个包装器function这可能会有所帮助)。

应该比启动Excel和逐个单元格拾取更快。

Robert M. Toups,Jr.在他的博客文章“ 加速读取PowerShell中的Excel文件”中解释说,虽然加载到PowerShell的速度很快,但实际读取Excel单元格的速度非常缓慢 。 另一方面,PowerShell可以快速读取文本文件,因此他的解决scheme是在PowerShell中加载电子表格,使用Excel的本机CSV导出过程将其保存为CSV文件,然后使用PowerShell的标准Import-Csv cmdlet处理数据非常快。 他报告说,这使他的import过程快了20倍!

利用Toups的代码,我创build了一个Import-Excel函数,可以让您轻松导入电子表格数据。 我的代码添加了在Excel工作簿中select特定工作表的function,而不仅仅是使用默认工作表(即在保存文件时的活动工作表)。 如果您省略–SheetName参数,它将使用默认的工作表。

 function Import-Excel([string]$FilePath, [string]$SheetName = "") { $csvFile = Join-Path $env:temp ("{0}.csv" -f (Get-Item -path $FilePath).BaseName) if (Test-Path -path $csvFile) { Remove-Item -path $csvFile } # convert Excel file to CSV file $xlCSVType = 6 # SEE: http://msdn.microsoft.com/en-us/library/bb241279.aspx $excelObject = New-Object -ComObject Excel.Application $excelObject.Visible = $false $workbookObject = $excelObject.Workbooks.Open($FilePath) SetActiveSheet $workbookObject $SheetName | Out-Null $workbookObject.SaveAs($csvFile,$xlCSVType) $workbookObject.Saved = $true $workbookObject.Close() # cleanup [System.Runtime.Interopservices.Marshal]::ReleaseComObject($workbookObject) | Out-Null $excelObject.Quit() [System.Runtime.Interopservices.Marshal]::ReleaseComObject($excelObject) | Out-Null [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers() # now import and return the data Import-Csv -path $csvFile } 

Import-Excel使用这些补充function:

 function FindSheet([Object]$workbook, [string]$name) { $sheetNumber = 0 for ($i=1; $i -le $workbook.Sheets.Count; $i++) { if ($name -eq $workbook.Sheets.Item($i).Name) { $sheetNumber = $i; break } } return $sheetNumber } function SetActiveSheet([Object]$workbook, [string]$name) { if (!$name) { return } $sheetNumber = FindSheet $workbook $name if ($sheetNumber -gt 0) { $workbook.Worksheets.Item($sheetNumber).Activate() } return ($sheetNumber -gt 0) }