使用foreach循环来计算列,最后添加sum

时间:2017-02-07 19:06:20

标签: powershell export-to-csv

我尝试接受CSV,逐行循环,逐字段循环,抓取两列的值,执行一些简单的数学运算,然后将结果设置为最后一列。我认为我在大多数情况下已将其删除,但我无法正确导出。

我尝试过迭代,更改最终字段的$field.Value并导出CSV,但是它错误地吐出来了。我也尝试将每一行输出到一个新的csv,但无法找到一种方法来过滤掉key:value对中的值。

Import-Csv $csv -Header "SubmissionID","SubmitterName","JobDate","JobTime","TotalDocs","AddnPages","InputFilename","ActualDocs" |
  foreach { 
    foreach ($field in $_.PSObject.Properties) {
      if ($global:count -eq 4) {
        [int]$global:totaldocs = $field.Value
      }
      if ($global:count -eq 5) {
        [int]$global:addnpages = $field.Value
      }
      if ($global:count -eq 7) {
        [int]$global:actualdocs = $global:totaldocs - $global:addnpages
        $global:count = -1
        $field.Value = $global:actualdocs
        Add-Content $outcsv $_.Value
      }
      $global:count = $global:count + 1
    }
  } | Export-Csv $outcsv -NoTypeInformation

3 个答案:

答案 0 :(得分:2)

使用Select-Object代替计算属性:

Import-Csv $csv -header "SubmissionID","SubmitterName","JobDate","JobTime","TotalDocs","AddnPages","InputFilename" |
  Select-Object *,@{Name='ActualDocs';Expression={[int]$_.TotalDocs - [int]$_.AddnPages}} |Export-Csv $outcsv -NoTypeInformation

答案 1 :(得分:0)

我创建了一个带有列的示例csv,用于测试,看起来像这样

 "1","John","01/31/2017","13:35:54","5","1","testfilename",""
 "2","John","01/31/2017","13:35:54","3","1","testfilename",""

我会失去双循环并将当前对象作为对象而不是像下面的示例那样使用多维数组方法。

 $csv = '.\so.csv'
 ## Remove ActualDocs from the header we will add it later
 import-csv $csv -header "SubmissionID","SubmitterName","JobDate","JobTime","TotalDocs","AddnPages","InputFilename" | foreach-object {
     ## Set current object to a veriable to make it nice to play with
     $RecordObject = $_
     ## Set used column values to a variables
     $TotalDocs = $RecordObject.TotalDocs
     $AddnPages = $RecordObject.AddnPages
     ## perform math
     $ActualDocs = $TotalDocs - $AddnPages
     ## Add ActualDocs column to record object
     $RecordObject | Add-Member -MemberType NoteProperty -Name 'ActualDocs' -Value $ActualDocs
     ## output record object for it to get exported via the pipeline to the csv file.
     $RecordObject
 } | export-csv $outcsv -NoTypeInformation

上面的精简版本将与$_循环中的当前对象(foreach-object)一起使用,就像下面的示例一样。

 ## a slimed down version of the above
 ## Remove ActualDocs from the header we will add it later
 import-csv $csv -header "SubmissionID","SubmitterName","JobDate","JobTime","TotalDocs","AddnPages","InputFilename" | foreach-object {
     ## perform math
     $ActualDocs = $_.TotalDocs - $_.AddnPages
     ## Add ActualDocs column to record object
     $_ | Add-Member -MemberType NoteProperty -Name 'ActualDocs' -Value $ActualDocs
     ## Output object
     $_
 } | export-csv $outcsv -NoTypeInformation

这两个示例都会创建一个如下所示的输出csv:

 "SubmissionID","SubmitterName","JobDate","JobTime","TotalDocs","AddnPages","InputFilename","ActualDocs"
 "1","John","01/31/2017","13:35:54","5","1","testfilename","4"
 "2","John","01/31/2017","13:35:54","3","1","testfilename","2"

答案 2 :(得分:0)

你可能只是忽略了将修改过的记录回到管道:

$header = 'SubmissionID', 'SubmitterName', ...
Import-Csv $csv -Header $header | ForEach-Object {
  $_.ActualDocs = [int]$_.TotalDocs - [int]$_.AddnPages
  $_     # <-- this line feeds the records back into the pipeline
} | Export-Csv $outcsv -NoType

请注意,如果要将修改后的数据写回同一文件,则需要在之前完成读取文件,然后开始写入。在表达式中运行Import-Csv(即将语句放在括号中)以实现:

(Import-Csv $csv -Header $header) | ForEach-Object {
  ...
} | Export-Csv $csv -NoType