Update-DataTable.ps1
function Update-DataTable { <# .Synopsis Updates a datatable .Description Updates data within a datatable, or adds new rows .Link New-DataTable .Example $dt = New-DataTable -ColumnName Name, Age -ColumnType [string], [int] -KeyColumn Name New-Object PSObject -Property @{ Name = "James" Age = 32 } | Update-Datatable $dt #> [OutputType([Data.DataRow], [Nullable])] param( # The data to add to the data table [Parameter(Mandatory=$true,ValueFromPipeline=$true)] [PSObject[]] $InputObject, # The datatable that will be updated [Parameter(Mandatory=$true,Position=0)] [Data.DataTable] $DataTable, # If set, will return the row added to the datatable [Switch] $PassThru, # If set, will add columns to the table if they are not found [Switch] $Force, # If set, will merge the found in a new record into the row. If not set, the row will be deleted and re-added. [Switch] $Merge ) begin { #region Define Simple Type Lookup Table $simpleTypes = ('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') $SimpletypeLookup = @{} foreach ($s in $simpleTypes) { $SimpletypeLookup[$s] = $s } #endregion Define Simple Type Lookup Table } process { foreach ($In in $InputObject) { $DataRow = $DataTable.NewRow() $isDataRow = $in.psobject.TypeNames -like "*.DataRow*" -as [bool] foreach($property in $In.PsObject.properties) { if ($isDataRow -and 'RowError', 'RowState', 'Table', 'ItemArray', 'HasErrors' -contains $property.Name) { continue } $propName = $property.Name $propValue = $property.Value $IsSimpleType = $SimpletypeLookup.ContainsKey($property.TypeNameOfValue) if (-not $DataTable.Columns.Contains($propName)) { if ($Force) { $DataTable.Columns.Add(( New-Object Data.DataColumn -Property @{ ColumnName = $propName DataType = if ($issimpleType) { $property.TypeNameOfValue } else { 'System.Object' } } )) } else { continue } } $DataRow.Item($propName) = if ($isSimpleType -and $propValue) { $propValue } elseif ($propValue) { [PSObject]$propValue } else { [DBNull]::Value } } if ($DataTable.PrimaryKey) { $keyColumns = $DataTable.PrimaryKey | Select-Object -ExpandProperty ColumnName $otherRow = $DataTable.Rows.Find($DataRow.$keyColumns) if ($otherRow -and $Merge) { foreach ($property in $in.psobject.properties) { if ($isDataRow -and 'RowError', 'RowState', 'Table', 'ItemArray', 'HasErrors' -contains $property.Name) { continue } $propName = $property.Name $propValue = $property.Value $IsSimpleType = $SimpletypeLookup.ContainsKey($property.TypeNameOfValue) $otherRow.Item($propName) = if ($isSimpleType -and $propValue) { $propValue } elseif ($propValue) { [PSObject]$propValue } else { [DBNull]::Value } } } elseif ($otherRow) { $DataTable.Rows.Remove($otherRow) $DataTable.Rows.Add($DataRow) } else { $DataTable.Rows.Add($DataRow) } } else { # No key, just add it to the table $DataTable.Rows.Add($DataRow) } if ($PassThru) { $DataRow } } } } |