Skip to content
AgileLogics
5 min read

Working with CSV

Prerequisites: Custom objects

CSV files map perfectly to PowerShell objects: each row becomes an object, and each column a property.

Importing

Set-Content sales.csv @'
Region,Product,Units,Price
North,Keyboard,12,89
South,Monitor,4,249.99
North,Monitor,7,249.99
South,Keyboard,20,89
'@

$sales = Import-Csv sales.csv
$sales[0]
$sales | Where-Object Region -eq 'North' | Select-Object -ExpandProperty Product

Region Product  Units Price
------ -------  ----- -----
North  Keyboard 12    89
Keyboard
Monitor

Every value is a string

Import-Csv can't know column types, so everything is text. Convert before doing math or sorting:

Set-Content sales.csv @'
Region,Product,Units,Price
North,Keyboard,12,89
South,Monitor,4,249.99
North,Monitor,7,249.99
South,Keyboard,20,89
'@

$sales = Import-Csv sales.csv
$sales | Sort-Object Units | Select-Object -ExpandProperty Units
'---'
$sales | Sort-Object { [int]$_.Units } | Select-Object -ExpandProperty Units
12
20
4
7
---
4
7
12
20

Sorted as text, '12' comes before '4'.

Transforming and exporting

Set-Content sales.csv @'
Region,Product,Units,Price
North,Keyboard,12,89
South,Monitor,4,249.99
North,Monitor,7,249.99
South,Keyboard,20,89
'@

Import-Csv sales.csv |
  Group-Object Region |
  ForEach-Object {
    [pscustomobject]@{
      Region  = $_.Name
      Revenue = [math]::Round(($_.Group | ForEach-Object { [int]$_.Units * [double]$_.Price } | Measure-Object -Sum).Sum, 2)
    }
  } |
  Export-Csv revenue.csv

Get-Content revenue.csv
"Region","Revenue"
"North","2817.93"
"South","2779.96"

Export-Csv writes objects as CSV, quoting values. In PowerShell 7 there's no type header line (5.1 needed -NoTypeInformation to avoid it).

Other options

  • -Delimiter ';' for semicolon-separated files; -Header to supply column names when the file has none.
  • ConvertFrom-Csv / ConvertTo-Csv work on strings instead of files — useful with API responses.