Powershell: Calculated Property not working as expected - powershell

I have a csv file in which i need to add a new column. I do that with import-csv and then adding a property to the objects before writing it back to csv with export-csv.
Somehow its not working as expected. I took all real functionality out and reduced it to the following snipped:
$findReplaceList = Import-Csv -Path $mappingListPath -Delimiter ';'
Import-Csv $sourceFile.FullName |
Select-Object *, #{Name = 'column3'; Expression =
{ $newKey = $_."Issue key" ; $newKey }
} |
Export-Csv $outputFullFileName -NoTypeInformation -Delimiter ';'
please note that in this code the real calculation of the Expression is replaced with something very simple.
here, with
$newKey = $_."Issue key"
I just try to take the value in column "issue key" and use that for the newly added column.
Somehow the $newKey is always NULL - although $_."Issue key" is not?
What am i doing wrong?
The real code for $newKey will be:
{$newKey = $_.$FieldsToSelectFromTargetFilesIntoMappingFile[0]; (#($findReplaceList).where( { $_.$FieldsToSelectFromTargetFilesIntoMappingFile[0] -eq $newKey })).$FieldsToSelectFromTargetFilesIntoMappingFile[3] }
The mapping File (reference by $mappingListPath) is a simple csv like that:
image of a simple sample mapping table

Problem solved.
Thanks to all the comments and the working code sample from #Bender the greatest i was able to identify the issue with my code: The csv mapping file has ';' as delimiters... With the code i wrote the different "columns" in the csv where not identified as such, but each line was just written into one single property.
By changing
Import-Csv $sourceFile.FullName |
to
Import-Csv $sourceFile.FullName -delimiter ';' |
the problem was solved.

Related

Powershell script to Find and replace Particular value in CSV file

I have a csv file in path and i need to fetch the file and do Find & Replace $(dollar) value to ,(comma) using PowerShell script. please help me on the script .
CSV file
id|name|place
1|adam$|USA
2|john|USA
3|Jack$|England
Expected output : Need to do Find & Replace $(dollar) value to ,(comma) under name column
id|name|place
1|adam,|USA
2|john|USA
3|Jack,|England
Command Used
Import-csv D:\CSV\Customer.csv
ForEach-Object { $_.name -replace '$',',' }
i didn't got any error nor the expected changes. i need to update the values in existing CSV file
Below Answer by Zett42 works but
(Import-Csv D:\CSV\Customer.csv -Delimiter '|') |
Select-Object 'id',
#{ n = 'name'; e = { $_.name.Replace('$', ',') } },
'place' |
Export-Csv D:\CSV\Customer.csv -Delimiter '|'
but the tricky part is we are replacing the ,(Comma) value and rewriting the CSV files again, so CSV file creation part considers the value after ,(comma) as new column and move the value to column B instead of Column A.
Before :
After :
This should do the trick:
Import-Csv D:\CSV\Customer.csv -Delimiter '|' |
ForEach-Object {
$_.name = $_.name.Replace('$', ',')
$_ # Implicit output - gets passed to Export-Csv
} |
Export-Csv D:\CSV\Customer_new.csv -Delimiter '|' -NoTypeInformation
In your code, there is a pipe symbol | missing at the end of the Import-Csv line.
As the CSV uses non-standard delimiters, you have to specify them using -Delimiter.
Also, the -replace operator doesn't modify its arguments, so you are actually just outputting the replaced value. Also, '$' has special meaning in regular expression patterns, which -replace uses, so you have to backslash-escape it or use the String.Replace() method as I did in the code above. The String.Replace() method doesn't use RegEx.
In the ForEach-Object script block, the $_ at the end is necessary to output the current object again, so it gets send down the pipeline to Export-Csv. Otherwise Export-Csv wouldn't have anything to output.
Alternative code using Select-Object:
Import-Csv D:\CSV\Customer.csv -Delimiter '|' |
Select-Object 'id',
#{ n = 'name'; e = { $_.name.Replace('$', ',') } },
'place' |
Export-Csv D:\CSV\Customer_new.csv -Delimiter '|' -NoTypeInformation
To overwrite the existing file instead of creating a new file use the group operator () to collect all data in memory and close the old file before overwriting the file:
(Import-Csv D:\CSV\Customer.csv -Delimiter '|') |
Select-Object 'id',
#{ n = 'name'; e = { $_.name.Replace('$', ',') } },
'place' |
Export-Csv D:\CSV\Customer.csv -Delimiter '|' -NoTypeInformation
IMO this is somewhat cleaner as you don't need to modify the current pipeline object and don't need to explicitly forward it to the next command.
It uses a calculated property to generate the new value for the name column. In this case we don't need to assign the result back to $_.name because calculated properties automatically assign the output from the script block to the property.

Looking for help optimizing a Powershell script to parse through a CSV line by line

I have a large csv file with 41000 rows of data. Within this I have to go through and inspect each row for a particular string PRCXX and if the row contains that in column 6 then I take the value of column 10 and replace the value in column 9 with it.
I have code that works however it takes a very long time to parse through line by line. I am looking for some help to try and optimize it. I have tried switching to a ForEach loop however I am not sure how exactly to get it to work with what I am trying to accomplish and haven't been able to find any examples to work from.
Here is the code that I have that currently is working just takes along time to complete.
Import-Csv $TransFile -Header 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 | ForEach-Object {
if ($_.6 -match "PRCXX") {
$_.9 = $_.10
}
$_ | Export-Csv test2.csv -NoTypeInformation -Append -Delimiter ","
}
Thanks for any help that you can provide.
Thanks to JosefZ this is fixed. Moved the Export to occur outside the loop and that cleared it up.
Import-Csv $TransFile -Header 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 | ForEach-Object {
if ($_.6 -match "PRCXX") {
$_.9 = $_.10
}
$_
} | Export-Csv test2.csv -NoTypeInformation -Append -Delimiter ","

Replace One CSV Field With Another Through PowerShell

In PowerShell I'm importing a CSV SAMTemp2 which will have a field called SO. Sometimes SO will be populated with "NW" and in these cases I just want to pull the field called ProdProj from the same line and replace the data in SO with the data in ProdProj then export it the data in that condition.
$RepNW = Import-Csv $SAMTemp2
foreach($d in $data){
If($d.SO -eq "NW"){($d.SO).Replace($d.ProdProj)}}
$RepNW | Export-Csv $SAMTemp -NoTypeInformation
I don't get an error, but this doesn't seem to do anything, either. Can anyone assist me, please?
Update
Per Matt below, I tried:
$RepNW = Import-Csv $SAMTemp2
foreach($d in $RepNW){
If($d.SO -eq "NW"){$d.SO = ($d.SO).Replace($d.ProdProj)}}
$RepNW | Export-Csv $SAMTemp -NoTypeInformation
But I'm not seeing any change. Any assistance is appreciated.
As LotPings pointed out in this line foreach($d in $data){, you haven't defined $data and it seems that you mean it to be foreach($d in $RepNW){
Secondly, rather than using Replace() you can just set one property to be equal to the other.
Last, this probably easiest to do all in the pipeline with ForEach-Object
Import-Csv $SAMTemp2 | ForEach-Object {
If($_.SO -eq "NW"){
$_.SO = $_.ProdProj
}
$_
} | Export-Csv $SAMTemp -NoTypeInformation

Add Column to CSV Windows PowerShell

I have a fairly standard csv file with headers I want to add a new column & set all the rows to the same data.
Original:
column1, column2
1,b
2,c
3,5
After
column1, column2, column3
1,b, setvalue
2,c, setvalue
3,5, setvalue
I can't find anything on this if anybody could point me in the right direction that would be great. Sorry very new to Power Shell.
Here's one way to do that using Calculated Properties:
Import-Csv file.csv |
Select-Object *,#{Name='column3';Expression={'setvalue'}} |
Export-Csv file.csv -NoTypeInformation
You can find more on calculated properties here: http://technet.microsoft.com/en-us/library/ff730948.aspx.
In a nutshell, you import the file, pipe the content to the Select-Object cmdlet, select all exiting properties (e.g '*') then add a new one.
The ShayLevy's answer also works for me!
If you don't want to provide a value for each object yet the code is even easier...
Import-Csv file.csv |
Select-Object *,"column3" |
Export-Csv file.csv -NoTypeInformation
None of the scripts I've seen are dynamic in nature, so they're fairly limited in their scope & what you can do with them.. that's probably because most PS Users & even Power Users aren't programmers. You very rarely see the use of arrays in Powershell. I took Shay Levy's answer & improved upon it.
Note here: The Import needs to be consistent (two columns for instance), but it would be fairly easy to modify this to dynamically count the columns & generate headers that way too. For this particular question, that wasn't asked. Or simply don't generate a header unless it's needed.
Needless to say the below will pull in as many CSV files that exist in the folder, add a header, and then later strip it. The reason I add the header is for consistency in the data, it makes manipulating the columns later down the line fairly straight forward too (if you choose to do so). You can modify this to your hearts content, feel free to use it for other purposes too. This is generally the format I stick with for just about any of my Powershell needs. The use of a counter basically allows you to manipulate individual files, so there's a lot of possibilities here.
$chargeFiles = 'C:\YOURFOLDER\BLAHBLAH\'
$existingReturns = Get-ChildItem $chargeFiles
for ($i = 0; $i -lt $existingReturns.count; $i++)
{
$CSV = Import-Csv -Path $existingReturns[$i].FullName -Header Header1,Header2
$csv | select *, #{Name='Header3';Expression={'Header3 Static'}}
| select *, #{Name='Header4';Expression={'Header4 Static Tet'}}
| select *, #{Name='Header5';Expression={'Header5 Static Text'}}|
CONVERTTO-CSV -DELIMITER "," -NoTypeInformation |
SELECT-OBJECT -SKIP 1 | % {$_ -replace '"', ""} |
OUT-FILE -FilePath $existingReturns[$i].FullName -FORCE -ENCODING ASCII
}
You could also use Add-Member:
$csv = Import-Csv 'input.csv'
foreach ($row in $csv)
{
$row | Add-Member -NotePropertyName 'MyNewColumn' -NotePropertyValue 'MyNewValue'
}
$csv | Export-Csv 'output.csv' -NoTypeInformation
For some applications, I found that producing a hashtable and using the .values as the column to be good (it would allow for cross reference validation against another object that was being enumerated).
In this case, #powershell on freenode brought my attention to an ordered hashtable (since the column header must be used).
Here is an example without any validation the .values
$newcolumnobj = [ordered]#{}
#input data into a hash table so that we can more easily reference the `.values` as an object to be inserted in the CSV
$newcolumnobj.add("volume name", $currenttime)
#enumerate $deltas [this will be the object that contains the volume information `$volumedeltas`)
# add just the new deltas to the newcolumn object
foreach ($item in $deltas){
$newcolumnobj.add($item.volume,$item.delta)
}
$originalcsv = #(import-csv $targetdeltacsv)
#thanks to pscookiemonster in #powershell on freenode
for($i=0; $i -lt $originalcsv.count; $i++){
$originalcsv[$i] | Select-Object *, #{l="$currenttime"; e={$newcolumnobj.item($i)}}
}
Example is related to How can I perform arithmetic to find differences of values in two CSVs?
create a csv file with nothin in it
$csv >> "$PSScriptRoot/dpg.csv"
define the csv file's path. here $psscriptroot is the root of the script
$csv = "$PSScriptRoot/dpg.csv"
now add columns to it
$csv | select vds, protgroup, vlan, ports | Export-Csv $csv

Powershell how to add data in the csv file to one column

I have a csv file with a few columns. For example
col1;col2;col3;col4
text1;text2;text3;text4
text5;text6;text7;text8
text9;text10;text11;text12
I want to add text to column col3, like this:
col1;col2;col3;col4
text1;text2;append\text3;text4
text5;text6;append\text7;text8
text9;text10;append\text11;text12
So question is:
How to do this?
(I'm stuck whit that how I add data to each column in col3.)
Give this a whirl:
Import-Csv -Delim ';' cols.csv |
ForEach-Object {$_.col3 = "prepend\$($_.col3)";$_} |
Export-Csv cols2.csv -Delim ';' -NoTypeInformation
Use the -NoTypeInformation parameter to avoid this comment getting put at the top of your CSV:
#TYPE System.Management.Automation.PSCustomObject
However, if you don't mind the comment then you can leave off the -NoTypeInformation parameter.
You probably know how to read/write data. To change the data, send them to Foreach-Object, alter the data and pass the object further to Export-Csv.
Import-Csv d:\temp\so\csv1.txt -Delimiter ';' |
ForEach-Object { $_.col3 = 'append\' +$_.col3; $_ } |
Export-Csv d:\temp\so\csv2.txt -Delimiter ';'