personio/modules/sqlite/Out-DataTable.ps1
2024-07-26 19:37:06 +02:00

193 lines
5.7 KiB
PowerShell

function Out-DataTable
{
<#
.SYNOPSIS
Creates a DataTable for an object
.DESCRIPTION
Creates a DataTable based on an object's properties.
.PARAMETER InputObject
One or more objects to convert into a DataTable
.PARAMETER NonNullable
A list of columns to set disable AllowDBNull on
.INPUTS
Object
Any object can be piped to Out-DataTable
.OUTPUTS
System.Data.DataTable
.EXAMPLE
$dt = Get-psdrive | Out-DataTable
# This example creates a DataTable from the properties of Get-psdrive and assigns output to $dt variable
.EXAMPLE
Get-Process | Select Name, CPU | Out-DataTable | Invoke-SQLBulkCopy -ServerInstance $SQLInstance -Database $Database -Table $SQLTable -force -verbose
# Get a list of processes and their CPU, create a datatable, bulk import that data
.NOTES
Adapted from script by Marc van Orsouw and function from Chad Miller
Version History
v1.0 - Chad Miller - Initial Release
v1.1 - Chad Miller - Fixed Issue with Properties
v1.2 - Chad Miller - Added setting column datatype by property as suggested by emp0
v1.3 - Chad Miller - Corrected issue with setting datatype on empty properties
v1.4 - Chad Miller - Corrected issue with DBNull
v1.5 - Chad Miller - Updated example
v1.6 - Chad Miller - Added column datatype logic with default to string
v1.7 - Chad Miller - Fixed issue with IsArray
v1.8 - ramblingcookiemonster - Removed if($Value) logic. This would not catch empty strings, zero, $false and other non-null items
- Added perhaps pointless error handling
.LINK
https://github.com/RamblingCookieMonster/PowerShell
.LINK
Invoke-SQLBulkCopy
.LINK
Invoke-Sqlcmd2
.LINK
New-SQLConnection
.FUNCTIONALITY
SQL
#>
[CmdletBinding()]
[OutputType([System.Data.DataTable])]
param(
[Parameter( Position=0,
Mandatory=$true,
ValueFromPipeline = $true)]
[PSObject[]]$InputObject,
[string[]]$NonNullable = @()
)
Begin
{
$dt = New-Object Data.datatable
$First = $true
function Get-ODTType
{
param($type)
$types = @(
'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')
if ( $types -contains $type ) {
Write-Output "$type"
}
else {
Write-Output 'System.String'
}
} #Get-Type
}
Process
{
foreach ($Object in $InputObject)
{
$DR = $DT.NewRow()
foreach ($Property in $Object.PsObject.Properties)
{
$Name = $Property.Name
$Value = $Property.Value
#RCM: what if the first property is not reflective of all the properties? Unlikely, but...
if ($First)
{
$Col = New-Object Data.DataColumn
$Col.ColumnName = $Name
#If it's not DBNull or Null, get the type
if ($Value -isnot [System.DBNull] -and $Value -ne $null)
{
$Col.DataType = [System.Type]::GetType( $(Get-ODTType $property.TypeNameOfValue) )
}
#Set it to nonnullable if specified
if ($NonNullable -contains $Name )
{
$col.AllowDBNull = $false
}
try
{
$DT.Columns.Add($Col)
}
catch
{
Write-Error "Could not add column $($Col | Out-String) for property '$Name' with value '$Value' and type '$($Value.GetType().FullName)':`n$_"
}
}
Try
{
#Handle arrays and nulls
if ($property.GetType().IsArray)
{
$DR.Item($Name) = $Value | ConvertTo-XML -As String -NoTypeInformation -Depth 1
}
elseif($Value -eq $null)
{
$DR.Item($Name) = [DBNull]::Value
}
else
{
$DR.Item($Name) = $Value
}
}
Catch
{
Write-Error "Could not add property '$Name' with value '$Value' and type '$($Value.GetType().FullName)'"
continue
}
#Did we get a null or dbnull for a non-nullable item? let the user know.
if($NonNullable -contains $Name -and ($Value -is [System.DBNull] -or $Value -eq $null))
{
write-verbose "NonNullable property '$Name' with null value found: $($object | out-string)"
}
}
Try
{
$DT.Rows.Add($DR)
}
Catch
{
Write-Error "Failed to add row '$($DR | Out-String)':`n$_"
}
$First = $false
}
}
End
{
Write-Output @(,$dt)
}
} #Out-DataTable