Export-Excel.ps1
Function Export-Excel { <# .SYNOPSIS Export data to an Excel work sheet. .EXAMPLE Get-Service | Export-Excel .\test.xlsx .EXAMPLE Get-Process | Export-Excel .\test.xlsx -show\ .EXAMPLE Get-Process | Export-Excel .\test.xlsx -WorkSheetname Processes -IncludePivotTable -Show -PivotRows Company -PivotData PM .EXAMPLE Get-Process | Export-Excel .\test.xlsx -WorkSheetname Processes -ChartType PieExploded3D -IncludePivotChart -IncludePivotTable -Show -PivotRows Company -PivotData PM .EXAMPLE Remove-Item "c:\temp\test.xlsx" -ErrorAction Ignore Get-Service | Export-Excel "c:\temp\test.xlsx" -Show -IncludePivotTable -PivotRows status -PivotData @{status='count'} #> [CmdLetBinding()] Param( #[Parameter(Mandatory=$true)] $Path, [Parameter(ValueFromPipeline=$true)] $TargetData, [String]$WorkSheetname='Sheet1', [String]$Title, [OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern='None', [Switch]$TitleBold, [Int]$TitleSize=22, [System.Drawing.Color]$TitleBackgroundColor, [String[]]$PivotRows, [String[]]$PivotColumns, $PivotData, [Switch]$PivotDataToColumn, [String]$Password, [OfficeOpenXml.Drawing.Chart.eChartType]$ChartType='Pie', [Switch]$IncludePivotTable, [Switch]$IncludePivotChart, [Switch]$NoLegend, [Switch]$ShowCategory, [Switch]$ShowPercent, [Switch]$AutoSize, [Switch]$Show, [Switch]$NoClobber, [Switch]$FreezeTopRow, [Switch]$FreezeFirstColumn, [Switch]$FreezeTopRowFirstColumn, [Int[]]$FreezePane, [Switch]$AutoFilter, [Switch]$BoldTopRow, [Switch]$NoHeader, [String]$RangeName, [ValidateScript({ if ($_.Contains(' ')) { throw 'Tablename has spaces.' } elseif (-not $_) { throw 'Tablename is null or empty.' } elseif ($_[0] -notmatch '[a-z]') { throw 'Tablename start with invalid character.' } else { $true } })] [String]$TableName, [OfficeOpenXml.Table.TableStyles]$TableStyle='Medium6', [Object[]]$ConditionalFormat, [Object[]]$ConditionalText, [Object[]]$ExcelChartDefinition, [ScriptBlock]$CellStyleSB, [String[]]$HideSheet, [Switch]$KillExcel, [Switch]$AutoNameRange, $StartRow=1, $StartColumn=1, [Switch]$PassThru, [String]$Numberformat='General', [Switch]$Now ) Begin { $script:Header = $null if ($KillExcel) { Get-Process excel -ErrorAction Ignore | Stop-Process while (Get-Process excel -ErrorAction Ignore) {} } Try { if ($Now) { $Path=[System.IO.Path]::GetTempFileName() -replace '\.tmp','.xlsx' $Show=$true $AutoSize=$true $AutoFilter=$true } $Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path) if (Test-Path $path) { Write-Debug "File `"$Path`" already exists" } $pkg = New-Object OfficeOpenXml.ExcelPackage $Path $ws = $pkg | Add-WorkSheet -WorkSheetname $WorkSheetname -NoClobber:$NoClobber foreach ($format in $ConditionalFormat ) { $target = "Add$($format.Formatter)" $rule = ($ws.ConditionalFormatting).PSObject.Methods[$target].Invoke($format.Range, $format.IconType) $rule.Reverse = $format.Reverse } # Force at least one cell value #$ws.Cells[1, 1].Value = '' $Row = $StartRow if ($Title) { $ws.Cells[$Row, $StartColumn].Value = $Title $ws.Cells[$Row, $StartColumn].Style.Font.Size = $TitleSize if ($TitleBold) { #set title to Bold if -TitleBold was specified. #Otherwise the default will be unbolded. $ws.Cells[$Row, $StartColumn].Style.Font.Bold = $True } $ws.Cells[$Row, $StartColumn].Style.Fill.PatternType = $TitleFillPattern #can only set TitleBackgroundColor if TitleFillPattern is something other than None if ($TitleBackgroundColor -AND ($TitleFillPattern -ne 'None')) { $ws.Cells[$Row, $StartColumn].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor) } else { Write-Warning "Title Background Color ignored. You must set the TitleFillPattern parameter to a value other than 'None'. Try 'Solid'." } $Row += 1 } } Catch { if ($AlreadyExists) { throw "$WorkSheetname already exists." } else { throw $Error[0].Exception.Message } } $firstTimeThru = $true $isDataTypeValueType=$false $pattern = "string|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ulong|ushort" } Process { if ($firstTimeThru) { $firstTimeThru=$false $isDataTypeValueType = $TargetData.GetType().name -match "string|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ulong|ushort" Write-Verbose "DataTypeName is '$($TargetData.GetType().name)' isDataTypeValueType $isDataTypeValueType" } if ($isDataTypeValueType) { $ColumnIndex = $StartColumn $targetCell = $ws.Cells[$Row, $ColumnIndex] $r=$null $cellValue=$TargetData if ([Double]::TryParse([string]$cellValue,[System.Globalization.NumberStyles]::Any,[System.Globalization.NumberFormatInfo]::CurrentInfo, [ref]$r)) { $targetCell.Value = $r $targetCell.Style.Numberformat.Format=$Numberformat } else { $targetCell.Value = $cellValue } switch ($TargetData.$Name) { {$_ -is [datetime]} {$targetCell.Style.Numberformat.Format = "m/d/yy h:mm"} } $ColumnIndex += 1 $Row += 1 } else { if (!$script:Header) { $ColumnIndex = $StartColumn $script:Header = $TargetData.psobject.properties.name if ($NoHeader) { # Don't push the headers to the spread sheet $Row -= 1 } else { foreach ($Name in $script:Header) { Write-Verbose "Add header '$Name'" $ws.Cells[$Row, $ColumnIndex].Value = $Name $ColumnIndex += 1 } } } $Row += 1 $ColumnIndex = $StartColumn foreach ($Name in $script:Header) { $targetCell = $ws.Cells[$Row, $ColumnIndex] $cellValue=$TargetData.$Name if ($cellValue -is [string] -and $cellValue.StartsWith('=')) { $targetCell.Formula = $cellValue } else { $r=$null if ([Double]::TryParse([string]$cellValue,[System.Globalization.NumberStyles]::Any,[System.Globalization.NumberFormatInfo]::CurrentInfo, [ref]$r)) { $targetCell.Value = $r $targetCell.Style.Numberformat.Format=$Numberformat Write-Verbose "Add cell value '$r' in Numberformat '$Numberformat'" } else { $targetCell.Value = $cellValue Write-Verbose "Add cell value '$cellValue' as String" } } switch ($TargetData.$Name) { {$_ -is [datetime]} { $targetCell.Style.Numberformat.Format = "m/d/yy h:mm" } } #[ref]$uriResult=$null #if ([uri]::TryCreate($cellValue, [System.UriKind]::Absolute, $uriResult)) { # $targetCell.Hyperlink = [uri]$cellValue # $namedStyle=$ws.Workbook.Styles.NamedStyles | where {$_.Name -eq 'HyperLink'} # if (!$namedStyle) { # $namedStyle=$ws.Workbook.Styles.CreateNamedStyle("HyperLink") # $namedStyle.Style.Font.UnderLine = $true # $namedStyle.Style.Font.Color.SetColor("Blue") # } # $targetCell.StyleName = "HyperLink" #} $ColumnIndex += 1 } } } End { Try { if ($AutoNameRange) { $totalRows=$ws.Dimension.Rows $totalColumns=$ws.Dimension.Columns foreach($c in 0..($totalColumns-1)) { $targetRangeName = "$($script:Header[$c])" $targetColumn = $c+1 $theCell = $ws.Cells[2,$targetColumn,$totalRows,$targetColumn ] $ws.Names.Add($targetRangeName, $theCell) | Out-Null if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress($targetRangeName)) { Write-Warning "AutoNameRange: Property name '$targetRangeName' is also a valid Excel address and may cause issues. Consider renaming the property name." } } } $startAddress=$ws.Dimension.Start.Address $dataRange="{0}:{1}" -f $startAddress, $ws.Dimension.End.Address Write-Debug "Data Range $dataRange" if (-not [string]::IsNullOrEmpty($RangeName)) { $ws.Names.Add($RangeName, $ws.Cells[$dataRange]) | Out-Null } if (-not [string]::IsNullOrEmpty($TableName)) { #$ws.Tables.Add($ws.Cells[$dataRange], $TableName) | Out-Null #"$($StartRow),$($StartColumn),$($ws.Dimension.End.Row-$StartRow),$($Header.Count)" $csr=$StartRow $csc=$StartColumn $cer=$ws.Dimension.End.Row #-$StartRow+1 $cec=$script:Header.Count $targetRange=$ws.Cells[$csr, $csc, $cer,$cec] $tbl = $ws.Tables.Add($targetRange, $TableName) $tbl.TableStyle=$TableStyle } if ($IncludePivotTable) { $pivotTableName = $WorkSheetname + "PivotTable" $wsPivot = $pkg | Add-WorkSheet -WorkSheetname $pivotTableName -NoClobber:$NoClobber $wsPivot.View.TabSelected = $true $pivotTableDataName=$WorkSheetname + "PivotTableData" if ($Title) {$startAddress="A2"} $pivotTable = $wsPivot.PivotTables.Add($wsPivot.Cells["A1"], $ws.Cells[$dataRange], $pivotTableDataName) if ($PivotRows) { foreach ($Row in $PivotRows) { $null=$pivotTable.RowFields.Add($pivotTable.Fields[$Row]) } } if ($PivotColumns) { foreach ($Column in $PivotColumns) { $null=$pivotTable.ColumnFields.Add($pivotTable.Fields[$Column]) } } if ($PivotData) { if ($PivotData -is [hashtable] -or $PivotData -is [System.Collections.Specialized.OrderedDictionary]) { $PivotData.Keys | % { $df=$pivotTable.DataFields.Add($pivotTable.Fields[$_]) $df.Function = $PivotData.$_ } } else { foreach ($Item in $PivotData) { $df=$pivotTable.DataFields.Add($pivotTable.Fields[$Item]) $df.Function = 'Count' } } if ($PivotDataToColumn) { $pivotTable.DataOnRows = $false } } if ($IncludePivotChart) { $chart = $wsPivot.Drawings.AddChart("PivotChart", $ChartType, $pivotTable) $chart.DataLabel.ShowCategory=$ShowCategory $chart.DataLabel.ShowPercent=$ShowPercent if ($NoLegend) { $chart.Legend.Remove() } $chart.SetPosition(1, 0, 6, 0) $chart.SetSize(600, 400) } } if ($Password) { $ws.Protection.SetPassword($Password) } if ($AutoFilter) { $ws.Cells[$dataRange].AutoFilter=$true } if ($FreezeTopRow) { $ws.View.FreezePanes(2,1) } if ($FreezeTopRowFirstColumn) { $ws.View.FreezePanes(2,2) } if ($FreezeFirstColumn) { $ws.View.FreezePanes(1,2) } if ($FreezePane) { $freezeRow,$freezeColumn=$FreezePane if (!$freezeColumn -or $freezeColumn -eq 0) {$freezeColumn=1} if ($freezeRow -gt 1) { $ws.View.FreezePanes($freezeRow,$freezeColumn) } } if ($BoldTopRow) { $range=$ws.Dimension.Address -replace $ws.Dimension.Rows, "1" $ws.Cells[$range].Style.Font.Bold=$true } if ($AutoSize) { $ws.Cells.AutoFitColumns() } #$pkg.Workbook.View.ActiveTab = $ws.SheetID foreach ($Sheet in $HideSheet) { $pkg.Workbook.WorkSheets[$Sheet].Hidden="Hidden" } $chartCount=0 foreach ($chartDef in $ExcelChartDefinition) { $ChartName = "Chart"+(Split-Path -Leaf ([System.IO.path]::GetTempFileName())) -replace 'tmp|\.','' $chart = $ws.Drawings.AddChart($ChartName, $chartDef.ChartType) $chart.Title.Text = $chartDef.Title if ($chartDef.NoLegend) { $chart.Legend.Remove() } #$chart.Datalabel.ShowLegendKey = $true if ($chart.Datalabel -ne $null) { $chart.Datalabel.ShowCategory = $chartDef.ShowCategory $chart.Datalabel.ShowPercent = $chartDef.ShowPercent } $chart.SetPosition($chartDef.Row, $chartDef.RowOffsetPixels,$chartDef.Column, $chartDef.ColumnOffsetPixels) $chart.SetSize($chartDef.Width, $chartDef.Height) $chartDefCount = @($chartDef.YRange).Count if ($chartDefCount -eq 1) { $Series=$chart.Series.Add($chartDef.YRange, $chartDef.XRange) $SeriesHeader=$chartDef.SeriesHeader if (!$SeriesHeader) {$SeriesHeader="Series 1"} $Series.Header = $SeriesHeader } else { for($idx=0; $idx -lt $chartDefCount; $idx+=1) { $Series=$chart.Series.Add($chartDef.YRange[$idx], $chartDef.XRange) if ($chartDef.SeriesHeader.Count -gt 0) { $SeriesHeader=$chartDef.SeriesHeader[$idx] } if (!$SeriesHeader) {$SeriesHeader="Series $($idx)"} $Series.Header = $SeriesHeader $SeriesHeader=$null } } } if ($ConditionalText) { foreach ($targetConditionalText in $ConditionalText) { $target = "Add$($targetConditionalText.ConditionalType)" $Range=$targetConditionalText.Range if (!$Range) { $Range=$ws.Dimension.Address } $rule=($ws.Cells[$Range].ConditionalFormatting).PSObject.Methods[$target].Invoke() if ($targetConditionalText.Text) { if ($targetConditionalText.ConditionalType -match "equal|notequal|lessthan|lessthanorequal|greaterthan|greaterthanorequal") { $rule.Formula= $targetConditionalText.Text } else { $rule.Text = $targetConditionalText.Text } } $rule.Style.Font.Color.Color = $targetConditionalText.ConditionalTextColor $rule.Style.Fill.PatternType=$targetConditionalText.PatternType $rule.Style.Fill.BackgroundColor.Color=$targetConditionalText.BackgroundColor } } if ($CellStyleSB) { $TotalRows=$ws.Dimension.Rows $LastColumn=(Get-ExcelColumnName $ws.Dimension.Columns).ColumnName & $CellStyleSB $ws $TotalRows $LastColumn } if ($PassThru) { $pkg } else { $pkg.Save() $pkg.Dispose() if ($Show) {Invoke-Item $Path} } } Catch { throw "Failed exporting the worksheet: $_" } } } |