New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Export-Csv
and ConvertTo-Csv
fail when the first object is empty
#15273
Comments
Based on that, were' seeing two inconsistencies:
We could consider emitting a warning in this case. See also:
|
You have a point, I indeed didn't look at it this way.
If the first empty object, is used to define the columns, the output should be a table with zero columns where you might question whether any of its rows (with zero columns) should be represented as an empty line or just nothing... |
Personally, I think emitting an empty line for each input object is more consistent, but it's definitely a pathological case, which is why I think a warning is called for. To me, the question is whether (public) property-less objects among the input objects occur frequently enough to warrant implementing their getting ignored as a fallback - when do such empty objects occur, and is ignoring them helpful, or are they the result of an upstream error that users had better be alerted to? And even if ignoring is the way to go, I'd be inclined to also emit a warning. |
Sorry, I think I wasn't clear, it only concerns the first consecutive empty objects. @(
[pscustomobject]@{} # Row 1
[pscustomobject]@{} # Row 2
[pscustomobject]@{a=1; b=5} # Row 3
[pscustomobject]@{a=2; b=6} # Row 4
[pscustomobject]@{} # Row 5
[pscustomobject]@{a=3; b=7} # Row 6
) | ConvertTo-Csv I would expect the output to be:
... and not to be empty (or any list of empty lines).
the warning could be something like:
For the empty object at |
Second/other thought (quoting myself):
Considering the fact that it might hardly use any memory just to count the preceding empty objects (
After that, treat each following pipeline object (Output "2","6" etc.) as usual. (if in the end no objects where found with properties, return nothing: Caveat: If the list of input objects also contains non-unified objects (#13906) it might get somewhat confusing as it will take the first object that has properties to define the column names (rather than the first possible empty object). |
Understood, but the questions in my mind still are:
In the latter case, I don't think it is worth special-casing this scenario, and a warning - as a courtesy - would alert users to the fact that the input results in no meaningful output. |
Situations like this cannot be solved in general. Specific scenarios need to be considered. Is there such a scenario? Example, I read an information from an service, then send to ConvertTo-Csv
This obviously says I need to pre-process my input before send to ConvertTo-Csv to get expected results. |
My used case is actually stackoverflow answer: PowerShell: Extracting HTML table as CSV. Read-HtmlTable (old)Function Read-HtmlTable {
[CmdletBinding()][OutputType([Object[]])] param(
[Parameter(ValueFromPipeLine = $True, Mandatory = $True)][String]$Html,
[Int[]]$TableIndex
)
Begin {
Function Get-Elements { # Get closed descendants by tag name
[CmdletBinding()][OutputType([__ComObject[]])] param(
[Parameter(Mandatory = $True)][String]$TagName,
[Parameter(Mandatory = $True, ValueFromPipeLine = $True)]$Element
)
if ($Element.tagName -eq $TagName) { $Element }
else { $Element.Children | Foreach-Object { $_ | Get-Elements $TagName } }
}
}
Process {
$Unicode = [System.Text.Encoding]::Unicode.GetBytes($Html)
$Document = New-Object -Com 'HTMLFile'
if ($Document.IHTMLDocument2_Write) { $Document.IHTMLDocument2_Write($Unicode) } else { $Document.write($Unicode) }
$Index = 0
foreach($table in ($Document.Body | Get-Elements 'table')) {
if (!$PSBoundParameters.ContainsKey('TableIndex') -or $Index++ -In $TableIndex) {
$Names = $Null
foreach ($tr in ($table | Get-Elements 'tr')) {
if (!$Names) { $Names = ($tr | Get-Elements 'th').innerText }
if (!$Names) { $Names = ($tr | Get-Elements 'td').innerText }
else {
$Values = ($tr | Get-Elements 'td').innerText
$Properties = [Ordered]@{}
$Count = [Math]::Min($Names.Count, $Values.Count)
for ($i = 0; $i -lt $Count; $i++) { $Properties[$Names[$i]] = $Values[$i] }
if ($Properties.Count -gt 0) { [pscustomobject]$Properties }
[pscustomobject]$Properties
}
}
}
}
}
}
$url = "https://winreleaseinfoprod.blob.core.windows.net/winreleaseinfoprod/en-US.html"
$webClient = New-Object System.Net.Webclient
$HTML = $webClient.DownloadString($url) There was a bug where it produced an unwanted empty object ( $HTML | Read-HtmlTable -Table 0 | Format-Table It appears to run just fine, yet if you output the results to a csv file (using $HTML | Read-HtmlTable -Table 0 | ConvertTo-Csv the output completely disappears. Maybe there is too much weight on this issue and should just be noted and closed... |
I can only think about |
If we were to take action here, my recommendation is as follows:
|
The Issue-Bug still exists:
|
Export-Csv
andConvertTo-Csv
fail when the first object is empty, yet the display output (and other cmdlets likeFormat-*
cmdlets) appear to work fine.Steps to reproduce
Expected behavior
Actual behavior
No results
Environment data
Related: ConvertTo-Csv and Export-Csv fail when -usequotes asneeded option is used and input object has null properties
#12279
The text was updated successfully, but these errors were encountered: