Почему ForEach-объект l oop перестает работать при чтении файла .CSV - PullRequest
0 голосов
/ 04 августа 2020

ОБНОВЛЕНИЕ:

Я внес рекомендуемые изменения. Вместо этого я переключился на операторы switch.

$csv = import-csv C:\TEST\Test_Data.csv 

$rowcount = 1

ForEach ($line in $CSV) {
   
   $rowcount++
   
   $Store = $line.Store
   $sheet.Cells.Item($rowcount,"A") = $Store

   $StoreNUM = $line.StoreNumber
   $sheet.Cells.Item($rowcount,"B") = $StoreNUM
  
   $COLUMNA = $line.A
   # use that switch statement!
    switch ($COLUMNA) {
        # Find "Prepared With:"
        {$_ -like "*Prepared With:*"}{  
            $sheet.Cells.Item($rowcount,"E") = $COLUMNA
        }
        # Find "Contains"
        {$_ -like "*Contains:*"}{ 
            $sheet.Cells.Item($rowcount,"F") = $COLUMNA
        }
        # You can do -match, it can be a little faster
        {$_ -like "Net Wt."}{  
            $sheet.Cells.Item($rowcount,"G") = $COLUMNA
        }

    } #end Switch

   $COLUMNB = $line.B
   # use that switch statement!
    switch ($COLUMNB) {
        # Find "Prepared With:"
        {$_ -like "*Prepared With:*"}{  
            $sheet.Cells.Item($rowcount,"E") = $COLUMNB
        }
        # Find "Contains"
        {$_ -like "*Contains:*"}{ 
            $sheet.Cells.Item($rowcount,"F") = $COLUMNB
        }
        # You can do -match, it can be a little faster
        {$_ -like "Net Wt."}{  
            $sheet.Cells.Item($rowcount,"G") = $COLUMNB
        }

    } #end Switch

   $COLUMNC = $line.C
   # use that switch statement!
    switch ($COLUMNC) {
        # Find "Prepared With:"
        {$_ -like "*Prepared With:*"}{  
            $sheet.Cells.Item($rowcount,"E") = $COLUMNC
        }
        # Find "Contains"
        {$_ -like "*Contains:*"}{ 
            $sheet.Cells.Item($rowcount,"F") = $COLUMNC
        }
        # You can do -match, it can be a little faster
        {$_ -like "Net Wt."}{  
            $sheet.Cells.Item($rowcount,"G") = $COLUMNC
        }

    } #end Switch

   $COLUMND = $line.D
   # use that switch statement!
    switch ($COLUMND) {
        # Find "Prepared With:"
        {$_ -like "*Prepared With:*"}{  
            $sheet.Cells.Item($rowcount,"E") = $COLUMND
        }
        # Find "Contains"
        {$_ -like "*Contains:*"}{ 
            $sheet.Cells.Item($rowcount,"F") = $COLUMND
        }
        # You can do -match, it can be a little faster
        {$_ -like "Net Wt."}{  
            $sheet.Cells.Item($rowcount,"G") = $COLUMND
        }

    } #end Switch

   $COLUMNE = $line.E
   # use that switch statement!
    switch ($COLUMNE) {
        # Find "Prepared With:"
        {$_ -like "*Prepared With:*"}{  
            $sheet.Cells.Item($rowcount,"E") = $COLUMNE
        }
        # Find "Contains"
        {$_ -like "*Contains:*"}{ 
            $sheet.Cells.Item($rowcount,"F") = $COLUMNE
        }
        # You can do -match, it can be a little faster
        {$_ -like "Net Wt."}{  
            $sheet.Cells.Item($rowcount,"G") = $COLUMNE
        }

    } #end Switch

   $COLUMNF = $line.F
   # use that switch statement!
    switch ($COLUMNF) {
        # Find "Prepared With:"
        {$_ -like "*Prepared With:*"}{  
            $sheet.Cells.Item($rowcount,"E") = $COLUMNF
        }
        # Find "Contains"
        {$_ -like "*Contains:*"}{ 
            $sheet.Cells.Item($rowcount,"F") = $COLUMNF
        }
        # You can do -match, it can be a little faster
        {$_ -like "Net Wt"}{  
            $sheet.Cells.Item($rowcount,"G") = $COLUMNF
        }

    } #end Switch

} #end Foreach

