2017-09-03 128 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语句,则会退出整个脚本。