Public/New-PivotTable.ps1
function New-PSPivotTable { param( [string[]]$index, [string[]]$values, [string[]]$ExcludeValues, [string[]]$column, [Parameter(ValueFromPipeline)] $InputObject, [ValidateScript( { $_ -in (Get-AggregateFunctionNames) })] [object[]]$aggregateFunction = 'Average', $MissingValueText = '[missing]', [double]$Fill = [double]::NaN, [Switch]$PrettyPrint, [Switch]$Raw ) Process { if ($null -ne $InputObject) { $data += @($InputObject) } } End { $boundParameters = @{} + $PSBoundParameters if ($index.Count -ge 2) { "Multiple indexes not yet implemented" return $null } if ($column) { "Column dimensions not yet implemented" return $null } if ($boundParameters.Keys.Count -eq 1 -and $boundParameters.Contains("InputObject")) { return $null } if ($null -eq $data) { return $null } $propertyNames = $data[0].psobject.properties.name [System.Collections.ArrayList]$values = $values for ($idx = $values.Count - 1; $idx -gt -1; $idx--) { $propertyName = $values[$idx] if (($propertyNames -eq $propertyName).Count -eq 0) { Write-Warning "Property [$propertyName] not found, and is removed from the measure calculations" $values.RemoveAt($idx) } } if ($aggregateFunction -eq 'AllStats') { $aggregateFunction = "Min", "Max", "Average", "STD", "Sum", "Count" } $aggregateFunction = [string[]]$aggregateFunction if ($index.Count -eq 1 -and $null -eq $values) { $numberProperties = Get-AllDataTypes $data | Where-Object { $_.DataType -match '^(int|float|double)$' } $values = @($numberProperties.Name) } if ($ExcludeValues) { for ($idx = $values.Count - 1; $idx -gt -1; $idx--) { $propertyName = $values[$idx] if (($ExcludeValues -eq $propertyName).Count -eq 1) { $values.RemoveAt($idx) } } } if ($column) { $index += @($column) } $result = [ordered]@{} foreach ($record in $data) { $currentKey = $null for ($idx = 0; $idx -lt $index.Count; $idx++) { $key = $record.($index[$idx]) if ([string]::IsNullOrEmpty($key)) { $key = $MissingValueText } if ($null -eq $currentKey) { if (!$result["$key"]) { $result["$key"] = [Ordered]@{} } $currentKey = $result["$key"] } else { if (!$currentKey["$key"]) { $currentKey["$key"] = [Ordered]@{} } $currentKey = $currentKey["$key"] } } foreach ($propertyName in $values) { foreach ($aggregation in $aggregateFunction) { $pn = "$($aggregation)_$($propertyName)" $measure = $record.$propertyName if ([string]::IsNullOrEmpty($measure)) { $measure = $Fill } if ($null -eq $currentKey.$pn) { $measure = ConvertFrom-IntPtr $measure $currentKey.$pn = New-Object $aggregation -ArgumentList $measure } else { $measure = ConvertFrom-IntPtr $measure $currentKey.$pn.AddToMeasure($measure) } } } } if ($PrettyPrint) { PrettyPrint $result return } if ($Raw -or $index.Count -gt 1) { $result.metaData = [ordered]@{ "index" = $index "values" = $values "excludeValues" = $ExcludeValues "column" = $column "aggregateFunction" = $aggregateFunction "missingValueText" = $MissingValueText } $result } else { doFmt $result } } } function ConvertFrom-IntPtr { param( [Parameter(Mandatory)] $measure ) if ($measure -is [IntPtr]) { $measure.ToInt32() -as [double] } else { $measure } } |