Но у меня все еще есть проблема в исходном CSV-файле: он не проходит мимо 8-го столбца данных. Мои данные занимают 17 столбцов. Не понимаю, почему перестает бегать по столбцам. Мне известно, что нет пустых столбцов. Вся ваша помощь до сих пор очень ценится.

Не понимает, почему мой ForEach l oop перестает работать. Все работает правильно, пока ####Evaluate Column E#### не достигнет E, поиск прекратится. Все, что я помещаю для данных в CSV, полностью игнорируется. Если я помещаю данные в столбцы A - D, все работает нормально.

Вероятно, есть более простой способ сделать то, что я пытаюсь выполнить sh.

$csv = import-csv C:\TEST\Test_Data.csv 
$csv | foreach-object {
    
  $ItemName = $_.Filename
  $Store = $_.Store
  $StoreNUM =$_.StoreNumber
  $Department =$_.Department 
  $COLUMNA = $_.A
  $COLUMNB = $_.B
  $COLUMNC = $_.C
  $COLUMND = $_.D
  $COLUMNE = $_.E
  $COLUMNF = $_.F
  $COLUMNG = $_.G
  $COLUMNH = $_.H

}
$csv | ForEach-Object {$rowcount = 2}{

   $Store = $_.Store
   $sheet.Cells.Item($rowcount,"A") = $Store

   $StoreNUM = $_.StoreNumber
   $sheet.Cells.Item($rowcount,"B") = $StoreNUM

   $Department = $_.Department
   $sheet.Cells.Item($rowcount,"C") = $Department

   $ItemName = $_.Filename
   $sheet.Cells.Item($rowcount,"D") = $ItemName


####Evaluate Column A####
   $COLUMNA = $_.A

   #Find Prepared With:
   if($COLUMNA -like "*Prepared*"){
        $sheet.Cells.Item($rowcount,"E") = $COLUMNA
   }

   #Find Contains:
   elseif($COLUMNA -like "*Contains:*"){
        $sheet.Cells.Item($rowcount,"F") = $COLUMNA
   }
   
   #Find Net Weight:
   elseif($COLUMNA -like "*Net Wt.:*"){
        $sheet.Cells.Item($rowcount,"G") = $COLUMNA
   }

   #Find OLD UPC:
   elseif($COLUMNA -like "*OLD*UPC*"){
        $sheet.Cells.Item($rowcount,"H") = $COLUMNA
   }

   #Find NEW UPC:
   elseif($COLUMNA -like "*NEW*UPC*"){
        $sheet.Cells.Item($rowcount,"I") = $COLUMNA
   }

   #Find UPC:
   elseif($COLUMNA -like "*UPC*"){
        $sheet.Cells.Item($rowcount,"J") = $COLUMNA
   }

   #Find Label Type
   elseif($COLUMNA -clike "*LABEL*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMNA
   }

   #Find Section
   elseif($COLUMNA -like "*Section:*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMNA
   }

   #Find Retail
   elseif($COLUMNA -like "*Retail:*"){
        $sheet.Cells.Item($rowcount,"M") = $COLUMNA
   }

   #Find Cost
   elseif($COLUMNA -like "*Cost:*"){
        $sheet.Cells.Item($rowcount,"N") = $COLUMNA
   }
   
   #Find Requested By
   elseif($COLUMNA -like "*Requested by:*"){
        $sheet.Cells.Item($rowcount,"O") = $COLUMNA
   }
   
   else{
        $sheet.Cells.Item($rowcount,"Q") = $COLUMNA
   }

####Evaluate Column B#####
   $COLUMNB = $_.B

   #Find Prepared With:
   if($COLUMNB -like "*Prepared*"){
        $sheet.Cells.Item($rowcount,"E") = $COLUMNB
   }

   #Find Contains:
   elseif($COLUMNB -like "*Contains:*"){
        $sheet.Cells.Item($rowcount,"F") = $COLUMNB
   }
   
   #Find Net Weight:
   elseif($COLUMNB -like "*Net Wt.:*"){
        $sheet.Cells.Item($rowcount,"G") = $COLUMNB
   }

   #Find OLD UPC:
   elseif($COLUMNB -like "*OLD*UPC*"){
        $sheet.Cells.Item($rowcount,"H") = $COLUMNB
   }

   #Find NEW UPC:
   elseif($COLUMNB -like "*NEW*UPC*"){
        $sheet.Cells.Item($rowcount,"I") = $COLUMNB
   }

   #Find UPC:
   elseif($COLUMNB -like "*UPC*"){
        $sheet.Cells.Item($rowcount,"J") = $COLUMNB
   }

   #Find Label Type
   elseif($COLUMNB -clike "*LABEL*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMNB
   }

   #Find Section
   elseif($COLUMNB -like "*Section:*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMNB
   }

   #Find Retail
   elseif($COLUMNB -like "*Retail:*"){
        $sheet.Cells.Item($rowcount,"M") = $COLUMNB
   }

   #Find Cost
   elseif($COLUMNB -like "*Cost:*"){
        $sheet.Cells.Item($rowcount,"N") = $COLUMNB
   }
   
   #Find Requested By
   elseif($COLUMNB -like "*Requested by:*"){
        $sheet.Cells.Item($rowcount,"O") = $COLUMNB
   }
   
   else{
        $sheet.Cells.Item($rowcount,"R") = $COLUMNB
   }

####Evaluate Column C####
   $COLUMNC = $_.C

   #Find Prepared With:
   if($COLUMNC -like "*Prepared*"){
        $sheet.Cells.Item($rowcount,"E") = $COLUMNC
   }

   #Find Contains:
   elseif($COLUMNC -like "*Contains:*"){
        $sheet.Cells.Item($rowcount,"F") = $COLUMNC
   }
   
   #Find Net Weight:
   elseif($COLUMNC -like "*Net Wt.:*"){
        $sheet.Cells.Item($rowcount,"G") = $COLUMNC
   }

   #Find OLD UPC:
   elseif($COLUMNC -like "*OLD*UPC*"){
        $sheet.Cells.Item($rowcount,"H") = $COLUMNC
   }

   #Find NEW UPC:
   elseif($COLUMNC -like "*NEW*UPC*"){
        $sheet.Cells.Item($rowcount,"I") = $COLUMNC
   }

   #Find UPC:
   elseif($COLUMNC -like "*UPC*"){
        $sheet.Cells.Item($rowcount,"J") = $COLUMNC
   }

   #Find Label Type
   elseif($COLUMNC -clike "*LABEL*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMNC
   }

   #Find Section
   elseif($COLUMNC -like "*Section:*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMNC
   }

   #Find Retail
   elseif($COLUMNC -like "*Retail:*"){
        $sheet.Cells.Item($rowcount,"M") = $COLUMNC
   }

   #Find Cost
   elseif($COLUMNC -like "*Cost:*"){
        $sheet.Cells.Item($rowcount,"N") = $COLUMNC
   }
   
   #Find Requested By
   elseif($COLUMNC -like "*Requested by:*"){
        $sheet.Cells.Item($rowcount,"O") = $COLUMNC
   }
   
   else{
        $sheet.Cells.Item($rowcount,"S") = $COLUMNC
   }

####Evaluate Column D####
   $COLUMND = $_.D

   #Find Prepared With:
   if($COLUMND -like "*Prepared*"){
        $sheet.Cells.Item($rowcount,"E") = $COLUMND
   }

   #Find Contains:
   elseif($COLUMND -like "*Contains:*"){
        $sheet.Cells.Item($rowcount,"F") = $COLUMND
   }
   
   #Find Net Weight:
   elseif($COLUMND -like "*Net Wt.:*"){
        $sheet.Cells.Item($rowcount,"G") = $COLUMND
   }

   #Find OLD UPC:
   elseif($COLUMND -like "*OLD*UPC*"){
        $sheet.Cells.Item($rowcount,"H") = $COLUMND
   }

   #Find NEW UPC:
   elseif($COLUMND -like "*NEW*UPC*"){
        $sheet.Cells.Item($rowcount,"I") = $COLUMND
   }

   #Find UPC:
   elseif($COLUMND -like "*UPC*"){
        $sheet.Cells.Item($rowcount,"J") = $COLUMND
   }

   #Find Label Type
   elseif($COLUMND -clike "*LABEL*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMND
   }

   #Find Section
   elseif($COLUMND -like "*Section:*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMND
   }

   #Find Retail
   elseif($COLUMND -like "*Retail:*"){
        $sheet.Cells.Item($rowcount,"M") = $COLUMND
   }

   #Find Cost
   elseif($COLUMND -like "*Cost:*"){
        $sheet.Cells.Item($rowcount,"N") = $COLUMND
   }
   
   #Find Requested By
   elseif($COLUMND -like "*Requested by:*"){
        $sheet.Cells.Item($rowcount,"O") = $COLUMND
   }
   
   else{
        $sheet.Cells.Item($rowcount,"T") = $COLUMND
   }

####Evaluate Column E####
   $COLUMNE = $_.E

   #Find Prepared With:
   if($COLUMNE -like "*Prepared*"){
        $sheet.Cells.Item($rowcount,"E") = $COLUMNE
   }

   #Find Contains:
   if($COLUMNE -like "*Contains:*"){
        $sheet.Cells.Item($rowcount,"F") = $COLUMNE
   }
   
   #Find Net Weight:
   elseif($COLUMNE -like "*Net Wt.:*"){
        $sheet.Cells.Item($rowcount,"G") = $COLUMNE
   }

   #Find OLD UPC:
   elseif($COLUMNE -like "*OLD*UPC*"){
        $sheet.Cells.Item($rowcount,"H") = $COLUMNE
   }

   #Find NEW UPC:
   elseif($COLUMNE -like "*NEW*UPC*"){
        $sheet.Cells.Item($rowcount,"I") = $COLUMNE
   }

   #Find UPC:
   elseif($COLUMNE -like "*UPC*"){
        $sheet.Cells.Item($rowcount,"J") = $COLUMNE
   }

   #Find Label Type
   elseif($COLUMNE -clike "*LABEL*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMNE
   }


   #Find Section
   elseif($COLUMNE -like "*Section:*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMNE
   }

   #Find Retail
   elseif($COLUMNE -like "*Retail:*"){
        $sheet.Cells.Item($rowcount,"M") = $COLUMNE
   }

   #Find Cost
   elseif($COLUMNE -like "*Cost:*"){
        $sheet.Cells.Item($rowcount,"N") = $COLUMNE
   }
   
   #Find Requested By
   elseif($COLUMNE -like "*Requested by:*"){
        $sheet.Cells.Item($rowcount,"O") = $COLUMNE
   }
   
   else{
        $sheet.Cells.Item($rowcount,"U") = $COLUMNE
   } 

####Evaluate Column F####
   $COLUMNF = $_.F

   #Find Prepared With:
   if($COLUMNF -like "*Prepared*"){
        $sheet.Cells.Item($rowcount,"E") = $COLUMNF
   }

   #Find Contains:
   elseif($COLUMNF -like "*Contains:*"){
        $sheet.Cells.Item($rowcount,"F") = $COLUMNF
   }
   
   #Find Net Weight:
   elseif($COLUMNF -like "*Net Wt.:*"){
        $sheet.Cells.Item($rowcount,"G") = $COLUMNF
   }

   #Find OLD UPC:
   elseif($COLUMNF -like "*OLD*UPC*"){
        $sheet.Cells.Item($rowcount,"H") = $COLUMNF
   }

   #Find NEW UPC:
   elseif($COLUMNF -like "*NEW*UPC*"){
        $sheet.Cells.Item($rowcount,"I") = $COLUMNF
   }

   #Find UPC:
   elseif($COLUMNF -like "*UPC*"){
        $sheet.Cells.Item($rowcount,"J") = $COLUMNF
   }

   #Find Label Type
   elseif($COLUMNF -clike "*LABEL*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMNF
   }


   #Find Section
   elseif($COLUMNF -like "*Section:*"){
        $sheet.Cells.Item($rowcount,"L") = $COLUMNF
   }

   #Find Retail
   elseif($COLUMNF -like "*Retail:*"){
        $sheet.Cells.Item($rowcount,"M") = $COLUMNF
   }

   #Find Cost
   elseif($COLUMNF -like "*Cost:*"){
        $sheet.Cells.Item($rowcount,"N") = $COLUMNF
   }
   
   #Find Requested By
   elseif($COLUMNF -like "*Requested by:*"){
        $sheet.Cells.Item($rowcount,"O") = $COLUMNF
   }
   
   else{
        $sheet.Cells.Item($rowcount,"V") = $COLUMNF
   }


    #Increase Row Count
    $rowcount++

}

