2017-09-03 130 views
0

因此,我一直在編寫一個腳本,它將獲取238個電子表格中存儲的所有數據,並將其複製到主表以及9個高級報表中。我真的不確定爲什麼,但是在特定的文檔之後,腳本過早地結束,沒有發佈任何錯誤。這很奇怪。我會在下面發佈一些匿名代碼,所以也許有人可以幫我在這裏找到我的方式的錯誤。Powershell腳本過早退出ForEach-Object循環

據我所知,它退出後的文件很好。我看不到任何數據錯誤,並且在PowerShell剛剛調用它完全退出腳本之前,信息已成功複製到主文檔。

我試過通過限制僅限於包含問題文件的文件夾來更改數據集的大小。它仍然在沒有錯誤輸出的同一個文件後結束。由於公司政策,我無法上傳文件,但與其他任何相同性質的文件相比,我確實沒有看到該文件上的任何數據。

此外,爲蹩腳的代碼提前道歉。我不是開發人員,並且已經重新學習PowerShell,因爲它是目前唯一可用的工具。

$StartTime = Get-Date -Format g 
Write-Host $StartTime 
pushd "Z:\Shared Documents\IO" 
$TrackTemplate = "C:\Users\USERNAME\Desktop\IODATA\MasterTemplate.xlsx" 

# Initialize the Master Spreadsheet 
$xlMaster = New-Object -ComObject Excel.Application 
$xlMaster.Visible = $False 
$xlMaster.DisplayAlerts = $False 
$MasterFilePath = "C:\Users\USERNAME\Desktop\IODATA\Master.xlsx" 
Copy-Item $TrackTemplate $MasterFilePath 
$wbMaster = $xlMaster.Workbooks.Open($MasterFilePath) 
$wsMaster = $wbMaster.Worksheets.Item(2) 
$wsMaster.Unprotect("PASSWORD") 
$wsMasterRow = 3 

# Initialize L4 Document Object 
$xlL4 = New-Object -ComObject Excel.Application 
$xlL4.Visible = $False 
$xlL4.DisplayAlerts = $False 

# Initialize object for input documents 
$xlInput = New-Object -ComObject Excel.Application 
$xlInput.Visible = $False 
$xlInput.DisplayAlerts = $False 

# Arrays used to create folder path names 
$ArrayRoot = @("FOLDER1","FOLDER2","FOLDER3","FOLDER4","FOLDER5","FOLDER6","FOLDER7","FOLDER8","FOLDER9") 
$ArrayShort = @("SUB1","SUB2","SUB3","SUB4","SUB5","SUB6","SUB7","SUB8","SUB9") 
# $counter is used to iterate inside the loop over the short name array. 
$counter = 0 
$FileNumber = 0 
$TotalFiles = 238 
$ArrayRoot | ForEach-Object { 
    $FilePathL4 = "C:\Users\USERNAME\Desktop\IODATA\ROLLUP\" + $ArrayShort[$counter] + "_DOC_ROLLUP.xlsx" 
    Copy-Item $TrackTemplate $FilePathL4 
    $wbL4 = $xlL4.Workbooks.Open($FilePathL4) 
    $wsL4 = $wbL4.Worksheets.Item(2) 
    $wsL4.Unprotect("PASSWORD") 
    $wsL4Row = 3 
    If ($ArrayShort[$counter] -eq "SUB7") {$FilePath = "Z:\Shared Documents\IO\" + $_ + "\" + $ArrayShort[$counter] + " - DOC v2\"} 
    Else {$FilePath = "Z:\Shared Documents\IO\" + $_ + "\!" + $ArrayShort[$counter] + " - DOC v2\"} 
    Get-ChildItem -Path $FilePath | ForEach-Object { 
     If ($_.Name -eq "SPECIFIC_DOC.xlsx") {Continue} 
     $FileNumber += 1 
     Write-Host "$FileNumber/$TotalFiles $_" 
     $wbInput = $xlInput.Workbooks.Open($_.FullName) 
     $wsInput = $wbInput.Worksheets.Item(2) 
     $wsInputLastRow = 0 

     #Find the last row in the Input document 
     For ($i = 3; $i -le 10000; $i++) { 
      If ([string]::IsNullOrEmpty($wsInput.Cells.Item($i,1).Value2)) { 
       $wsInputLastRow = $i - 1 
       Break 
      } 
      Else { Continue } 
     } 

     [void]$wsInput.Range("A3:AC$wsInputLastRow").Copy() 
     Start-Sleep -Seconds 1 
     [void]$wsMaster.Range("A$wsMasterRow").PasteSpecial(-4163) 
     Start-Sleep -Seconds 1 
     $wsMasterRow += $wsInputLastRow - 2 
     [void]$wsL4.Range("A$wsL4Row").PasteSpecial(-4163) 
     Start-Sleep -Seconds 1 
     $wsL4Row += $wsInputLastRow - 2 

     $wbInput.Close() 
     $wbMaster.Save() 
    } 
    $counter += 1 
    $wsL4.Protect("PASSWORD") 
    $wbL4.Save() 
    $wbL4.Close() 
} 
$wsMaster.Protect("PASSWORD") 
$wbMaster.Save() 
$wbMaster.Close() 
$xlMaster.Quit() 

$EndTime = Get-Date -Format g 
$TimeTotal = New-Timespan -Start $StartTime -End $EndTime 
Write-Host $TimeTotal 
+0

你可以下載'Notepad ++',然後進入'View> Show Symbol> Show All Characters'。比較加載好的文檔和出現問題的文檔。我猜測它可能是**行尾(EOL)**轉換。如果是這種情況,請轉至編輯EOL Conversion來修改問題文件並重試。 – ian0411

+0

不幸的是,由於我們工作電腦的限制,我無法下載Notepad ++。 EOL問題會導致此問題嗎?所有這些文件都是由同一個進程同時生成的。 我也嘗試重建問題文檔並重新運行腳本,現在它退出沒有錯誤在以前工作正常的文檔上。 – darkstarohio

+2

我找到了解決方案。 Continue命令不能用於ForEach-Object Loop內部。我用Return代替它,它現在工作正常。 – darkstarohio

回答

0

要繼續流水線處理下一個輸入對象,使用return - 不continue - 在傳遞給ForEach-Object cmdlet的腳本塊。

下面的簡單示例通過Get-ChildItem跳過第一對象輸出,並通過穿過其餘的:

$i = 0; Get-ChildItem | ForEach-Object{ if ($i++ -eq 0) { return }; $_ } 

目前(PSv5.1)沒有直接的方法來停止另外的輸入對象的處理 - 有關解決方法,請參閱我的this answer


相比之下,因爲你已經發現,breakcontinue只有預期在for/foreach聲明的腳本塊工作,而不是直接傳遞給ForeEach-Objectcmdlet的腳本塊:

例如,下面的產生沒有輸出(使用break將具有相同的效果):

$i = 0; Get-ChildItem | ForEach-Object{ if ($i++ -eq 0) { continue }; $_ } 

的原因是continuebreak尋找一個封閉for/foreach聲明繼續/打出來的,既然沒有,整個命令退出;在腳本中,如果調用堆棧中沒有包含for/foreach/switch語句,則會退出整個腳本。