Clean-up of Set-Row/Column (value no long mandatory); support array formulas in set-format

This commit is contained in:
jhoneill
2018-08-16 17:33:44 +01:00
parent d770646dc7
commit 31e6eaf59b
4 changed files with 56 additions and 53 deletions

View File

@@ -51,7 +51,9 @@ Install-Module ImportExcel -scope CurrentUser
```PowerShell ```PowerShell
Install-Module ImportExcel Install-Module ImportExcel
``` ```
# New to Aug 15h # New to Aug 16th
- Value does not need to be mandatory in Set-Row or Set-Column, also tidied their paramters a little.
- Added support for array formulas in Set-Format (it really should be set range now that it sets values, formulas and hyperlinks - that can go on the to-do list )
- Fixed a bug with -Append in Export-Excel which caused it to overwrite the last row if the new data was a simple type. - Fixed a bug with -Append in Export-Excel which caused it to overwrite the last row if the new data was a simple type.
- NumberFormat in Export-Excel now sets the default for on a new / blank sheet; but [still] sets individual cells when adding to a sheet - NumberFormat in Export-Excel now sets the default for on a new / blank sheet; but [still] sets individual cells when adding to a sheet
- Added support for timespans in Export excel ; set as elapsed hours, mins, secs [h]:mm:sss - Added support for timespans in Export excel ; set as elapsed hours, mins, secs [h]:mm:sss

View File

