PowerShell ForEach-Object 仅匹配第一个传递的值
PowerShell ForEach-Object Only Matching first Value passed
我正在编写读取以下格式的 CSV 文件的 PowerShell 脚本:
A,B,ProgrammeSeller,D,E,F,G,H,I,J,K,L,M,N,O,P,SellerCode,Date,Seller,Currency1,InvoiceAmmount,DiscountAmount,PurchasePrice,TotalsCurrency,TotalInvoiceAmmount,TotalDiscountAmmount,TotalPurchasePrice,Reviewed,AC,Signed
,,PROGRAMME,,,,,,,,,,,,,,380,09/12/2021,SELLER_BE,EUR,2813828.46,17594.22,2796234.24,EUR,0,0,0,Reviewed by:,,Signed:
,,PROGRAMME,,,,,,,,,,,,,,383,09/12/2021,SELLER_DE,EUR,3287812.58,17595.8,3270216.78,EUR,0,0,0,Reviewed by:,,Signed:
,,PROGRAMME,,,,,,,,,,,,,,383,09/12/2021,SELLER_DE,USD,1520725.4,11428.98,1509296.42,USD,0,0,0,Reviewed by:,,Signed:
,,PROGRAMME,,,,,,,,,,,,,,381,09/12/2021,SELLER_DK,DKK,6047281.25,26163.13,6021118.12,DKK,0,0,0,Reviewed by:,,Signed:
,,PROGRAMME,,,,,,,,,,,,,,381,09/12/2021,SELLER_DK,EUR,11376479.39,39580.28,11336899.11,EUR,0,0,0,Reviewed by:,,Signed:
,,PROGRAMME,,,,,,,,,,,,,,381,09/12/2021,SELLER_DK,USD,12571895.13,71198.51,12500696.62,USD,0,0,0,Reviewed by:,,Signed:
我想对 3 列 (InvoiceAmmount、DiscountAmount、PurchasePrice) 进行分组和求和,并在新文件上更新列 (TotalInvoiceAmmount、TotalDiscountAmmount、TotalPurchasePrice),该文件是原始文件的副本,但包含列只要货币值匹配,(TotalInvoiceAmmount,TotalDiscountAmmount,TotalPurchasePrice) 就会更新为总和值。
我写了以下脚本:
$csvFile = Import-Csv "C:\OutputFiles\OTC_Purchase_Report_EUProgramme_20220420_TMP.csv"
$csvFinal = "C:\OutputFiles\OTC_Purchase_Report_EUProgramme_20220420.csv"
function WriteTotalsToCSV
{
$totals | ForEach-Object {
$totalCurrency = $_.Currency
$totalInvoiceAmmount = $_.TotalInvoiceAmmount
$totalDiscountAmmount = $_.TotalDiscountAmmount
$totalPurchasePrice = $_.TotalPurchasePrice
$csvFile | ForEach-Object {
if($_.Currency1 -eq $totalCurrency){
$_.TotalsCurrency = $totalCurrency
$_.TotalInvoiceAmmount = $totalInvoiceAmmount
$_.TotalDiscountAmmount = $totalDiscountAmmount
$_.TotalPurchasePrice = $totalPurchasePrice
}
$_ | Export-Csv $csvFinal -NoTypeInformation -Append
}
}
}
function InvoiceAmmountTotals
{
param ($file)
$headers = ($file | Get-Member -MemberType NoteProperty).Name
$totals = $file | Select-Object $headers | Group-Object Currency1
foreach ($total in $totals)
{
$showtotal = New-Object System.Management.Automation.PsObject
$showtotal | Add-Member NoteProperty Currency $total.Name
$showtotal | Add-Member NoteProperty TotalInvoiceAmmount ($total.Group | Measure-Object -Sum InvoiceAmmount).Sum
$showtotal | Add-Member NoteProperty TotalDiscountAmmount ($total.Group | Measure-Object -Sum DiscountAmount).Sum
$showtotal | Add-Member NoteProperty TotalPurchasePrice ($total.Group | Measure-Object -Sum PurchasePrice).Sum
$showtotal
}
}
#execution
$totals = InvoiceAmmountTotals $csvFile
WriteTotalsToCSV
该脚本按预期对总计进行分组和求和,但是当它写入新的 CSV 文件时,它应该根据 Currency1 列的匹配更新列,但它只对第一个匹配(在本例为 EUR) 并忽略剩余的匹配项,即:
"A","B","ProgrammeSeller","D","E","F","G","H","I","J","K","L","M","N","O","P","SellerCode","Date","Seller","Currency1","InvoiceAmmount","DiscountAmount","PurchasePrice","TotalsCurrency","TotalInvoiceAmmount","TotalDiscountAmmount","TotalPurchasePrice","Reviewed","AC","Signed"
"","","PROGRAMME","","","","","","","","","","","","","","380","09/12/2021","SELLER_BE","EUR","2813828.46","17594.22","2796234.24","EUR","153995434.65","797318.07","153198116.58","Reviewed by:","","Signed:"
"","","PROGRAMME","","","","","","","","","","","","","","383","09/12/2021","SELLER_DE","EUR","3287812.58","17595.8","3270216.78","EUR","153995434.65","797318.07","153198116.58","Reviewed by:","","Signed:"
"","","PROGRAMME","","","","","","","","","","","","","","383","09/12/2021","SELLER_DE","USD","1520725.4","11428.98","1509296.42","USD","0","0","0","Reviewed by:","","Signed:"
"","","PROGRAMME","","","","","","","","","","","","","","381","09/12/2021","SELLER_DK","DKK","6047281.25","26163.13","6021118.12","DKK","0","0","0","Reviewed by:","","Signed:"
"","","PROGRAMME","","","","","","","","","","","","","","381","09/12/2021","SELLER_DK","EUR","11376479.39","39580.28","11336899.11","EUR","153995434.65","797318.07","153198116.58","Reviewed by:","","Signed:"
"","","PROGRAMME","","","","","","","","","","","","","","381","09/12/2021","SELLER_DK","USD","12571895.13","71198.51","12500696.62","USD","0","0","0","Reviewed by:","","Signed:"
请注意,当 Currency1 列的值为 USD 时,列 (TotalInvoiceAmmount、TotalDiscountAmmount、TotalPurchasePrice) 不会更新。
有什么关于我哪里出错的建议吗?
注意: CSV 文件要大得多,为了举例,我添加了少量条目
谢谢
看起来你循环遍历 csv 的每一行的次数与你拥有货币的次数一样多,因为你循环遍历 $totals
并且在每个循环中你循环遍历 csv 的每一行导致重复。
只在 csv 行中循环一次,并为每一行在 $totals 数组中找到匹配的货币以更新每个 csv 行。最后一次性全部输出到Export-Csv
function WriteTotalsToCSV {
# only one loop through csv lines
$csvFile | ForEach-Object {
$line = $_
# find matching currency in your $totals array using Where()
$totalsMatch = $totals.Where({ $line.Currency1 -eq $_.Currency })
$line.TotalsCurrency = $totalsMatch.Currency
$line.TotalInvoiceAmmount = $totalsMatch.TotalInvoiceAmmount
$line.TotalDiscountAmmount = $totalsMatch.TotalDiscountAmmount
$line.TotalPurchasePrice = $totalsMatch.TotalPurchasePrice
$line
# collect all the lines first and then export to csv once at the end
} | Export-Csv -Path $csvFinal -NoTypeInformation
}
我正在编写读取以下格式的 CSV 文件的 PowerShell 脚本:
A,B,ProgrammeSeller,D,E,F,G,H,I,J,K,L,M,N,O,P,SellerCode,Date,Seller,Currency1,InvoiceAmmount,DiscountAmount,PurchasePrice,TotalsCurrency,TotalInvoiceAmmount,TotalDiscountAmmount,TotalPurchasePrice,Reviewed,AC,Signed
,,PROGRAMME,,,,,,,,,,,,,,380,09/12/2021,SELLER_BE,EUR,2813828.46,17594.22,2796234.24,EUR,0,0,0,Reviewed by:,,Signed:
,,PROGRAMME,,,,,,,,,,,,,,383,09/12/2021,SELLER_DE,EUR,3287812.58,17595.8,3270216.78,EUR,0,0,0,Reviewed by:,,Signed:
,,PROGRAMME,,,,,,,,,,,,,,383,09/12/2021,SELLER_DE,USD,1520725.4,11428.98,1509296.42,USD,0,0,0,Reviewed by:,,Signed:
,,PROGRAMME,,,,,,,,,,,,,,381,09/12/2021,SELLER_DK,DKK,6047281.25,26163.13,6021118.12,DKK,0,0,0,Reviewed by:,,Signed:
,,PROGRAMME,,,,,,,,,,,,,,381,09/12/2021,SELLER_DK,EUR,11376479.39,39580.28,11336899.11,EUR,0,0,0,Reviewed by:,,Signed:
,,PROGRAMME,,,,,,,,,,,,,,381,09/12/2021,SELLER_DK,USD,12571895.13,71198.51,12500696.62,USD,0,0,0,Reviewed by:,,Signed:
我想对 3 列 (InvoiceAmmount、DiscountAmount、PurchasePrice) 进行分组和求和,并在新文件上更新列 (TotalInvoiceAmmount、TotalDiscountAmmount、TotalPurchasePrice),该文件是原始文件的副本,但包含列只要货币值匹配,(TotalInvoiceAmmount,TotalDiscountAmmount,TotalPurchasePrice) 就会更新为总和值。
我写了以下脚本:
$csvFile = Import-Csv "C:\OutputFiles\OTC_Purchase_Report_EUProgramme_20220420_TMP.csv"
$csvFinal = "C:\OutputFiles\OTC_Purchase_Report_EUProgramme_20220420.csv"
function WriteTotalsToCSV
{
$totals | ForEach-Object {
$totalCurrency = $_.Currency
$totalInvoiceAmmount = $_.TotalInvoiceAmmount
$totalDiscountAmmount = $_.TotalDiscountAmmount
$totalPurchasePrice = $_.TotalPurchasePrice
$csvFile | ForEach-Object {
if($_.Currency1 -eq $totalCurrency){
$_.TotalsCurrency = $totalCurrency
$_.TotalInvoiceAmmount = $totalInvoiceAmmount
$_.TotalDiscountAmmount = $totalDiscountAmmount
$_.TotalPurchasePrice = $totalPurchasePrice
}
$_ | Export-Csv $csvFinal -NoTypeInformation -Append
}
}
}
function InvoiceAmmountTotals
{
param ($file)
$headers = ($file | Get-Member -MemberType NoteProperty).Name
$totals = $file | Select-Object $headers | Group-Object Currency1
foreach ($total in $totals)
{
$showtotal = New-Object System.Management.Automation.PsObject
$showtotal | Add-Member NoteProperty Currency $total.Name
$showtotal | Add-Member NoteProperty TotalInvoiceAmmount ($total.Group | Measure-Object -Sum InvoiceAmmount).Sum
$showtotal | Add-Member NoteProperty TotalDiscountAmmount ($total.Group | Measure-Object -Sum DiscountAmount).Sum
$showtotal | Add-Member NoteProperty TotalPurchasePrice ($total.Group | Measure-Object -Sum PurchasePrice).Sum
$showtotal
}
}
#execution
$totals = InvoiceAmmountTotals $csvFile
WriteTotalsToCSV
该脚本按预期对总计进行分组和求和,但是当它写入新的 CSV 文件时,它应该根据 Currency1 列的匹配更新列,但它只对第一个匹配(在本例为 EUR) 并忽略剩余的匹配项,即:
"A","B","ProgrammeSeller","D","E","F","G","H","I","J","K","L","M","N","O","P","SellerCode","Date","Seller","Currency1","InvoiceAmmount","DiscountAmount","PurchasePrice","TotalsCurrency","TotalInvoiceAmmount","TotalDiscountAmmount","TotalPurchasePrice","Reviewed","AC","Signed"
"","","PROGRAMME","","","","","","","","","","","","","","380","09/12/2021","SELLER_BE","EUR","2813828.46","17594.22","2796234.24","EUR","153995434.65","797318.07","153198116.58","Reviewed by:","","Signed:"
"","","PROGRAMME","","","","","","","","","","","","","","383","09/12/2021","SELLER_DE","EUR","3287812.58","17595.8","3270216.78","EUR","153995434.65","797318.07","153198116.58","Reviewed by:","","Signed:"
"","","PROGRAMME","","","","","","","","","","","","","","383","09/12/2021","SELLER_DE","USD","1520725.4","11428.98","1509296.42","USD","0","0","0","Reviewed by:","","Signed:"
"","","PROGRAMME","","","","","","","","","","","","","","381","09/12/2021","SELLER_DK","DKK","6047281.25","26163.13","6021118.12","DKK","0","0","0","Reviewed by:","","Signed:"
"","","PROGRAMME","","","","","","","","","","","","","","381","09/12/2021","SELLER_DK","EUR","11376479.39","39580.28","11336899.11","EUR","153995434.65","797318.07","153198116.58","Reviewed by:","","Signed:"
"","","PROGRAMME","","","","","","","","","","","","","","381","09/12/2021","SELLER_DK","USD","12571895.13","71198.51","12500696.62","USD","0","0","0","Reviewed by:","","Signed:"
请注意,当 Currency1 列的值为 USD 时,列 (TotalInvoiceAmmount、TotalDiscountAmmount、TotalPurchasePrice) 不会更新。
有什么关于我哪里出错的建议吗?
注意: CSV 文件要大得多,为了举例,我添加了少量条目
谢谢
看起来你循环遍历 csv 的每一行的次数与你拥有货币的次数一样多,因为你循环遍历 $totals
并且在每个循环中你循环遍历 csv 的每一行导致重复。
只在 csv 行中循环一次,并为每一行在 $totals 数组中找到匹配的货币以更新每个 csv 行。最后一次性全部输出到Export-Csv
function WriteTotalsToCSV {
# only one loop through csv lines
$csvFile | ForEach-Object {
$line = $_
# find matching currency in your $totals array using Where()
$totalsMatch = $totals.Where({ $line.Currency1 -eq $_.Currency })
$line.TotalsCurrency = $totalsMatch.Currency
$line.TotalInvoiceAmmount = $totalsMatch.TotalInvoiceAmmount
$line.TotalDiscountAmmount = $totalsMatch.TotalDiscountAmmount
$line.TotalPurchasePrice = $totalsMatch.TotalPurchasePrice
$line
# collect all the lines first and then export to csv once at the end
} | Export-Csv -Path $csvFinal -NoTypeInformation
}