Ответы [ 2 ]

1 голос
/ 05 августа 2020

У вас есть Foreach-Object конвейерная передача содержимого вашего CSV-файла в один блок сценария, но затем у вас есть другой полностью отдельный блок сценария, который "унаследовал" $rowcount = 2 от предыдущего блока.

Все, что я делаю ниже, - это добавляю некоторые разрывы строк, отступы и комментарии в ваш код. Форматирование ваших сценариев, когда каждый блок сценариев начинается с отдельной строки, отступ и выравнивание последней скобки с уровнем отступа начальной строки блока может помочь в устранении неполадок.

# process each CSV line
$csv | ForEach-Object {
    $rowcount = 2
} # End Foreach-Object
 
# this starts a new block - $rowcount is definitely 2!
# but it's no longer processing each line of your CSV
{
   $Store = $_.Store
   $sheet.Cells.Item($rowcount,"A") = $Store

   $StoreNUM = $_.StoreNumber
   $sheet.Cells.Item($rowcount,"B") = $StoreNUM
   …
   $COLUMNA = $_.A
   … 
}

Другой способ сделать l oop, который может проясните, если это все еще не так:

# since we're not using the pipeline, this is now a Foreach
# it's a lot faster than Foreach-Object for this kind of thing

ForEach ($line in $CSV) {
    $rowcount = 2
    # notice we've done nothing with $line!
}  # End Foreach
 
