Append, and formatting

Changed Export-Excel.ps1

#1 @ Line 197 Made new parameter sets . Default, and table already
existed and use path. Added DefaultPackage and TablePackage
A New parameter  "Package" allows an ExcelPackage object returned by
-passThru to be passed in
~Line 400 code to use package or path depending on path passed.

(also added Open-ExcelPackage  to get the object without exporting and
Close-ExcelPackage to close it nicely - these are in their own file)

#2.  @ Line 256 added new parameter excludeProperty to remove unwanted
properties without needing to go through select-object
~Line 459 added logic to exclude the properties specified in the new
parameter

#3 .  @ Line 262 Added new parameter Append
~Line 420 code to read the existing headers and move the insertion point
below the current data
(normal behaviour is to check if headers exist when adding data in the
process block, which makes this change wonderfully easy)
~Line 510 changed basis for identifying named ranges and changed scope
for rangeName so it can be used on other sheets

#4.  ~Line 550. Remove any existing Pivot table before trying to
[re]create it.

Added formatting.ps1 which applies conditional and normal formats -
requires an ExcelPackage to be open.

Added Open-ExcelPackage.ps1 (which contains a close function as well to
get the the object and save it )  open allows the sheet to be loaded
into a package object without needing to export .

Updated .psm1 to add the formating and open/close ps1 files.
This commit is contained in:
jhoneill
2017-10-21 18:14:02 +01:00
parent 954ed8d736
commit bd40cfe829
4 changed files with 328 additions and 35 deletions

View File

