Powershell CSV-Export with PSCustomObject - export-to-csv

I have a script with which I'm collecting data about users like this:
$testObject = [PSCustomObject]#{
username = $username
name = $name
}
Next, I'm getting more info and add to testObject like this:
$testObject | Add-Member address address
At the end I'm exporting it to csv:
$testObject | Export-Csv -Path "output.csv" -NoTypeInformation
I need to change the script so the creation of the testObject is in a loop since I will run it for a list of users.
How can I write this to create a new csv when the script starts, but append all new objects?
I'm trying to avoid creating an array of PSCustomObject since I'm using the script on large amount of data and I would prefer to write one object at a time to the csv.

Related

Exporting multiple PSCustomObject s to a single CSV

I have 2 PScustomObjects that i would like to combine into a single csv as follows:
$Output1 = [PSCustomObject]#{
Timestamp1 = (Get-Date)
InstanceName1 = $ProcessName1
Count1 = $Processes1.Count
Memory1 = $MEMLoad1
CPU1 = $CPULoad1
}
$Output2 = [PSCustomObject]#{
Timestamp2 = (Get-Date)
InstanceName2 = $ProcessName2
Count2 = $Processes2.Count
Memory2 = $MEMLoad2
CPU2 = $CPULoad2
}
The CSV should have the titles TimeStamp1, InstanceName1......TimeStamp2, InstanceName2....
This code runs in a loop and exports data each pass.
Is there a way to do this? Also is there a way to do this dynamically to avoid replicating large amounts of code if i am to export data on say 100 PsCustomObjects, maybe lookping through the input data for the object and the putting in in one object and passing that to the csv while dynamically changing titles?
I use the following line to export. I've tried -InputObject $Output1, $Output2 but that gives gibberish.
Export-Csv -InputObject $Output1 -path $Path1 -NoTypeInformation -Append -Force
The only solution i have so far is to export multiple CSV's but that gets bulky fast.
Any help is greatly appreciated!
The best solution is to ensure all the objects your script/function outputs use the same schema (that is, they should all share the same common property names).
If that's not possible, you can use Select-Object to ensure all possible properties are selected for all objects:
$Output1,$Output2 |Select-Object Count1,Count2,CPU1,CPU2,InstanceName1,InstanceName2,Memory1,Memory2,Timestamp1,Timestamp2 |Export-Csv ...
This is obviously not very practical, so if you have many different object schemas, you'll want to automate the discovery of all possible property names.
To do that, we can inspect the psobject hidden memberset:
$allTheObjectsToExport = $Output1,$Output2
$propertyNames = $allTheObjectsToExport |ForEach-Object {
# Discover all the object's properties
$_.psobject.Properties |ForEach-Object {
# Get each property name
$_.Name
}
} |Sort-Object -Unique
# Now the CSV will have a column for every single unique property name
$allTheObjectsToExport |Select-Object $propertyNames |Export-Csv -Path $Path1 -NoTypeInformation

Declaring an array in CSV

I am trying to Declare $GroupName array and add a couple statements for the array. I have an additional code from a different script and am trying to create an array for that script. I am trying to test the Row.Category = group and the Row.excluded = false. Then it will check the $groupname Array for duplicates. If no duplicates are found, populate $groupname.
I am need help just creating the array since I am a powershell novice.
$GroupName = #(column1 = "Domain")(column2 = "Account")
If ($_.category0 -eq "Group") -and ($_.Excluded -match "False")
"Account0", "Domain0" | sort Account0 -Unique
How do I improve the following code above to display the 2 columns in the new CSV.
This is one method to achieve what you're after, creating a new CSV file:
$Object = New-Object -TypeName PSObject -Property #{ Domain=''; Account='' }
$Object | Export-CSV $env:temp\MyCSV.csv -NoTypeInformation
We create a new PSObject called $Object and provide a hashtable object with the structure you require to the -Property parameter.
We then pass the PSObject down the pipeline to the Export-CSV cmdlet. Adding -NoTypeInformation on the end allows us to create a clean CSV file without additional information from PowerShell that other systems would not recognise.
However, I should note there are other ways to create/generate CSVs, especially if you're wanting to populate them with data.

Find and replace inside one csv column with powershell

