mirror of
https://github.com/dfinke/ImportExcel.git
synced 2025-12-10 21:33:16 +00:00
Merge remote-tracking branch 'refs/remotes/origin/master' into dfinke/master
This commit is contained in:
184
Export-Excel.ps1
184
Export-Excel.ps1
@@ -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: $_"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user