@@ -1,4 +1,4 @@
Function Export-Excel {
Function Export-Excel {
<#
.SYNOPSIS
Export data to an Excel worksheet.
@@ -196,8 +196,13 @@ Function Export-Excel {
[CmdletBinding(DefaultParameterSetName = 'Default')]
Param(
$Path,
[Parameter(ValueFromPipeline = $true)]
[Parameter(Mandatory=$true,ParameterSetName="Default",Position=0)]
[Parameter(Mandatory=$true,ParameterSetName="Table" ,Position=0)]
[String]$Path,
[Parameter(Mandatory=$true,ParameterSetName="PackageDefault")]
[Parameter(Mandatory=$true,ParameterSetName="PackageTable")]
[OfficeOpenXml.ExcelPackage]$ExcelPackage,
[Parameter(ValueFromPipeline=$true)]
$TargetData,
[String]$WorkSheetname = 'Sheet1',
[String]$Title,
@@ -225,6 +230,7 @@ Function Export-Excel {
[Switch]$FreezeTopRowFirstColumn,
[Int[]]$FreezePane,
[Parameter(ParameterSetName = 'Default')]
[Parameter(ParameterSetName = 'PackageDefault')]
[Switch]$AutoFilter,
[Switch]$BoldTopRow,
[Switch]$NoHeader,
@@ -244,8 +250,10 @@ Function Export-Excel {
}
})]
[Parameter(ParameterSetName = 'Table')]
[Parameter(ParameterSetName = 'PackageTable')]
[String]$TableName,
[Parameter(ParameterSetName = 'Table')]
[Parameter(ParameterSetName = 'PackageTable')]
[OfficeOpenXml.Table.TableStyles]$TableStyle = 'Medium6',
[Object[]]$ExcelChartDefinition,
[String[]]$HideSheet,
@@ -255,11 +263,13 @@ Function Export-Excel {
[Int]$StartColumn = 1,
[Switch]$PassThru,
[String]$Numberformat = 'General',
[string[]]$ExcludeProperty,
[String[]]$NoNumberConversion,
[Object[]]$ConditionalFormat,
[Object[]]$ConditionalText,
[ScriptBlock]$CellStyleSB,
[Switch]$Now
[Switch]$Now,
[switch]$Append
)
Begin {
@@ -354,7 +364,7 @@ Function Export-Excel {
if ($TitleBackgroundColor -AND ($TitleFillPattern -ne 'None')) {
$ws.Cells[$Row, $StartColumn].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor)
}
else {
elseif ($TitleBackgroundColor) {
Write-Warning "Title Background Color ignored. You must set the TitleFillPattern parameter to a value other than 'None'. Try 'Solid'."
}
}
@@ -403,35 +413,52 @@ Function Export-Excel {
}
}
$Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
if ($ExcelPackage) {
$pkg = $ExcelPackage
$Path = $pkg.File
}
Else {
$Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
if (Test-Path $Path) {
Write-Debug "Path '$Path' already exists"
}
$pkg = New-Object OfficeOpenXml.ExcelPackage $Path
$ws = $pkg | Add-WorkSheet -WorkSheetname $WorkSheetname -NoClobber:$NoClobber
if (Test-Path $Path) {
Write-Debug "Path '$Path' already exists"
}
$pkg = New-Object OfficeOpenXml.ExcelPackage $Path
}
[OfficeOpenXml.ExcelWorksheet]$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
}
$Row = $StartRow
if ($Title) {
Add-Title
$Row += 1
if ($append) {
$headerRange = $ws.Dimension.Address -replace "\d+$","1"
#if there is a title or anything else above the header row, specifying StartRow will skip it.
if ($StartRow -ne 1) {$headerRange = $headerRange -replace "1","$StartRow"}
$script:Header = $ws.Cells[$headerrange].Value
$row = $ws.Dimension.Rows
Write-Debug -Message ("Appending: headers are " + ($script:Header -join ", ") + "Start row $row")
}
elseif($Title) { #Can only add a title if not appending
$Row = $StartRow
Add-Title
$Row ++
}
else {
$Row = $StartRow
}
$ColumnIndex = $StartColumn
$firstTimeThru = $true
$isDataTypeValueType = $false
$pattern = 'string|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ulong|ushort'
}
Catch {
if ($AlreadyExists) {
if ($AlreadyExists) { #Is this set anywhere ?
throw "Failed exporting worksheet '$WorkSheetname' to '$Path': The worksheet '$WorkSheetname' already exists."
}
else {
@@ -460,7 +487,7 @@ Function Export-Excel {
#region Add headers
if (-not $script:Header) {
$ColumnIndex = $StartColumn
$script:Header = $TargetData.PSObject.Properties.Name
$script:Header = $TargetData.PSObject.Properties.Name | Where-Object {$_ -notin $ExcludeProperty}
if ($NoHeader) {
# Don't push the headers to the spread sheet
@@ -536,7 +563,9 @@ Function Export-Excel {
$cer = $ws.Dimension.End.Row
$cec = $script:Header.Count
$targetRange = $ws.Cells[$csr, $csc, $cer, $cec]
$targetRange = $ws.Cells[$csr, $csc, $cer, $cec]
#if we're appending data the table may already exist: but excel doesn't like the result if I put
# if ($ws.Tables[$TableName]) {$ws.Tables.Delete($TableName) }
$tbl = $ws.Tables.Add($targetRange, $TableName)
$tbl.TableStyle = $TableStyle
}
@@ -545,6 +574,8 @@ Function Export-Excel {
foreach ($item in $PivotTableDefinition.GetEnumerator()) {
$targetName = $item.Key
$pivotTableName = $targetName #+ 'PivotTable'
#Make sure the Pivot table sheet doesn't already exist
try { $pkg.Workbook.Worksheets.Delete( $pivotTableName) } catch {}
$wsPivot = $pkg | Add-WorkSheet -WorkSheetname $pivotTableName -NoClobber:$NoClobber
$pivotTableDataName = $targetName + 'PivotTableData'
@@ -611,6 +642,8 @@ Function Export-Excel {
if ($IncludePivotTable) {
$pivotTableName = $WorkSheetname + 'PivotTable'
#Make sure the Pivot table sheet doesn't already exist
try { $pkg.Workbook.Worksheets.Delete( $pivotTableName) } catch {}
$wsPivot = $pkg | Add-WorkSheet -WorkSheetname $pivotTableName -NoClobber:$NoClobber
$wsPivot.View.TabSelected = $true

View File

@@ -1,4 +1,4 @@
Add-Type -Path "$($PSScriptRoot)\EPPlus.dll"
Add-Type -Path "$($PSScriptRoot)\EPPlus.dll"
. $PSScriptRoot\Charting.ps1
. $PSScriptRoot\ConvertFromExcelData.ps1
@@ -7,6 +7,7 @@ Add-Type -Path "$($PSScriptRoot)\EPPlus.dll"
. $PSScriptRoot\Copy-ExcelWorkSheet.ps1
. $PSScriptRoot\Export-Excel.ps1
. $PSScriptRoot\Export-ExcelSheet.ps1
. $PSScriptRoot\Formatting.ps1
. $PSScriptRoot\Get-ExcelColumnName.ps1
. $PSScriptRoot\Get-ExcelSheetInfo.ps1
. $PSScriptRoot\Get-ExcelWorkbookInfo.ps1
@@ -20,16 +21,20 @@ Add-Type -Path "$($PSScriptRoot)\EPPlus.dll"
. $PSScriptRoot\New-ConditionalText.ps1
. $PSScriptRoot\New-ExcelChart.ps1
. $PSScriptRoot\New-PSItem.ps1
. $PSScriptRoot\Open-ExcelPackage.ps1
. $PSScriptRoot\Pivot.ps1
. $PSScriptRoot\Set-CellStyle.ps1
. $PSScriptRoot\TrackingUtils.ps1
. $PSScriptRoot\Update-FirstObjectProperties.ps1
if ($PSVersionTable.PSVersion.Major -ge 5) {
. $PSScriptRoot\Plot.ps1
Function New-Plot {
[OutputType([PSPlot])]
Param()
[PSPlot]::new()
}
@@ -46,11 +51,11 @@ Function Import-Excel {
Create custom objects from the rows in an Excel worksheet.
.DESCRIPTION
The Import-Excel cmdlet creates custom objects from the rows in an Excel worksheet. Each row represents one object. All of this is possible without installing Microsoft Excel and by using the .NET library <EFBFBD>EPPLus.dll<EFBFBD>.
The Import-Excel cmdlet creates custom objects from the rows in an Excel worksheet. Each row represents one object. All of this is possible without installing Microsoft Excel and by using the .NET library EPPLus.dll.
By default, the property names of the objects are retrieved from the column headers. Because an object cannot have a blanc property name, only columns with column headers will be imported.
If the default behavior is not desired and you want to import the complete worksheet <EFBFBD>as is<EFBFBD>, the parameter <EFBFBD>-NoHeader<EFBFBD> can be used. In case you want to provide your own property names, you can use the parameter <EFBFBD>-HeaderName<EFBFBD>.
If the default behavior is not desired and you want to import the complete worksheet as is, the parameter -NoHeader can be used. In case you want to provide your own property names, you can use the parameter -HeaderName.
.PARAMETER Path
Specifies the path to the Excel file.
@@ -71,18 +76,18 @@ Function Import-Excel {
.PARAMETER NoHeader
Automatically generate property names (P1, P2, P3, ..) instead of the ones defined in the column headers of the TopRow.
This switch is best used when you want to import the complete worksheet <EFBFBD>as is<EFBFBD> and are not concerned with the property names.
This switch is best used when you want to import the complete worksheet as is and are not concerned with the property names.
.PARAMETER StartRow
The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row.
When the parameters <EFBFBD>-NoHeader<EFBFBD> and <EFBFBD>-HeaderName<EFBFBD> are not provided, this row will contain the column headers that will be used as property names. When one of both parameters are provided, the property names are automatically created and this row will be treated as a regular row containing data.
When the parameters -NoHeader and -HeaderName are not provided, this row will contain the column headers that will be used as property names. When one of both parameters are provided, the property names are automatically created and this row will be treated as a regular row containing data.
.PARAMETER Password
Accepts a string that will be used to open a password protected Excel file.
.EXAMPLE
Import data from an Excel worksheet. One object is created for each row. The property names of the objects consist of the column names defined in the first row. In case a column doesn<EFBFBD>t have a column header (usually in row 1 when <EFBFBD>-StartRow<EFBFBD> is not used), then the unnamed columns will be skipped and the data in those columns will not be imported.
Import data from an Excel worksheet. One object is created for each row. The property names of the objects consist of the column names defined in the first row. In case a column doesnt have a column header (usually in row 1 when -StartRow is not used), then the unnamed columns will be skipped and the data in those columns will not be imported.
----------------------------------------------
| File: Movies.xlsx - Sheet: Actors |
@@ -104,7 +109,7 @@ Function Import-Excel {
Notice that column 'B' is not imported because there's no value in cell 'B1' that can be used as property name for the objects.
.EXAMPLE
Import the complete Excel worksheet <EFBFBD>as is<EFBFBD> by using the <EFBFBD>-NoHeader<EFBFBD> switch. One object is created for each row. The property names of the objects will be automatically generated (P1, P2, P3, ..).
Import the complete Excel worksheet as is by using the -NoHeader switch. One object is created for each row. The property names of the objects will be automatically generated (P1, P2, P3, ..).
----------------------------------------------
| File: Movies.xlsx - Sheet: Actors |
@@ -132,7 +137,7 @@ Function Import-Excel {
Notice that the column header (row 1) is imported as an object too.
.EXAMPLE
Import data from an Excel worksheet. One object is created for each row. The property names of the objects consist of the names defined in the parameter <EFBFBD>-HeaderName<EFBFBD>. The properties are named starting from the most left column (A) to the right. In case no value is present in one of the columns, that property will have an empty value.
Import data from an Excel worksheet. One object is created for each row. The property names of the objects consist of the names defined in the parameter -HeaderName. The properties are named starting from the most left column (A) to the right. In case no value is present in one of the columns, that property will have an empty value.
----------------------------------------------------------
| File: Movies.xlsx - Sheet: Movies |
@@ -169,7 +174,7 @@ Function Import-Excel {
Notice that empty rows are imported and that data for the property 'Genre' is not present in the worksheet. As such, the 'Genre' property will be blanc for all objects.
.EXAMPLE
Import data from an Excel worksheet. One object is created for each row. The property names of the objects are automatically generated by using the switch <EFBFBD>-NoHeader<EFBFBD> (P1, P@, P#, ..). The switch <EFBFBD>-DataOnly<EFBFBD> will speed up the import because empty rows and empty columns are not imported.
Import data from an Excel worksheet. One object is created for each row. The property names of the objects are automatically generated by using the switch -NoHeader (P1, P@, P#, ..). The switch -DataOnly will speed up the import because empty rows and empty columns are not imported.
----------------------------------------------------------
| File: Movies.xlsx - Sheet: Movies |
@@ -181,7 +186,7 @@ Function Import-Excel {
|4 Skyfall 2012 9 |
----------------------------------------------------------
PS C:\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Movies <EFBFBD>NoHeader -DataOnly
PS C:\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Movies NoHeader -DataOnly
P1: The Bodyguard
P2: 1992
@@ -198,7 +203,7 @@ Function Import-Excel {
Notice that empty rows and empty columns are not imported.
.EXAMPLE
Import data from an Excel worksheet. One object is created for each row. The property names are provided with the <EFBFBD>-HeaderName<EFBFBD> parameter. The import will start from row 2 and empty columns and rows are not imported.
Import data from an Excel worksheet. One object is created for each row. The property names are provided with the -HeaderName parameter. The import will start from row 2 and empty columns and rows are not imported.
----------------------------------------------------------
| File: Movies.xlsx - Sheet: Actors |
@@ -209,13 +214,13 @@ Function Import-Excel {
|3 Jean-Claude Vandamme Brussels |
----------------------------------------------------------
PS C:\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Actors -DataOnly -HeaderName 'FirstName', 'SecondName', 'City' <EFBFBD>StartRow 2
PS C:\> Import-Excel -Path 'C:\Movies.xlsx' -WorkSheetname Actors -DataOnly -HeaderName 'FirstName', 'SecondName', 'City' StartRow 2
FirstName : Jean-Claude
SecondName: Vandamme
City : Brussels
Notice that only 1 object is imported with only 3 properties. Column B and row 2 are empty and have been disregarded by using the switch '-DataOnly'. The property names have been named with the values provided with the parameter '-HeaderName'. Row number 1 with <EFBFBD>Chuck Norris<EFBFBD> has not been imported, because we started the import from row 2 with the parameter <EFBFBD>-StartRow 2<EFBFBD>.
Notice that only 1 object is imported with only 3 properties. Column B and row 2 are empty and have been disregarded by using the switch '-DataOnly'. The property names have been named with the values provided with the parameter '-HeaderName'. Row number 1 with Chuck Norris has not been imported, because we started the import from row 2 with the parameter -StartRow 2.
.LINK
https://github.com/dfinke/ImportExcel

50
Open-ExcelPackage.ps1 Normal file
View File

@@ -0,0 +1,50 @@
Function Open-ExcelPackage {
<#
.Synopsis
Returns an Excel Package Object with for the specified XLSX ile
.Example
$excel = Open-ExcelPackage -path $xlPath
$sheet1 = $excel.Workbook.Worksheets["sheet1"]
set-Format -Address $sheet1.Cells["E1:S1048576"], $sheet1.Cells["V1:V1048576"] -NFormat ([cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern)
close-ExcelPackage $excel -Show
This will open the file at $xlPath, select sheet1 apply formatting to two blocks of the sheet and close the package
#>
[OutputType([OfficeOpenXml.ExcelPackage])]
Param ([Parameter(Mandatory=$true)]$path,
[switch]$KillExcel)
if($KillExcel) {
Get-Process -Name "excel" -ErrorAction Ignore | Stop-Process
while (Get-Process -Name "excel" -ErrorAction Ignore) {}
}
$Path = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
if (Test-Path $path) {New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path }
Else {Write-Warning "Could not find $path" }
}
Function Close-ExcelPackage {
<#
.Synopsis
Closes an Excel Package, saving, saving under a new name or abandoning changes and opening the file as required
#>
Param (
#File to close
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
[OfficeOpenXml.ExcelPackage]$ExcelPackage,
#Open the file
[switch]$Show
#Abandon the file without saving
[Switch]$NoSave,
#Save file with a new name (ignored if -NoSaveSpecified)
$SaveAs,
)
if ( $NoSave) {$ExcelPackage.Dispose()}
else {
if ($SaveAs) {$ExcelPackage.SaveAs( $SaveAs ) }
Else {$ExcelPackage.Save(); $SaveAs = $ExcelPackage.File.FullName }
$ExcelPackage.Dispose()
if ($show) {Start-Process -FilePath $SaveAs }
}
}

205
formatting.ps1 Normal file
View File

@@ -0,0 +1,205 @@
Function Add-ConditionalFormatting {
<#
.Synopsis Adds contitional formatting to worksheet
.Example
$excel = $avdata | Export-Excel -Path (Join-path $FilePath "\Machines.XLSX" ) -WorksheetName "Server Anti-Virus" -AutoSize -FreezeTopRow -AutoFilter -PassThru
Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "b":b1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "2003"
Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "i2:i1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "Disabled"
$excel.Workbook.Worksheets[1].Cells["D1:G1048576"].Style.Numberformat.Format = [cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern
$excel.Workbook.Worksheets[1].Row(1).style.font.bold = $true
$excel.Save() ; $excel.Dispose()
Here Export-Excel is called with the -passThru parameter so the Excel Package object is stored in $Excel
The desired worksheet is selected and the then columns B and i are conditially formatted (excluding the top row) to show
Fixed formats are then applied to dates in columns D..G and the top row is formatted
Finally the workbook is saved and the Excel closed.
#>
Param (
[OfficeOpenXml.ExcelWorksheet]$WorkSheet ,
[OfficeOpenXml.ExcelAddress]$Range ,
[Parameter(Mandatory=$true,ParameterSetName="NamedRule",Position=3)]
[OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType]$RuleType ,
[Alias("ForeGroundColour")]
[System.Drawing.Color]$ForeGroundColor,
[Parameter(Mandatory=$true,ParameterSetName="DataBar")]
[Alias("DataBarColour")]
[System.Drawing.Color]$DataBarColor,
[Parameter(Mandatory=$true,ParameterSetName="ThreeIconSet")]
[OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting3IconsSetType]$ThreeIconsSet,
[Parameter(Mandatory=$true,ParameterSetName="FourIconSet")]
[OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting4IconsSetType]$FourIconsSet,
[Parameter(Mandatory=$true,ParameterSetName="FiveIconSet")]
[OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting5IconsSetType]$FiveIconsSet,
$ConditionValue,
$ConditionValue2,
[System.Drawing.Color]$BackgroundColor,
[OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern,
[System.Drawing.Color]$PatternColor,
$NumberFormat,
[switch]$Bold,
[switch]$Italic,
[switch]$Underline,
[switch]$StrikeThru
)
If ($ThreeIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddThreeIconSet($Range , $ThreeIconsSet)}
elseif ($FourIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddFourIconSet( $Range , $FourIconsSet) }
elseif ($FiveIconsSet) {$rule = $WorkSheet.ConditionalFormatting.AddFiveIconSet( $Range , $IconType) }
elseif ($DataBarColor) {$rule = $WorkSheet.ConditionalFormatting.AddDatabar( $Range , $DataBarColor) }
else { $rule = ($WorkSheet.ConditionalFormatting)."Add$RuleType"($Range)}
if ($ConditionValue -and $RuleType -match "Top|Botom") {$rule.Rank = $ConditionValue }
if ($ConditionValue -and $RuleType -match "StdDev") {$rule.StdDev = $ConditionValue }
if ($ConditionValue -and $RuleType -match "Than|Equal|Expression") {$rule.Formula = $ConditionValue }
if ($ConditionValue -and $RuleType -match "Text|With") {$rule.Text = $ConditionValue }
if ($ConditionValue -and
$ConditionValue2 -and $RuleType -match "Between") {$rule.Formula = $ConditionValue
$rule.Formula2 = $ConditionValue2}
$rule.Style.Font.Bold = $Bold
$rule.Style.Font.Italic = $Italic
$rule.Style.Font.Underline = $Underline
$rule.Style.Font.Strike = $StrikeThru
if ($ForeGroundColor) {$rule.Style.Font.Color = $ForeGroundColor}
if ($BackgroundColor) {$rule.Style.Fill.BackgroundColor = $BackgroundColor }
if ($BackgroundPattern) {$rule.Style.Fill.PatternType = $BackgroundPattern }
if ($PatternColor) {$rule.Style.Fill.PatternColor = $PatternColor}
if ($NumberFormat) {$rule.Style.NumberFormat.Format = $NumberFormat}
}
Function Set-Format {
Param (
#A row, Column or block of cells to format
[Parameter(ValueFromPipeline=$true)]
$Address ,
#Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc
[Alias("NFormat")]
$NumberFormat,
#Style of border to draw around the range
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround,
#Colour for the text - if none specified it will be left as it it is
[System.Drawing.Color]$FontColor,
#Clear Bold, Italic, StrikeThrough and Underline and set colour to black
[switch]$ResetFont,
#Make text bold
[switch]$Bold,
#Make text italic
[switch]$Italic,
#Underline the text using the underline style in -underline type
[switch]$Underline,
#Should Underline use single or double, normal or accounting mode : default is single normal
[OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single,
#StrikeThrough text
[switch]$StrikeThru,
#Subscript or superscript
[OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift,
#Font to use - Excel defaults to Calibri
[String]$FontName,
#Point size for the text
[float]$FontSize,
#Change background colour
[System.Drawing.Color]$BackgroundColor,
#Background pattern - solid by default
[OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern =[OfficeOpenXml.Style.ExcelFillStyle]::Solid ,
#Secondary colour for background pattern
[Alias("PatternColour")]
[System.Drawing.Color]$PatternColor,
#Turn on text wrapping
[switch]$WrapText,
#Position cell contents to left, right or centre ...
[OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment,
#Position cell contents to top bottom or centre
[OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment,
#Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise.
[ValidateRange(-90,90)]
[int]$TextRotation ,
#Autofit cells to width (columns or ranges only)
[switch]$AutoFit,
#Set cells to a fixed width (columns or ranges only), ignored if Autofit is specified
[float]$Width,
#Set cells to a fixed hieght (rows or ranges only)
[float]$Height,
#Hide a row or column (not a range)
[switch]$Hidden
)
process {
Foreach ($range in $Address) {
if ($ResetFont) {$Range.Style.Font.Color.SetColor("Black")
$Range.Style.Font.Bold = $false
$Range.Style.Font.Italic = $false
$Range.Style.Font.UnderLine = $false
$Range.Style.Font.Strike = $falsee
}
if ($Underline) {$Range.Style.Font.UnderLine = $true
$Range.Style.Font.UnderLineType =$UnderLineType
}
if ($Bold) {$Range.Style.Font.Bold = $true }
if ($Italic) {$Range.Style.Font.Italic = $true }
if ($StrikeThru) {$Range.Style.Font.Strike = $true }
if ($FontShift) {$Range.Style.Font.VerticalAlign = $FontShift }
if ($FontColor) {$Range.Style.Font.Color.SetColor( $FontColor ) }
if ($BorderRound) {$Range.Style.Border.BorderAround( $BorderAround ) }
if ($NumberFormat) {$Range.Style.Numberformat.Format= $NumberFormat }
if ($TextRotation) {$Range.Style.TextRotation = $TextRotation }
if ($WrapText) {$Range.Style.WrapText = $true }
if ($HorizontalAlignment) {$Range.Style.HorizontalAlignment= $HorizontalAlignment }
if ($VerticalAlignment) {$Range.Style.VerticalAlignment = $VerticalAlignment }
if ($BackgroundColor) {
$Range.Style.Fill.PatternType = $BackgroundPattern
$Range.Style.Fill.BackgroundColor.SetColor($BackgroundColor)
if ($PatternColor) {
$range.Style.Fill.PatternColor.SetColor( $PatternColor)
}
}
if ($Height) {
if ($Range -is [OfficeOpenXml.ExcelRow] ) {$Range.Height = $Height }
elseif ($Range -is [OfficeOpenXml.ExcelRange] ) {
($range.Start.Row)..($range.Start.Row + $range.Rows) |
ForEach-Object {$ws.Row($_).Height = $Height }
}
else {Write-Warning -Message ("Can set the height of a row or a range but not a {0} object" -f ($Range.GetType().name)) }
}
if ($AutoFit) {
if ($Range -is [OfficeOpenXml.ExcelColumn]) {$Range.AutoFit() }
elseif ($Range -is [OfficeOpenXml.ExcelRange] ) {$Range.AutoFitColumns() }
else {Write-Warning -Message ("Can autofit a column or a range but not a {0} object" -f ($Range.GetType().name)) }
}
elseif ($Width) {
if ($Range -is [OfficeOpenXml.ExcelColumn]) {$Range.Width = $Width}
elseif ($Range -is [OfficeOpenXml.ExcelRange] ) {
($range.Start.Column)..($range.Start.Column+ $range.Columns) |
ForEach-Object {$ws.Column($_).Width = $Width}
}
else {Write-Warning -Message ("Can set the width of a column or a range but not a {0} object" -f ($Range.GetType().name)) }
}
if ($Hidden) {
if ($Range -is [OfficeOpenXml.ExcelRow] -or
$Range -is [OfficeOpenXml.ExcelColumn] ) {$Range.Hidden = $True}
else {Write-Warning -Message ("Can hide a row or a column but not a {0} object" -f ($Range.GetType().name)) }
}
}
}
}
#Argument completer for colours. If we have PS 5 or Tab expansion++ then we'll register it. Otherwise it does nothing.
Function ColorCompletion{
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter)
[System.Drawing.KnownColor].GetFields() | Where-Object {$_.IsStatic -and $_.name -like "$wordToComplete*" } |
Sort-Object name | ForEach-Object {New-CompletionResult $_.name $_.name
}
}
if (Get-Command -Name register-argumentCompleter -ErrorAction SilentlyContinue) {
Register-ArgumentCompleter -CommandName Export-Excel -ParameterName TitleBackgroundColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Add-ConditionalFormatting -ParameterName ForeGroundColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Add-ConditionalFormatting -ParameterName DataBarColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Add-ConditionalFormatting -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Set-Format -ParameterName FontColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Set-Format -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Set-Format -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion
}