# the next block 
# $line will be set to the last line of the CSV processed above
{
    $Store = $line.Store
    $sheet.Cells.Item($rowcount,"A") = $Store
 
    $StoreNUM = $line.StoreNumber
    $sheet.Cells.Item($rowcount,"B") = $StoreNUM
    … 
    $COLUMNA = $line.A
    … 
} 

И для решения, что вы действительно хотели сделать, это установить $rowcount = 2 за пределы вашего блока скрипта. Вы не используете его в качестве счетчика и не увеличиваете его, поэтому на самом деле его там не должно быть - вам не нужно постоянно устанавливать его для каждой строки вашего CSV.

Довольно часто вы Посмотрите, как люди создают секцию в начале своих скриптов для определения подобных «констант» - ничего особенного в этом нет, кроме установки значения, но секция вдали от любых циклов дает понять, что переменная не предназначена для изменения.

# We're using Foreach again for speed - 
# Consumes more memory, but typically no big deal for a text file

$rowcount = 2

ForEach ($line in $CSV) {
   $Store = $line.Store
   $sheet.Cells.Item($rowcount,"A") = $Store

   $StoreNUM = $line.StoreNumber
   $sheet.Cells.Item($rowcount,"B") = $StoreNUM
   …
   $COLUMNA = $line.A
   # use that switch statement!
    switch ($COLUMNA) {
        # Find "Prepared With:"
        {$_ -like "*Prepared*"}{  
            $sheet.Cells.Item($rowcount,"E") = $COLUMNA
        }
        # Find "Contains"
        {$_ -like "*Contains:*"}{ 
            $sheet.Cells.Item($rowcount,"F") = $COLUMNA
        }
        # You can do -match, it can be a little faster
        {$_ -match "Net Wt\."}{  
            $sheet.Cells.Item($rowcount,"G") = $COLUMNA
        }
       … 
    } #end Switch
} #end Foreach

