diff --git a/ColorCompletion.ps1 b/ColorCompletion.ps1 index ece2fde..6c26684 100644 --- a/ColorCompletion.ps1 +++ b/ColorCompletion.ps1 @@ -15,6 +15,7 @@ if (Get-Command -Name register-argumentCompleter -ErrorAction SilentlyContinue) Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName FontColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName TabColor -ScriptBlock $Function:ColorCompletion + Register-ArgumentCompleter -CommandName Join-Worksheet -ParameterName TitleBackgroundColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Merge-Worksheet -ParameterName AddBackgroundColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Merge-Worksheet -ParameterName ChangeBackgroundColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Merge-Worksheet ` -ParameterName DeleteBackgroundColor -ScriptBlock $Function:ColorCompletion @@ -36,4 +37,5 @@ if (Get-Command -Name register-argumentCompleter -ErrorAction SilentlyContinue) Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName FontColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion + } \ No newline at end of file diff --git a/Examples/Index - Music.ps1 b/Examples/Index - Music.ps1 index 862ae07..d518495 100644 --- a/Examples/Index - Music.ps1 +++ b/Examples/Index - Music.ps1 @@ -1,15 +1,41 @@ -Remove-item -path ~\documents\music.xlsx -$excel = Get-IndexedItem "itemtype='.mp3'","AlbumArtist like '%'","RatingText <> '1 star'" -NoFiles -orderby AlbumArtist,AlbumTitle,TrackNumber -path c:\users -Recurse -Property AlbumArtist,Duration,title,EncodingBitrate,SampleRate,AlbumTitle,TrackNumber, Size | - Select-Object -Property AlbumArtist, AlbumTitle, TrackNumber, Title, Duration, SampleRate, EncodingBitRate, Size | Export-excel -path ~\documents\music.xlsx -WorksheetName Music -AutoNameRange -AutoSize -BoldTopRow -FreezeTopRow -PassThru -$ws = $excel.Workbook.Worksheets[1] -Set-ExcelColumn -Worksheet $ws -Column 6 -NumberFormat '0,"KHz"' -Set-ExcelColumn -Worksheet $ws -Column 7 -NumberFormat '0,"Kbits/Sec"' -Width 18 -Set-ExcelColumn -Worksheet $ws -Column 8 -NumberFormat '#.#,,"MB"' -Width 7 -$pt = Add-PivotTable -PivotTableName SpaceUsedByMusic -ExcelPackage $excel -SourceWorkSheet $ws -PivotRows ALBUMARTIST -PivotData @{"Size"="Sum"} -PivotNumberFormat '#.#,,"MB"' -Activate -PassThru -$pt.RowFields[0].Sort = [OfficeOpenXml.Table.PivotTable.eSortType]::Ascending +#requires -modules "Get-IndexedItem" +[cmdletbinding()] +Param() +Remove-Item ~\documents\music.xlsx -ErrorAction SilentlyContinue +[System.Diagnostics.Stopwatch]$stopwatch = [System.Diagnostics.Stopwatch]::StartNew() -$a = $ws.Dimension.address -Add-ExcelTable -Range $ws.cells[$a] -TableStyle Light1 -TableName Musictable -ShowFilter:$false -ShowTotal -ShowFirstColumn -Add-ConditionalFormatting -Address $ws.Names[1] -RuleType ContainsText -ConditionValue "Hits" -ForeGroundColor Blue -Add-ConditionalFormatting -Address $ws.Cells["Albumartist"] -RuleType ContainsText -ConditionValue "Numan" -ForeGroundColor red -Close-ExcelPackage -show $excel \ No newline at end of file +#Query system index for .MP3 files in C:\Users, where album artist is non-blank. Leave sorted table with columns of interest in $Music. + +Get-IndexedItem "itemtype='.mp3'","AlbumArtist like '%'" -Recurse C:\Users -OutputVariable Music ` + -OrderBy AlbumArtist, AlbumTitle, TrackNumber, Title -NoFiles ` + -Property AlbumArtist, AlbumTitle, TrackNumber, Title, Duration, Size, SampleRate +Write-Verbose -Message ("Fetched " + $music.Rows.Count + " rows from index: " + $stopwatch.Elapsed.TotalSeconds) +#Send Table in $Music to Excel, format as a table, point $ws to the Worksheet +$excel = Send-SQLDataToExcel -Path ~\documents\music.xlsx -DataTable $music -WorkSheetname Music -TableName Music -Passthru +Write-Verbose -Message ("Inserted into Excel: " + $stopwatch.Elapsed.TotalSeconds) +$ws = $excel.Music + +#Strip "SYSTEM.", "SYSTEM.AUDIO", "SYSTEM.MEDIA", "SYSTEM.MUSIC" from the column headings +#Convert Duration (column 5) from 100ns ticks to days and format as minutes, seconds, decimal +#Format filesize and sample rate nicely +#Autofit the columns. +Set-ExcelRow -Worksheet $ws -Row 1 -Value {($worksheet.cells[$row,$column].value -replace '^SYSTEM\.','') -replace '^MEDIA\.|^AUDIO\.|^MUSIC\.','' } +Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'mm:ss.0' -StartRow 2 -Value {$worksheet.cells[$row,$column].value / 864000000000 } +Write-Verbose -Message ("Cells Reset: " + $stopwatch.Elapsed.TotalSeconds) +Set-Column -Worksheet $ws -Column 6 -NumberFormat '#.#,,"MB"' +Set-ExcelColumn -Worksheet $ws -Column 7 -NumberFormat '0.0,"KHz"' +$ws.Cells[$ws.Dimension].AutoFitColumns() + +#Make a Pivot table for sum of space and count of tracks by artist. Sort by artist, apply formatting to space, give it nice titles. +$pt = Add-PivotTable -PassThru -PivotTableName SpaceUsedByMusic -ExcelPackage $excel -SourceWorkSheet $ws ` + -PivotRows ALBUMARTIST -PivotData ([ordered]@{"Size"="Sum"; "Duration"="Count"}) -PivotDataToColumn + +$pt.RowFields[0].Sort = [OfficeOpenXml.Table.PivotTable.eSortType]::Ascending +$pt.DataFields[0].Format = '#.0,,"MB"' +$pt.DataFields[0].Name = 'Space Used' +$pt.DataFields[1].Name = 'Tracks' + +#Save the file, and load it into Excel +$stopwatch.Stop() +Write-Verbose -Message ("Pivot Done: " + $stopwatch.Elapsed.TotalSeconds) +Close-ExcelPackage -show $excel diff --git a/Examples/SQL+FillColumns+Pivot/Example2.ps1 b/Examples/SQL+FillColumns+Pivot/Example2.ps1 index 2e9eb64..58fa933 100644 --- a/Examples/SQL+FillColumns+Pivot/Example2.ps1 +++ b/Examples/SQL+FillColumns+Pivot/Example2.ps1 @@ -1,5 +1,7 @@ -try {. $PSScriptRoot\..\..\LoadPSD1.ps1} catch {} +#requires -modules "getSql" +try {. $PSScriptRoot\..\..\LoadPSD1.ps1} catch {} +#download f1Results from https://1drv.ms/f/s!AhfYu7-CJv4egbt5FD7Cdxi8jSz3aQ and update the path below Get-SQL -Session f1 -Excel -Connection C:\Users\mcp\OneDrive\Public\F1\f1Results.xlsx -showtables -Verbose Remove-Item .\demo3.xlsx diff --git a/Export-Excel.ps1 b/Export-Excel.ps1 index 10b26c1..901c39f 100644 --- a/Export-Excel.ps1 +++ b/Export-Excel.ps1 @@ -762,29 +762,29 @@ $headerRange = $ws.Dimension.Address -replace "\d+$", $StartRow #using a slightly odd syntax otherwise header ends up as a 2D array $ws.Cells[$headerRange].Value | ForEach-Object -Begin {$Script:header = @()} -Process {$Script:header += $_ } - #if there is no header start the range at $startRow - $targetRow = $StartRow - } - else { - #if there is a header, start the range and the next row down. - $targetRow = $StartRow + 1 - } + if ($PSBoundParameters.ContainsKey($TargetData)) { #if Export was called with data that writes no header start the range at $startRow ($startRow is data) + $targetRow = $StartRow + } + else { $targetRow = $StartRow + 1 } #if Export was called without data to add names (assume $startRow is a header) or... + } # ... called with data that writes a header, then start the range at $startRow + 1 + else { $targetRow = $StartRow + 1 } #Dimension.start.row always seems to be one so we work out the target row #, but start.column is the first populated one and .Columns is the count of populated ones. # if we have 5 columns from 3 to 8, headers are numbered 0..4, so that is in the for loop and used for getting the name... # but we have to add the start column on when referencing positions foreach ($c in 0..($LastCol - $StartColumn)) { - $targetRangeName = $script:Header[$c] -replace '\W' , '_' + $targetRangeName = $script:Header[$c] #Let Add-ExcelName fix (and warn about) bad names Add-ExcelName -RangeName $targetRangeName -Range $ws.Cells[$targetRow, ($StartColumn + $c ), $LastRow, ($StartColumn + $c )] - if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress($targetRangeName)) { - Write-Warning "AutoNameRange: Property name '$targetRangeName' is also a valid Excel address and may cause issues. Consider renaming the property name." - } + try {#this test can throw with some names, surpress any error + if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress(($targetRangeName -replace '\W' , '_' ))) { + Write-Warning "AutoNameRange: Property name '$targetRangeName' is also a valid Excel address and may cause issues. Consider renaming the property name." + } + } Catch {} } } catch {Write-Warning -Message "Failed adding named ranges to worksheet '$WorksheetName': $_" } } - if ($RangeName) { Add-ExcelName -Range $ws.Cells[$dataRange] -RangeName $RangeName} if ($TableName) { diff --git a/Join-Worksheet.ps1 b/Join-Worksheet.ps1 index 58264a2..a1aa547 100644 --- a/Join-Worksheet.ps1 +++ b/Join-Worksheet.ps1 @@ -78,7 +78,7 @@ #Text of a title to be placed in Cell A1. [String]$Title, #Sets the fill pattern for the title cell. - [OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'None', + [OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'Solid', #Sets the cell background color for the title cell. [System.Drawing.Color]$TitleBackgroundColor, #Sets the title in boldface type. diff --git a/README.md b/README.md index ebd36ae..dfc9c12 100644 --- a/README.md +++ b/README.md @@ -52,6 +52,15 @@ Install-Module ImportExcel -scope CurrentUser Install-Module ImportExcel ``` + # What's new +- In Export-Excel fixed a bug where -AutoNameRange on pre-existing data included the header in the range +- In Join-Worksheet: added Argument completer to -TitleBackgroundColor and Set default for -TitleBackgroundStyle to 'Solid'. +- In Send-SqlDataToExcel: improved robustness of check for no data returned. +- In Set-ExcelColumn: -column can come from the pipeline (supporting an array introduces complications for supporting script blocks); -AutoNameRange no longer requires heading to specified (so you can do 1..10 | Set-ExcelColumn -AutoNameRange ) +- In Set-ExcelRow: -Row can come from the pipeline +- Fleshed out Examples In "Index - music.ps1" the module for querying the index can be downloaded from PowerShell gallery #requires set to demand it. In SQL+FillColumns+Pivot\example2.ps1 the GetSQL module can be downloaded and #Requires has been set. The F1 results spreadsheet is available from one drive and a link is provided. +- Improved test coverage (back over 80%). + # What's new in Release 5.3 - Help improvements and tidying up of examples and extra examples diff --git a/Send-SqlDataToExcel.ps1 b/Send-SqlDataToExcel.ps1 index a178e3a..d95a0aa 100644 --- a/Send-SqlDataToExcel.ps1 +++ b/Send-SqlDataToExcel.ps1 @@ -254,7 +254,7 @@ $rowCount = $dataAdapter.fill($dataTable) Write-Verbose -Message "Query returned $rowCount row(s)" } - if ($DataTable.Rows) { + if ($DataTable.Rows.Count) { #ExportExcel user a -NoHeader parameter so that's what we use here, but needs to be the other way around. $printHeaders = -not $NoHeader if ($Title) {$r = $StartRow +1 } diff --git a/Set-Column.ps1 b/Set-Column.ps1 index 6b822d3..91813c0 100644 --- a/Set-Column.ps1 +++ b/Set-Column.ps1 @@ -41,6 +41,7 @@ [Parameter(ParameterSetName="sheet",Mandatory=$true)] [OfficeOpenXml.ExcelWorksheet]$Worksheet, #Column to fill down - first column is 1. 0 will be interpreted as first unused column + [Parameter(ValueFromPipeline=$true)] [ValidateRange(0,16384)] $Column = 0 , #First row to fill data in @@ -103,64 +104,74 @@ #If Specified, return an ExcelPackage object to allow further work to be done on the file. [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 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 -eq 0 ) {$Column = $endColumn + 1 } - $columnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1","" + begin { + #if we were passed a package object and a worksheet name , get the worksheet. + if ($ExcelPackage) {$Worksheet = $ExcelPackage.Workbook.Worksheets[$Worksheetname] } - - 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) { Add-ExcelName -Range $Worksheet.Cells[$StartRow, $Column, $endRow, $Column] -RangeName $Heading } + #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 } - #Fill in the data - 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 + process { + if ($Column -eq 0 ) {$Column = $endColumn + 1 } + $columnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1","" + 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 ($PSBoundParameters.ContainsKey('Heading')) { + $Worksheet.Cells[$StartRow, $Column].Value = $Heading + $StartRow ++ + if ($AutoNameRange) { + Add-ExcelName -Range $Worksheet.Cells[$StartRow, $Column, $endRow, $Column] -RangeName $Heading + } } - else { $cellData = $Value} - if ($cellData -match "^=") { $Worksheet.Cells[$Row, $Column].Formula = ($cellData -replace '^=','') } #EPPlus likes formulas with no = sign; Excel doesn't care - elseif ( [System.Uri]::IsWellFormedUriString($cellData , [System.UriKind]::Absolute)) { - # Save a hyperlink : internal links can be in the form xl://sheet!E419 (use A1 as goto sheet), or xl://RangeName - if ($cellData -match "^xl://internal/") { - $referenceAddress = $cellData -replace "^xl://internal/" , "" - $display = $referenceAddress -replace "!A1$" , "" - $h = New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList $referenceAddress , $display - $Worksheet.Cells[$Row, $Column].HyperLink = $h + elseif ($AutoNameRange) { + Add-ExcelName -Range $Worksheet.Cells[($StartRow+1), $Column, $endRow, $Column] -RangeName $Worksheet.Cells[$StartRow, $Column].Value + } + + #Fill in the data + 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 } - else {$Worksheet.Cells[$Row, $Column].HyperLink = $cellData } - $Worksheet.Cells[$Row, $Column].Style.Font.Color.SetColor([System.Drawing.Color]::Blue) - $Worksheet.Cells[$Row, $Column].Style.Font.UnderLine = $true + else { $cellData = $Value} + if ($cellData -match "^=") { $Worksheet.Cells[$Row, $Column].Formula = ($cellData -replace '^=','') } #EPPlus likes formulas with no = sign; Excel doesn't care + elseif ( [System.Uri]::IsWellFormedUriString($cellData , [System.UriKind]::Absolute)) { + # Save a hyperlink : internal links can be in the form xl://sheet!E419 (use A1 as goto sheet), or xl://RangeName + if ($cellData -match "^xl://internal/") { + $referenceAddress = $cellData -replace "^xl://internal/" , "" + $display = $referenceAddress -replace "!A1$" , "" + $h = New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList $referenceAddress , $display + $Worksheet.Cells[$Row, $Column].HyperLink = $h + } + else {$Worksheet.Cells[$Row, $Column].HyperLink = $cellData } + $Worksheet.Cells[$Row, $Column].Style.Font.Color.SetColor([System.Drawing.Color]::Blue) + $Worksheet.Cells[$Row, $Column].Style.Font.UnderLine = $true + } + 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 = @{} + foreach ($p in @('Underline','Bold','Italic','StrikeThru','FontSize','FontShift','NumberFormat','TextRotation', + 'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Autosize', 'Width', 'FontColor' + 'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { + if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} } - 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 = @{} - foreach ($p in @('Underline','Bold','Italic','StrikeThru','FontSize','FontShift','NumberFormat','TextRotation', - 'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Autosize', 'Width', 'FontColor' - 'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { - if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} + if ($params.Count) { + $theRange = "$columnName$StartRow`:$columnName$endRow" + Set-ExcelRange -WorkSheet $Worksheet -Range $theRange @params + } + #endregion + if ($PSBoundParameters.ContainsKey('Hide')) {$workSheet.Column($Column).Hidden = [bool]$Hide} + #return the new data if -passthru was specified. + if ($passThru) { $Worksheet.Column($Column)} + elseif ($ReturnRange) { $theRange} } - $theRange = "$columnName$StartRow`:$columnName$endRow" - if ($params.Count) { - Set-ExcelRange -WorkSheet $Worksheet -Range $theRange @params - } - #endregion - if ($PSBoundParameters["Hide"]) {$workSheet.Column($Column).Hidden = [bool]$Hide} - #return the new data if -passthru was specified. - if ($passThru) { $Worksheet.Column($Column)} - elseif ($ReturnRange) { $theRange} } \ No newline at end of file diff --git a/Set-Row.ps1 b/Set-Row.ps1 index af26eb8..33c99f7 100644 --- a/Set-Row.ps1 +++ b/Set-Row.ps1 @@ -36,6 +36,7 @@ [Parameter(ParameterSetName="Sheet",Mandatory=$true)] [OfficeOpenXml.Excelworksheet] $Worksheet, #Row to fill right - first row is 1. 0 will be interpreted as first unused row + [Parameter(ValueFromPipeline = $true)] $Row = 0 , #Position in the row to start from [int]$StartColumn, @@ -105,67 +106,70 @@ #If Specified, return a row object to allow further work to be done [Switch]$PassThru ) + begin { + #if we were passed a package object and a worksheet name , get the worksheet. + if ($ExcelPackage) {$Worksheet = $ExcelPackage.Workbook.worksheets[$Worksheetname] } - #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 row and start column aren't specified assume first unused row, and first column - if (-not $StartColumn) {$StartColumn = $Worksheet.Dimension.Start.Column } - $startRow = $Worksheet.Dimension.Start.Row + 1 - $endColumn = $Worksheet.Dimension.End.Column - $endRow = $Worksheet.Dimension.End.Row - if ($Row -eq 0 ) {$Row = $endRow + 1 } - Write-Verbose -Message "Updating Row $Row" - #Add a row label - if ($Heading) { - $Worksheet.Cells[$Row, $StartColumn].Value = $Heading - if ($HeadingBold) {$Worksheet.Cells[$Row, $StartColumn].Style.Font.Bold = $true} - if ($HeadingSize) {$Worksheet.Cells[$Row, $StartColumn].Style.Font.Size = $HeadingSize} - $StartColumn ++ + #In a script block to build a formula, we may want any of corners or the columnname, + #if row and start column aren't specified assume first unused row, and first column + if (-not $StartColumn) {$StartColumn = $Worksheet.Dimension.Start.Column } + $startRow = $Worksheet.Dimension.Start.Row + 1 + $endColumn = $Worksheet.Dimension.End.Column + $endRow = $Worksheet.Dimension.End.Row } - #Fill in the data - 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] ) { - #re-create the script block otherwise variables from this function are out of scope. - $cellData = & ([scriptblock]::create( $Value )) - Write-Verbose -Message $cellData + process { + if ($Row -eq 0 ) {$Row = $endRow + 1 } + Write-Verbose -Message "Updating Row $Row" + #Add a row label + if ($Heading) { + $Worksheet.Cells[$Row, $StartColumn].Value = $Heading + if ($HeadingBold) {$Worksheet.Cells[$Row, $StartColumn].Style.Font.Bold = $true} + if ($HeadingSize) {$Worksheet.Cells[$Row, $StartColumn].Style.Font.Size = $HeadingSize} + $StartColumn ++ } - else{$cellData = $Value} - if ($cellData -match "^=") { $Worksheet.Cells[$Row, $column].Formula = ($cellData -replace '^=','') } #EPPlus likes formulas with no = sign; Excel doesn't care - elseif ( [System.Uri]::IsWellFormedUriString($cellData , [System.UriKind]::Absolute)) { - # Save a hyperlink : internal links can be in the form xl://sheet!E419 (use A1 as goto sheet), or xl://RangeName - if ($cellData -match "^xl://internal/") { - $referenceAddress = $cellData -replace "^xl://internal/" , "" - $display = $referenceAddress -replace "!A1$" , "" - $h = New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList $referenceAddress , $display - $Worksheet.Cells[$Row, $Column].HyperLink = $h + #Fill in the data + 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] ) { + #re-create the script block otherwise variables from this function are out of scope. + $cellData = & ([scriptblock]::create( $Value )) + Write-Verbose -Message $cellData } - else {$Worksheet.Cells[$Row, $Column].HyperLink = $cellData } - $Worksheet.Cells[$Row, $Column].Style.Font.Color.SetColor([System.Drawing.Color]::Blue) - $Worksheet.Cells[$Row, $Column].Style.Font.UnderLine = $true + else{$cellData = $Value} + if ($cellData -match "^=") { $Worksheet.Cells[$Row, $column].Formula = ($cellData -replace '^=','') } #EPPlus likes formulas with no = sign; Excel doesn't care + elseif ( [System.Uri]::IsWellFormedUriString($cellData , [System.UriKind]::Absolute)) { + # Save a hyperlink : internal links can be in the form xl://sheet!E419 (use A1 as goto sheet), or xl://RangeName + if ($cellData -match "^xl://internal/") { + $referenceAddress = $cellData -replace "^xl://internal/" , "" + $display = $referenceAddress -replace "!A1$" , "" + $h = New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList $referenceAddress , $display + $Worksheet.Cells[$Row, $Column].HyperLink = $h + } + else {$Worksheet.Cells[$Row, $Column].HyperLink = $cellData } + $Worksheet.Cells[$Row, $Column].Style.Font.Color.SetColor([System.Drawing.Color]::Blue) + $Worksheet.Cells[$Row, $Column].Style.Font.UnderLine = $true + } + 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 = @{} + foreach ($p in @('Underline','Bold','Italic','StrikeThru','FontSize', 'FontShift','NumberFormat','TextRotation', + 'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Height', 'FontColor' + 'BorderAround', 'BorderBottom', 'BorderTop', 'BorderLeft', 'BorderRight', 'BorderColor', + 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { + if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} } - 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 = @{} - foreach ($p in @('Underline','Bold','Italic','StrikeThru','FontSize', 'FontShift','NumberFormat','TextRotation', - 'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Height', 'FontColor' - 'BorderAround', 'BorderBottom', 'BorderTop', 'BorderLeft', 'BorderRight', 'BorderColor', - 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { - if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} + if ($params.Count) { + $theRange = [OfficeOpenXml.ExcelAddress]::New($Row, $StartColumn, $Row, $endColumn) + Set-ExcelRange -WorkSheet $Worksheet -Range $theRange @params + } + #endregion + if ($PSBoundParameters.ContainsKey('Hide')) {$workSheet.Row($Row).Hidden = [bool]$Hide} + #return the new data if -passthru was specified. + if ($passThru) {$Worksheet.Row($Row)} + elseif ($ReturnRange) {$theRange} } - $theRange = [OfficeOpenXml.ExcelAddress]::New($Row, $StartColumn, $Row, $endColumn) - if ($params.Count) { - Set-ExcelRange -WorkSheet $Worksheet -Range $theRange @params - } - #endregion - if ($PSBoundParameters["Hide"]) {$workSheet.Row($Row).Hidden = [bool]$Hide} - #return the new data if -passthru was specified. - if ($passThru) {$Worksheet.Row($Row)} - elseif ($ReturnRange) {$theRange} } \ No newline at end of file diff --git a/__tests__/Export-Excel.Tests.ps1 b/__tests__/Export-Excel.Tests.ps1 index 3d51996..a811a37 100644 --- a/__tests__/Export-Excel.Tests.ps1 +++ b/__tests__/Export-Excel.Tests.ps1 @@ -279,12 +279,12 @@ Describe ExportExcel { ($ws.Cells[2, 20].Value -is [valuetype] ) | Should be $true } it "Converted a nested object to a string (Y2) " { - $ws.Cells[2, 26].Value | should match '^System\.Diagnostics\.Process\s+\(.*\)$' + $ws.Cells[2, 26].Value | Should match '^System\.Diagnostics\.Process\s+\(.*\)$' } it "Processed a timespan object (Z2) " { - $ws.cells[2, 27].Value.ToOADate() | should beGreaterThan 0 - $ws.cells[2, 27].Value.ToOADate() | should beLessThan 1 - $ws.cells[2, 27].Style.Numberformat.Format | should be '[h]:mm:ss' + $ws.cells[2, 27].Value.ToOADate() | Should beGreaterThan 0 + $ws.cells[2, 27].Value.ToOADate() | Should beLessThan 1 + $ws.cells[2, 27].Style.Numberformat.Format | Should be '[h]:mm:ss' } } @@ -452,7 +452,7 @@ Describe ExportExcel { #Test -passthru and -worksheetName creating a new, named, sheet in an existing file. $Excel = Get-Process | Select-Object -first 20 -Property Name, cpu, pm, handles, company | Export-Excel $path -WorkSheetname Processes -PassThru #Testing -Excel Pacakage and adding a Pivot-table as a second step. Want to save and re-open it ... - Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -NoTotalsInPivot + Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -NoTotalsInPivot -PivotDataToColumn -Activate $Excel = Open-ExcelPackage $path $PTws = $Excel.Workbook.Worksheets["ProcessesPivotTable"] @@ -461,6 +461,7 @@ Describe ExportExcel { $excel.ProcessesPivotTable | Should not beNullOrEmpty $PTws | Should not beNullOrEmpty $PTws.PivotTables.Count | Should be 1 + $PTws.View.TabSelected | Should be $true $Excel.Workbook.Worksheets["Processes"] | Should not beNullOrEmpty $Excel.Workbook.Worksheets.Count | Should beGreaterThan 2 $excel.Workbook.Worksheets["Processes"].Dimension.rows | Should be 21 #20 data + 1 header @@ -476,7 +477,7 @@ Describe ExportExcel { } #test adding pivot chart using the already open sheet $warnvar = $null - Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -ShowCategory -NoLegend -WarningAction SilentlyContinue -WarningVariable warnvar + Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -ShowCategory -ShowPercent -NoLegend -WarningAction SilentlyContinue -WarningVariable warnvar $Excel = Open-ExcelPackage $path it "Added a chart to the pivot table without rebuilding " { $ws = $Excel.Workbook.Worksheets["ProcessesPivotTable"] @@ -512,7 +513,8 @@ Describe ExportExcel { $null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "NewSheet" -MoveAfter "*" -CopySource ($excel.Workbook.Worksheets["Sheet1"]) # Now its NewSheet, Sheet1, ProcessesPivotTable, Processes $null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "Sheet1" -MoveAfter "Processes" # Now its NewSheet, ProcessesPivotTable, Processes, Sheet1 $null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "Another" -MoveToStart # Now its Another, NewSheet, ProcessesPivotTable, Processes, Sheet1 - $null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "OneLast" -MoveBefore "ProcessesPivotTable" # Now its Another, NewSheet, Onelast, ProcessesPivotTable, Processes, Sheet1 + $null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "NearDone" -MoveBefore 5 # Now its Another, NewSheet, ProcessesPivotTable, Processes, NearDone ,Sheet1 + $null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "OneLast" -MoveBefore "ProcessesPivotTable" # Now its Another, NewSheet, Onelast, ProcessesPivotTable, Processes,NearDone ,Sheet1 Close-ExcelPackage $Excel $Excel = Open-ExcelPackage $path @@ -523,7 +525,8 @@ Describe ExportExcel { $excel.Workbook.Worksheets[3].Name | Should be "Onelast" $excel.Workbook.Worksheets[4].Name | Should be "ProcessesPivotTable" $excel.Workbook.Worksheets[5].Name | Should be "Processes" - $excel.Workbook.Worksheets[6].Name | Should be "Sheet1" + $excel.Workbook.Worksheets[6].Name | Should be "NearDone" + $excel.Workbook.Worksheets[7].Name | Should be "Sheet1" } it "Cloned 'Sheet1' to 'NewSheet' " { @@ -553,32 +556,33 @@ Describe ExportExcel { $dataWs.Cells[3, 3].Value | Should not beNullOrEmpty $dataWs.Cells[3, 3].Style.Font.Bold | Should be $true $dataWs.Dimension.End.Row | Should be 23 - $dataWs.names[0].end.row | Should be 23 - $dataWs.names[0].name | Should be 'Name' + $dataWs.names[0].Start.row | Should be 4 # StartRow + 1 + $dataWs.names[0].End.row | Should be $dataWs.Dimension.End.Row + $dataWs.names[0].Name | Should be 'Name' $dataWs.names.Count | Should be 7 # Name, cpu, pm, handles & company + Named Range "Procs" + xl one for autofilter $dataWs.cells[$dataws.Dimension].AutoFilter | Should be true } it "Applied and auto-extended an autofilter " { - $dataWs.Names["_xlnm._FilterDatabase"].Start.Row | should be 3 #offset - $dataWs.Names["_xlnm._FilterDatabase"].Start.Column | should be 3 - $dataWs.Names["_xlnm._FilterDatabase"].Rows | should be 21 #2 x 10 data + 1 header - $dataWs.Names["_xlnm._FilterDatabase"].Columns | should be 5 #Name, cpu, pm, handles & company - $dataWs.Names["_xlnm._FilterDatabase"].AutoFilter | should be $true + $dataWs.Names["_xlnm._FilterDatabase"].Start.Row | Should be 3 #offset + $dataWs.Names["_xlnm._FilterDatabase"].Start.Column | Should be 3 + $dataWs.Names["_xlnm._FilterDatabase"].Rows | Should be 21 #2 x 10 data + 1 header + $dataWs.Names["_xlnm._FilterDatabase"].Columns | Should be 5 #Name, cpu, pm, handles & company + $dataWs.Names["_xlnm._FilterDatabase"].AutoFilter | Should be $true } it "Created and auto-extended the named ranges " { - $dataWs.names["procs"].rows | should be 21 - $dataWs.names["procs"].Columns | should be 5 - $dataWs.Names["CPU"].Rows | should be 20 - $dataWs.Names["CPU"].Columns | should be 1 + $dataWs.names["procs"].rows | Should be 21 + $dataWs.names["procs"].Columns | Should be 5 + $dataWs.Names["CPU"].Rows | Should be 20 + $dataWs.Names["CPU"].Columns | Should be 1 } it "Created and extended the pivot table " { $pt.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref | Should be "C3:G23" - $pt.ColumGrandTotals | should be $false - $pt.RowGrandTotals | should be $false - $pt.Fields["Company"].IsRowField | should be $true - $pt.Fields["PM"].IsDataField | should be $true - $pt.Fields["Name"].IsPageField | should be $true + $pt.ColumGrandTotals | Should be $false + $pt.RowGrandTotals | Should be $false + $pt.Fields["Company"].IsRowField | Should be $true + $pt.Fields["PM"].IsDataField | Should be $true + $pt.Fields["Name"].IsPageField | Should be $true } it "Generated a message on extending the Pivot table " { $warnVar | Should not beNullOrEmpty @@ -587,18 +591,22 @@ Describe ExportExcel { Context " # Create and append explicit and auto table and range extension" { $path = "$env:TEMP\Test.xlsx" - #Test -Append automatically extends a table, even when it is not specified in the append command - Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company | Export-Excel -Path $path -TableName ProcTab -AutoNameRange -WorkSheetname NoOffset -ClearSheet - Get-Process | Select-Object -last 10 -Property Name, cpu, pm, handles, company | Export-Excel -Path $path -AutoNameRange -WorkSheetname NoOffset -Append + #Test -Append automatically extends a table, even when it is not specified in the append command; + Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company | Export-Excel -Path $path -TableName ProcTab -AutoNameRange -WorkSheetname NoOffset -ClearSheet + #Test number format applying to new data + Get-Process | Select-Object -last 10 -Property Name, cpu, pm, handles, company | Export-Excel -Path $path -AutoNameRange -WorkSheetname NoOffset -Append -Numberformat 'Number' $Excel = Open-ExcelPackage $path $dataWs = $Excel.Workbook.Worksheets["NoOffset"] it "Created a new sheet and auto-extended a table and explicitly extended named ranges " { - $dataWs.Tables["ProcTab"].Address.Address | should be "A1:E21" - $dataWs.Names["CPU"].Rows | should be 20 - $dataWs.Names["CPU"].Columns | should be 1 + $dataWs.Tables["ProcTab"].Address.Address | Should be "A1:E21" + $dataWs.Names["CPU"].Rows | Should be 20 + $dataWs.Names["CPU"].Columns | Should be 1 + } + it "Set the expected number formats " { + $dataWs.cells["C2"].Style.Numberformat.Format | Should be "General" + $dataWs.cells["C12"].Style.Numberformat.Format | Should be "0.00" } - #Test extneding autofilter and range when explicitly specified in the append $excel = Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company | Export-Excel -ExcelPackage $excel -RangeName procs -AutoFilter -WorkSheetname NoOffset -ClearSheet -PassThru Get-Process | Select-Object -last 10 -Property Name, cpu, pm, handles, company | Export-Excel -ExcelPackage $excel -RangeName procs -AutoFilter -WorkSheetname NoOffset -Append @@ -606,11 +614,11 @@ Describe ExportExcel { $dataWs = $Excel.Workbook.Worksheets["NoOffset"] it "Created a new sheet and explicitly extended named range and autofilter " { - $dataWs.names["procs"].rows | should be 21 - $dataWs.names["procs"].Columns | should be 5 - $dataWs.Names["_xlnm._FilterDatabase"].Rows | should be 21 #2 x 10 data + 1 header - $dataWs.Names["_xlnm._FilterDatabase"].Columns | should be 5 #Name, cpu, pm, handles & company - $dataWs.Names["_xlnm._FilterDatabase"].AutoFilter | should be $true + $dataWs.names["procs"].rows | Should be 21 + $dataWs.names["procs"].Columns | Should be 5 + $dataWs.Names["_xlnm._FilterDatabase"].Rows | Should be 21 #2 x 10 data + 1 header + $dataWs.Names["_xlnm._FilterDatabase"].Columns | Should be 5 #Name, cpu, pm, handles & company + $dataWs.Names["_xlnm._FilterDatabase"].AutoFilter | Should be $true } } @@ -680,10 +688,10 @@ Describe ExportExcel { $pt1.RowFields[0].Name | Should be 'Status' $pt1.DataFields[0].Field.name | Should be 'Status' $pt1.DataFields[0].Function | Should be 'Count' - $pt1.ColumGrandTotals | should be $true - $pt1.RowGrandTotals | should be $false - $pt2.ColumGrandTotals | should be $false - $pt2.RowGrandTotals | should be $true + $pt1.ColumGrandTotals | Should be $true + $pt1.RowGrandTotals | Should be $false + $pt2.ColumGrandTotals | Should be $false + $pt2.RowGrandTotals | Should be $true $pc1.ChartType | Should be 'BarClustered3D' $pc1.From.Column | Should be 0 #chart 1 at 0,10 chart 2 at 4,0 (default) $pc2.From.Column | Should be 4 @@ -715,14 +723,14 @@ Describe ExportExcel { #Test Set-ExcelRange with a column foreach ($c in 5..9) {Set-ExcelRange $sheet.Column($c) -AutoFit } Add-PivotTable -PivotTableName "PT_Procs" -ExcelPackage $excel -SourceWorkSheet 1 -PivotRows Company -PivotData @{'Name' = 'Count'} -IncludePivotChart -ChartType ColumnClustered -NoLegend - Close-ExcelPackage $excel + Export-Excel -ExcelPackage $excel -WorksheetName "Processes" -AutoNameRange #Test adding named ranges seperately from adding data. $excel = Open-ExcelPackage $path $sheet = $excel.Workbook.Worksheets["Processes"] it "Returned the rule when calling Add-ConditionalFormatting -passthru " { - $rule | should not beNullOrEmpty - $rule.getType().fullname | should be "OfficeOpenXml.ConditionalFormatting.ExcelConditionalFormattingTopPercent" - $rule.Style.Font.Strike | should be true + $rule | Should not beNullOrEmpty + $rule.getType().fullname | Should be "OfficeOpenXml.ConditionalFormatting.ExcelConditionalFormattingTopPercent" + $rule.Style.Font.Strike | Should be true } it "Applied the formating " { $sheet | Should not beNullOrEmpty @@ -750,6 +758,17 @@ Describe ExportExcel { $sheet.ConditionalFormatting[2].Formula | Should be '104857600' $sheet.ConditionalFormatting[2].Style.Font.Color.Color.Name | Should be 'ffff0000' } + it "Created the named ranges " { + $sheet.Names.Count | Should be 7 + $sheet.Names[0].Start.Column | Should be 1 + $sheet.Names[0].Start.Row | Should be 2 + $sheet.Names[0].End.Row | Should be $sheet.Dimension.End.Row + $sheet.Names[0].Name | Should be $sheet.Cells['A1'].Value + $sheet.Names[6].Start.Column | Should be 7 + $sheet.Names[6].Start.Row | Should be 2 + $sheet.Names[6].End.Row | Should be $sheet.Dimension.End.Row + $sheet.Names[6].Name | Should be $sheet.Cells['G1'].Value + } it "Froze the panes " { $sheet.view.Panes.Count | Should be 3 } @@ -832,6 +851,7 @@ Describe ExportExcel { -Column 2 -ColumnOffSetPixels 35 -Width 800 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -XAxisNumberformat "000" ` -YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -YAxisTitleText "Sine" -YAxisTitleBold -YAxisTitleSize 12 ` -LegendSize 8 -legendBold -LegendPostion Bottom + #Test simple formula based conditional formatting rule Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets["Sinx"] -Range "B2:B362" -RuleType LessThan -ConditionValue "=B1" -ForeGroundColor Red $ws = $Excel.Workbook.Worksheets["Sinx"] $d = $ws.Drawings[0] @@ -864,6 +884,24 @@ Describe ExportExcel { } Close-ExcelPackage -ExcelPackage $excel -nosave } + Context " # Quick line chart" { + $path = "$env:TEMP\Test.xlsx" + Remove-Item -Path $path -ErrorAction SilentlyContinue + #test drawing a chart when data doesn't have a string + 0..360 | ForEach-Object {[pscustomobject][ordered]@{x = $_; Sinx = "=Sin(Radians(x)) "}} | Export-Excel -AutoNameRange -Path $path -LineChart + $excel = Open-ExcelPackage -Path $path + $ws = $excel.Sheet1 + $d = $ws.Drawings[0] + it "Created the chart " { + $d.Title.text | Should beNullOrEmpty + $d.ChartType | Should be "line" + $d.Series[0].Header | Should be "Sinx" + $d.Series[0].xSeries | Should be "'Sheet1'!A2:B362" + $d.Series[0].Series | Should be "'Sheet1'!B2:B362" + } + + } + Context " # Quick Pie chart and three icon conditional formating" { $path = "$Env:TEMP\Pie.xlsx" @@ -875,8 +913,8 @@ Describe ExportExcel { $Cf = New-ConditionalFormattingIconSet -Range ($range -replace "^.*:","B2:") -ConditionalFormat ThreeIconSet -Reverse -IconType Flags $ct = New-ConditionalText -Text "Microsoft" -ConditionalTextColor red -BackgroundColor AliceBlue -ConditionalType ContainsText it "Created the Conditional formatting rules " { - $cf.Formatter | should be "ThreeIconSet" - $cf.IconType | should be "Flags" + $cf.Formatter | Should be "ThreeIconSet" + $cf.IconType | Should be "Flags" $cf.Range | Should be ($range -replace "^.*:","B2:") $cf.Reverse | Should be $true $ct.BackgroundColor.Name | Should be "AliceBlue" @@ -891,13 +929,13 @@ Describe ExportExcel { $chart = $excel.Workbook.Worksheets["sheet1"].Drawings[0] $cFmt = $excel.Workbook.Worksheets["sheet1"].ConditionalFormatting it "Created the chart with the right series " { - $chart.ChartType | should be "PieExploded3D" - $chart.series.series | should be "'Sheet1'!B1:B$rows" #would be B2 and A2 if we had a header. - $chart.series.Xseries | should be "'Sheet1'!A1:A$rows" - $chart.DataLabel.ShowPercent | should be $true + $chart.ChartType | Should be "PieExploded3D" + $chart.series.series | Should be "'Sheet1'!B1:B$rows" #would be B2 and A2 if we had a header. + $chart.series.Xseries | Should be "'Sheet1'!A1:A$rows" + $chart.DataLabel.ShowPercent | Should be $true } it "Created two Conditional formatting rules " { - $cFmt.Count | should be $true + $cFmt.Count | Should be $true $cFmt.Where({$_.type -eq "ContainsText"}) | Should not beNullOrEmpty $cFmt.Where({$_.type -eq "ThreeIconSet"}) | Should not beNullOrEmpty } @@ -923,17 +961,17 @@ Describe ExportExcel { $excel = Open-ExcelPackage -Path $path $ws = $excel.Workbook.Worksheets[1] it "Created 3 tables " { - $ws.tables.count | should be 3 + $ws.tables.count | Should be 3 } it "Created the FileSize table in the right place with the right size and style " { - $ws.Tables["FileSize"].Address.Address | should be "G2:H16" #Insert at row 2, Column 7, 14 rows x 2 columns of data - $ws.Tables["FileSize"].StyleName | should be "TableStyleMedium2" + $ws.Tables["FileSize"].Address.Address | Should be "G2:H16" #Insert at row 2, Column 7, 14 rows x 2 columns of data + $ws.Tables["FileSize"].StyleName | Should be "TableStyleMedium2" } it "Created the ExtSize table in the right place with the right size " { - $ws.Tables["ExtSize"].Address.Address | should be "A2:B14" #tile, then 12 rows x 2 columns of data + $ws.Tables["ExtSize"].Address.Address | Should be "A2:B14" #tile, then 12 rows x 2 columns of data } it "Created the ExtCount table in the right place with the right size " { - $ws.Tables["ExtCount"].Address.Address | should be "D2:E12" #title, then 10 rows x 2 columns of data + $ws.Tables["ExtCount"].Address.Address | Should be "D2:E12" #title, then 10 rows x 2 columns of data } } diff --git a/__tests__/Join-Worksheet.tests.ps1 b/__tests__/Join-Worksheet.tests.ps1 index bf4c083..5731d7b 100644 --- a/__tests__/Join-Worksheet.tests.ps1 +++ b/__tests__/Join-Worksheet.tests.ps1 @@ -30,9 +30,9 @@ Describe "Join Worksheet" { $data2 | Export-Excel -Path $path -WorkSheetname Abingdon $data3 | Export-Excel -Path $path -WorkSheetname Banbury $ptdef = New-PivotTableDefinition -PivotTableName "SummaryPivot" -PivotRows "Store" -PivotColumns "Product" -PivotData @{"Total"="SUM"} -IncludePivotChart -ChartTitle "Sales Breakdown" -ChartType ColumnStacked -ChartColumn 10 - Join-Worksheet -Path $path -WorkSheetName "Total" -Clearsheet -FromLabel "Store" -TableName "SummaryTable" -TableStyle Light1 -AutoSize -BoldTopRow -FreezePane 2,1 -Title "Store Sales Summary" -TitleBold -TitleSize 14 -PivotTableDefinition $ptdef + Join-Worksheet -Path $path -WorkSheetName "Total" -Clearsheet -FromLabel "Store" -TableName "SummaryTable" -TableStyle Light1 -AutoSize -BoldTopRow -FreezePane 2,1 -Title "Store Sales Summary" -TitleBold -TitleSize 14 -TitleBackgroundColor AliceBlue -PivotTableDefinition $ptdef - $excel = Export-Excel -path $path -WorkSheetname SummaryPivot -Activate -HideSheet * -UnHideSheet "Total","SummaryPivot" -PassThru + $excel = Export-Excel -path $path -WorkSheetname SummaryPivot -Activate -NoTotalsInPivot -PivotDataToColumn -HideSheet * -UnHideSheet "Total","SummaryPivot" -PassThru # Open-ExcelPackage -Path $path $ws = $excel.Workbook.Worksheets["Total"] @@ -52,28 +52,31 @@ Describe "Join Worksheet" { it "Activated the correct worksheet " { $excel.Workbook.worksheets["SummaryPivot"].View.TabSelected | Should be $true $excel.Workbook.worksheets["Total"].View.TabSelected | Should be $false - } + } Context "Merging 3 blocks" { it "Created sheet of the right size with a title and a table " { $ws.Dimension.Address | Should be "A1:F16" $ws.Tables[0].Address.Address | Should be "A2:F16" - $ws.cells["A1"].Value | Should be "Store Sales Summary" - $ws.cells["A1"].Style.Font.Size | Should be 14 + $ws.Cells["A1"].Value | Should be "Store Sales Summary" + $ws.Cells["A1"].Style.Font.Size | Should be 14 + $ws.Cells["A1"].Style.Font.Bold | Should be $True + $ws.Cells["A1"].Style.Fill.BackgroundColor.Rgb | Should be "FFF0F8FF" + $ws.Cells["A1"].Style.Fill.PatternType.ToString() | Should be "Solid" $ws.Tables[0].StyleName | Should be "TableStyleLight1" - $ws.cells["A2:F2"].Style.Font.Bold | Should be $True + $ws.Cells["A2:F2"].Style.Font.Bold | Should be $True } it "Added a from column with the right heading " { - $ws.cells["F2" ].Value | Should be "Store" - $ws.cells["F3" ].Value | Should be "Oxford" - $ws.cells["F8" ].Value | Should be "Abingdon" - $ws.cells["F13"].Value | Should be "Banbury" + $ws.Cells["F2" ].Value | Should be "Store" + $ws.Cells["F3" ].Value | Should be "Oxford" + $ws.Cells["F8" ].Value | Should be "Abingdon" + $ws.Cells["F13"].Value | Should be "Banbury" } it "Filled in the data " { - $ws.cells["C3" ].Value | Should be $data1[0].quantity - $ws.cells["C8" ].Value | Should be $data2[0].quantity - $ws.cells["C13"].Value | Should be $data3[0].quantity + $ws.Cells["C3" ].Value | Should be $data1[0].quantity + $ws.Cells["C8" ].Value | Should be $data2[0].quantity + $ws.Cells["C13"].Value | Should be $data3[0].quantity } it "Created the pivot table " { $pt | Should not beNullOrEmpty diff --git a/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 b/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 index 80f1f0d..5ba8d47 100644 --- a/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 +++ b/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 @@ -145,7 +145,8 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" { Set-ExcelRange -Address $ws.Column(1) -Width 0 Set-ExcelRange -Address $ws.Column(2) -AutoFit Set-ExcelRange -Address $ws.Cells["E:E"] -AutoFit - Set-ExcelRange -Address $ws.row(5) -Height 0 + #Test alias + Set-Format -Address $ws.row(5) -Height 0 $rr = $r.row Set-ExcelRange -WorkSheet $ws -Range "B$rr" -Value "Total" $BadHideWarnvar = $null @@ -242,7 +243,10 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" { else {[datetime]::new($cyear, $bmonth, $bday) } } Set-ExcelColumn -Worksheet $ws -Heading "Age" -Value "=INT((NOW()-DateOfBirth)/365)" - Set-ExcelRange -Address $c,$ws.column(3) -NumberFormat 'Short Date' -AutoSize + # Test Piping column Numbers into Set excelColumn + 3, $c.ColumnMin | Set-ExcelColumn -Worksheet $ws -NumberFormat 'Short Date' -AutoSize + + 4..6 | Set-ExcelColumn -Worksheet $ws -AutoNameRange Close-ExcelPackage -ExcelPackage $excel -Calculate $excel = Open-ExcelPackage $path @@ -251,9 +255,8 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" { It "Inserted Hyperlinks " { $ws.Cells["D2"].Hyperlink | Should not beNullorEmpty $ws.Cells["D2"].Style.Font.UnderLine | Should be $true - } - It "Inserted Dates " { + It "Inserted and formatted Dates " { $ws.Cells["C2"].Value.GetType().name | should be "DateTime" $ws.Cells["C2"].Style.Numberformat.NumFmtID | should be 14 $ws.Cells["E2"].Value.GetType().name | should be "DateTime" @@ -262,6 +265,17 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" { It "Inserted Formulas " { $ws.Cells["F2"].Formula | Should not beNullorEmpty } + It "Created Named ranges " { + $ws.Names.Count | Should be 6 + $ws.Names["Age"] | Should not beNullorEmpty + $ws.Names["Age"].Start.Column | Should be 6 + $ws.Names["Age"].Start.Row | Should be 2 + $ws.Names["Age"].End.Row | Should be 7 + $ws.names[0].name | Should be "Name" + $ws.Names[0].Start.Column | Should be 1 + $ws.Names[0].Start.Row | Should be 2 + } + } } diff --git a/compare-worksheet.ps1 b/compare-worksheet.ps1 index 25498a5..3e86b4e 100644 --- a/compare-worksheet.ps1 +++ b/compare-worksheet.ps1 @@ -1,4 +1,4 @@ -Function Compare-WorkSheet { +Function Compare-WorkSheet { <# .Synopsis Compares two worksheets with the same name in different files. @@ -198,6 +198,8 @@ Function Compare-WorkSheet { #if nothing was found write a message which wont be redirected if (-not $diff) {Write-Host "Comparison of $Referencefile::$worksheet1 and $Differencefile::$WorkSheet2 returned no results." } + + if ($Show) { Start-Process -FilePath $Referencefile if (-not $oneFile) { Start-Process -FilePath $Differencefile }