2013-03-20 19 views
7

Tôi đang giao tiếp với tài liệu MS Excel qua Powershell. Có khả năng mỗi tài liệu excel có khoảng 1000 hàng dữ liệu.Có cách nào nhanh hơn để phân tích tài liệu excel bằng Powershell không?

Hiện tại, tập lệnh này có vẻ như đọc tệp Excel và viết giá trị cho màn hình ở tốc độ 1 bản ghi sau mỗi 6 giây. Thoạt nhìn có vẻ rất chậm.

Đây là lần đầu tiên tôi đọc tệp Excel với Powershell, đây có phải là tiêu chuẩn không? Có cách nào nhanh hơn để tôi đọc và phân tích cú pháp dữ liệu Excel không?

Đây là kết quả kịch bản (tỉa để có thể đọc)

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> 

Đây là Powershell kịch bản:

######################################################################################################## 
# 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) 

Trả lời

6

Nếu dữ liệu là tĩnh (không công thức tham gia, chỉ dữ liệu trong các tế bào), bạn có thể truy cập bảng tính dưới dạng nguồn dữ liệu ODBC và thực thi các truy vấn SQL (hoặc ít nhất là SQL) đối với nó. Hãy xem this reference để thiết lập chuỗi kết nối của bạn (mỗi trang tính trong sổ làm việc sẽ là "bảng" cho bài tập này) và sử dụng System.Data để truy vấn giống như bạn làm cơ sở dữ liệu thông thường (Don Jones đã viết wrapper function cho điều này có thể giúp).

Điều này nên nhanh hơn khởi chạy Excel & chọn qua ô theo ô.

+0

Đó là rất thú vị, tôi sẽ cho nó một shot vào ngày mai và xem cách nó thực hiện. – ProfessionalAmateur

+0

Điều này thật tuyệt. Insanely nhanh hơn. – ProfessionalAmateur

7

Trong mục nhập blog của mình Speed Up Reading Excel Files in PowerShell, Robert M. Toups, Jr. giải thích rằng khi tải lên PowerShell nhanh, thực sự đọc các ô Excel rất chậm. Mặt khác, PowerShell có thể đọc tệp văn bản rất nhanh, vì vậy giải pháp của anh là tải bảng tính trong PowerShell, sử dụng quá trình xuất CSV gốc của Excel để lưu tệp dưới dạng tệp CSV, sau đó sử dụng lệnh ghép ngắn chuẩn Import-Csv của PowerShell để xử lý dữ liệu Nhanh. Anh ta báo cáo rằng điều này đã cho anh ta một quy trình nhập khẩu nhanh hơn gấp 20 lần!

Tận dụng mã của tôi, tôi đã tạo một hàm Import-Excel cho phép bạn nhập dữ liệu bảng tính rất dễ dàng. Mã của tôi thêm khả năng chọn một trang tính cụ thể trong sổ làm việc Excel, thay vì chỉ sử dụng trang tính mặc định (tức là trang tính hiện hoạt tại thời điểm bạn lưu tệp). Nếu bạn bỏ qua tham số –SheetName, nó sẽ sử dụng trang tính mặc định.

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 
} 

Những chức năng bổ sung được sử dụng bởi nhập Excel:

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) 
} 
+0

Liệu 'Nhập CSV có cung cấp cho bạn khả năng chọn dữ liệu ô và cột cụ thể không? – ProfessionalAmateur

+0

Các thực hành tốt nhất cho tiện ích dòng lệnh (quay trở lại với các ngày của Unix) là nó nên làm * một điều tốt. Vì vậy, nhập khẩu-Csv chỉ cần nhập khẩu toàn bộ điều. Nhưng sau đó bạn chỉ cần áp dụng sức mạnh của PowerShell, điển hình là “Object-Object” để chọn các hàng, 'Select-Object' để chọn các cột. –

+0

Hmm Ill hãy kiểm tra. Sẽ trở nên khó khăn vì dữ liệu excel không được định dạng nhất quán. Dữ liệu cột không thống nhất cả ngày. Tôi sẽ chơi với nó và xem.Tôi có thể cần phải có powershell lưu tài liệu excel như một CSV như là bởi vì sẽ không có bất kỳ tương tác người dùng nhận được các tài liệu này. – ProfessionalAmateur

Các vấn đề liên quan