@@ -20,16 +20,16 @@
#The sheet to update can be a given as a name or an Excel Worksheet object - this sets it by name #The sheet to update can be a given as a name or an Excel Worksheet object - this sets it by name
[Parameter(ParameterSetName="Package")] [Parameter(ParameterSetName="Package")]
#The sheet to update can be a given as a name or an Excel Worksheet object - $workSheet contains the object #The sheet to update can be a given as a name or an Excel Worksheet object - $workSheet contains the object
$Worksheetname = "Sheet1", [String]$Worksheetname = "Sheet1",
[Parameter(ParameterSetName="sheet",Mandatory=$true)] [Parameter(ParameterSetName="sheet",Mandatory=$true)]
[OfficeOpenXml.ExcelWorksheet] [OfficeOpenXml.ExcelWorksheet]$Worksheet,
$Worksheet,
#Column to fill down - first column is 1. 0 will be interpreted as first unused column #Column to fill down - first column is 1. 0 will be interpreted as first unused column
[ValidateRange(0,16384)]
$Column = 0 , $Column = 0 ,
#First row to fill data in #First row to fill data in
[ValidateRange(1,1048576)]
[Int]$StartRow , [Int]$StartRow ,
#value, formula or script block for to fill in. Script block can use $row, $column [number], $ColumnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn #value, formula or script block to fill in. Script block can use $row, $column [number], $columnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn
[parameter(Mandatory=$true)]
$Value , $Value ,
#Optional column heading #Optional column heading
$Heading , $Heading ,
@@ -41,15 +41,15 @@
#Colour for the text - if none specified it will be left as it it is #Colour for the text - if none specified it will be left as it it is
[System.Drawing.Color]$FontColor, [System.Drawing.Color]$FontColor,
#Make text bold; use -Bold:$false to remove bold #Make text bold; use -Bold:$false to remove bold
[switch]$Bold, [Switch]$Bold,
#Make text italic; use -Italic:$false to remove italic #Make text italic; use -Italic:$false to remove italic
[switch]$Italic, [Switch]$Italic,
#Underline the text using the underline style in -underline type; use -Underline:$false to remove underlining #Underline the text using the underline style in -underline type; use -Underline:$false to remove underlining
[switch]$Underline, [Switch]$Underline,
#Should Underline use single or double, normal or accounting mode : default is single normal #Should Underline use single or double, normal or accounting mode : default is single normal
[OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single,
#Strike through text; use -Strikethru:$false to remove Strike through #Strike through text; use -Strikethru:$false to remove Strike through
[switch]$StrikeThru, [Switch]$StrikeThru,
#Subscript or superscript (or none) #Subscript or superscript (or none)
[OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift,
#Font to use - Excel defaults to Calibri #Font to use - Excel defaults to Calibri
@@ -64,7 +64,7 @@
[Alias("PatternColour")] [Alias("PatternColour")]
[System.Drawing.Color]$PatternColor, [System.Drawing.Color]$PatternColor,
#Turn on text wrapping; use -WrapText:$false to turn off word wrapping #Turn on text wrapping; use -WrapText:$false to turn off word wrapping
[switch]$WrapText, [Switch]$WrapText,
#Position cell contents to left, right, center etc. default is 'General' #Position cell contents to left, right, center etc. default is 'General'
[OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment,
#Position cell contents to top bottom or centre #Position cell contents to top bottom or centre
@@ -80,31 +80,31 @@
#Set the inserted data to be a named range (ignored if header is not specified) #Set the inserted data to be a named range (ignored if header is not specified)
[Switch]$AutoNameRange, [Switch]$AutoNameRange,
#If Sepecified returns the range of cells which were affected #If Sepecified returns the range of cells which were affected
[switch]$ReturnRange, [Switch]$ReturnRange,
#If Specified, return an ExcelPackage object to allow further work to be done on the file. #If Specified, return an ExcelPackage object to allow further work to be done on the file.
[switch]$PassThru [Switch]$PassThru
) )
#if we were passed a package object and a worksheet name , get the worksheet. #if we were passed a package object and a worksheet name , get the worksheet.
if ($ExcelPackage) {$Worksheet = $ExcelPackage.Workbook.Worksheets[$Worksheetname] } if ($ExcelPackage) {$Worksheet = $ExcelPackage.Workbook.Worksheets[$Worksheetname] }
#In a script block to build a formula, we may want any of corners or the columnname, #In a script block to build a formula, we may want any of corners or the column name,
#if column and startrow aren't specified, assume first unused column, and first row #if Column and Startrow aren't specified, assume first unused column, and first row
if (-not $StartRow) {$startRow = $Worksheet.Dimension.Start.Row } if (-not $StartRow) {$startRow = $Worksheet.Dimension.Start.Row }
$startColumn = $Worksheet.Dimension.Start.Column $startColumn = $Worksheet.Dimension.Start.Column
$endColumn = $Worksheet.Dimension.End.Column $endColumn = $Worksheet.Dimension.End.Column
$endRow = $Worksheet.Dimension.End.Row $endRow = $Worksheet.Dimension.End.Row
if ($Column -lt 2 ) {$Column = $endColumn + 1 } if ($Column -eq 0 ) {$Column = $endColumn + 1 }
$ColumnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1","" $columnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1",""
Write-Verbose -Message "Updating Column $ColumnName" Write-Verbose -Message "Updating Column $columnName"
#If there is a heading, insert it and use it as the name for a range (if we're creating one) #If there is a heading, insert it and use it as the name for a range (if we're creating one)
if ($Heading) { if ($Heading) {
$Worksheet.Cells[$StartRow, $Column].Value = $heading $Worksheet.Cells[$StartRow, $Column].Value = $Heading
$startRow ++ $StartRow ++
if ($AutoNameRange) { $Worksheet.Names.Add( $heading, ($Worksheet.Cells[$startrow, $Column, $endRow, $Column]) ) | Out-Null } if ($AutoNameRange) { $Worksheet.Names.Add( $Heading, ($Worksheet.Cells[$StartRow, $Column, $endRow, $Column]) ) | Out-Null }
} }
#Fill in the data #Fill in the data
if ($PSBoundParameters.ContainsKey('value')) { foreach ($row in ($StartRow.. $endRow)) { if ($PSBoundParameters.ContainsKey('Value')) { foreach ($row in ($StartRow..$endRow)) {
if ($Value -is [scriptblock]) { #re-create the script block otherwise variables from this function are out of scope. if ($Value -is [scriptblock]) { #re-create the script block otherwise variables from this function are out of scope.
$cellData = & ([scriptblock]::create( $Value )) $cellData = & ([scriptblock]::create( $Value ))
Write-Verbose -Message $cellData Write-Verbose -Message $cellData
@@ -125,6 +125,7 @@
} }
else { $Worksheet.Cells[$Row, $Column].Value = $cellData } else { $Worksheet.Cells[$Row, $Column].Value = $cellData }
if ($cellData -is [datetime]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = 'm/d/yy h:mm' } # This is not a custom format, but a preset recognized as date and localized. if ($cellData -is [datetime]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = 'm/d/yy h:mm' } # This is not a custom format, but a preset recognized as date and localized.
if ($cellData -is [timespan]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = '[h]:mm:ss' }
}} }}
#region Apply formatting #region Apply formatting
$params = @{} $params = @{}
@@ -133,7 +134,7 @@
'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { 'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) {
if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]}
} }
$theRange = "$ColumnName$startRow`:$ColumnName$endRow" $theRange = "$columnName$StartRow`:$columnName$endRow"
if ($params.Count) { if ($params.Count) {
Set-Format -WorkSheet $Worksheet -Range $theRange @params Set-Format -WorkSheet $Worksheet -Range $theRange @params
} }

