Powershell Append CSV fail - powershell

I am fairly new to powershell, but when I try to run this portion of the code, it works sometimes, but I usually get an error message:
"Method invocation failed because [System.Management.Automation.PSObject] doesn't contain a method named 'op_Addition'."
It seems to fail when I add $in + $o, and it has worked in the past. I haven't changed anything for it to stop working though. I am trying to append to a csv, and I have tried Export-CSV -append, however that does not work for me. Any ideas on what might be wrong with this code?
$in = Import-Csv $csv
$obj = New-Object PSObject
$obj | Add-Member NoteProperty Column1 "$c1"
$obj | Add-Member NoteProperty Column2 "$c2"
$obj | Add-Member NoteProperty Column3 "$c3"
$in + $obj | Export-Csv -Encoding ASCII -NoTypeInformation $csv

That probably worked before when $in is an array. However if you read in a CSV with just a single element it will fail. You can do this instead in PowerShell 3.0 (you don't need to even read in $in):
$obj | Export-Csv $csv -Encoding ASCII -NoTypeInformation -Append
The -Append parameter on Export-Csv is new in PowerShell 3.0. If you don't have 3.0 then modify this line:
$in = #(Import-Csv $csv)
Then it should work. That makes sure that $in is always an array.

Related

Using Powershell to add values to existing CSV

I have been battling this for way too long and I hope you can be of assistance.
I have a CSV for which I need to add some values, preferrably with Powershell. I need to add header row and one column with a fixed text value.
My CSV, before anything done to it, looks like this:
contact-email;contact-sms;contact-firstname
test#example.com;+3580000000;Mike
And I need it to look like this:
contact-email;contact-sms;contact-firstname;order-site
test#example.com;+3580000000;Mike;Finland
So the last column "order-site" needs to be added and every line in that column should have a value of "Finland".
So far I have written this Powershell script I got off a tutorial:
$file = Import-Csv E:\Raportit\SALES\SALES_TD_S01.csv -Delimiter "`t" -Encoding Default -Header "contact-email;contact-sms;contact-firstname"
foreach($c in $file) {
Add-Member -Input $c -MemberType NoteProperty -Name "order-site" -Value "Finland"
}
$file | Export-Csv -Path "C:\Temp\test.csv" -Encoding Default -NoTypeInformation
But unfortunately, this makes the CSV look like this:
"contact-email;contact-sms;contact-firstname","order-site"
"test#example.com;+3580000000;Mike","Finland"
For the use case I have for this file, it need to look like the first should-look-like example, without double quotes and columns separated by semicolon (;). The double quotes are OK as long as the output looks like this:
"contact-email;contact-sms;contact-firstname;order-site"
"test#example.com;+3580000000;Mike;Finland"
I thank you guys so much in advance, I know this is probably a super simple task but I just cannot wrap my head around it to save my life.
if the file HAS headers:
Import-Csv -Path 'E:\Raportit\SALES\SALES_TD_S01.csv' -Delimiter ';' |
Select-Object *, #{Name = 'order-site'; Expression = {'Finland'}} |
Export-Csv -Path "C:\Temp\test.csv" -Delimiter ';' -NoTypeInformation
if the file DOES NOT HAVE headers:
$headers = 'contact-email','contact-sms','contact-firstname'
Import-Csv -Path 'E:\Raportit\SALES\SALES_TD_S01.csv' -Delimiter ';' -Header $headers |
Select-Object *, #{Name = 'order-site'; Expression = {'Finland'}} |
Export-Csv -Path "C:\Temp\test.csv" -Delimiter ';' -NoTypeInformation
CSV Output:
"contact-email";"contact-sms";"contact-firstname";"order-site"
"test#example.com";"+3580000000";"Mike";"Finland"

Add column CSV in existing CSV with powershell

I have a Powershell script, which collects the size of a backup, and exports it to CSV, I would like to know if it is possible that it could be added to the next csv column, or an excel.
I've been looking at the documentation, because I think it looks better on an excel, but I can't add one more column, I always believe it from scratch.
$today = (get-date).Date
$backup = Get-VBRBackup | where {$_.info.jobname -eq "A. ProduccionInterna.Infraestructura Backup Copy"}
if ($backup) {
$backup.GetAllStorages() | where {$_.CreationTime.Date -eq $today} | select {$_.PartialPath}, {$_.Stats.BackupSize/1GB} |
export-csv -Path C:\Users\acepero\Documents\test.csv -NoTypeInformation -Delimiter ';'
}
UPDATE
I have managed to create new columns once, then it gives an error:
Select-Object : The property cannot be processed because the property "{$_.PartialPath}, {$_.Stats.BackupSize/1GB} , {$Session.BackupStats.DedupRatio} ,
{$Session.BackupStats.CompressRatio}" already exists.
The code now has this form
$today = (get-date).Date
$backup = Get-VBRBackup | where {$_.info.jobname -eq "A. ProduccionInterna.Infraestructura Backup Copy"}
if ($backup) {
$backup.GetAllStorages() | where {$_.CreationTime.Date -eq $today} | select {$_.PartialPath}, {$_.Stats.BackupSize/1GB} , {$Session.BackupStats.DedupRatio} , {$Session.BackupStats.CompressRatio}
(Import-Csv "C:\Users\acepero\Documents\test.csv") |
Select-Object *, {{$_.PartialPath}, {$_.Stats.BackupSize/1GB} , {$Session.BackupStats.DedupRatio} , {$Session.BackupStats.CompressRatio}} |
Export-csv -Path C:\Users\acepero\Documents\test.csv -NoTypeInformation #-Delimiter ';'
}
When you take output from a command and pipe it through select, you are creating an output object, which has the selected values as properties. Here is an example using the Get-ChildItem command:
$result = Get-ChildItem C:\Temp | select Name, Length
The $result array contains objects which have the "Length" and "Name" NoteProperties. When you pipe that object to Export-CSV, it creates one column for each Property/NoteProperty the object has. In order to 'add a column to the CSV', all you need to do is add a NoteProperty to the object. You can do that with the Add-Member cmdlet, like this:
$result | Add-Member -MemberType NoteProperty -Name 'ColumnName' -Value 'ColumnValue'
Be careful how you do this. If $result is a single object, this command will add the NoteProperty/Value pair to that object. If $result is an array of objects, it will add that NoteProperty/Value pair to all objects held in the array. If you need to assign different values to each object, you'll need to iterate through the array:
ForEach ($res in $result)
{
$thisvalue = '' #Assign specific value here
$res | Add-Member -MemberType NoteProperty -Name 'ColumnName' -Value $thisvalue
}
I hope this helps you. If it does, please don't forget to accept the answer.

Powershell adding name of file to each new line (add-content)

I am trying to export Groupmembers list from azuread, my whole script works fairly well, but I need each new line in the final file to have the name of the file it is importing from (as well as the content it is importing)
the part of the script i am using to do this is as follows
(found this code here
Merging multiple CSV files into one using PowerShell)
get-childItem "C:\Users\user\Documents\Azure\Intune\management\*.csv" | foreach {
$filePath = $_
$lines = $lines = Get-Content $filePath | Select -Skip 1
$linesToWrite = switch($getFirstLine) {
$true {$lines}
$false {$lines | Select -Skip 1}
}
$getFirstLine = $false
Add-Content "C:\Users\user\Documents\Azure\Intune\management\master_list.csv" $linesToWrite
}
I would probably do something like this:
$files = Get-ChildItem -Path "C:\Users\user\Documents\Azure\Intune\management\*.csv"
ForEach ($file in $files) {
Import-Csv -Path $File.FullName |
Select-Object -Property *, #{n='FileName';e={$file.Name}} |
Export-Csv -Path "C:\Users\user\Documents\Azure\Intune\management\master_list.csv" -NoTypeInformation -Append
}
Note that you need v3 or later of PowerShell to get the -Append flag for Export-Csv.
Another way to do it. This way would be potentially memory intensive if the files are large but I like the method and it fits well with the way my brain works.
$result = New-Object System.Collections.ArrayList
foreach($file in Get-ChildItem 'C:\Users\User\Documents\Azure\InTune\Management\*.csv'){
$result.AddRange((Import-CSV $file | Add-Member -InputObject $_ -Name 'File' -MemberType NoteProperty -Value $file.Name))
}
$result | Export-CSV 'C:\Users\user\Documents\Azure\Intune\management\master_list.csv' -NoTypeInformation
I think that would be version agnostic but I always lose track of which features happen in which version. Actually I think Add-Member would put it at v3+.

Remove comma in a field but not delimeter in powershell when not all values are in commas

I receive a CSV file, in which some records for some fields have commas in them. So when I open the file in notepad a row looks like the following
1,John,Wayne,"movies,actor",1950s
I have scrambled to write the syntax to remove the comma between movies and actor in column 4 in the example above and replace it with space. And then output the file as CSV again.
Here is what I have below, which replaces the entire string "movies,actor" with space.
(Get-Content $path) -replace '(".*),(.*")',' ' | Out-File -Encoding UTF8 $newpath
How do I replace only the comma with space?
So you could try and write regex to strip the commas but I would tend to break it out like this for supportability and ease of modifying additional fields.
$csv = import-csv C:\Old.csv
$NewCSV = #()
Foreach($row in $csv)
{
$Object = New-Object -TypeName PSObject
$Object | Add-Member -Type NoteProperty -Name "ID" -Value $csv.ID
$Object | Add-Member -Type NoteProperty -Name "First" -Value $csv.First
$Object | Add-Member -Type NoteProperty -Name "Last" -Value $csv.Last
$Object | Add-Member -Type NoteProperty -Name "Desc" -Value $csv.Desc -replace ","," "
$Object | Add-Member -Type NoteProperty -Name "Year" -Value $csv.Year
$NewCSV += $Object
}
$NewCSV | Export-Csv C:\New.csv
Import the csv
Create a new object, populate it with the rows from $csv
As we add each row to NewCSV we do a replace on commas
Export the NewCSV object
It looks complex but you can almost compact it in to one line using the pipeline
$csv | % { $_.Desc = $_.Desc -replace ","," "; $_ | Export-Csv C:\New.csv -Append -NoClobber}
You can actually do it much simpler with -replace. When replacing, you can reference the capture groups directly as below:
(Get-Content $path) -replace '"(.*?),(.*?)"','$1 $2'
Its very similar to the OP solution, except you create two capture groups with only the words, not the quotes. Then the two values are referenced directly in the replace string as $1 and $2 respectively.
we can do this in online with regex, like this:
(Get-Content D:\dummycsv.csv) | %{if($_ -match '(".*),(.*")'){$_ -replace $matches[0],($matches[1]+' '+$matches[2]);$_}}
I'm matching the regex and utilizing the match groups that you are using with $matches variable

powershell convert array of hastables into csv

Have done googling but have not found suitable answer
I have
$a = #(
#{"name"="a"; "value"="1"},
#{"name"="b"; "value"="2"}
)
Foreach($x in $a){
$obj = New-object psobject
Foreach($key in $x.keys) {
$obj ¦ add-member -membertype NoteProperty -name $key -value $x[$key]
}
$obj ¦ export-cvs test.csv
}
I get only last line in cab. I want all the lines
It's truth that Export-Csv won't append (< v3), but I do not think ConvertTo-Csv will solve the problem... In the end you will get file with headers repeated for every object in your array. I would suggest one of two things:
move Export-Csv outside foreach {} (need to put it in subexpression though, because it won't be possible to pipe it by default)
use Foreach-Object instead and get same results
I would also suggest to use New-Object PSObject -Property parameter instead of adding members later: because you use hashtable as a base you are half way there, see attached code samples:
# Using $( foreach ($x in $a) {} ) | Export-Csv
$(Foreach($x in $a){
New-object psobject -Property $x
}) | Export-Csv test.csv
# Using $a | Foreach-Object {} | Export-Csv
$a | ForEach-Object {
New-Object PSObject -Property $_
} | Export-Csv test.csv
You're overwriting the csv file each time. Try using convertTo-CSV each time (instead of export-csv) and appending that to a file.
2022 update
You always need to use the -append parameter if you are iterating through a collection
using powershell 7.2 and later you don`t need to parse the hashtable again, it matches the repeating properties and writes to csv.
so this will work automatically
$hashtable=#()
$hashtable += $pscustomobject
$hashtable | export-csv