I have a large CSV file that looks like this named student.export.text
Student Number,Last Name,Middle Name,First Name,Schoolid,Grade Level,Dob
I'm trying to build an automated task that will run nightly so that another piece of software can understand the CSV correctly.
Here is my code, but I'm missing something that is causing an error. I am new to Powershell and I am hoping for some advice.
Any help will be greatly appreciated!
$Replacements = #{
"5" = "AE";
"7" = "ER";
"10" = "FM";
"12" = "HC";
"14" = "JH";
"18" = "LE";
#...]
}
Import-Csv .\student.export.text | ForEach-Object {
$_.Schoolid = $Replacements[$_.Schoolid]
$_
} | Export-Csv -NoTypeInformation .\new.csv
Here's one approach that can work.
# declare hash table with School ID to School Name mapping
$schoolIdsToNames = #{
"3" = "SchoolA";
"4" = "SchoolB"
}
# import the CSV file
$csv = Import-Csv "C:\input.csv";
# for each row, replace the School ID field with the School Name
foreach($row in $csv)
{
$row.Schoolid = $schoolIdsToNames[$row.Schoolid];
}
# export the modified CSV
$csv | Export-Csv "C:\replaced.csv" -NoTypeInformation;
In the first step, we set up a PowerShell hashtable (a sort of key-value pair list), then import the CSV file using Import-Csv and store it in the $csv variable. This cmdlet will create an object from every row of the CSV that we can manipulate easily. For each row, we simply replace the Schoolid field with the value assigned to the ID key in the $schoolIdsToNames hashtable. Finally, we export the CSV to another file.
Another, more PowerShell-ly approach would be something like this:
Import-Csv "C:\test\school.csv" | Select-Object *, #{ Name = "SchoolName"; Expression = { $schoolIdsToNames[$_.Schoolid] } } | Export-Csv "C:\test\replaced2.csv" -NoTypeInformation
This one-liner imports the CSV and sends it down the pipeline. For each row, we select all properties of the row using Select-Object and add a new property called SchoolName, setting its value using the same hash table-based technique as above. Finally, we export the object list to CSV.

Find value in array of objects after importing from CSV file

I am reading in values from a CSV file using Import-Csv which include server name, ip address and a note field
Is there a built in mechanism to find an object based on the server name without having to loop through the entire array?
I'm keeping the array in memory to use multiple times.
$ServerList = Import-Csv ".\ServerList.csv"
I'm creating a GUI with Powershell Studio and populating a dropdown with all the server names read in from the file. The user will choose a server from the dropdown and there will be buttons to perform actions on that server using the IP address read in.
You could populate a hashtable with the data from the CSV, using the servername as key:
$ServerList = #{}
Import-Csv '.\ServerList.csv' | % { $ServerList[$_.ServerName] = $_ }
That way you can access the data like this:
$server = 'foo'
$ServerList[$server].IPAddress
$csv = Import-csv my.csv | where {$_.servername -eq "MyServer"}
foreach ($server in $csv) {
# Do your thing
}
If you need to call it multiple times you can use a function that you call when the user selects a server:
function getServer($selectedServer){
$ServerInfo = Import-Csv ".\ServerList.csv" | where {$_.servername -eq $selectedServer}
return $ServerInfo
}
When the user makes a selection the code would like like so:
$Server = getServer('ABCSRV')
Then $Server.IP and $Server.Notes would have the information from that specific server, granted that you have these columns in place in your csv.

In Powershell -- Export object to textfile in custom format

Since, i am a beginner, i 've no much hands-on to the powershell programming.Although
i had a script developed to insert data from an array to the csv file as follows:
#Following is the array
$InventoryReport = New-Object -TypeName PSobject -Property #{
ComputerName = "1myComputerName"
DomainName = "2myComputerDomain"
Manufacturer = "3myComputerManufacturer"
}
#Now to export the data to csv, i am using following:
$InventoryReport |Select-Object -Property ComputerName, DomainName, Manufacturer | Export-Csv -Path "c:\abc.csv" -NoTypeInformation -ErrorAction Stop
#This works fine
and the output of above is :
"ComputerName","DomainName","Manufacturer"
"1myComputerName","2myComputerDomain","3myComputerManufacturer"
....
Now, i don't want this , i want the ouput to appear in columnar fashion i.e.
"ComputerName","1myComputerName"
"DomainName","2myComputerDomain"
"Manufacturer","3myComputerManufacturer"
What code changes should be done to achieve this. ?
Either you want CSV, which you already have, or you want a custom txt-file. If you want the latter, try this:
$comp = gwmi win32_computersystem
#"
"ComputerName","$($comp.Name)"
"DomainName","$($comp.Domain)"
"Manufacturer","$($comp.Manufacturer)"
"# | Out-File test.txt
sample of test.txt output below. I've got a non-domain, custom built pc, so don't worry about the values.
"ComputerName","GRAIMER-PC"
"DomainName","WORKGROUP"
"Manufacturer","System manufacturer"
EDIT I suggest you learn what CSV is. Remember that CSV is not a fileformat, it's a formatting-style used in a normal textfile. The .csv extension is just cosmetic to let people know that the textfile uses the csv-style. Check out Wikipedia and Technet
In the CSV file, each object is represented by a comma-separated list
of the property values of the object. The property values are
converted to strings (by using the ToString() method of the object),
so they are generally represented by the name of the property value.
Export-CSV does not export the methods of the object.
The format of an exported file is as follows:
-- The first line of the CSV file contains the string '#TYPE ' followed by the fully qualified name of the object, such as #TYPE
System.Diagnostics.Process. To suppress this line, use the
NoTypeInformation parameter.
-- The next line of the CSV file represents the column headers. It contains a comma-separated list of the names of all the properties of
the first object.
-- Additional lines of the file consist of comma-separated lists of the property values of each object.
You could try something like this:
$InventoryReport | Format-List ComputerName, DomainName, Manufacturer `
| Out-String -Stream `
| ? { $_ -ne '' } `
| % { $_ -replace '\s+:\s+', '","' -replace '(^|$)', '"' }