From 378a20a094f4d62f08ad19a53a3f6a849e42c6d2 Mon Sep 17 00:00:00 2001 From: jhoneill Date: Wed, 5 Sep 2018 16:56:48 +0100 Subject: [PATCH] Further refinements to Conditional format, made new test more robust --- AddConditionalFormatting.ps1 | 7 +++--- Export-Excel.ps1 | 40 ++++++++++++++++---------------- README.md | 2 +- __tests__/First10Races.tests.ps1 | 36 ++++++++++++++-------------- 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/AddConditionalFormatting.ps1 b/AddConditionalFormatting.ps1 index aae3849..7e62935 100644 --- a/AddConditionalFormatting.ps1 +++ b/AddConditionalFormatting.ps1 @@ -168,10 +168,11 @@ if ($RuleType -match "Than|Equal|Between" ) { if ($ConditionValue) { $number = $Null + #if the condition type is not a value type, but parses as a number, make it the number if ($ConditionValue -isnot [System.ValueType] -and [Double]::TryParse($ConditionValue, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number) ) { $ConditionValue = $number - } - elseif (($ConditionValue -notmatch '^=') -and ($ConditionValue -notmatch '^".*"$') ) { + } #else if it is not a value type, or a formula, or wrapped in quotes, wrap it in quotes. + elseif (($ConditionValue -isnot [System.ValueType])-and ($ConditionValue -notmatch '^=') -and ($ConditionValue -notmatch '^".*"$') ) { $ConditionValue = '"' + $ConditionValue +'"' } } @@ -180,7 +181,7 @@ if ($ConditionValue -isnot [System.ValueType] -and [Double]::TryParse($ConditionValue2, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number) ) { $ConditionValue2 = $number } - elseif (($ConditionValue2 -notmatch '^=') -and ($ConditionValue2 -notmatch '^".*"$') ) { + elseif (($ConditionValue -isnot [System.ValueType]) -and ($ConditionValue2 -notmatch '^=') -and ($ConditionValue2 -notmatch '^".*"$') ) { $ConditionValue2 = '"' + $ConditionValue2 + '"' } } diff --git a/Export-Excel.ps1 b/Export-Excel.ps1 index e19881a..07636a9 100644 --- a/Export-Excel.ps1 +++ b/Export-Excel.ps1 @@ -594,16 +594,6 @@ } } catch {throw "Could not get worksheet $worksheetname"} - try { - foreach ($format in $ConditionalFormat ) { - switch ($format.formatter) { - "ThreeIconSet" {Add-ConditionalFormatting -WorkSheet $ws -ThreeIconsSet $format.IconType -range $format.range -reverse:$format.reverse } - "FourIconSet" {Add-ConditionalFormatting -WorkSheet $ws -FourIconsSet $format.IconType -range $format.range -reverse:$format.reverse } - "FiveIconSet" {Add-ConditionalFormatting -WorkSheet $ws -FiveIconsSet $format.IconType -range $format.range -reverse:$format.reverse } - } - } - } - catch {throw "Error applying confitional formatting to worksheet"} try { if ($Append -and $ws.Dimension) { #if there is a title or anything else above the header row, append needs to be combined wih a suitable startrow parameter @@ -961,20 +951,30 @@ Add-ExcelChart -Worksheet $ws @params } } - - foreach ($ct in $ConditionalText) { + # It now doesn't matter if the conditional formating rules are passed in $conditionalText or $conditional format. + # Just one with an alias for compatiblity it will break things for people who are using both at once + foreach ($c in (@() + $ConditionalText + $ConditionalFormat) ) { try { - $cfParams = @{RuleType = $ct.ConditionalType; ConditionValue = $ct.text ; - BackgroundColor = $ct.BackgroundColor; BackgroundPattern = $ct.PatternType ; - ForeGroundColor = $ct.ConditionalTextColor + if ($c.ConditionalType) { + $cfParams = @{RuleType = $c.ConditionalType; ConditionValue = $c.Text ; + BackgroundColor = $c.BackgroundColor; BackgroundPattern = $c.PatternType ; + ForeGroundColor = $c.ConditionalTextColor} + if ($c.Range) {$cfParams.Range = $c.Range} + else {$cfParams.Range = $ws.Dimension.Address } + Add-ConditionalFormatting -WorkSheet $ws @cfParams + Write-Verbose -Message "Added conditional formatting to range $($c.range)" + } + elseif ($c.formatter) { + switch ($c.formatter) { + "ThreeIconSet" {Add-ConditionalFormatting -WorkSheet $ws -ThreeIconsSet $c.IconType -range $c.range -reverse:$c.reverse } + "FourIconSet" {Add-ConditionalFormatting -WorkSheet $ws -FourIconsSet $c.IconType -range $c.range -reverse:$c.reverse } + "FiveIconSet" {Add-ConditionalFormatting -WorkSheet $ws -FiveIconsSet $c.IconType -range $c.range -reverse:$c.reverse } + } + Write-Verbose -Message "Added conditional formatting to range $($c.range)" } - if ($ct.Range) {$cfParams.range = $ct.range} else { $cfParams.Range = $ws.Dimension.Address } - Add-ConditionalFormatting -WorkSheet $ws @cfParams - Write-Verbose -Message "Added conditional formatting to range $($ct.range)" } - catch {Write-Warning -Message "Failed adding conditional formatting to worksheet '$WorksheetName': $_"} + catch {throw "Error applying confitional formatting to worksheet $_"} } - if ($CellStyleSB) { try { $TotalRows = $ws.Dimension.Rows diff --git a/README.md b/README.md index b4f313d..c26604d 100644 --- a/README.md +++ b/README.md @@ -52,7 +52,7 @@ Install-Module ImportExcel -scope CurrentUser Install-Module ImportExcel ``` - Lots of help improvements. -- Conditional formatting can now support named ranges, and booleans in the as a condition. +- Conditional formatting can now support named ranges, and booleans in the sheet as a condition. Also brought the two different kinds together inside export-excel - Improved handling of hyperlinks. - Moved logic for adding a named range out of Export-Excel and into new function named Add-ExcelName, and for adding a table into a function named Add-Excel table; this is to make it easier to do these things independently of Export-Excel but minimize duplication. Add-Table command can now toggle the options from table tools toolbar (show totals etc) - Fixed issues where formatting could be reset when using Export-Excel to manipulate an existing sheet without appending data; this applied to number formats and tables. diff --git a/__tests__/First10Races.tests.ps1 b/__tests__/First10Races.tests.ps1 index c9e2f64..4ce05b1 100644 --- a/__tests__/First10Races.tests.ps1 +++ b/__tests__/First10Races.tests.ps1 @@ -1,15 +1,17 @@ -Describe "Creating small named ranges with hyperlinks" { +$scriptPath = Split-Path -Path $MyInvocation.MyCommand.path -Parent +$dataPath = Join-Path -Path $scriptPath -ChildPath "First10Races.csv" + +Describe "Creating small named ranges with hyperlinks" { BeforeAll { $path = "$env:TEMP\Results.xlsx" - Remove-Item -Path $path -ErrorAction SilentlyContinue - - #Read race results, and group by race name : export 1 row to get headers, leaving enough rows aboce to put in a link for each race - $results = Import-Csv -Path .\First10Races.csv | Group-Object -Property RACE + Remove-Item -Path $path -ErrorAction SilentlyContinue + #Read race results, and group by race name : export 1 row to get headers, leaving enough rows aboce to put in a link for each race + $results = Import-Csv -Path $dataPath | Group-Object -Property RACE $topRow = $lastDataRow = 1 + $results.Count - $excel = $results[0].Group[0] | Export-Excel -Path $path -StartRow $TopRow -BoldTopRow -PassThru + $excel = $results[0].Group[0] | Export-Excel -Path $path -StartRow $TopRow -BoldTopRow -PassThru - #export each group (race) below the last one, without headers, and create a range for each using the group name (Race) - foreach ($r in $results) { + #export each group (race) below the last one, without headers, and create a range for each using the group name (Race) + foreach ($r in $results) { $excel = $R.Group | Export-Excel -ExcelPackage $excel -NoHeader -StartRow ($lastDataRow +1) -RangeName $R.Name -PassThru -AutoSize $lastDataRow += $R.Group.Count } @@ -18,12 +20,12 @@ 1..$columns | foreach {Add-ExcelName -Range $worksheet.cells[$topRow,$_,$lastDataRow,$_]} - $scwarnVar = $null + $scwarnVar = $null Set-Column -Worksheet $worksheet -StartRow $topRow -Heading "PlacesGained/Lost" -Value "=GridPostion-FinishPosition" -AutoNameRange -WarningVariable scWarnVar -WarningAction SilentlyContinue $columns ++ - #create a table which covers all the data. And define a pivot table which uses the same address range. - $table = Add-ExcelTable -PassThru -Range $worksheet.cells[$topRow,1,$lastDataRow,$columns] -TableName "AllResults" -TableStyle Light7 -ShowHeader -ShowFilter -ShowColumnStripes -ShowRowStripes:$false -ShowFirstColumn:$false -ShowLastColumn:$false -ShowTotal:$false + #create a table which covers all the data. And define a pivot table which uses the same address range. + $table = Add-ExcelTable -PassThru -Range $worksheet.cells[$topRow,1,$lastDataRow,$columns] -TableName "AllResults" -TableStyle Light7 -ShowHeader -ShowFilter -ShowColumnStripes -ShowRowStripes:$false -ShowFirstColumn:$false -ShowLastColumn:$false -ShowTotal:$false $pt = New-PivotTableDefinition -PivotTableName Analysis -SourceWorkSheet $worksheet -SourceRange $table.address.address -PivotRows Driver -PivotData @{Points="SUM"} -PivotTotals None $cf = Add-ConditionalFormatting -Address $worksheet.cells[$topRow,$columns,$lastDataRow,$columns] -ThreeIconsSet Arrows -Passthru @@ -31,14 +33,14 @@ $cf.Icon2.Value = 0 $cf.Icon3.Value = 1 Add-ConditionalFormatting -Address $worksheet.cells["FinishPosition"] -RuleType Equal -ConditionValue 1 -ForeGroundColor Purple -Bold -Priority 1 -StopIfTrue - + $ct = New-ConditionalText -Text "Ferrari" - $ct2 = New-ConditionalText -Range $worksheet.Names["FinishPosition"].Address -ConditionalType LessThanOrEqual -Text 3 -ConditionalTextColor Red -BackgroundColor White + $ct2 = New-ConditionalText -Range $worksheet.Names["FinishPosition"].Address -ConditionalType LessThanOrEqual -Text 3 -ConditionalTextColor Red -BackgroundColor White #Create links for each group name (race) and Export them so they start at Cell A1; create a pivot table with definition just created, save the file and open in Excel - $results | foreach {(New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList "Sheet1!$($_.Name)" , "$($_.name) GP")} | + $results | foreach {(New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList "Sheet1!$($_.Name)" , "$($_.name) GP")} | Export-Excel -ExcelPackage $excel -AutoSize -PivotTableDefinition $pt -Calculate -Conditionaltext $ct,$ct2 - $excel = Open-ExcelPackage $path + $excel = Open-ExcelPackage $path $sheet = $excel.Workbook.Worksheets[1] $m = $results | measure -sum -Property count $expectedRows = 1 + $m.count + $m.sum @@ -51,7 +53,7 @@ $sheet.Names[$results[0].Name] | should not benullorEmpty $sheet.Names[$results[-1].Name] | should not benullorEmpty } - it "Added hyperlinks to the named ranges " { + it "Added hyperlinks to the named ranges " { $sheet.cells["a1"].Hyperlink.Display | should match $results[0].Name $sheet.cells["a1"].Hyperlink.ReferenceAddress | should match $results[0].Name } @@ -66,7 +68,7 @@ It "Performed the calculation " { $placesMade = $Sheet.Cells[(2+$results.Count),5].value - $Sheet.Cells[(2+$results.Count),3].value $sheet.Cells[(2+$results.Count),$columns].value | Should be $placesmade - } + } It "Applied ConditionalFormatting, including stopifTrue and Priority " { $sheet.ConditionalFormatting[0].Address.Start.Column | should be $columns $sheet.ConditionalFormatting[0].Address.End.Column | should be $columns