View File

@@ -25,15 +25,13 @@
[Parameter(ParameterSetName="Package")] [Parameter(ParameterSetName="Package")]
$Worksheetname = "Sheet1", $Worksheetname = "Sheet1",
#A worksheet object #A worksheet object
[Parameter(ParameterSetName="sheet",Mandatory=$true)] [Parameter(ParameterSetName="Sheet",Mandatory=$true)]
[OfficeOpenXml.Excelworksheet] [OfficeOpenXml.Excelworksheet] $Worksheet,
$Worksheet,
#Row to fill right - first row is 1. 0 will be interpreted as first unused row #Row to fill right - first row is 1. 0 will be interpreted as first unused row
$Row = 0 , $Row = 0 ,
#Position in the row to start from #Position in the row to start from
[Int]$StartColumn, [int]$StartColumn,
#value, formula or script block for to fill in. Script block can use $worksheet, $row, $column [number], $ColumnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn #Value, formula or script block to fill in. Script block can use $worksheet, $row, $Column [number], $ColumnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn
[parameter(Mandatory=$true)]
$Value, $Value,
#Optional Row heading #Optional Row heading
$Heading , $Heading ,
@@ -45,15 +43,15 @@
#Colour for the text - if none specified it will be left as it it is #Colour for the text - if none specified it will be left as it it is
[System.Drawing.Color]$FontColor, [System.Drawing.Color]$FontColor,
#Make text bold; use -Bold:$false to remove bold #Make text bold; use -Bold:$false to remove bold
[switch]$Bold, [Switch]$Bold,
#Make text italic; use -Italic:$false to remove italic #Make text italic; use -Italic:$false to remove italic
[switch]$Italic, [Switch]$Italic,
#Underline the text using the underline style in -underline type; use -Underline:$false to remove underlining #Underline the text using the underline style in -underline type; use -Underline:$false to remove underlining
[switch]$Underline, [Switch]$Underline,
#Should Underline use single or double, normal or accounting mode : default is single normal #Should Underline use single or double, normal or accounting mode : default is single normal
[OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single,
#Strike through text; use -Strikethru:$false to remove Strike through #Strike through text; use -Strikethru:$false to remove Strike through
[switch]$StrikeThru, [Switch]$StrikeThru,
#Subscript or superscript (or none) #Subscript or superscript (or none)
[OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift,
[String]$FontName, [String]$FontName,
@@ -67,7 +65,7 @@
[Alias("PatternColour")] [Alias("PatternColour")]
[System.Drawing.Color]$PatternColor, [System.Drawing.Color]$PatternColor,
#Turn on text wrapping; use -WrapText:$false to turn off word wrapping #Turn on text wrapping; use -WrapText:$false to turn off word wrapping
[switch]$WrapText, [Switch]$WrapText,
#Position cell contents to left, right, center etc. default is 'General' #Position cell contents to left, right, center etc. default is 'General'
[OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment,
#Position cell contents to top bottom or centre #Position cell contents to top bottom or centre
@@ -78,9 +76,9 @@
#Set cells to a fixed hieght #Set cells to a fixed hieght
[float]$Height, [float]$Height,
#If Sepecified returns the range of cells which were affected #If Sepecified returns the range of cells which were affected
[switch]$ReturnRange, [Switch]$ReturnRange,
#If Specified, return a row object to allow further work to be done #If Specified, return a row object to allow further work to be done
[switch]$PassThru [Switch]$PassThru
) )
#if we were passed a package object and a worksheet name , get the worksheet. #if we were passed a package object and a worksheet name , get the worksheet.
@@ -92,7 +90,7 @@
$startRow = $Worksheet.Dimension.Start.Row + 1 $startRow = $Worksheet.Dimension.Start.Row + 1
$endColumn = $Worksheet.Dimension.End.Column $endColumn = $Worksheet.Dimension.End.Column
$endRow = $Worksheet.Dimension.End.Row $endRow = $Worksheet.Dimension.End.Row
if ($Row -lt 2 ) {$Row = $endRow + 1 } if ($Row -eq 0 ) {$Row = $endRow + 1 }
Write-Verbose -Message "Updating Row $Row" Write-Verbose -Message "Updating Row $Row"
#Add a row label #Add a row label
if ($Heading) { if ($Heading) {
@@ -100,7 +98,7 @@
$StartColumn ++ $StartColumn ++
} }
#Fill in the data #Fill in the data
if ($PSBoundParameters.ContainsKey('Value')) {foreach ($column in ($StartColumn..$EndColumn)) { if ($PSBoundParameters.ContainsKey('Value')) {foreach ($column in ($StartColumn..$endColumn)) {
#We might want the column name in a script block #We might want the column name in a script block
$columnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1","" $columnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1",""
if ($Value -is [scriptblock] ) { if ($Value -is [scriptblock] ) {
@@ -124,6 +122,7 @@
} }
else { $Worksheet.Cells[$Row, $column].Value = $cellData } else { $Worksheet.Cells[$Row, $column].Value = $cellData }
if ($cellData -is [datetime]) { $Worksheet.Cells[$Row, $column].Style.Numberformat.Format = 'm/d/yy h:mm' } #This is not a custom format, but a preset recognized as date and localized. if ($cellData -is [datetime]) { $Worksheet.Cells[$Row, $column].Style.Numberformat.Format = 'm/d/yy h:mm' } #This is not a custom format, but a preset recognized as date and localized.
if ($cellData -is [timespan]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = '[h]:mm:ss' }
}} }}
#region Apply formatting #region Apply formatting
$params = @{} $params = @{}
@@ -132,7 +131,7 @@
'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { 'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) {
if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]}
} }
$theRange = [OfficeOpenXml.ExcelAddress]::New($Row, $StartColumn, $Row, $EndColumn) $theRange = [OfficeOpenXml.ExcelAddress]::New($Row, $StartColumn, $Row, $endColumn)
if ($params.Count) { if ($params.Count) {
Set-Format -WorkSheet $Worksheet -Range $theRange @params Set-Format -WorkSheet $Worksheet -Range $theRange @params
} }

