diff --git a/Export-Excel.ps1 b/Export-Excel.ps1 index 0747249..1faa3a9 100644 --- a/Export-Excel.ps1 +++ b/Export-Excel.ps1 @@ -362,8 +362,8 @@ .LINK https://github.com/dfinke/ImportExcel #> - [CmdletBinding(DefaultParameterSetName = 'Default')] + [OutputType([OfficeOpenXml.ExcelPackage])] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] Param( [Parameter(ParameterSetName = "Default", Position = 0)] @@ -1209,7 +1209,8 @@ Function Add-ExcelName { function Add-ExcelTable { [CmdletBinding()] - <# + [OutputType([OfficeOpenXml.Table.ExcelTable])] + <# .SYNOPSIS Adds Tables to Excel workbooks. .DESCRIPTION @@ -1271,7 +1272,6 @@ function Add-ExcelTable { Write-Verbose -Message "Defined table '$TableName' at $($Range.Address)" } #it seems that show total changes some of the others, so the sequence matters. - if ($PSBoundParameters.ContainsKey('TableStyle')) {$tbl.TableStyle = $TableStyle} if ($PSBoundParameters.ContainsKey('ShowHeader')) {$tbl.ShowHeader = [bool]$ShowHeader} if ($PSBoundParameters.ContainsKey('ShowTotal')) {$tbl.ShowTotal = [bool]$ShowTotal} if ($PSBoundParameters.ContainsKey('ShowFilter')) {$tbl.ShowFilter = [bool]$ShowFilter} @@ -1279,6 +1279,7 @@ function Add-ExcelTable { if ($PSBoundParameters.ContainsKey('ShowLastColumn')) {$tbl.ShowLastColumn = [bool]$ShowLastColumn} if ($PSBoundParameters.ContainsKey('ShowRowStripes')) {$tbl.ShowRowStripes = [bool]$ShowRowStripes} if ($PSBoundParameters.ContainsKey('ShowColumnStripes')) {$tbl.ShowColumnStripes = [bool]$ShowColumnStripes} + if ($PSBoundParameters.ContainsKey('TableStyle')) {$tbl.TableStyle = $TableStyle} if ($PassThru) {return $tbl} } catch {Write-Warning -Message "Failed adding table '$TableName' to worksheet '$WorksheetName': $_"} diff --git a/README.md b/README.md index d2437eb..3dfb113 100644 --- a/README.md +++ b/README.md @@ -51,13 +51,13 @@ Install-Module ImportExcel -scope CurrentUser ```PowerShell Install-Module ImportExcel ``` -- Improved handling of hyperlinks. [To do write example] +- 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. - Moved PivotTable Functions out of Export-Excel.PS1 into their own file and moved Add-ExcelChart out of Export-Excel.ps1 into New-ExcelChart.ps1 - in Export-Excel there is better checking of Table and PivotTable names (for uniqueness) and a new test in quick charts that there is suitable data for charting. - in New-ConditionalText, more types of conditional format are supported, and conditionalTextColor now has an argument completer -- in Add-ConditionalFormatting: improved parameter intellisense and now wrap those strings which need it in quotes (for = <= >= string needs to be in double quotes), added StopIfTrue and Priority Parameters [to do tests for these] +- in Add-ConditionalFormatting: improved parameter intellisense and now wrap those strings which need it in quotes (for = <= >= string needs to be in double quotes), added StopIfTrue and Priority Parameters - in New-ExcelChartDefinition: Legend parameters (for size, bold & position ) are now supported - Add-ExcelChart now supports -PassThru to return the chart for tweaking after creation; there is now a -PivotTable parameter to allow Add-PivotTable to call the code in Add-ExcelChart - in Add-PivotTable: chart creation has been moved out to Add-ExcelChart. -PassThru returns the pivot table (e.g. to allow names /sort orders of data series to be tweaked ) -Address parameter allows Pivot to be placed on an existing sheet; -PivotTableStyle allows a change from "Medium6", -PivotNumberFormat sets data cells and -PivotChartDefinition allows a defintion created with New-ExcelChartDefinition to be used. This opens up all the things that Add-Excel chart can do without duplicating the parameters on Add-Pivot table and Export-Excel. Definition, TableStyle, Numberformat and ChartDefiniton can be used in New-PivotTableDefinition . diff --git a/__tests__/First10Races.csv b/__tests__/First10Races.csv new file mode 100644 index 0000000..014ca5b --- /dev/null +++ b/__tests__/First10Races.csv @@ -0,0 +1,101 @@ +Race,Date,FinishPosition,Driver,GridPostion,Team,Points +Australian,25/03/2018,1,Sebastian Vettel,3,Ferrari,25 +Australian,25/03/2018,2,Lewis Hamilton,1,Mercedes,18 +Australian,25/03/2018,3,Kimi Räikkönen,2,Ferrari,15 +Australian,25/03/2018,4,Daniel Ricciardo,8,Red Bull Racing-TAG Heuer,12 +Australian,25/03/2018,5,Fernando Alonso,10,McLaren-Renault,10 +Australian,25/03/2018,6,Max Verstappen,4,Red Bull Racing-TAG Heuer,8 +Australian,25/03/2018,7,Nico Hülkenberg,7,Renault,6 +Australian,25/03/2018,8,Valtteri Bottas,15,Mercedes,4 +Australian,25/03/2018,9,Stoffel Vandoorne,11,McLaren-Renault,2 +Australian,25/03/2018,10,Carlos Sainz,9,Renault,1 +Bahrain,08/04/2018,1,Sebastian Vettel,1,Ferrari,25 +Bahrain,08/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Bahrain,08/04/2018,3,Lewis Hamilton,9,Mercedes,15 +Bahrain,08/04/2018,4,Pierre Gasly,5,STR-Honda,12 +Bahrain,08/04/2018,5,Kevin Magnussen,6,Haas-Ferrari,10 +Bahrain,08/04/2018,6,Nico Hülkenberg,7,Renault,8 +Bahrain,08/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Bahrain,08/04/2018,8,Stoffel Vandoorne,14,McLaren-Renault,4 +Bahrain,08/04/2018,9,Marcus Ericsson,17,Sauber-Ferrari,2 +Bahrain,08/04/2018,10,Esteban Ocon,8,Force India-Mercedes,1 +Chinese,15/04/2018,1,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,25 +Chinese,15/04/2018,2,Valtteri Bottas,3,Mercedes,18 +Chinese,15/04/2018,3,Kimi Räikkönen,2,Ferrari,15 +Chinese,15/04/2018,4,Lewis Hamilton,4,Mercedes,12 +Chinese,15/04/2018,5,Max Verstappen,5,Red Bull Racing-TAG Heuer,10 +Chinese,15/04/2018,6,Nico Hülkenberg,7,Renault,8 +Chinese,15/04/2018,7,Fernando Alonso,13,McLaren-Renault,6 +Chinese,15/04/2018,8,Sebastian Vettel,1,Ferrari,4 +Chinese,15/04/2018,9,Carlos Sainz,9,Renault,2 +Chinese,15/04/2018,10,Kevin Magnussen,11,Haas-Ferrari,1 +Azerbaijan,29/04/2018,1,Lewis Hamilton,2,Mercedes,25 +Azerbaijan,29/04/2018,2,Kimi Räikkönen,6,Ferrari,18 +Azerbaijan,29/04/2018,3,Sergio Pérez,8,Force India-Mercedes,15 +Azerbaijan,29/04/2018,4,Sebastian Vettel,1,Ferrari,12 +Azerbaijan,29/04/2018,5,Carlos Sainz,9,Renault,10 +Azerbaijan,29/04/2018,6,Charles Leclerc,13,Sauber-Ferrari,8 +Azerbaijan,29/04/2018,7,Fernando Alonso,12,McLaren-Renault,6 +Azerbaijan,29/04/2018,8,Lance Stroll,10,Williams-Mercedes,4 +Azerbaijan,29/04/2018,9,Stoffel Vandoorne,16,McLaren-Renault,2 +Azerbaijan,29/04/2018,10,Brendon Hartley,19,STR-Honda,1 +Spanish,13/05/2018,1,Lewis Hamilton,1,Mercedes,25 +Spanish,13/05/2018,2,Valtteri Bottas,2,Mercedes,18 +Spanish,13/05/2018,3,Max Verstappen,5,Red Bull Racing-TAG Heuer,15 +Spanish,13/05/2018,4,Sebastian Vettel,3,Ferrari,12 +Spanish,13/05/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +Spanish,13/05/2018,6,Kevin Magnussen,7,Haas-Ferrari,8 +Spanish,13/05/2018,7,Carlos Sainz,9,Renault,6 +Spanish,13/05/2018,8,Fernando Alonso,8,McLaren-Renault,4 +Spanish,13/05/2018,9,Sergio Pérez,15,Force India-Mercedes,2 +Spanish,13/05/2018,10,Charles Leclerc,14,Sauber-Ferrari,1 +Monaco,27/05/2018,1,Daniel Ricciardo,1,Red Bull Racing-TAG Heuer,25 +Monaco,27/05/2018,2,Sebastian Vettel,2,Ferrari,18 +Monaco,27/05/2018,3,Lewis Hamilton,3,Mercedes,15 +Monaco,27/05/2018,4,Kimi Räikkönen,4,Ferrari,12 +Monaco,27/05/2018,5,Valtteri Bottas,5,Mercedes,10 +Monaco,27/05/2018,6,Esteban Ocon,6,Force India-Mercedes,8 +Monaco,27/05/2018,7,Pierre Gasly,10,STR-Honda,6 +Monaco,27/05/2018,8,Nico Hülkenberg,11,Renault,4 +Monaco,27/05/2018,9,Max Verstappen,20,Red Bull Racing-TAG Heuer,2 +Monaco,27/05/2018,10,Carlos Sainz,8,Renault,1 +Canadian,10/06/2018,1,Sebastian Vettel,1,Ferrari,25 +Canadian,10/06/2018,2,Valtteri Bottas,2,Mercedes,18 +Canadian,10/06/2018,3,Max Verstappen,3,Red Bull Racing-TAG Heuer,15 +Canadian,10/06/2018,4,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,12 +Canadian,10/06/2018,5,Lewis Hamilton,4,Mercedes,10 +Canadian,10/06/2018,6,Kimi Räikkönen,5,Ferrari,8 +Canadian,10/06/2018,7,Nico Hülkenberg,7,Renault,6 +Canadian,10/06/2018,8,Carlos Sainz,9,Renault,4 +Canadian,10/06/2018,9,Esteban Ocon,8,Force India-Mercedes,2 +Canadian,10/06/2018,10,Charles Leclerc,13,Sauber-Ferrari,1 +French,24/06/2018,1,Lewis Hamilton,1,Mercedes,25 +French,24/06/2018,2,Max Verstappen,4,Red Bull Racing-TAG Heuer,18 +French,24/06/2018,3,Kimi Räikkönen,6,Ferrari,15 +French,24/06/2018,4,Daniel Ricciardo,5,Red Bull Racing-TAG Heuer,12 +French,24/06/2018,5,Sebastian Vettel,3,Ferrari,10 +French,24/06/2018,6,Kevin Magnussen,9,Haas-Ferrari,8 +French,24/06/2018,7,Valtteri Bottas,2,Mercedes,6 +French,24/06/2018,8,Carlos Sainz,7,Renault,4 +French,24/06/2018,9,Nico Hülkenberg,12,Renault,2 +French,24/06/2018,10,Charles Leclerc,8,Sauber-Ferrari,1 +Austrian,01/07/2018,1,Max Verstappen,4,Red Bull Racing-TAG Heuer,25 +Austrian,01/07/2018,2,Kimi Räikkönen,3,Ferrari,18 +Austrian,01/07/2018,3,Sebastian Vettel,6,Ferrari,15 +Austrian,01/07/2018,4,Romain Grosjean,5,Haas-Ferrari,12 +Austrian,01/07/2018,5,Kevin Magnussen,8,Haas-Ferrari,10 +Austrian,01/07/2018,6,Esteban Ocon,11,Force India-Mercedes,8 +Austrian,01/07/2018,7,Sergio Pérez,15,Force India-Mercedes,6 +Austrian,01/07/2018,8,Fernando Alonso,20,McLaren-Renault,4 +Austrian,01/07/2018,9,Charles Leclerc,17,Sauber-Ferrari,2 +Austrian,01/07/2018,10,Marcus Ericsson,18,Sauber-Ferrari,1 +British,08/07/2018,1,Sebastian Vettel,2,Ferrari,25 +British,08/07/2018,2,Lewis Hamilton,1,Mercedes,18 +British,08/07/2018,3,Kimi Räikkönen,3,Ferrari,15 +British,08/07/2018,4,Valtteri Bottas,4,Mercedes,12 +British,08/07/2018,5,Daniel Ricciardo,6,Red Bull Racing-TAG Heuer,10 +British,08/07/2018,6,Nico Hülkenberg,11,Renault,8 +British,08/07/2018,7,Esteban Ocon,10,Force India-Mercedes,6 +British,08/07/2018,8,Fernando Alonso,13,McLaren-Renault,4 +British,08/07/2018,9,Kevin Magnussen,7,Haas-Ferrari,2 +British,08/07/2018,10,Sergio Pérez,12,Force India-Mercedes,1 \ No newline at end of file diff --git a/__tests__/First10Races.tests.ps1 b/__tests__/First10Races.tests.ps1 new file mode 100644 index 0000000..9cbd288 --- /dev/null +++ b/__tests__/First10Races.tests.ps1 @@ -0,0 +1,93 @@ +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 + $topRow = $lastDataRow = 1 + $results.Count + $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) { + $excel = $R.Group | Export-Excel -ExcelPackage $excel -NoHeader -StartRow ($lastDataRow +1) -RangeName $R.Name -PassThru -AutoSize + $lastDataRow += $R.Group.Count + } + $worksheet = $excel.Workbook.Worksheets[1] + $columns = $worksheet.Dimension.Columns + + 1..$columns | foreach {Add-ExcelName -Range $worksheet.cells[$topRow,$_,$lastDataRow,$_]} + + Set-Column -Worksheet $worksheet -StartRow $topRow -Heading "PlacesGained/Lost" -Value "=GridPostion-FinishPosition" -AutoNameRange + $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 + $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 + $cf.Icon2.Type = $cf.Icon3.Type = "Num" + $cf.Icon2.Value = 0 + $cf.Icon3.Value = 1 + Add-ConditionalFormatting -Address $worksheet.cells["FinishPosition"] -RuleType Equal -ConditionValue 1 -ForeGroundColor Purple -Bold -Priority 1 -StopIfTrue + Add-ConditionalFormatting -Address $worksheet.cells["FinishPosition"] -RuleType LessThanOrEqual -ConditionValue 3 -Bold -Priority 2 -StopIfTrue + + #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")} | + Export-Excel -ExcelPackage $excel -AutoSize -PivotTableDefinition $pt -Calculate + + $excel = Open-ExcelPackage $path + $sheet = $excel.Workbook.Worksheets[1] + $m = $results | measure -sum -Property count + $expectedRows = 1 + $m.count + $m.sum + } + Context "Creating hyperlinks" { + it "Put the data into the sheet and created the expected named ranges " { + $sheet.dimension.rows | should be $expectedRows + $sheet.dimension.columns | should be $columns + $sheet.names.count | should be ($columns + $results.Count) + $sheet.Names[$results[0].Name] | should not benullorEmpty + $sheet.Names[$results[-1].Name] | should not benullorEmpty + } + 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 + } + } + Context "Adding calculated column" { + It "Populated the cells with the right heading and formulas " { + $sheet.Cells[( $results.Count),$columns] | Should benullorEmpty + $sheet.Cells[(1+$results.Count),$columns].Value | Should be "PlacesGained/Lost" + $sheet.Cells[(2+$results.Count),$columns].Formula | should be "GridPostion-FinishPosition" + $sheet.Names["PlacesGained/Lost"] | should not benullorEmpty + } + 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 + $sheet.ConditionalFormatting[0].Address.End.Row | should be $expectedRows + $sheet.ConditionalFormatting[0].Address.Start.Row | should be ($results.Count + 1) + $sheet.ConditionalFormatting[0].Icon3.Type.ToString() | Should be "Num" + $sheet.ConditionalFormatting[0].Icon3.Value | Should be 1 + $sheet.ConditionalFormatting[0].Priority | Should be 3 + $sheet.ConditionalFormatting[1].Priority | Should be 1 + $sheet.ConditionalFormatting[2].Priority | Should be 2 + $sheet.ConditionalFormatting[1].StopIfTrue | Should be $true + } + } + Context "Adding adding a table" { + it "Created a table " { + $sheet.tables[0] | Should not beNullOrEmpty + $sheet.tables[0].Address.Start.Column | should be 1 + $sheet.tables[0].Address.End.Column | should be $columns + $sheet.tables[0].Address.Start.row | should be ($results.Count + 1) + $sheet.Tables[0].Address.End.Row | should be $expectedRows + $sheet.Tables[0].StyleName | should be "TableStyleLight7" + $sheet.Tables[0].ShowColumnStripes | should be $true + $sheet.Tables[0].ShowRowStripes | should not be $true + } + } +} \ No newline at end of file diff --git a/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 b/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 index 3759450..aeaa6c8 100644 --- a/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 +++ b/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 @@ -310,7 +310,7 @@ Describe "Table Formatting" { $ws = $excel.Workbook.Worksheets[1] Set-Column -Worksheet $ws -Column 4 -NumberFormat 'Currency' Set-Column -Worksheet $ws -Column 5 -NumberFormat 'Currency' - Add-ExcelTable -Range $ws.cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName HardwareTable -ShowTotal -ShowFirstColumn + Add-ExcelTable -Range $ws.cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName HardwareTable -ShowTotal -ShowFirstColumn -ShowFilter:$false $PtDef =New-PivotTableDefinition -PivotTableName Totals -PivotRows Product -PivotData @{"Total"="Sum"} -PivotNumberFormat Currency -PivotTotals None -PivotTableSyle Dark2 Export-excel -ExcelPackage $excel -WorksheetName Hardware -PivotTableDefinition $PtDef