I have used Chad Millers (@cmille19) Out-DataTable function on numerous occasions. It is used to convert a regular PowerShell object to a DataTable object. It had it quirks though, so I decided to rewrite it to try to fix some of them.
Most notably I have changed it so, in addition to arrays, also collections will be added as XML. I (think) I have also fixed the null/dbnull issue. Let me know if that is not the case though!
Here is the code, check it out and let me know what you think.
| function ConvertTo-DataTable { | |
| <# | |
| .SYNOPSIS | |
| Convert regular PowerShell objects to a DataTable object. | |
| .DESCRIPTION | |
| Convert regular PowerShell objects to a DataTable object. | |
| .EXAMPLE | |
| $myDataTable = $myObject | ConvertTo-DataTable | |
| .NOTES | |
| Name: ConvertTo-DataTable | |
| Author: Øyvind Kallstad @okallstad | |
| Version: 1.1 | |
| #> | |
| [CmdletBinding()] | |
| param ( | |
| # The object to convert to a DataTable | |
| [Parameter(ValueFromPipeline = $true)] | |
| [PSObject[]] $InputObject, | |
| # Override the default type. | |
| [Parameter()] | |
| [string] $DefaultType = 'System.String' | |
| ) | |
| begin { | |
| # create an empty datatable | |
| try { | |
| $dataTable = New-Object -TypeName 'System.Data.DataTable' | |
| Write-Verbose -Message 'Empty DataTable created' | |
| } | |
| catch { | |
| Write-Warning -Message $_.Exception.Message | |
| break | |
| } | |
| # define a boolean to keep track of the first datarow | |
| $first = $true | |
| # define array of supported .NET types | |
| $types = @( | |
| 'System.String', | |
| 'System.Boolean', | |
| 'System.Byte[]', | |
| 'System.Byte', | |
| 'System.Char', | |
| 'System.DateTime', | |
| 'System.Decimal', | |
| 'System.Double', | |
| 'System.Guid', | |
| 'System.Int16', | |
| 'System.Int32', | |
| 'System.Int64', | |
| 'System.Single', | |
| 'System.UInt16', | |
| 'System.UInt32', | |
| 'System.UInt64' | |
| ) | |
| } | |
| process { | |
| # iterate through each input object | |
| foreach ($object in $InputObject) { | |
| try { | |
| # create a new datarow | |
| $dataRow = $dataTable.NewRow() | |
| Write-Verbose -Message 'New DataRow created' | |
| # iterate through each object property | |
| foreach ($property in $object.PSObject.get_properties()) { | |
| # check if we are dealing with the first row or not | |
| if ($first) { | |
| # handle data types | |
| if ($types -contains $property.TypeNameOfValue) { | |
| $dataType = $property.TypeNameOfValue | |
| Write-Verbose -Message "$($property.Name): Supported datatype <$($dataType)>" | |
| } | |
| else { | |
| $dataType = $DefaultType | |
| Write-Verbose -Message "$($property.Name): Unsupported datatype ($($property.TypeNameOfValue)), using default <$($DefaultType)>" | |
| } | |
| # create a new datacolumn | |
| $dataColumn = New-Object 'System.Data.DataColumn' $property.Name, $dataType | |
| Write-Verbose -Message 'Created new DataColumn' | |
| # add column to DataTable | |
| $dataTable.Columns.Add($dataColumn) | |
| Write-Verbose -Message 'DataColumn added to DataTable' | |
| } | |
| # add values to column | |
| if ($property.Value -ne $null) { | |
| # if array or collection, add as XML | |
| if (($property.Value.GetType().IsArray) -or ($property.TypeNameOfValue -like '*collection*')) { | |
| $dataRow.Item($property.Name) = $property.Value | ConvertTo-Xml -As 'String' -NoTypeInformation -Depth 1 | |
| Write-Verbose -Message 'Value added to row as XML' | |
| } | |
| else{ | |
| $dataRow.Item($property.Name) = $property.Value -as $dataType | |
| Write-Verbose -Message "Value ($($property.Value)) added to row as $($dataType)" | |
| } | |
| } | |
| } | |
| # add DataRow to DataTable | |
| $dataTable.Rows.Add($dataRow) | |
| Write-Verbose -Message 'DataRow added to DataTable' | |
| $first = $false | |
| } | |
| catch { | |
| Write-Warning -Message $_.Exception.Message | |
| } | |
| } | |
| } | |
| end { Write-Output (,($dataTable)) } | |
| } |
First I’d like to thank you for that code. But I have difficutlies converting data containing zeros. The zeros are just not in the table, the fields are empty 😦
LikeLike
It’s interpreting 0 as empty, and thus the type of the value will be DBNull in the resulting datatable. I’ll see if I can come up with a quick fix for this 🙂
LikeLike
Published a fix for this bug. Thanks for reporting it! 🙂
LikeLike