I am trying to achieve the following with imported CSV Data in Powershell:
the CSV has the following structure:
| FirstName | LastName | Tier |
| --------- | ------- | ---- |
| George | Smith | 0 |
| John | Fritz | 1 |
| Thomas | Adams | 1 |
| Manuel | Evans | 0 |
I import the CSV Data as follows:
$csv = Import-Csv csvfile.csv
Now here is the Problem. I am trying to add few more lines to the object
$csv
If a User is of Tier 0 then the same User should be added to the object with Tier 1.
The resulting $csv object should look like:
| FirstName | LastName | Tier |
| --------- | ------- | ---- |
| George | Smith | 0 |
| John | Fritz | 1 |
| Thomas | Adams | 1 |
| Manuel | Evans | 0 |
| George | Smith | 1 |
| Manuel | Evans | 1 |
The order in which the new Tier 1 rows are placed in the object do not matter. They should just be somewhere in the object with all the original data. I also do not need the resulting Tier 1 Lines in any CSV File. I only need those new Lines (Members) to be a part of $csv object with all other Data untouched so i can then iterate through original and new data in the same object using a foreach loop.
What i tried so far without positive results:
$csv = Import-Csv csvfile.csv
foreach ($User in $csv){
$tier = $User.Tier -replace '\s',''
if($tier -eq '0'){
$csv+= @{FirstName= $User.FirstName; LastName=$User.LastName; Tier='1'}
}
}
another try without positive results:
$csv = Import-Csv csvfile.csv
foreach ($User in $csv){
$tier = $User.Tier -replace '\s',''
if($tier -eq '0'){
$csv | Add-Member -MemberType NoteProperty -Name 'FirstName' -Value $User.FirstName -Force
$csv | Add-Member -MemberType NoteProperty -Name 'LastName' -Value $User.LastName -Force
$csv | Add-Member -MemberType NoteProperty -Name 'Tier' -Value '1' -Force
}
}
After failing miserably i have come to get help from the Wizards of StackOverflow.
How can i achieve this? How do i get the Tier 0 Rows duplicated with a different Tier Value while leaving all other Data untouched into the same object?
This is one way you can do it but note that this example does not check if Tier 1
object already exists for a Tier 0
object.
$newCsv = Import-Csv ... | ForEach-Object {
$_
if ($_.Tier -eq 0) {
$copy = $_.PSObject.Copy()
$copy.Tier = 1
$copy
}
}
Demo:
@'
FirstName|LastName|Tier
George|Smith|0
John|Fritz|1
Thomas|Adams|1
Manuel|Evans|0
'@ | ConvertFrom-Csv -Delimiter '|' | ForEach-Object {
$_
if ($_.Tier -eq 0) {
$copy = $_.PSObject.Copy()
$copy.Tier = 1
$copy
}
}
FirstName LastName Tier
--------- -------- ----
George Smith 0
George Smith 1
John Fritz 1
Thomas Adams 1
Manuel Evans 0
Manuel Evans 1
Your first attempt was very close, the problem is that you're adding a hashtable @{ ... }
instead of a custom object [pscustomobject]@{ ... }
to the $Csv
, then it should work fine but you should also try to avoid +=
as it is inefficient, you can do this instead which in the end is very similar to my example above:
$csv = Import-Csv ...
$newCsv = foreach ($User in $csv) {
$User
if ($User.Tier -eq '0') {
[pscustomobject]@{
FirstName = $User.FirstName
LastName = $User.LastName
Tier = '1'
}
}
}
If you want to add to $Csv
without producing a new array te recommendation is to use a List<T>
and its .Add
method. This method also requires a for
loop instead of foreach
otherwise you would get an error due to trying to mutate a collection while being enumerated.
[System.Collections.Generic.List[object]] $csv = Import-Csv ...
for ($i = 0; $i -lt $csv.Count; $i++) {
if ($csv[$i].Tier -eq '0') {
$csv.Add([pscustomobject]@{
FirstName = $User.FirstName
LastName = $User.LastName
Tier = '1'
})
}
}