From 31e6eaf59b8d0611a81ea8ad990d0f162473a28a Mon Sep 17 00:00:00 2001 From: jhoneill Date: Thu, 16 Aug 2018 17:33:44 +0100 Subject: [PATCH] Clean-up of Set-Row/Column (value no long mandatory); support array formulas in set-format --- README.md | 4 +++- Set-Column.ps1 | 45 +++++++++++++++++++++++---------------------- Set-Row.ps1 | 31 +++++++++++++++---------------- SetFormat.ps1 | 29 +++++++++++++++-------------- 4 files changed, 56 insertions(+), 53 deletions(-) diff --git a/README.md b/README.md index bfcb991..e428a90 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,9 @@ Install-Module ImportExcel -scope CurrentUser ```PowerShell 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. - 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 diff --git a/Set-Column.ps1 b/Set-Column.ps1 index 9f8cdd7..bd060dc 100644 --- a/Set-Column.ps1 +++ b/Set-Column.ps1 @@ -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 [Parameter(ParameterSetName="Package")] #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)] - [OfficeOpenXml.ExcelWorksheet] - $Worksheet, + [OfficeOpenXml.ExcelWorksheet]$Worksheet, #Column to fill down - first column is 1. 0 will be interpreted as first unused column + [ValidateRange(0,16384)] $Column = 0 , #First row to fill data in + [ValidateRange(1,1048576)] [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 - [parameter(Mandatory=$true)] + #value, formula or script block to fill in. Script block can use $row, $column [number], $columnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn $Value , #Optional column heading $Heading , @@ -41,15 +41,15 @@ #Colour for the text - if none specified it will be left as it it is [System.Drawing.Color]$FontColor, #Make text bold; use -Bold:$false to remove bold - [switch]$Bold, + [Switch]$Bold, #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 - [switch]$Underline, + [Switch]$Underline, #Should Underline use single or double, normal or accounting mode : default is single normal [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, #Strike through text; use -Strikethru:$false to remove Strike through - [switch]$StrikeThru, + [Switch]$StrikeThru, #Subscript or superscript (or none) [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, #Font to use - Excel defaults to Calibri @@ -64,7 +64,7 @@ [Alias("PatternColour")] [System.Drawing.Color]$PatternColor, #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' [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, #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) [Switch]$AutoNameRange, #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. - [switch]$PassThru + [Switch]$PassThru ) #if we were passed a package object and a worksheet name , get the worksheet. if ($ExcelPackage) {$Worksheet = $ExcelPackage.Workbook.Worksheets[$Worksheetname] } - #In a script block to build a formula, we may want any of corners or the columnname, - #if column and startrow aren't specified, assume first unused column, and first row + #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 (-not $StartRow) {$startRow = $Worksheet.Dimension.Start.Row } $startColumn = $Worksheet.Dimension.Start.Column $endColumn = $Worksheet.Dimension.End.Column $endRow = $Worksheet.Dimension.End.Row - if ($Column -lt 2 ) {$Column = $endColumn + 1 } - $ColumnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1","" + if ($Column -eq 0 ) {$Column = $endColumn + 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 ($Heading) { - $Worksheet.Cells[$StartRow, $Column].Value = $heading - $startRow ++ - if ($AutoNameRange) { $Worksheet.Names.Add( $heading, ($Worksheet.Cells[$startrow, $Column, $endRow, $Column]) ) | Out-Null } + $Worksheet.Cells[$StartRow, $Column].Value = $Heading + $StartRow ++ + if ($AutoNameRange) { $Worksheet.Names.Add( $Heading, ($Worksheet.Cells[$StartRow, $Column, $endRow, $Column]) ) | Out-Null } } #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. $cellData = & ([scriptblock]::create( $Value )) Write-Verbose -Message $cellData @@ -125,6 +125,7 @@ } 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 [timespan]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = '[h]:mm:ss' } }} #region Apply formatting $params = @{} @@ -133,7 +134,7 @@ 'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} } - $theRange = "$ColumnName$startRow`:$ColumnName$endRow" + $theRange = "$columnName$StartRow`:$columnName$endRow" if ($params.Count) { Set-Format -WorkSheet $Worksheet -Range $theRange @params } diff --git a/Set-Row.ps1 b/Set-Row.ps1 index 12e8803..3db7881 100644 --- a/Set-Row.ps1 +++ b/Set-Row.ps1 @@ -25,15 +25,13 @@ [Parameter(ParameterSetName="Package")] $Worksheetname = "Sheet1", #A worksheet object - [Parameter(ParameterSetName="sheet",Mandatory=$true)] - [OfficeOpenXml.Excelworksheet] - $Worksheet, + [Parameter(ParameterSetName="Sheet",Mandatory=$true)] + [OfficeOpenXml.Excelworksheet] $Worksheet, #Row to fill right - first row is 1. 0 will be interpreted as first unused row $Row = 0 , #Position in the row to start from - [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 - [parameter(Mandatory=$true)] + [int]$StartColumn, + #Value, formula or script block to fill in. Script block can use $worksheet, $row, $Column [number], $ColumnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn $Value, #Optional Row heading $Heading , @@ -45,15 +43,15 @@ #Colour for the text - if none specified it will be left as it it is [System.Drawing.Color]$FontColor, #Make text bold; use -Bold:$false to remove bold - [switch]$Bold, + [Switch]$Bold, #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 - [switch]$Underline, + [Switch]$Underline, #Should Underline use single or double, normal or accounting mode : default is single normal [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, #Strike through text; use -Strikethru:$false to remove Strike through - [switch]$StrikeThru, + [Switch]$StrikeThru, #Subscript or superscript (or none) [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, [String]$FontName, @@ -67,7 +65,7 @@ [Alias("PatternColour")] [System.Drawing.Color]$PatternColor, #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' [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, #Position cell contents to top bottom or centre @@ -78,9 +76,9 @@ #Set cells to a fixed hieght [float]$Height, #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 - [switch]$PassThru + [Switch]$PassThru ) #if we were passed a package object and a worksheet name , get the worksheet. @@ -92,7 +90,7 @@ $startRow = $Worksheet.Dimension.Start.Row + 1 $endColumn = $Worksheet.Dimension.End.Column $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" #Add a row label if ($Heading) { @@ -100,7 +98,7 @@ $StartColumn ++ } #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 $columnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1","" if ($Value -is [scriptblock] ) { @@ -124,6 +122,7 @@ } 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 [timespan]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = '[h]:mm:ss' } }} #region Apply formatting $params = @{} @@ -132,7 +131,7 @@ 'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { 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) { Set-Format -WorkSheet $Worksheet -Range $theRange @params } diff --git a/SetFormat.ps1 b/SetFormat.ps1 index afc7d68..6dcb979 100644 --- a/SetFormat.ps1 +++ b/SetFormat.ps1 @@ -20,7 +20,7 @@ #The area of the worksheet where the format is to be applied [Parameter(ParameterSetName="SheetAndRange",Mandatory=$True)] [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")] $NumberFormat, #Style of border to draw around the range @@ -36,18 +36,20 @@ $Value, #Formula for the cell $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 - [switch]$ResetFont, + [Switch]$ResetFont, #Make text bold; use -Bold:$false to remove bold - [switch]$Bold, + [Switch]$Bold, #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 - [switch]$Underline, + [Switch]$Underline, #Should Underline use single or double, normal or accounting mode : default is single normal [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, #Strike through text; use -Strikethru:$false to remove Strike through - [switch]$StrikeThru, + [Switch]$StrikeThru, #Subscript or superscript (or none) [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, #Font to use - Excel defaults to Calibri @@ -62,7 +64,7 @@ [Alias("PatternColour")] [System.Drawing.Color]$PatternColor, #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' [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, #Position cell contents to top bottom or center @@ -78,7 +80,7 @@ #Set cells to a fixed hieght (rows or ranges only) [float]$Height, #Hide a row or column (not a range); use -Hidden:$false to unhide - [switch]$Hidden + [Switch]$Hidden ) begin { #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 } 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 { $Address.Value = $Value - 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 - } + 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 + if ($Value -is [timespan]) { $Address.Style.Numberformat.Format = '[h]:mm:ss' } } } - if ($PSBoundParameters.ContainsKey('Formula')) { - $Address.Formula = ( $Formula -replace '^=','') + if ($ArrayFormula) {$Address.CreateArrayFormula(($Formula -replace '^=','')) } + else {$Address.Formula = ($Formula -replace '^=','') } } if ($PSBoundParameters.ContainsKey('NumberFormat')) { $Address.Style.Numberformat.Format = (Expand-NumberFormat $NumberFormat)