PowerShell ForEach-Object Only Matching first Value passed - powershell

I am writing a PowerShell script that reads a CSV file in the following format:
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:
And I want to group and sum 3 of the columns (InvoiceAmmount,DiscountAmount,PurchasePrice), and update the columns (TotalInvoiceAmmount,TotalDiscountAmmount,TotalPurchasePrice) on a new file which is a copy of the original but with the columns (TotalInvoiceAmmount,TotalDiscountAmmount,TotalPurchasePrice) updated with the values of the sums whenever there is a match on Currency value.
I have written the following script:
$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
The script is grouping and summing the totals as expected but when it writes the new CSV file it is supposed to update the columns based on a match of column Currency1, but it is only doing this for the first match (in this case EUR) and ignoring the remaining matches i.e.:
"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:"
Note when column Currency1 value is USD the columns (TotalInvoiceAmmount,TotalDiscountAmmount,TotalPurchasePrice) are not being updated.
Any suggestions on where I am going wrong here?
Note: The CSV files are much larger, I have added a small number of entries for example purpose
Thanks

It looks like you are looping through each line of the csv as many times as you have currencies because you are looping through $totals and inside of each of those loops you are looping through each line of the csv causing duplicates.
Loop only once through the csv lines and for each line find the matching currency in your $totals array to update each csv line with. Finally output all at once to 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
}

Related

append rows in CSV using powershell

I have piece of code like below.
$month = Get-Date -Format "yyyy_MM"
$csv_location = "C:\brivo\csv\" + $month + ".csv"
if (!(Test-Path $csv_location))
{
$newcsv = {} | Select "Time","Name","Surname","Email","Telephone","Company","Department","Address","Postcode","City","State","Country" | Export-Csv $csv_location -NoTypeInformation
}
ForEach($line in $lines){
Try
{
$line = $line.Trim()
$file = "C:\brivo\json\" + $line
$data = Get-Content $file | ConvertFrom-Json
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm"
$userline = $timestamp,$data.name,$data.surname,$data.email,$data.telephone,$data.company_name,$data.department,$data.address,$data.postcode,$data.city,$data.state,$data.country
$userline | out-file $csv_location -Append
}
Catch [Exception]
{
Write-Host $_.Exception | format-list -force
}
}
where first part is creating csv file if not exist with headers. and in second part $lines is file names like 123.json, 456.json... and all those json files has content like below.
{
"name": "kamal",
"sur_name": "wewetwe",
"email": "asdasd#gmail.com",
"telephone": "311234544567",
"company_name": "",
"department": "",
"address": "qwe",
"postcode": "1234 ad",
"city": "qwe",
"state": "GR",
"country": "NL"
}
what I want is to append all this json data to csv file. I have tried like above but it adds data in 1st column itself.
Don't try to initialize your CSV file without data using Export-Csv, because that won't work:
The dummy object with $null property values created by Select-Object results not in just in a header row, but invariably also in a data row representing the $null values, which end up as empty strings; in other words, you'll get a data row that looks like this: ,,,,,,,,,,,
Instead, make sure that the properties of the objects representing data rows you pass to Export-Csv are named for the desired CSV columns.
Don't try to construct your data rows as an array of values to save to the CSV file as plain text;[1] instead, construct a [pscustomobject] for each data row, which Export-Csv automatically converts to a data row, with the property names serving as column names (as you attempted with your header row).
As the code below shows, you can construct an object in each iteration and pipe it to a single Export-Csv call for efficiency.
Use the -Encoding parameter to control the output character encoding as needed; notably, in Windows PowerShell the default encoding is ASCII(!).
-Append is still used in that single call, because it looks like you want to append to a preexisting target file, if present.
Important:
The first object sent to Export-Csv locks in the list of columns and their names based on its properties; subsequent objects are expected to have the same set of properties (or a meaningful subset).
Similarly, when appending to a preexisting CSV file with -Append, the objects to append must match the existing columns, although you can override this requirement with -Force.
$month = Get-Date -Format "yyyy_MM"
$csv_location = "C:\brivo\csv\" + $month + ".csv"
# $lines is assumed to be an array of your input JSON file names.
$lines | ForEach-Object {
Try
{
$file = "C:\brivo\json\" + $_.Trim()
$data = Get-Content -ErrorAction Stop -Raw $file |
ConvertFrom-Json -ErrorAction Stop
# Construct and output an object with the desired values and the
# properties named for the desired CSV columns.
[pscustomobject] #{
Time = Get-Date -Format 'yyyy-MM-dd HH:mm'
Name = $data.name
Surname = $data.surname
Email = $data.email
Telephone = $data.telephone
Company = $data.company_name
Department = $data.department
Address = $data.address
Postcode = $data.postcode
City = $data.city
State = $data.state
Country = $data.country
}
}
Catch
{
Write-Host $_.Exception | format-list -force
}
} | Export-Csv -NoTypeInformation -Append $csv_location
[1] If you send an array of values to Out-File, each value becomes its own line in the output file. While you could address that with $userline -join ',', such plain-text processing is brittle, because values with embedded , chars. wouldn't be handled correctly.
**this is some example **
#add your json files on temp dir
$a= Get-ChildItem C:\Temp\PatchingServer*
foreach($g in $a){
$j=gc $g
$f=$j| ConvertFrom-Json
$obj=New-Object PSobject
$obj | Add-Member Noteproperty "Port" $f.Port
$obj | Add-Member Noteproperty "ApplicationName" $f.ApplicationName
$obj | Add-Member Noteproperty "MaintenanceWindow" $f.MaintenanceWindow
$obj | Add-Member Noteproperty "BusinessUnit" $f.BusinessUnit
$obj | Add-Member Noteproperty "AppOwner" $f.AppOwner
$obj | Add-Member Noteproperty "AppID" $f.AppID
$obj | Add-Member Noteproperty "Location" $f.Location
$obj | export-csv C:\Temp\Patching.csv -NoTypeInformation -Append
}

