Reputation: 11
I want each row to be populated with the data retrieved from each file. Currently, the 2nd and 3rd column entries are being written to a newline.CSV file output I have tried using "export-csv" and the "-nonewline" command. Perhaps there is a regex command that would solve this?
#Column headings
$headings = "Source file, Review file existence, Review Result, Compilation Check Result, Static Analysis Result, Review up-to-date, Reviewed code version, Latest code version"
# Create array with $headings as first input
$output = @($headings)
$SourceParentDir = "C:\Document"
$Files = get-childitem -Path $SourceParentDir -Recurse -Filter '*.?pp' | % { $_.FullName }
foreach ($File in $Files)
{
$BaseName = [System.IO.Path]::GetFileName($File)
# Populate each row for each file
$output += $BaseName
$output += ", Review Exists" # writes to a newline
$output += ", " + $Result + "," + $Compilation + "," + $StaticAnalysis + "," + $UpToDateFlag + "," + $ReviewFileVersionNumber + "," + $SourceFileVersionNumber + ","
}
# write output to a csv file
$output | Out-File -FilePath Documents\Example-csv.csv -encoding utf8
Upvotes: 1
Views: 604
Reputation: 415810
$output
is an array, so each of those +=
inside the loop is a new entry in the array, and therefore a new line in the file.
You can fix this by using a temporary string variable in the middle of the loop, and appending it to $output
once at the end of each iteration:
foreach ($File in $Files)
{
$row = [System.IO.Path]::GetFileName($File)
$row += ", Review Exists"
$row += ", " + $Result + "," + $Compilation + "," + $StaticAnalysis + "," + $UpToDateFlag + "," + $ReviewFileVersionNumber + "," + $SourceFileVersionNumber + ","
$output += $row
}
or by putting everything in one big string interpolation:
foreach ($File in $Files)
{
$BaseName = [System.IO.Path]::GetFileName($File)
$output += "$BaseName, Review Exists, $Result, $Compilation, $StaticAnalysis, $UpToDateFlag, $ReviewFileVersionNumber, $SourceFileVersionNumber"
}
But I agree with the other answer that building up an array of custom objects for the Export-Csv
commandlet is more idiomatic for PowerShell.
Upvotes: 1
Reputation: 32170
You can do things that way, but there's definitely a more-Powershelley way:
Get-ChildItem -Path $SourceParentDir -Recurse -Filter '*.?pp' |
ForEach-Object {
$File = $_
# Put your other code here
# This will output an object to the stream
[PSCustomObject]@{
'Source file' = $File.Name
'Review file existence' = 'Review Exists'
'Review Result' = $Result
'Compilation Check Result' = $Compilation
'Static Analysis Result' = $StaticAnalysis
'Review up-to-date' = $UpToDateFlag
'Reviewed code version' = $ReviewFileVersionNumber
'Latest code version' = $SourceFileVersionNumber
}
} | Export-Csv Example-csv.csv -NoTypeInformation
The big drawback here is that you don't get a lot of formatting choices about the CSV. Every field is quoted, for example.
Alternately, if you really want really detailed control of the $output
string, you should use a StringBuilder
instead of a String
. StringBuilder
is one of the most potent and widely used classes in C#. This is because strings in C# and Powershell are immutable, so when you +=
a String you create a new string, copy everything over with the new bit, then throw the old string away. It can be very memory intensive with large operations. StringBuilder lets you get around all that. It's a class that's designed to let you append stuff to strings and format them however you want.
You instance it like so:
$output = [System.Text.StringBuilder]::new()
And then you typically call one of two methods to add text. Append($string)
appends the string, AppendLine($string)
appends the line and then adds a newline. You can also call AppendLine()
with no argument to just add a newline. To get your final string, you call the ToString()
method. The append methods do return a status when you call them which you can prevent from outputting pretty easily with a [void]
, or by saving it to another variable if you need it.
$output = [System.Text.StringBuilder]::new()
[void]$output.AppendLine($headings)
$SourceParentDir = "C:\StarTeam\00011114-JSENS_TRS\ATR\04_SW_Implementation\Operational"
$Files = get-childitem -Path $SourceParentDir -Recurse -Filter '*.?pp' | % { $_.FullName }
foreach ($File in $Files)
{
$BaseName = [System.IO.Path]::GetFileName($File)
# Populate each row for each file
[void]$output.Append($BaseName)
[void]$output.Append(", Review Exists")
[void]$output.Append(", $Result,$Compilation,$StaticAnalysis,$UpToDateFlag,$ReviewFileVersionNumber,$SourceFileVersionNumber,")
[void]$output.AppendLine()
}
$output.ToString() | Out-File -FilePath Documents\Example-csv.csv -encoding utf8
Upvotes: 2
Reputation: 111
The issue is how you're populating $Output. Since it is defined as an array, each time you're adding new information it's creating a new entry rather than just adding the additional information to a string.
If you make your $output into one line with all required fields it should correct it without you changing the array.
$output += $BaseName + ", Review Exists" + ", " + $Result + "," + $Compilation + "," + $StaticAnalysis + "," + $UpToDateFlag + "," + $ReviewFileVersionNumber + "," + $SourceFileVersionNumber + ","
Upvotes: 0