2017-09-03 38 views
0

238のスプレッドシートに格納されているすべてのデータをマスターシートにコピーするスクリプトを作成しました。私は本当に理由は分かりませんが、特定の文書の後では、スクリプトはエラーが出ることなく途中で終了します。それは非常に奇妙です。私はいくつかの匿名化されたコードを以下に掲載しますので、誰かが私のここでの方法の誤りを見つけるのを助けるかもしれません。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 ++'をダウンロードし、 '表示>記号を表示>すべての文字を表示'に行くことができます。読み込まれたドキュメントと問題のあるドキュメントを比較します。私はそれが**行末(EOL)の**変換かもしれないと推測しています。そのような場合は、 'Edit> EOL Conversion'を開いて問題のファイルを修正し、もう一度やり直してください。 – ian0411

+0

残念ながら私たちの仕事用PCの制限のため、Notepad ++をダウンロードすることはできません。 EOLの問題が原因でしょうか?これらの文書はすべて同じプロセスで同時に生成されています。 問題のドキュメントを再構築してスクリプトを再実行しようとしましたが、以前は正常に機能していたドキュメントでエラーなく終了します。 – darkstarohio

+2

解決策が見つかりました。 Continueコマンドは、ForEach-Objectループ内で使用することはできません。私はそれを返品と交換しました。今はうまくいきます。 – darkstarohio

答えて

0

returnを使用し、次の入力オブジェクトにパイプライン処理を継続する - ないcontinueからForEach-Objectレットに渡されるスクリプトブロック内。

次の簡単な例は、Get-ChildItemによって第1オブジェクトの出力をスキップしを通して残りを通過させる:(PSv5.1)停止前記入力オブジェクトの処理に直接的な方法は現在存在し

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

- 回避策については、私のthis answerを参照してください。これとは対照的に


あなたが発見したとしてForeEach-Objectレットに渡されたスクリプトブロックに直接、for/foreach声明のスクリプトブロックではない予想通り、breakcontinueのみ動作します。例えば

、以下では、ない出力(breakを使用して同じ効果を有するであろう)を生成しない:

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

理由はfor/foreach囲む声明ためcontinuebreak外観はからの脱出/継続する、と何も存在しないため、コマンド全体が終了するということです。呼び出しスタックにfor/foreach/switch文が含まれていない場合、スクリプト内でスクリプト全体が終了します。

関連する問題