Add a column to a csv file and fill up new column based on an existing column powershell

I have been trying to add a new column to a csv file and populating the new column based on value in an existing column.
I have a table like this:
|name | number | state | desc|
| ---- | ------ |-------|-----|
|a | 1 | n | i |
|b | 2 | n | j |
|c | 3 | l | j |
|d | 4 | m | k |
I want to add a new column data and populate it based on number column matching with an array.
This is my code so far:
$a=("a","b","c")
$b=("p","q","r")
.
.
.
$c= import-csv -Path "C:\..."
$b |where-object {filtered the file based on some criteria}| select-object number, state, desc, #{Name="data"; Expression={Foreach-object {if ($_.number in $a){$_data = "x"}
elseif($_.number in $b){$_.data = "y"}.......} | export-csv -notypeinformation -path "C:\...."
The script runs but do not populate the new column. Please help
You've got the right idea. Import-Csv will produce an array of objects and you can use Select-Object to add calculated properties, then pipe again to Export-Csv. However, it's not exactly clear from the description or the example code what the expression should be. How do you want to define the new "data" property?
For now I'll work with what we have. The array variables $a & $b will never match anything. Also you can't use ForEach-Object like that, nor will assigning to $data work. The returning value of the Expression script block gets assigned to the property you named data. The following example demonstrates the point:
$a = ( "1", "2", "3")
$b = ( "4", "5", "6")
Import-Csv -Path "C:\temp\12-22-20.csv"|
Select-Object number, state, desc,
#{Name = 'Data'; Expression = { If( $_.Number -in $a ){ 'x' } elseif( $_.Number -in $b ){ 'y' } Else { $null }}} |
Export-Csv -Path "C:\temp\12-22-20_New.csv" -NoTypeInformation
The resulting Csv file will look something like:
number state desc Data
------ ----- ---- ----
1 n i x
2 n j x
3 l j x
4 m k y
Update: Example Using Add-Member
You do not need to use a loop to add the property:
$a = ( "1", "2", "3")
$b = ( "4", "5", "6")
Import-Csv -Path "C:\temp\12-22-20.csv" |
Add-Member -MemberType ScriptProperty -Name "data" -Value { If( $this.Number -in $a ){ 'x' } elseif( $this.Number -in $b ){ 'y' } Else { $null }} -PassThru |
Export-Csv -Path C:\temp\12-22-20_New.csv -NoTypeInformation
By using a MemberType of ScriptProperty we can make a slight modification to script block, replacing $_ with $this The pipe is an implicit loop. I'm not sure if there are any detractions to using a ScriptProperty, but this exports as expected. This approach doesn't require storing the output in $c, but -PassThru would facilitate that if preferred.
99% of the time Select-Object is used for this. The only difference I'm aware of it Select-Object converts the objects to PSCustomObjects. Get-Member will preserve the underlying type, however Import-Csv only outputs PSCustomObjects in the first place, so there's no impact here.
Try iterating over the $c array of imported objects and add the new property to all objects. You want to make sure the new column exists in all of the objects. You can either use Select-Object as in your example, or you can use Add-Member to add it to the imported object.
$a=("a","b","c")
$b=("p","q","r")
...
$c = Import-Csv -Path "C:\..."
$c | ForEach-Object {
$value = ""
# custom logic for value of "data"
# if (...) { $value = ... }
$_ | Add-Member -MemberType NoteProperty -Name "data" -Value $value
}
$c | Export-Csv -NoTypeInformation -path "C:\...."

