diff --git a/Examples/CustomizeExportExcel/Out-Excel.ps1 b/Examples/CustomizeExportExcel/Out-Excel.ps1 new file mode 100644 index 0000000..b320241 --- /dev/null +++ b/Examples/CustomizeExportExcel/Out-Excel.ps1 @@ -0,0 +1,89 @@ +<# + This is an example on how to customize Export-Excel to your liking. + First select a name for your function, in ths example its "Out-Excel" you can even set the name to "Export-Excel". + You can customize the following things: + 1. To add parameters to the function define them in "param()", here I added "Preset1" and "Preset2". + The parameters need to be removed after use (see comments and code below). + 2. To remove parameters from the function add them to the list under "$_.Name -notmatch", I removed "Now". + 3. Add your custom code, here I defined what the Presets do: + Preset1 configure the TableStyle, name the table depending on WorksheetName and FreezeTopRow. + Preset2 will set AutoFilter and add the Title "Daily Report". + (see comments and code below). +#> +Function Out-Excel { + [CmdletBinding(DefaultParameterSetName = 'Default')] + param( + [switch] + ${Preset1}, + [switch] + ${Preset2} + ) + DynamicParam { + $paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new() + foreach ($P in (Get-Command -Name Export-Excel).Parameters.values.where( { $_.Name -notmatch 'Verbose|Debug|Action$|Variable$|Buffer$|Now' })) { + $paramDictionary.Add($P.Name, [System.Management.Automation.RuntimeDefinedParameter]::new( $P.Name, $P.ParameterType, $P.Attributes ) ) + } + return $paramDictionary + } + + begin { + try { + # Run you custom code here if it need to run before calling Export-Excel. + $PSBoundParameters['Now'] = $true + if ($Preset1) { + $PSBoundParameters['TableStyle'] = 'Medium7' + $PSBoundParameters['FreezeTopRow'] = $true + if ($PSBoundParameters['WorksheetName'] -and -not $PSBoundParameters['TableName']) { + $PSBoundParameters['TableName'] = $PSBoundParameters['WorksheetName'] + '_Table' + } + } + elseif ($Preset2) { + $PSBoundParameters['Title'] = 'Daily Report' + $PSBoundParameters['AutoFilter'] = $true + } + # Remove the extra params we added as Export-Excel will not know what to do with them: + $null = $PSBoundParameters.Remove('Preset1') + $null = $PSBoundParameters.Remove('Preset2') + + # The rest of the code was auto generated. + $outBuffer = $null + if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { + $PSBoundParameters['OutBuffer'] = 1 + } + + $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Export-Excel', [System.Management.Automation.CommandTypes]::Function) + # You can add a pipe after @PSBoundParameters to manipulate the output. + $scriptCmd = { & $wrappedCmd @PSBoundParameters } + + $steppablePipeline = $scriptCmd.GetSteppablePipeline() + $steppablePipeline.Begin($PSCmdlet) + } + catch { + throw + } + } + + process { + try { + $steppablePipeline.Process($_) + } + catch { + throw + } + } + + end { + try { + $steppablePipeline.End() + } + catch { + throw + } + } + <# + + .ForwardHelpTargetName Export-Excel + .ForwardHelpCategory Function + + #> +} \ No newline at end of file diff --git a/Export-Excel.ps1 b/Export-Excel.ps1 index 3e2dd1a..1aad858 100644 --- a/Export-Excel.ps1 +++ b/Export-Excel.ps1 @@ -138,7 +138,7 @@ .PARAMETER Activate If there is already content in the workbook, a new sheet will not be active UNLESS Activate is specified; if a PivotTable is included it will be the active sheet .PARAMETER Now - The -Now switch is a shortcut that automatically creates a temporary file, enables "AutoSize", "AutoFilter" and "Show", and opens the file immediately. + The -Now switch is a shortcut that automatically creates a temporary file, enables "AutoSize", "TableName" and "Show", and opens the file immediately. .PARAMETER NumberFormat Formats all values that can be converted to a number to the format specified. @@ -418,12 +418,12 @@ .LINK https://github.com/dfinke/ImportExcel #> - [CmdletBinding(DefaultParameterSetName = 'Now')] + [CmdletBinding(DefaultParameterSetName = 'Default')] [OutputType([OfficeOpenXml.ExcelPackage])] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] Param( - [Parameter(Mandatory = $true, ParameterSetName = "Path", Position = 0)] + [Parameter(ParameterSetName = 'Default', Position = 0)] [String]$Path, [Parameter(Mandatory = $true, ParameterSetName = "Package")] @@ -473,14 +473,9 @@ else { $true } })] [String]$RangeName, - [ValidateScript( { - if (-not $_) { throw 'Tablename is null or empty.' } - elseif ($_[0] -notmatch '[a-z]') { throw 'Tablename starts with an invalid character.' } - else { $true } - })] - [String]$TableName, + $TableName, [OfficeOpenXml.Table.TableStyles]$TableStyle, @@ -512,7 +507,7 @@ [ScriptBlock]$CellStyleSB, #If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified [switch]$Activate, - [Parameter(ParameterSetName = 'Now')] + [Parameter(ParameterSetName = 'Default')] [Switch]$Now, [Switch]$ReturnRange, #By default PivotTables have Totals for each Row (on the right) and for each column at the bottom. This allows just one or neither to be selected. @@ -531,12 +526,15 @@ try { $script:Header = $null if ($Append -and $ClearSheet) {throw "You can't use -Append AND -ClearSheet."} + $TableName = if ($null -eq $TableName -or ($TableName -is [bool] -and $false -eq $TableName)) { $null } else {[String]$TableName} if ($PSBoundParameters.Keys.Count -eq 0 -Or $Now -or (-not $Path -and -not $ExcelPackage) ) { - $Path = [System.IO.Path]::GetTempFileName() -replace '\.tmp', '.xlsx' - $Show = $true - $AutoSize = $true - if (-not $TableName) { - $AutoFilter = $true + if (-not $PSBoundParameters.ContainsKey("Path")) { $Path = [System.IO.Path]::GetTempFileName() -replace '\.tmp', '.xlsx' } + if (-not $PSBoundParameters.ContainsKey("Show")) { $Show = $true } + if (-not $PSBoundParameters.ContainsKey("AutoSize")) { $AutoSize = $true } + if (-not $PSBoundParameters.ContainsKey("TableName") -and + -not $PSBoundParameters.ContainsKey("TableStyle") -and + -not $AutoFilter) { + $TableName = '' } } if ($ExcelPackage) { @@ -578,7 +576,7 @@ } #if we did not get a table name but there is a table which covers the active part of the sheet, set table name to that, and don't do anything with autofilter - if (-not $TableName -and $ws.Tables.Where({$_.address.address -eq $ws.dimension.address})) { + if ($null -eq $TableName -and $ws.Tables.Where({$_.address.address -eq $ws.dimension.address})) { $TableName = $ws.Tables.Where({$_.address.address -eq $ws.dimension.address},'First', 1).Name $AutoFilter = $false } @@ -809,7 +807,7 @@ if ($RangeName) { Add-ExcelName -Range $ws.Cells[$dataRange] -RangeName $RangeName} #Allow table to be inserted by specifying Name, or Style or both; only process autoFilter if there is no table (they clash). - if ($TableName) { + if ($null -ne $TableName) { if ($PSBoundParameters.ContainsKey('TableStyle')) { Add-ExcelTable -Range $ws.Cells[$dataRange] -TableName $TableName -TableStyle $TableStyle } diff --git a/__tests__/Export-Excel.Tests.ps1 b/__tests__/Export-Excel.Tests.ps1 index e0d4222..d259369 100644 --- a/__tests__/Export-Excel.Tests.ps1 +++ b/__tests__/Export-Excel.Tests.ps1 @@ -975,4 +975,86 @@ Describe ExportExcel { } } + Context " # Parameters and ParameterSets" { + $Path = "$Env:TEMP\test.xlsx" + Remove-Item -Path $Path -ErrorAction SilentlyContinue + $Processes = Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company + + it "Default Set with Path".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Path $Path -PassThru + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $ExcelPackage.File | Should Be $Path + $Worksheet.Cells['A1'].Value | Should Be 'Name' + $Worksheet.Tables | Should BeNullOrEmpty + $Worksheet.AutoFilterAddress | Should BeNullOrEmpty + } + it "ExcelPackage Set. Path and (ExcelPackage or Now) should throw".PadRight(87) { + $ExcelPackage = Export-Excel -Path $Path -PassThru + {Export-Excel -ExcelPackage $ExcelPackage -Path $Path} | Should Throw 'Parameter set cannot be resolved using the specified named parameters' + {Export-Excel -ExcelPackage $ExcelPackage -Now} | Should Throw 'Parameter set cannot be resolved using the specified named parameters' + + $Processes | Export-Excel -ExcelPackage $ExcelPackage + Remove-Item -Path $Path + } + it "If TableName and AutoFilter provided AutoFilter will be ignored".PadRight(87) { + $ExcelPackage = Export-Excel -Path $Path -PassThru -TableName 'Data' -AutoFilter + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $Worksheet.Tables[0].Name | Should Be 'Data' + $Worksheet.AutoFilterAddress | Should BeNullOrEmpty + } + it "Default Set with Path and TableName with generated name".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Path $Path -PassThru -TableName '' + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $ExcelPackage.File | Should Be $Path + $Worksheet.Tables[0].Name | Should Be 'Table1' + } + it "Now will use temp Path, set TableName with generated name and AutoSize".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Now -PassThru + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $ExcelPackage.File | Should BeLike ([IO.Path]::GetTempPath() + '*') + $Worksheet.Tables[0].Name | Should Be 'Table1' + $Worksheet.AutoFilterAddress | Should BeNullOrEmpty + $Worksheet.Column(5).Width | Should BeGreaterThan 9.5 + } + it "Now allows override of Path and TableName".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Now -PassThru -Path $Path -TableName:$false + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $ExcelPackage.File | Should Be $Path + $Worksheet.Tables | Should BeNullOrEmpty + $Worksheet.AutoFilterAddress | Should BeNullOrEmpty + $Worksheet.Column(5).Width | Should BeGreaterThan 9.5 + } + <# Mock looks unreliable need to check + Mock -CommandName 'Invoke-Item' + it "Now will Show".PadRight(87) { + $Processes | Export-Excel + Assert-MockCalled -CommandName 'Invoke-Item' -Times 1 -Exactly -Scope 'It' + } + it "Now allows override of Show".PadRight(87) { + $Processes | Export-Excel -Show:$false + Assert-MockCalled -CommandName 'Invoke-Item' -Times 0 -Exactly -Scope 'It' + } + #> + it "Now allows override of AutoSize and TableName to AutoFilter".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Now -PassThru -AutoSize:$false -AutoFilter + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $Worksheet.Tables | Should BeNullOrEmpty + $Worksheet.AutoFilterAddress | Should Not BeNullOrEmpty + [math]::Round($Worksheet.Column(5).Width, 2) | Should Be 9.14 + } + it "Now allows to set TableName".PadRight(87) { + $ExcelPackage = $Processes | Export-Excel -Now -PassThru -TableName 'Data' + $Worksheet = $ExcelPackage.Workbook.Worksheets[1] + + $Worksheet.Tables[0].Name | Should Be 'Data' + $Worksheet.AutoFilterAddress | Should BeNullOrEmpty + $Worksheet.Column(5).Width | Should BeGreaterThan 9.5 + } + } }