View File

@@ -20,7 +20,7 @@
#The area of the worksheet where the format is to be applied #The area of the worksheet where the format is to be applied
[Parameter(ParameterSetName="SheetAndRange",Mandatory=$True)] [Parameter(ParameterSetName="SheetAndRange",Mandatory=$True)]
[OfficeOpenXml.ExcelAddress]$Range, [OfficeOpenXml.ExcelAddress]$Range,
#Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc #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")] [Alias("NFormat")]
$NumberFormat, $NumberFormat,
#Style of border to draw around the range #Style of border to draw around the range
@@ -36,18 +36,20 @@
$Value, $Value,
#Formula for the cell #Formula for the cell
$Formula, $Formula,
#Specifies formula should be an array formula (a.k.a CSE [ctrl-shift-enter] formula )
[Switch]$ArrayFormula,
#Clear Bold, Italic, StrikeThrough and Underline and set colour to black #Clear Bold, Italic, StrikeThrough and Underline and set colour to black
[switch]$ResetFont, [Switch]$ResetFont,
#Make text bold; use -Bold:$false to remove bold #Make text bold; use -Bold:$false to remove bold
[switch]$Bold, [Switch]$Bold,
#Make text italic; use -Italic:$false to remove italic #Make text italic; use -Italic:$false to remove italic
[switch]$Italic, [Switch]$Italic,
#Underline the text using the underline style in -underline type; use -Underline:$false to remove underlining #Underline the text using the underline style in -underline type; use -Underline:$false to remove underlining
[switch]$Underline, [Switch]$Underline,
#Should Underline use single or double, normal or accounting mode : default is single normal #Should Underline use single or double, normal or accounting mode : default is single normal
[OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single,
#Strike through text; use -Strikethru:$false to remove Strike through #Strike through text; use -Strikethru:$false to remove Strike through
[switch]$StrikeThru, [Switch]$StrikeThru,
#Subscript or superscript (or none) #Subscript or superscript (or none)
[OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift,
#Font to use - Excel defaults to Calibri #Font to use - Excel defaults to Calibri
@@ -62,7 +64,7 @@
[Alias("PatternColour")] [Alias("PatternColour")]
[System.Drawing.Color]$PatternColor, [System.Drawing.Color]$PatternColor,
#Turn on text wrapping; use -WrapText:$false to turn off word wrapping #Turn on text wrapping; use -WrapText:$false to turn off word wrapping
[switch]$WrapText, [Switch]$WrapText,
#Position cell contents to left, right, center etc. default is 'General' #Position cell contents to left, right, center etc. default is 'General'
[OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment,
#Position cell contents to top bottom or center #Position cell contents to top bottom or center
@@ -78,7 +80,7 @@
#Set cells to a fixed hieght (rows or ranges only) #Set cells to a fixed hieght (rows or ranges only)
[float]$Height, [float]$Height,
#Hide a row or column (not a range); use -Hidden:$false to unhide #Hide a row or column (not a range); use -Hidden:$false to unhide
[switch]$Hidden [Switch]$Hidden
) )
begin { begin {
#Allow Set-Format to take Worksheet and range parameters (like Add Contitional formatting) - convert them to an address #Allow Set-Format to take Worksheet and range parameters (like Add Contitional formatting) - convert them to an address
@@ -133,17 +135,16 @@
$Address.Style.VerticalAlignment = $VerticalAlignment $Address.Style.VerticalAlignment = $VerticalAlignment
} }
if ($PSBoundParameters.ContainsKey('Value')) { if ($PSBoundParameters.ContainsKey('Value')) {
if ($Value -like '=*') {$Address.Formula = ($Value -replace'^=','')} #EPPlus likes formulas with no = sign; Excel doesn't care if ($Value -like '=*') {$PSBoundParameters["Formula"] = $Value }
else { else {
$Address.Value = $Value $Address.Value = $Value
if ($Value -is [DateTime]) { if ($Value -is [datetime]) { $Address.Style.Numberformat.Format = 'm/d/yy h:mm' }# This is not a custom format, but a preset recognized as date and localized. It might be overwritten in a moment
$Address.Style.Numberformat.Format = 'm/d/yy h:mm' # This is not a custom format, but a preset recognized as date and localized. It might be overwritten in a moment if ($Value -is [timespan]) { $Address.Style.Numberformat.Format = '[h]:mm:ss' }
} }
} }
}
if ($PSBoundParameters.ContainsKey('Formula')) { if ($PSBoundParameters.ContainsKey('Formula')) {
$Address.Formula = ( $Formula -replace '^=','') if ($ArrayFormula) {$Address.CreateArrayFormula(($Formula -replace '^=','')) }
else {$Address.Formula = ($Formula -replace '^=','') }
} }
if ($PSBoundParameters.ContainsKey('NumberFormat')) { if ($PSBoundParameters.ContainsKey('NumberFormat')) {
$Address.Style.Numberformat.Format = (Expand-NumberFormat $NumberFormat) $Address.Style.Numberformat.Format = (Expand-NumberFormat $NumberFormat)