Powershell - Insert column in between specific columns in csv file

I have 2 csv files
First file:
firstName,secondName
1234,Value1
2345,Value1
3456,Value1
4567,Value3
7645,Value3
Second file:
firstName,fileSplitter,Csv2ColumnOne,Csv2ColumnTwo,Csv2ColumnThree
1234,,1234,abc,Value1
1234,,1234,asd,Value1
3456,,3456,qwe,Value1
4567,,4567,mnb,Value1
I want to insert column secondName in the second file in between columns firstName and fileSplitter.
The result should look like this:
firstName,secondName,fileSplitter,Csv2ColumnOne,Csv2ColumnTwo,Csv2ColumnThree
1234,Value1,,1234,abc,Value1
1234,Value1,,1234,asd,Value1
3456,Value1,,3456,qwe,Value1
4567,Value3,,4567,mnb,Value1
I'm trying the following code:
Function InsertColumnInBetweenColumns
{
Param ($FirstFileFirstColumnTitle, $firstFile, [string]$1stColumnName, [string]$2ndColumnName, [string]$columnMergedFileBeforeInput)
Write-Host "Creating hash table with columns values `"$1stColumnName`" `"$2ndColumnName`" From $OimFileWithMatches"
$hashFirstFileTwoColumns = #{}
Import-Csv $firstFile | ForEach-Object {$hashFirstFileTwoColumns[$_.$1stColumnName] = $_.$2ndColumnName}
Write-Host "Complete."
Write-Host "Appending Merge file with column `"$2ndColumnName`" from file $secondCsvFileWithLocalPath"
Import-Csv $outputCsvFileWithLocalPath | Select-Object $columnMergedFileBeforeInput, #{n=$2ndColumnName; e={
if ($hashFirstFileTwoColumns.ContainsKey($_.$FirstFileFirstColumnTitle)) {
$hashFirstFileTwoColumns[$_.$FirstFileFirstColumnTitle]
} Else {
'Not Found'
}}}, * | Export-Csv "$outputCsvFileWithLocalPath-temp" -NoType -Force
Move-Item "$outputCsvFileWithLocalPath-temp" $outputCsvFileWithLocalPath -Force
Write-Host "Complete."
Write-Host ""
}
This function will be called in a for loop for each column found in the first file (can contain an indefinite number). For testing, I am only using 2 columns from the first file.
I'm getting an error output resulting the following:
Select : Property cannot be processed because property "firstName" already exists.
At C:\Scripts\Tests\Compare2CsvFilesOutput1WithMatchesOnly.ps1:490 char:43
+ Import-Csv $outputCsvFileWithLocalPath | Select $columnMergedFileBeforeInput, # ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (#{firstName=L...ntName=asdfas}:PSObject) [Select-Object], PSArgume
ntException
+ FullyQualifiedErrorId : AlreadyExistingUserSpecifiedPropertyNoExpand,Microsoft.PowerShell.Commands.SelectObjectC
ommand
I know the issue is where it says Select-Object $columnMergedFileBeforeInput,.
How can I get the loop statement to insert the column in between the before column (name is specified), and append the rest using *?
Update
Just an fyi, changing this line Select-Object $columnMergedFileBeforeInput, #{n=$2ndColumnName..... to this line Select-Object #{n=$2ndColumnName..... works, it just attaches the columns out of order. That is why I'm trying to insert the column in between. Maybe if i do it this way but insert the columns in backwards using the for loop, this would work...
Not sure if this is the most efficient way to do it, but it should do the trick. It just adds the property to the record from file2, then reorders the output so secondName is the second column. You can output results to csv where required too (ConvertTo-Csv).
$file1 = Import-Csv -Path file1.csv
$file2 = Import-Csv -Path file2.csv
$results = #()
ForEach ($record In $file2) {
Add-Member -InputObject $record -MemberType NoteProperty -Name secondName -Value $($file1 | ? { $_.firstName -eq $record.firstName } | Select -ExpandProperty secondName)
$results += $record
}
$results | Select-Object -Property firstName,secondName,fileSplitter,Csv2ColumnOne,Csv2ColumnTwo,Csv2ColumnThree
I've created the following function. What it does is find the match (in this case "firstname") and adds the matching columnname to the new array afther the columnname on which the match is made (little difficult to explain in my poor English).
function Add-ColumnAfterMatchingColumn{
[CmdletBinding()]
param(
[string]$MainFile,
[string]$MatchingFile,
[string]$MatchColumnName,
[string]$MatchingColumnName
)
# Import data from two files
$file1 = Import-Csv -Path $MainFile
$file2 = Import-Csv -Path $MatchingFile
# Find column names and order them
$columnnames = $file2 | gm | where {$_.MemberType -like "NoteProperty"} | Select Name | %{$_.Name}
[array]::Reverse($columnnames)
# Find $MatchColumnName index and put the $MatchingColumnName after it
$MatchColumnNameIndex = [array]::IndexOf($columnnames, $MatchColumnName)
if($MatchColumnNameIndex -eq -1){
$MatchColumnNameIndex = 0
}
$columnnames = $columnnames[0..$MatchColumnNameIndex] + $MatchingColumnName + $columnnames[($MatchColumnNameIndex+1)..($columnnames.Length -1)]
$returnObject = #()
foreach ($item in $file2){
# Find corresponding value MatchingColumnName in $file1 and add it to the current item
$item | Add-Member -Name "$MatchingColumnName" -Value ($file1 | ?{$_."$($MatchColumnName)" -eq $item."$($MatchColumnName)"})."$MatchingColumnName" -MemberType NoteProperty
# Add current item to the returnObject array, in the correct order
$newItem = New-Object psobject
foreach ($columnname in [string[]]$columnnames){
$newItem | Add-Member -Name $columnname -Value $item."$columnname" -MemberType NoteProperty
}
$returnObject += $newItem
}
return $returnObject
}
When you run this function you will have the following output:
Add-ColumnAfterMatchingColumn -MainFile C:\Temp\file1.csv -MatchingFile C:\Temp\file2.csv -MatchColumnName "firstname" -MatchingColumnName "secondname" | ft
firstName secondname fileSplitter Csv2ColumnTwo Csv2ColumnThree Csv2ColumnOne
--------- ---------- ------------ ------------- --------------- -------------
1234 Value1 abc Value1 1234
1234 Value1 asd Value1 1234
3456 Value1 qwe Value1 3456
4567 Value3 mnb Value1 4567

Loop through csv compare content with an array and then add content to csv

I don't know how to append a string to CSV. What am I doing:
I have two csv files. One with a list of host-names and id's and another one with a list of host-names and some numbers.
Example file 1:
Hostname | ID
IWBW140004 | 3673234
IWBW130023 | 2335934
IWBW120065 | 1350213
Example file 2:
ServiceCode | Hostname | ID
4 | IWBW120065 |
4 | IWBW140004 |
4 | IWBW130023 |
Now I read the content of file 1 in a two dimensional array:
$pcMatrix = #(,#())
Import-Csv $outputFile |ForEach-Object {
foreach($property in $_.PSObject.Properties){
$pcMatrix += ,($property.Value.Split(";")[1],$property.Value.Split(";")[2])
}
}
Then I read the content of file 2 and compare it with my array:
Import-Csv $Group".csv" | ForEach-Object {
foreach($property in $_.PSObject.Properties){
for($i = 0; $i -lt $pcMatrix.Length; $i++){
if($pcMatrix[$i][0] -eq $property.Value.Split('"')[1]){
#Add-Content here
}
}
}
}
What do I need to do, to append $pcMatrix[$i][1] to the active column in file 2 in the row ID?
Thanks for your suggestions.
Yanick
It seems like you are over-complicating this task.
If I understand you correctly, you want to populate the ID column in file two, with the ID that corresponds to the correct hostname from file 1. The easiest way to do that, is to fill all the values from the first file into a HashTable and use that to lookup the ID for each row in the second file:
# Read the first file and populate the HashTable:
$File1 = Import-Csv .\file1.txt -Delimiter "|"
$LookupTable = #{}
$File1 |ForEach-Object {
$LookupTable[$_.Hostname] = $_.ID
}
# Now read the second file and update the ID values:
$File2 = Import-Csv .\file2.txt -Delimiter "|"
$File2 |ForEach-Object {
$_.ID = $LookupTable[$_.Hostname]
}
# Then write the updated rows back to a new CSV file:
$File2 | Export-CSV -Path .\file3.txt -NoTypeInformation -Delimiter "|"

Get a variable by dynamic variable name

How does one access data imported from a CSV file by using dynamic note property names? That is, one doesn't know the colunm names beforehand. They do match a pattern and are extracted from the CSV file when the script runs.
As for an example, consider a CSV file:
"Header 1","Header A","Header 3","Header B"
0,0,0,0
1,2,3,4
5,6,7,8
I'd like to extract only columns that end with a letter. To do this, I read the header row and extract names with a regex like so,
$reader = new-object IO.StreamReader("C:\tmp\data.csv")
$line = $reader.ReadLine()
$headers = #()
$line.Split(",") | % {
$m = [regex]::match($_, '("Header [A-Z]")')
if($m.Success) { $headers += $m.value } }
This will get all the column names I care about:
"Header A"
"Header B"
Now, to access a CSV file I import it like so,
$csvData = import-csv "C:\tmp\data.csv"
Import-CSV will create a custom object that has properties as per the header row. One can access the fields by NoteProperty names like so,
$csvData | % { $_."Header A" } # Works fine
This obviously requires one to know the column name in advance. I'd like to use colunn names I extracted and stored into the $headers. How would I do that?
Some things I've tried so far
$csvData | % { $_.$headers[0] } # Error: Cannot index into a null array.
$csvData | % { $np = $headers[0]; $_.$np } # Doesn't print anything.
$csvData | % { $_.$($headers[0]) } # Doesn't print anything.
I could change the script like so it will write another a script that does know the column names. Is that my only solution?
I think you want this:
[string[]]$headers = $csvdata | gm -MemberType "noteproperty" |
?{ $_.Name -match "Header [a-zA-Z]$"} |
select -expand Name
$csvdata | select $headers
Choose the headers that match the condition (in this case, ones ending with characters) and then get the csv data for those headers.
the first thing ( and the only one... sorry) that came in my mind is:
$csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[0].name) }
for get the first's column values and
$csvData | % { $_.$(( $csvData | gm | ? { $_.membertype -eq "noteproperty"} )[1].name) }
for second column and so on....
is this what you need?
you can use custom script to parse csv manually:
$content = Get-Content "C:\tmp\data.csv"
$header = $content | Select -first 1
$columns = $header.Split(",")
$indexes = #()
for($i; $i -lt $columns.Count;$i++)
{
# to verify whether string end with letter matches this regex: "[A-Za-z]$"
if ($column[$i] -match "[A-Za-z]$")
{
$indexes += $i
}
}
$outputFile = "C:\tmp\outdata.csv"
Remove-Item $outputFile -ea 0
foreach ($line in $content)
{
$output = ""
$rowcol = $line.Split(",")
[string]::Join(",", ($indexes | foreach { $rowcol[$_] })) | Add-Content $outputFile
}