1 голос
/ 04 августа 2020

Раньше я отвечал, что думал, что вы заканчиваете свой l oop раньше, но я ошибался. Я забыл, что ForEach-Object поддерживает как -Begin, так и -End блоки сценариев, которые вы использовали.

Например, вот аналогичная команда, но с включенными именами параметров.

1..3 | ForEach-Object `
    -Begin {"starting..."; $baseVar = "ham"} `
    -Process {"$basevar + $_"} `
    -End {"all done"}

starting...
ham + 1
ham + 2
ham + 3
all done

Это поддерживается в PowerShell, но практически не используется. Я писал PowerShell в течение десяти лет на уровне предприятия, и это бросило меня на oop. Я бы предостерегал от этого.

И последнее, стилистически вы делаете так много сравнений If, что довольно сложно отслеживать свой код. Я бы упростил часть вашего кода следующим образом.

#Find Prepared With:
   if($COLUMNA -like "*Prepared*"){
        $sheet.Cells.Item($rowcount,"E") = $COLUMNA
   }

   #Find Contains:
   elseif($COLUMNA -like "*Contains:*"){
        $sheet.Cells.Item($rowcount,"F") = $COLUMNA
   }
   
   #Find Net Weight:
   elseif($COLUMNA -like "*Net Wt.:*"){
        $sheet.Cells.Item($rowcount,"G") = $COLUMNA
   }

   #Find OLD UPC:
   elseif($COLUMNA -like "*OLD*UPC*"){
        $sheet.Cells.Item($rowcount,"H") = $COLUMNA
   }

этот код будет переписан с использованием оператора switch и будет выглядеть так.

switch ($COLUMNA)
{
    {$_ -like "*Prepared*"}{   #Find Prepared With:
        $sheet.Cells.Item($rowcount,"E") = $COLUMNA
    }
    {$_ -like "*Contains:*"}{  #Find Contains
        $sheet.Cells.Item($rowcount,"F") = $COLUMNA
    }
    {$_ -like "*Net Wt.:*"}{   #Find Net Weight:
        $sheet.Cells.Item($rowcount,"G") = $COLUMNA
    }
    {$_ -like "*OLD*UPC*"}{    #Find OLD UPC:
        $sheet.Cells.Item($rowcount,"H") = $COLUMNA
    }
}

Еще лучший подход был бы чтобы переместить этот код в функцию, например, Set-ColumnValue


Function Set-ColumnValue{ 
    Param
        ($rowcount,
         $cellInfo
        )

    switch ($cellInfo)
    {
        {$_ -like "*Prepared*"}{   #Find Prepared With:
            $sheet.Cells.Item($rowcount,"E") = $cellInfo
        }
        {$_ -like "*Contains:*"}{  #Find Contains
            $sheet.Cells.Item($rowcount,"F") = $cellInfo
        }
        {$_ -like "*Net Wt.:*"}{   #Find Net Weight:
            $sheet.Cells.Item($rowcount,"G") = $cellInfo
        }
        {$_ -like "*OLD*UPC*"}{    #Find OLD UPC:
            $sheet.Cells.Item($rowcount,"H") = $cellInfo
        }
    }
}

Затем вы замените эти блоки if на Set-ColumnValue -rowCount $rowCount -CellInfo $columnA

Изменить: это ниже было неверным

Как будто @notjustme намекает, вы очень рано заканчиваете свой forEach-object.

$csv | ForEach-Object {$rowcount = 2}{

   $Store = $_.Store

Итак, чтобы уточнить c, вы заканчиваете прямо здесь

$csv | ForEach-Object {$rowcount = 2} <==== Ends the forEach
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...