使用 foreach 循环来计算列,在末尾添加总和

Using a foreach loop to tally up columns, adding sum at the end

我正在尝试获取 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

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

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

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

我会失去双循环并使用当前对象作为对象而不是你的 multi-dimensional 数组方法,如下例所示。

 $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"

您可能只是忽略了将修改后的记录回显到管道:

$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