2016-06-20 28 views
3

So habe ich dieses Skript, das ich auf meinem Laptop codiert, funktioniert gut, der Job besteht darin, zwei .csv-Dateien in eine .xls-Datei zu kombinieren. Und das Ausführen des Skripts mit zwei .csv-Dateien mit ein paar tausend Zeilen dauert ein paar Sekunden max.Powershell-Skript mit Excel läuft langsam

Aber wenn ich versuche, es auf dem Server auszuführen, wo es sich befinden soll, dauert es ... Stunden. Ich habe keinen vollständigen Lauf gemacht, aber das Schreiben einer Zeile in der .xls-Datei dauert vielleicht 2-3 Sekunden.

Also was ich mich wundere ist, was verursacht die enorme Steigerung der Laufzeit. Ich überwache die CPU-Last während das Skript läuft und es liegt bei 50-60% Auslastung.

Der Server hat eine Menge RAM und zwei CPU-Kern. Wie kann ich das beschleunigen?

Das Skript sieht wie folgt aus:

$path = "C:\test\*" 
$path2 = "C:\test" 
$date = Get-Date -Format d 
$csvs = Get-ChildItem $path -Include *.csv | Sort-Object LastAccessTime -Descending | Select-Object -First 2 
$y = $csvs.Count 

Write-Host "Detected the following CSV files: ($y)" 
foreach ($csv in $csvs) { 
    Write-Host " "$csv.Name 
} 

$outputfilename = "regSCI " + $date 
Write-Host Creating: $outputfilename 

$excelapp = New-Object -ComObject Excel.Application 
$excelapp.sheetsInNewWorkbook = $csvs.Count 
$xlsx = $excelapp.Workbooks.Add() 
$sheet = 1 
$xlleft = -4131 

foreach ($csv in $csvs) { 
    $row = 1 
    $column = 1 
    $worksheet = $xlsx.Worksheets.Item($sheet) 
    $worksheet.Name = $csv.Name 
    $worksheet.Rows.HorizontalAlignment = $xlleft 
    $file = (Get-Content $csv) 
    Write-Host Worksheet created: $worksheet.Name 

    foreach($line in $file) { 
     Write-Host Writing Line 
     $linecontents = $line -split ',(?!\s*\w+")' 

     foreach($cell in $linecontents) { 
      Write-Host Writing Cell 
      $cell1 = $cell.Trim('"') 
      $worksheet.Cells.Item($row, $column) = $cell1 
      $column++ 
     } 
     $column = 1 
     $row++ 
     $WorkSheet.UsedRange.Columns.Autofit() | Out-Null 
    } 
    $sheet++ 
    $headerRange = $worksheet.Range("a1", "q1") 
    $headerRange.AutoFilter() | Out-Null 
} 

$output = $path2 + "\" + $outputfilename 
Write-Host $output 
$xlsx.SaveAs($output) 
$excelapp.Quit() 

Antwort

2

Ihre vorhandenen Code zu beschleunigen, fügen Sie diese einfach nach dem Erstellen Excel-Objekt:

$excelapp.ScreenUpdating = $false 
$excelapp.DisplayStatusBar = $false 
$excelapp.EnableEvents = $false 
$excelapp.Visible = $false 

und diese kurz vor dem Speichern unter:

$excelapp.ScreenUpdating = $true 
$excelapp.DisplayStatusBar = $true 
$excelapp.EnableEvents = $true 

Dies führt dazu, dass Excel das Arbeitsblatt nicht in Echtzeit rendert und jedes Mal, wenn Sie den Con ändern, Ereignisse auslöst tets. Höchstwahrscheinlich DisplayStatusBar und ScreenUpdating spielt keine Rolle, wenn Sie eine Anwendung unsichtbar machen, aber ich habe es nur für den Fall enthalten.

Auch Sie laufen Autofit() nach jeder Zeile. Dies hilft sicherlich nicht mit der Leistung.

+0

Danke für die Antwort, werde dies definitiv versuchen. Könnten Sie auf dem 'Autofit()' -Teil klären, da ich gerade den Excel-Code gestohlen habe, bin ich nicht genau sicher, was alles das tut –

+0

@AndersEkelund AutoFit() passt die Spaltenbreiten an Zelleninhalte an. Wenn Sie es brauchen, tun Sie es einmal pro Blatt, nicht nach dem Einfügen jeder Zeile. –