I have a CSV file that contains both empty line and line breaks in cells like this:
Richard Roe
Mary Major
"Alex Smith
Betty Brown
Chris Clark"
"Betty Brown
Donna Davis
Edward Evans"
Alex Smith
"Richard Roe
Mary Major"
I am trying to write a PowerShell script to read this CSV file and get the following result (insert the name of their department in the list):
"Legal
Richard Roe"
"Accounting
Mary Major"
"R&D
Alex Smith
Betty Brown
Design
Chris Clark"
"R&D
Betty Brown
Design
Donna Davis
Edward Evans"
"R&D
Alex Smith"
"Legal
Richard Roe
Accounting
Mary Major"
When you read the CSV file with Import-CSV
, it ignores the empty lines like this:
PS C:\tmp> Import-Csv -Header Names .\NamesList.csv
Names
-----
Richard Roe
Mary Major
Alex Smith...
Betty Brown...
Alex Smith
Richard Roe...
PS C:\tmp>
What I expected is:
Names
-----
Richard Roe
Mary Major
Alex Smith...
Betty Brown...
Alex Smith
Richard Roe...
You can switch to Get-Content
to read the CSV, but it seems difficult to process the line breaks in the cell.
Is there any way to prevent Import-Csv
ignores empty lines?
Department-Name mappings in the another CSV file like this:
Legal,Richard Roe
Accounting,Mary Major
R&D,Alex Smith
R&D,Betty Brown
Design,Chris Clark
Design,Donna Davis
Design,Edward Evans
Import-Csv
doesn't have this option but you can work your way around it by reading line by line and parsing the content. It requires a bit of work though.
Assuming the file look exactly like you have shared in your question, something like this approach might work:
function Read {
param(
[Parameter(Mandatory)] [string] $Path,
[Parameter(Mandatory)] [string] $Header
)
$Path = Convert-Path $Path -ErrorAction Stop
$sb = [System.Text.StringBuilder]::new()
$startQuote = $false
foreach ($line in [System.IO.File]::ReadLines($Path)) {
if ($line.StartsWith('"')) {
$startQuote = $true
$sb = $sb.AppendLine($line.TrimStart('"'))
continue
}
if (-not $startQuote) {
[pscustomobject]@{ $Header = $line }
continue
}
if ($line.EndsWith('"')) {
$startQuote = $false
$sb = $sb.Append($line.TrimEnd('"'))
[pscustomobject]@{ $Header = $sb.ToString() }
$sb = $sb.Clear()
continue
}
$sb = $sb.AppendLine($line.TrimStart('"'))
}
}
$names = Read .\NamesList.csv -Header Names
$names
This will output an array of objects like the one you're expecting:
Names
-----
Richard Roe
Mary Major
Alex Smith…
Betty Brown…
Alex Smith
Richard Roe…
Then you can prepend the Departments by updating the objects by index. It's unclear where these are coming from, if we had this information the these could be prepended earlier for a more efficient approach:
$names[1].Names = "Legal`n$($names[1].Names)"
$names[2].Names = "Accounting`n$($names[2].Names)"
$names[3].Names = "R&D`n$($names[3].Names)"
$names | ConvertTo-Csv # <= This for demo, it should be `Export-Csv` instead
Then the resulting CSV would look like what you are expecting:
"Names"
""
"Legal
Richard Roe"
"Accounting
Mary Major"
"R&D
Alex Smith
Betty Brown
Chris Clark"
""
"Betty Brown
Donna Davis
Edward Evans"
""
"Alex Smith"
""
"Richard Roe
Mary Major"