Merge remote-tracking branch 'refs/remotes/origin/master' into dfinke/master

This commit is contained in:
DarkLite1
2017-02-23 08:59:39 +01:00
2 changed files with 252 additions and 221 deletions

View File

@@ -1,36 +1,43 @@
function Export-Excel {
Function Export-Excel {
<#
.SYNOPSIS
Export data to an Excel work sheet.
.EXAMPLE
gsv | Export-Excel .\test.xlsx
Get-Service | Export-Excel .\test.xlsx
.EXAMPLE
ps | Export-Excel .\test.xlsx -show\
Get-Process | Export-Excel .\test.xlsx -show\
.EXAMPLE
ps | Export-Excel .\test.xlsx -WorkSheetname Processes -IncludePivotTable -Show -PivotRows Company -PivotData PM
Get-Process | Export-Excel .\test.xlsx -WorkSheetname Processes -IncludePivotTable -Show -PivotRows Company -PivotData PM
.EXAMPLE
ps | Export-Excel .\test.xlsx -WorkSheetname Processes -ChartType PieExploded3D -IncludePivotChart -IncludePivotTable -Show -PivotRows Company -PivotData PM
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'}
#>
param(
[CmdLetBinding()]
Param(
#[Parameter(Mandatory=$true)]
$Path,
[Parameter(ValueFromPipeline=$true)]
$TargetData,
[string]$WorkSheetname="Sheet1",
[string]$Title,
[OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern="None",
[String]$WorkSheetname='Sheet1',
[String]$Title,
[OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern='None',
[Switch]$TitleBold,
[int]$TitleSize=22,
[Int]$TitleSize=22,
[System.Drawing.Color]$TitleBackgroundColor,
[string[]]$PivotRows,
[string[]]$PivotColumns,
[String[]]$PivotRows,
[String[]]$PivotColumns,
$PivotData,
[Switch]$PivotDataToColumn,
[string]$Password,
[OfficeOpenXml.Drawing.Chart.eChartType]$ChartType="Pie",
[String]$Password,
[OfficeOpenXml.Drawing.Chart.eChartType]$ChartType='Pie',
[Switch]$IncludePivotTable,
[Switch]$IncludePivotChart,
[Switch]$NoLegend,
@@ -42,37 +49,51 @@ function Export-Excel {
[Switch]$FreezeTopRow,
[Switch]$FreezeFirstColumn,
[Switch]$FreezeTopRowFirstColumn,
[int[]]$FreezePane,
[Int[]]$FreezePane,
[Switch]$AutoFilter,
[Switch]$BoldTopRow,
[Switch]$NoHeader,
[string]$RangeName,
[string]$TableName,
[OfficeOpenXml.Table.TableStyles]$TableStyle="Medium6",
[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,
[String[]]$HideSheet,
[Switch]$KillExcel,
[Switch]$AutoNameRange,
$StartRow=1,
$StartColumn=1,
[Switch]$PassThru,
[string]$Numberformat="General",
[String]$Numberformat='General',
[Switch]$Now
)
Begin {
$script:Header = $null
if($KillExcel) {
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"
Try {
if ($Now) {
$Path=[System.IO.Path]::GetTempFileName() -replace '\.tmp','.xlsx'
$Show=$true
$AutoSize=$true
$AutoFilter=$true
@@ -87,18 +108,18 @@ function Export-Excel {
$ws = $pkg | Add-WorkSheet -WorkSheetname $WorkSheetname -NoClobber:$NoClobber
foreach($format in $ConditionalFormat ) {
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 = ""
#$ws.Cells[1, 1].Value = ''
$Row = $StartRow
if($Title) {
if ($Title) {
$ws.Cells[$Row, $StartColumn].Value = $Title
$ws.Cells[$Row, $StartColumn].Style.Font.Size = $TitleSize
@@ -110,7 +131,7 @@ function Export-Excel {
$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")) {
if ($TitleBackgroundColor -AND ($TitleFillPattern -ne 'None')) {
$ws.Cells[$Row, $StartColumn].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor)
}
else {
@@ -120,8 +141,9 @@ function Export-Excel {
$Row += 1
}
} Catch {
if($AlreadyExists) {
}
Catch {
if ($AlreadyExists) {
throw "$WorkSheetname already exists."
} else {
throw $Error[0].Exception.Message
@@ -134,19 +156,20 @@ function Export-Excel {
}
Process {
if($firstTimeThru) {
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) {
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]::InvariantInfo, [ref]$r)) {
if ([Double]::TryParse([string]$cellValue,[System.Globalization.NumberStyles]::Any,[System.Globalization.NumberFormatInfo]::CurrentInfo, [ref]$r)) {
$targetCell.Value = $r
$targetCell.Style.Numberformat.Format=$Numberformat
} else {
@@ -161,18 +184,19 @@ function Export-Excel {
$Row += 1
} else {
if(!$script:Header) {
if (!$script:Header) {
$ColumnIndex = $StartColumn
$script:Header = $TargetData.psobject.properties.name
if($NoHeader) {
if ($NoHeader) {
# Don't push the headers to the spread sheet
$Row -= 1
} else {
foreach ($Name in $script:Header) {
$ws.Cells[$Row, $ColumnIndex].Value = $name
Write-Verbose "Add header '$Name'"
$ws.Cells[$Row, $ColumnIndex].Value = $Name
$ColumnIndex += 1
}
}
@@ -182,26 +206,28 @@ function Export-Excel {
$ColumnIndex = $StartColumn
foreach ($Name in $script:Header) {
$targetCell = $ws.Cells[$Row, $ColumnIndex]
$cellValue=$TargetData.$Name
if($cellValue -is [string] -and $cellValue.StartsWith('=')) {
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]::InvariantInfo, [ref]$r)) {
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"}
{$_ -is [datetime]} {
$targetCell.Style.Numberformat.Format = "m/d/yy h:mm"
}
}
#[ref]$uriResult=$null
@@ -210,7 +236,7 @@ function Export-Excel {
# $targetCell.Hyperlink = [uri]$cellValue
# $namedStyle=$ws.Workbook.Styles.NamedStyles | where {$_.Name -eq 'HyperLink'}
# if(!$namedStyle) {
# if (!$namedStyle) {
# $namedStyle=$ws.Workbook.Styles.CreateNamedStyle("HyperLink")
# $namedStyle.Style.Font.UnderLine = $true
# $namedStyle.Style.Font.Color.SetColor("Blue")
@@ -225,7 +251,8 @@ function Export-Excel {
}
End {
if($AutoNameRange) {
Try {
if ($AutoNameRange) {
$totalRows=$ws.Dimension.Rows
$totalColumns=$ws.Dimension.Columns
@@ -236,7 +263,7 @@ function Export-Excel {
$theCell = $ws.Cells[2,$targetColumn,$totalRows,$targetColumn ]
$ws.Names.Add($targetRangeName, $theCell) | Out-Null
if([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress($targetRangeName)) {
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."
}
}
@@ -267,7 +294,7 @@ function Export-Excel {
$tbl.TableStyle=$TableStyle
}
if($IncludePivotTable) {
if ($IncludePivotTable) {
$pivotTableName = $WorkSheetname + "PivotTable"
$wsPivot = $pkg | Add-WorkSheet -WorkSheetname $pivotTableName -NoClobber:$NoClobber
@@ -275,23 +302,23 @@ function Export-Excel {
$pivotTableDataName=$WorkSheetname + "PivotTableData"
if($Title) {$startAddress="A2"}
if ($Title) {$startAddress="A2"}
$pivotTable = $wsPivot.PivotTables.Add($wsPivot.Cells["A1"], $ws.Cells[$dataRange], $pivotTableDataName)
if($PivotRows) {
if ($PivotRows) {
foreach ($Row in $PivotRows) {
$null=$pivotTable.RowFields.Add($pivotTable.Fields[$Row])
}
}
if($PivotColumns) {
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]) {
if ($PivotData) {
if ($PivotData -is [hashtable] -or $PivotData -is [System.Collections.Specialized.OrderedDictionary]) {
$PivotData.Keys | % {
$df=$pivotTable.DataFields.Add($pivotTable.Fields[$_])
$df.Function = $PivotData.$_
@@ -302,55 +329,54 @@ function Export-Excel {
$df.Function = 'Count'
}
}
if($PivotDataToColumn) {
if ($PivotDataToColumn) {
$pivotTable.DataOnRows = $false
}
}
if($IncludePivotChart) {
if ($IncludePivotChart) {
$chart = $wsPivot.Drawings.AddChart("PivotChart", $ChartType, $pivotTable)
$chart.DataLabel.ShowCategory=$ShowCategory
$chart.DataLabel.ShowPercent=$ShowPercent
if($NoLegend) { $chart.Legend.Remove() }
if ($NoLegend) { $chart.Legend.Remove() }
$chart.SetPosition(1, 0, 6, 0)
$chart.SetSize(600, 400)
}
}
if($Password) { $ws.Protection.SetPassword($Password) }
if ($Password) { $ws.Protection.SetPassword($Password) }
if($AutoFilter) {
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 ($FreezeTopRow) { $ws.View.FreezePanes(2,1) }
if ($FreezeTopRowFirstColumn) { $ws.View.FreezePanes(2,2) }
if ($FreezeFirstColumn) { $ws.View.FreezePanes(1,2) }
if($FreezePane) {
if ($FreezePane) {
$freezeRow,$freezeColumn=$FreezePane
if(!$freezeColumn -or $freezeColumn -eq 0) {$freezeColumn=1}
if (!$freezeColumn -or $freezeColumn -eq 0) {$freezeColumn=1}
if($freezeRow -gt 1) {
if ($freezeRow -gt 1) {
$ws.View.FreezePanes($freezeRow,$freezeColumn)
}
}
if($BoldTopRow) {
if ($BoldTopRow) {
$range=$ws.Dimension.Address -replace $ws.Dimension.Rows, "1"
$ws.Cells[$range].Style.Font.Bold=$true
}
if($AutoSize) { $ws.Cells.AutoFitColumns() }
if ($AutoSize) { $ws.Cells.AutoFitColumns() }
#$pkg.Workbook.View.ActiveTab = $ws.SheetID
foreach($Sheet in $HideSheet) {
foreach ($Sheet in $HideSheet) {
$pkg.Workbook.WorkSheets[$Sheet].Hidden="Hidden"
}
$chartCount=0
@@ -359,7 +385,7 @@ function Export-Excel {
$chart = $ws.Drawings.AddChart($ChartName, $chartDef.ChartType)
$chart.Title.Text = $chartDef.Title
if($chartDef.NoLegend) {
if ($chartDef.NoLegend) {
$chart.Legend.Remove()
}
#$chart.Datalabel.ShowLegendKey = $true
@@ -373,22 +399,22 @@ function Export-Excel {
$chart.SetSize($chartDef.Width, $chartDef.Height)
$chartDefCount = @($chartDef.YRange).Count
if($chartDefCount -eq 1) {
if ($chartDefCount -eq 1) {
$Series=$chart.Series.Add($chartDef.YRange, $chartDef.XRange)
$SeriesHeader=$chartDef.SeriesHeader
if(!$SeriesHeader) {$SeriesHeader="Series 1"}
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) {
if ($chartDef.SeriesHeader.Count -gt 0) {
$SeriesHeader=$chartDef.SeriesHeader[$idx]
}
if(!$SeriesHeader) {$SeriesHeader="Series $($idx)"}
if (!$SeriesHeader) {$SeriesHeader="Series $($idx)"}
$Series.Header = $SeriesHeader
$SeriesHeader=$null
@@ -396,17 +422,17 @@ function Export-Excel {
}
}
if($ConditionalText) {
if ($ConditionalText) {
foreach ($targetConditionalText in $ConditionalText) {
$target = "Add$($targetConditionalText.ConditionalType)"
$Range=$targetConditionalText.Range
if(!$Range) { $Range=$ws.Dimension.Address }
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") {
if ($targetConditionalText.Text) {
if ($targetConditionalText.ConditionalType -match "equal|notequal|lessthan|lessthanorequal|greaterthan|greaterthanorequal") {
$rule.Formula= $targetConditionalText.Text
} else {
$rule.Text = $targetConditionalText.Text
@@ -419,19 +445,23 @@ function Export-Excel {
}
}
if($CellStyleSB) {
if ($CellStyleSB) {
$TotalRows=$ws.Dimension.Rows
$LastColumn=(Get-ExcelColumnName $ws.Dimension.Columns).ColumnName
& $CellStyleSB $ws $TotalRows $LastColumn
}
if($PassThru) {
if ($PassThru) {
$pkg
} else {
$pkg.Save()
$pkg.Dispose()
if($Show) {Invoke-Item $Path}
if ($Show) {Invoke-Item $Path}
}
}
Catch {
throw "Failed exporting the worksheet: $_"
}
}
}

View File

@@ -192,6 +192,7 @@ function Add-WorkSheet {
$ws = $ExcelPackage.Workbook.Worksheets[$WorkSheetname]
if(!$ws) {
Write-Verbose "Add worksheet '$WorkSheetname'"
$ws=$ExcelPackage.Workbook.Worksheets.Add($WorkSheetname)
}