diff --git a/Copy-ExcelWorkSheet.ps1 b/Copy-ExcelWorkSheet.ps1 index 5e6c2ac..801cf66 100644 --- a/Copy-ExcelWorkSheet.ps1 +++ b/Copy-ExcelWorkSheet.ps1 @@ -29,12 +29,12 @@ [CmdletBinding()] param( #An ExcelWorkbook or ExcelPackage object or the path to an XLSx file where the data is found. - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] $SourceWorkbook, #Name or number (starting from 1) of the worksheet in the source workbook (defaults to 1). $SourceWorkSheet = 1 , #An ExcelWorkbook or ExcelPackage object or the path to an XLSx file where the data should be copied. - [Parameter(Mandatory=$true)] + [Parameter(Mandatory = $true)] $DestinationWorkbook, #Name of the worksheet in the destination workbook; by default the same as the source worksheet's name. If the sheet exists it will be deleted and re-copied. $DestinationWorkSheet, @@ -65,46 +65,47 @@ } } else { - if ($SourceWorkbook -is [OfficeOpenXml.ExcelWorkbook]) {$sourcews=$SourceWorkbook.Worksheets[$SourceWorkSheet]} - elseif ($SourceWorkbook -is [OfficeOpenXml.ExcelPackage] ) {$sourcews=$SourceWorkbook.Workbook.Worksheets[$SourceWorkSheet]} + if ($SourceWorkbook -is [OfficeOpenXml.ExcelWorkbook]) {$sourcews = $SourceWorkbook.Worksheets[$SourceWorkSheet]} + elseif ($SourceWorkbook -is [OfficeOpenXml.ExcelPackage] ) {$sourcews = $SourceWorkbook.Workbook.Worksheets[$SourceWorkSheet]} else { - $SourceWorkbook = (Resolve-Path $SourceWorkbook).ProviderPath - try { - Write-Verbose "Opening worksheet '$Worksheetname' in Excel workbook '$SourceWorkbook'." - $Stream = New-Object -TypeName System.IO.FileStream -ArgumentList $SourceWorkbook, 'Open', 'Read' ,'ReadWrite' - $Package1 = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Stream - $sourceWs = $Package1.Workbook.Worksheets[$SourceWorkSheet] - } - catch {Write-Warning -Message "Could not open $SourceWorkbook" ; return} + $SourceWorkbook = (Resolve-Path $SourceWorkbook).ProviderPath + try { + Write-Verbose "Opening worksheet '$Worksheetname' in Excel workbook '$SourceWorkbook'." + $Stream = New-Object -TypeName System.IO.FileStream -ArgumentList $SourceWorkbook, 'Open', 'Read' , 'ReadWrite' + $Package1 = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Stream + $sourceWs = $Package1.Workbook.Worksheets[$SourceWorkSheet] + } + catch {Write-Warning -Message "Could not open $SourceWorkbook" ; return} } - if (-not $sourceWs) {Write-Warning -Message "Could not find worksheet '$Sourceworksheet' in the source workbook." ; return} + if (-not $sourceWs) {Write-Warning -Message "Could not find worksheet '$Sourceworksheet' in the source workbook." ; return} else { - try { - if ($DestinationWorkbook -is [OfficeOpenXml.ExcelWorkbook]) { - $wb = $DestinationWorkbook - } - elseif ($DestinationWorkbook -is [OfficeOpenXml.ExcelPackage] ) { - $wb = $DestinationWorkbook.workbook - if ($show) {$package2 =$DestinationWorkbook} - } - else { - $package2 = Open-ExcelPackage -Create -Path $DestinationWorkbook - $wb = $package2.Workbook - } - if (-not $DestinationWorkSheet) {$DestinationWorkSheet = $SourceWs.Name} - if ($wb.Worksheets[$DestinationWorkSheet]) { - Write-Verbose "Destination workbook already has a sheet named '$DestinationWorkSheet', deleting it." - $wb.Worksheets.Delete($DestinationWorkSheet) - } - Write-Verbose "Copying $($SourceWorkSheet) from $($SourceWorkbook) to $($DestinationWorkSheet) in $($DestinationWorkbook)" - $null = Add-WorkSheet -ExcelWorkbook $wb -WorkSheetname $DestinationWorkSheet -CopySource $sourceWs - if ($package1) {Close-ExcelPackage -ExcelPackage $Package1 -NoSave } - if ($package2) {Close-ExcelPackage -ExcelPackage $Package2 -Show:$show } - if ($show -and $DestinationWorkbook -is [OfficeOpenXml.ExcelWorkbook]) { - Write-Warning -Message "-Show only works if the Destination workbook is given as a file path or an ExcelPackage object." - } + try { + if ($DestinationWorkbook -is [OfficeOpenXml.ExcelWorkbook]) { + $wb = $DestinationWorkbook } - catch {Write-Warning -Message "Could not write to sheet '$DestinationWorkSheet' in the destination workbook" ; return} + elseif ($DestinationWorkbook -is [OfficeOpenXml.ExcelPackage] ) { + $wb = $DestinationWorkbook.workbook + if ($show) {$package2 = $DestinationWorkbook} + } + else { + $package2 = Open-ExcelPackage -Create -Path $DestinationWorkbook + $wb = $package2.Workbook + } + if (-not $DestinationWorkSheet) {$DestinationWorkSheet = $SourceWs.Name} + if ($wb.Worksheets[$DestinationWorkSheet]) { + Write-Verbose "Destination workbook already has a sheet named '$DestinationWorkSheet', deleting it." + $wb.Worksheets.Delete($DestinationWorkSheet) + } + Write-Verbose "Copying $($SourceWorkSheet) from $($SourceWorkbook) to $($DestinationWorkSheet) in $($DestinationWorkbook)" + $null = Add-WorkSheet -ExcelWorkbook $wb -WorkSheetname $DestinationWorkSheet -CopySource $sourceWs + if ($Stream) {$Stream.Close() } + if ($package1) {Close-ExcelPackage -ExcelPackage $Package1 -NoSave } + if ($package2) {Close-ExcelPackage -ExcelPackage $Package2 -Show:$show } + if ($show -and $DestinationWorkbook -is [OfficeOpenXml.ExcelWorkbook]) { + Write-Warning -Message "-Show only works if the Destination workbook is given as a file path or an ExcelPackage object." + } + } + catch {Write-Warning -Message "Could not write to sheet '$DestinationWorkSheet' in the destination workbook" ; return} } } } \ No newline at end of file diff --git a/Examples/Grouping/TimestampBucket.ps1 b/Examples/Grouping/TimestampBucket.ps1 new file mode 100644 index 0000000..7acb421 --- /dev/null +++ b/Examples/Grouping/TimestampBucket.ps1 @@ -0,0 +1,39 @@ +$data = ConvertFrom-Csv @" +Timestamp,Tenant +10/29/2018 3:00:00.123,1 +10/29/2018 3:00:10.456,1 +10/29/2018 3:01:20.389,1 +10/29/2018 3:00:30.222,1 +10/29/2018 3:00:40.143,1 +10/29/2018 3:00:50.809,1 +10/29/2018 3:01:00.193,1 +10/29/2018 3:01:10.555,1 +10/29/2018 3:01:20.739,1 +10/29/2018 3:01:30.912,1 +10/29/2018 3:01:40.989,1 +10/29/2018 3:01:50.545,1 +10/29/2018 3:02:00.999,1 +"@ | Select-Object @{n = 'Timestamp'; e = {get-date $_.timestamp}}, tenant, @{n = 'Bucket'; e = { - (get-date $_.timestamp).Second % 30}} + +$f = "$env:temp\pivottest.xlsx" +Remove-Item $f -ErrorAction SilentlyContinue + +$pivotDefParams = @{ + PivotTableName = 'Timestamp Buckets' + PivotRows = @('Timestamp', 'Tenant') + PivotData = @{'Bucket' = 'count'} + GroupDateRow = 'TimeStamp' + GroupDatePart = @('Hours', 'Minutes') + Activate = $true +} + +$excelParams = @{ + PivotTableDefinition = New-PivotTableDefinition @pivotDefParams + Path = $f + WorkSheetname = "Log Data" + AutoSize = $true + AutoFilter = $true + Show = $true +} + +$data | Export-Excel @excelParams \ No newline at end of file diff --git a/Examples/PivotTable/MultiplePivotTables.ps1 b/Examples/PivotTable/MultiplePivotTables.ps1 new file mode 100644 index 0000000..b4af519 --- /dev/null +++ b/Examples/PivotTable/MultiplePivotTables.ps1 @@ -0,0 +1,55 @@ +$data = ConvertFrom-Csv @" +Region,Date,Fruit,Sold +North,1/1/2017,Pears,50 +South,1/1/2017,Pears,150 +East,4/1/2017,Grapes,100 +West,7/1/2017,Bananas,150 +South,10/1/2017,Apples,200 +North,1/1/2018,Pears,100 +East,4/1/2018,Grapes,200 +West,7/1/2018,Bananas,300 +South,10/1/2018,Apples,400 +"@ | Select-Object -Property Region, @{n = "Date"; e = {[datetime]::ParseExact($_.Date, "M/d/yyyy", (Get-Culture))}}, Fruit, Sold + +$xlfile = "$env:temp\multiplePivotTables.xlsx" +Remove-Item $xlfile -ErrorAction SilentlyContinue + +$excel = $data | Export-Excel $xlfile -PassThru -AutoSize -TableName FruitData + +$pivotTableParams = @{ + PivotTableName = "ByRegion" + Address = $excel.Sheet1.cells["F1"] + SourceWorkSheet = $excel.Sheet1 + PivotRows = echo Region Fruit Date + PivotData = @{'sold' = 'sum'} + PivotTableStyle = 'Light21' + GroupDateRow = "Date" + GroupDatePart = echo Years Quarters +} + +$pt = Add-PivotTable @pivotTableParams -PassThru +#$pt.RowHeaderCaption ="By Region,Fruit,Date" +$pt.RowHeaderCaption = "By " + ($pivotTableParams.PivotRows -join ",") + +$pivotTableParams.PivotTableName = "ByFruit" +$pivotTableParams.Address = $excel.Sheet1.cells["J1"] +$pivotTableParams.PivotRows = echo Fruit Region Date + +$pt = Add-PivotTable @pivotTableParams -PassThru +$pt.RowHeaderCaption = "By Fruit,Region" + +$pivotTableParams.PivotTableName = "ByDate" +$pivotTableParams.Address = $excel.Sheet1.cells["N1"] +$pivotTableParams.PivotRows = echo Date Region Fruit + +$pt = Add-PivotTable @pivotTableParams -PassThru +$pt.RowHeaderCaption = "By Date,Region,Fruit" + +$pivotTableParams.PivotTableName = "ByYears" +$pivotTableParams.Address = $excel.Sheet1.cells["S1"] +$pivotTableParams.GroupDatePart = echo Years + +$pt = Add-PivotTable @pivotTableParams -PassThru +$pt.RowHeaderCaption = "By Years,Region" + +Close-ExcelPackage $excel -Show \ No newline at end of file diff --git a/Examples/Stocks/Get-StockInfo.ps1 b/Examples/Stocks/Get-StockInfo.ps1 index ffe862e..24f125a 100644 --- a/Examples/Stocks/Get-StockInfo.ps1 +++ b/Examples/Stocks/Get-StockInfo.ps1 @@ -1,25 +1,24 @@ -<# - Revisit I think yahoo deprecated their service -#> - function Get-StockInfo { param( - $stock, - [datetime]$startDate, - [datetime]$endDate + [Parameter(Mandatory)] + $symbols, + [ValidateSet('open', 'close', 'high', 'low', 'avgTotalVolume')] + $dataPlot = "close" ) - Process { + $xlfile = "$env:TEMP\stocks.xlsx" + rm $xlfile -ErrorAction Ignore - if (!$endDate) { $endDate = $startDate} + $result = Invoke-RestMethod "https://api.iextrading.com/1.0/stock/market/batch?symbols=$($symbols)&types=quote&last=1" - $baseUrl = "http://query.yahooapis.com/v1/public/yql?q=" - $q = @" -select * from yahoo.finance.historicaldata where symbol = "$($stock)" and startDate = "$($startDate.ToString('yyyy-MM-dd'))" and endDate = "$($endDate.ToString('yyyy-MM-dd'))" -"@ - $suffix = "&env=store://datatables.org/alltableswithkeys&format=json" - $r = Invoke-RestMethod ($baseUrl + $q + $suffix) - $r.query.results.quote + $symbolCount = $symbols.Split(",").count - } -} \ No newline at end of file + + $ecd = New-ExcelChartDefinition -Row 1 -Column 1 -SeriesHeader $dataPlot ` + -XRange symbol -YRange $dataPlot ` + -Title "$($dataPlot)`r`n As Of $((Get-Date).ToShortDateString())" + + $(foreach ($name in $result.psobject.Properties.name) { + $result.$name.quote + }) | Export-Excel $xlfile -AutoNameRange -AutoSize -Show -ExcelChartDefinition $ecd -StartRow 21 -StartColumn 2 +} diff --git a/Examples/Stocks/GetMSFT.ps1 b/Examples/Stocks/GetMSFT.ps1 deleted file mode 100644 index 416547e..0000000 --- a/Examples/Stocks/GetMSFT.ps1 +++ /dev/null @@ -1,20 +0,0 @@ -<# - Revisit I think yahoo deprecated their service -#> - -# try {. $PSScriptRoot\..\..\LoadPSD1.ps1} catch {} - -# $Symbol = "MSFT" - -# . .\Get-StockInfo.ps1 - -# Remove-Item *.xlsx -ErrorAction Ignore - -# $chart = New-ExcelChart -XRange Date -YRange Volume ` -# -ChartType ColumnStacked ` -# -Column 9 -Title "$Symbol Volume" - -# Get-StockInfo $Symbol 11/2 11/30 | -# Export-Excel .\stocks.xlsx -Show ` -# -AutoSize -AutoNameRange ` -# -ExcelChartDefinition $chart \ No newline at end of file diff --git a/Examples/Stocks/GetStocksAvgTotVol.ps1 b/Examples/Stocks/GetStocksAvgTotVol.ps1 new file mode 100644 index 0000000..665e776 --- /dev/null +++ b/Examples/Stocks/GetStocksAvgTotVol.ps1 @@ -0,0 +1,3 @@ +. $PSScriptRoot\Get-StockInfo.ps1 + +Get-StockInfo -symbols "msft,ibm,ge,xom,aapl" -dataPlot avgTotalVolume \ No newline at end of file diff --git a/Export-Excel.ps1 b/Export-Excel.ps1 index 8d63796..4fa5038 100644 --- a/Export-Excel.ps1 +++ b/Export-Excel.ps1 @@ -17,7 +17,7 @@ .PARAMETER ClearSheet If specified Export-Excel will remove any existing worksheet with the selected name. The Default behaviour is to overwrite cells in this sheet as needed (but leaving non-overwritten ones in place). .PARAMETER Append - If specified dat,a will be added to the end of an existing sheet, using the same column headings. + If specified data will be added to the end of an existing sheet, using the same column headings. .PARAMETER TargetData Data to insert onto the worksheet - this is usually provided from the pipeline. .PARAMETER DisplayPropertySet @@ -824,7 +824,7 @@ # 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] #Let Add-ExcelName fix (and warn about) bad names + $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 )] try {#this test can throw with some names, surpress any error if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress(($targetRangeName -replace '\W' , '_' ))) { @@ -1405,4 +1405,4 @@ function Add-ExcelTable { if ($PassThru) {return $tbl} } catch {Write-Warning -Message "Failed adding table '$TableName' to worksheet '$WorksheetName': $_"} -} \ No newline at end of file +} diff --git a/ImportExcel.psd1 b/ImportExcel.psd1 index 0d10c59..35fbf8a 100644 --- a/ImportExcel.psd1 +++ b/ImportExcel.psd1 @@ -4,7 +4,7 @@ RootModule = 'ImportExcel.psm1' # Version number of this module. - ModuleVersion = '5.4.2' + ModuleVersion = '5.4.4' # ID used to uniquely identify this module GUID = '60dd4136-feff-401a-ba27-a84458c57ede' diff --git a/ImportExcel.psm1 b/ImportExcel.psm1 index 8763513..a01477f 100644 --- a/ImportExcel.psm1 +++ b/ImportExcel.psm1 @@ -31,6 +31,7 @@ Add-Type -Path "$($PSScriptRoot)\EPPlus.dll" . $PSScriptRoot\Open-ExcelPackage.ps1 . $PSScriptRoot\Pivot.ps1 . $PSScriptRoot\PivotTable.ps1 +. $PSScriptRoot\RemoveWorksheet.ps1 . $PSScriptRoot\Send-SQLDataToExcel.ps1 . $PSScriptRoot\Set-CellStyle.ps1 . $PSScriptRoot\Set-Column.ps1 diff --git a/README.md b/README.md index ca8a073..eec27c6 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,15 @@ Install-Module ImportExcel - In Set-ExcelRange , added a 'Locked' option eqivalent to the checkbox on the Protection Tab of the format cells dialog box in Excel. - Created a Set-WorksheetProtection function. This gives the same options the protection dialog in Excel but is 0.9 release at the moment. +# What's new 5.4.4 + +- Fix issue when only a single property is piped into Export-Excel +- Fix issue in `Copy-ExcelWorksheet`, close the `$Stream` + +# What's new 5.4.3 + +- Added Remove-Worksheet: Removes one or more worksheets from one or more workbooks + # What's new 5.4.2 - Added parameters -GroupDateRow and -GroupDatePart & -GroupNumericRow, -GroupNumericMin, -GroupNumericMax and -GroupNumericInterval diff --git a/RemoveWorksheet.ps1 b/RemoveWorksheet.ps1 index a62cfd5..06c6a9c 100644 --- a/RemoveWorksheet.ps1 +++ b/RemoveWorksheet.ps1 @@ -1,34 +1,43 @@ Function Remove-WorkSheet { - Param ( - $Path, - $WorksheetName + <# + .SYNOPSIS + Removes one or more worksheets from one or more workbooks + .EXAMPLE + C:\> Remove-WorkSheet -Path Test1.xlsx -WorksheetName Sheet1 + Removes the worksheet named 'Sheet1' from 'Test1.xlsx' + + C:\> Remove-WorkSheet -Path Test1.xlsx -WorksheetName Sheet1,Target1 + Removes the worksheet named 'Sheet1' and 'Target1' from 'Test1.xlsx' + + C:\> Remove-WorkSheet -Path Test1.xlsx -WorksheetName Sheet1,Target1 -Show + Removes the worksheets and then launches the xlsx in Excel + + C:\> dir c:\reports\*.xlsx | Remove-WorkSheet + Removes 'Sheet1' from all the xlsx files in the c:\reports directory + +#> + param( + # [Parameter(ValueFromPipelineByPropertyName)] + [Parameter(ValueFromPipelineByPropertyName)] + [Alias('Path')] + $FullName, + [String[]]$WorksheetName = "Sheet1", + [Switch]$Show ) - $Path = (Resolve-Path $Path).ProviderPath - - $Excel = New-Object -TypeName OfficeOpenXml.ExcelPackage $Path - - $workSheet = $Excel.Workbook.Worksheets[$WorkSheetName] - - if($workSheet) { - if($Excel.Workbook.Worksheets.Count -gt 1) { - $Excel.Workbook.Worksheets.Delete($workSheet) - } else { - throw "Cannot delete $WorksheetName. A workbook must contain at least one visible worksheet" + Process { + if (!$FullName) { + throw "Remove-WorkSheet requires the and Excel file" } - } else { - throw "$WorksheetName not found" + $pkg = Open-ExcelPackage -Path $FullName + + if ($pkg) { + foreach ($wsn in $WorksheetName) { + $pkg.Workbook.Worksheets.Delete($wsn) + } + + Close-ExcelPackage -ExcelPackage $pkg -Show:$Show + } } - - $Excel.Save() - $Excel.Dispose() -} - - -Import-Module .\ImportExcel.psd1 -Force - -$names = Get-ExcelSheetInfo C:\Temp\testDelete.xlsx -$names | Foreach-Object { Remove-WorkSheet C:\Temp\testDelete.xlsx $_.Name} - -##Remove-WorkSheet C:\Temp\testDelete.xlsx sheet6 \ No newline at end of file +} \ No newline at end of file diff --git a/__tests__/Copy-ExcelWorksheet.Tests.ps1 b/__tests__/Copy-ExcelWorksheet.Tests.ps1 index c180027..70785eb 100644 --- a/__tests__/Copy-ExcelWorksheet.Tests.ps1 +++ b/__tests__/Copy-ExcelWorksheet.Tests.ps1 @@ -2,10 +2,10 @@ $path1 = "$env:TEMP\Test1.xlsx" $path2 = "$env:TEMP\Test2.xlsx" Remove-item -Path $path1, $path2 -ErrorAction SilentlyContinue -$ProcRange = Get-Process | Export-Excel $path1 -DisplayPropertySet -WorkSheetname Processes -ReturnRange +$ProcRange = Get-Process | Export-Excel $path1 -DisplayPropertySet -WorkSheetname Processes -ReturnRange -if ((Get-Culture).NumberFormat.CurrencySymbol -eq "£") {$OtherCurrencySymbol = "$"} -else {$OtherCurrencySymbol = "£"} +if ((Get-Culture).NumberFormat.CurrencySymbol -eq "�") {$OtherCurrencySymbol = "$"} +else {$OtherCurrencySymbol = "�"} [PSCustOmobject][Ordered]@{ Date = Get-Date Formula1 = '=SUM(F2:G2)' @@ -31,7 +31,7 @@ else {$OtherCurrencySymbol = " Link2 = "https://github.com/dfinke/ImportExcel" # Links are not copied correctly, hopefully this will be fixed at some future date } | Export-Excel -NoNumberConversion IPAddress, StrLeadZero, StrAltPhone2 -WorkSheetname MixedTypes -Path $path2 Describe "Copy-Worksheet" { - Context "Simplest copy"{ + Context "Simplest copy" { BeforeAll { Copy-ExcelWorkSheet -SourceWorkbook $path1 -DestinationWorkbook $path2 $excel = Open-ExcelPackage -Path $path2 @@ -43,12 +43,12 @@ Describe "Copy-Worksheet" { $ws.Dimension.Address | should be $ProcRange } } - Context "Mixed types using a package object"{ + Context "Mixed types using a package object" { BeforeAll { Copy-ExcelWorkSheet -SourceWorkbook $excel -DestinationWorkbook $excel -DestinationWorkSheet "CopyOfMixedTypes" Close-ExcelPackage -ExcelPackage $excel $excel = Open-ExcelPackage -Path $path2 - $ws = $Excel.Workbook.Worksheets[3] + $ws = $Excel.Workbook.Worksheets[3] } it "Copied a worksheet, giving the expected name, number of rows and number of columns " { $Excel.Workbook.Worksheets.count | Should be 3 @@ -60,29 +60,57 @@ Describe "Copy-Worksheet" { it "Copied the expected data into the worksheet " { $ws.Cells[2, 1].Value.Gettype().name | Should be 'DateTime' $ws.Cells[2, 2].Formula | Should be 'SUM(F2:G2)' - $ws.Cells[2, 5].Value.GetType().name | Should be 'String' - $ws.Cells[2, 6].Value.GetType().name | Should be 'String' + $ws.Cells[2, 5].Value.GetType().name | Should be 'String' + $ws.Cells[2, 6].Value.GetType().name | Should be 'String' $ws.Cells[2, 18].Value.GetType().name | Should be 'String' ($ws.Cells[2, 11].Value -is [valuetype] ) | Should be $true ($ws.Cells[2, 12].Value -is [valuetype] ) | Should be $true ($ws.Cells[2, 13].Value -is [valuetype] ) | Should be $true - $ws.Cells[2, 11].Value | Should beLessThan 0 - $ws.Cells[2, 12].Value | Should beLessThan 0 - $ws.Cells[2, 13].Value | Should beLessThan 0 + $ws.Cells[2, 11].Value | Should beLessThan 0 + $ws.Cells[2, 12].Value | Should beLessThan 0 + $ws.Cells[2, 13].Value | Should beLessThan 0 if ((Get-Culture).NumberFormat.NumberGroupSeparator -EQ ",") { ($ws.Cells[2, 8].Value -is [valuetype] ) | Should be $true - $ws.Cells[2, 9].Value.GetType().name | Should be 'String' + $ws.Cells[2, 9].Value.GetType().name | Should be 'String' } elseif ((Get-Culture).NumberFormat.NumberGroupSeparator -EQ ".") { ($ws.Cells[2, 9].Value -is [valuetype] ) | Should be $true - $ws.Cells[2, 8].Value.GetType().name | Should be 'String' + $ws.Cells[2, 8].Value.GetType().name | Should be 'String' } ($ws.Cells[2, 14].Value -is [valuetype] ) | Should be $true - $ws.Cells[2, 15].Value.GetType().name | Should be 'String' - $ws.Cells[2, 16].Value.GetType().name | Should be 'String' - $ws.Cells[2, 17].Value.GetType().name | Should be 'String' + $ws.Cells[2, 15].Value.GetType().name | Should be 'String' + $ws.Cells[2, 16].Value.GetType().name | Should be 'String' + $ws.Cells[2, 17].Value.GetType().name | Should be 'String' ($ws.Cells[2, 19].Value -is [valuetype] ) | Should be $true ($ws.Cells[2, 20].Value -is [valuetype] ) | Should be $true } } + + Context "Copy worksheet should close all files" { + BeforeAll { + $xlfile = "$env:TEMP\reports.xlsx" + $xlfileArchive = "$env:TEMP\reportsArchive.xlsx" + + rm $xlfile -ErrorAction SilentlyContinue + rm $xlfileArchive -ErrorAction SilentlyContinue + + $sheets = echo 1.1.2019 1.2.2019 1.3.2019 1.4.2019 1.5.2019 + + $sheets | ForEach-Object { + "Hello World" | Export-Excel $xlfile -WorksheetName $_ + } + } + + it "Should copy and remove sheets" { + $targetSheets = echo 1.1.2019 1.4.2019 + + $targetSheets | ForEach-Object { + Copy-ExcelWorkSheet -SourceWorkbook $xlfile -DestinationWorkbook $xlfileArchive -SourceWorkSheet $_ -DestinationWorkSheet $_ + } + + $targetSheets | ForEach-Object { Remove-WorkSheet -FullName $xlfile -WorksheetName $_ } + + (Get-ExcelSheetInfo -Path $xlfile ).Count | Should Be 3 + } + } } \ No newline at end of file diff --git a/__tests__/Remove-WorkSheet.tests.ps1 b/__tests__/Remove-WorkSheet.tests.ps1 new file mode 100644 index 0000000..bf39a13 --- /dev/null +++ b/__tests__/Remove-WorkSheet.tests.ps1 @@ -0,0 +1,78 @@ +#Requires -Modules Pester +Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force + +Describe "Remove Worksheet" { + Context "Remove a worksheet output" { + BeforeEach { + # Create three sheets + $data = ConvertFrom-Csv @" +Name,Age +Jane,10 +John,20 +"@ + $xlFile1 = "$env:TEMP\RemoveWorsheet1.xlsx" + Remove-Item $xlFile1 -ErrorAction SilentlyContinue + + $data | Export-Excel -Path $xlFile1 -WorksheetName Target1 + $data | Export-Excel -Path $xlFile1 -WorksheetName Target2 + $data | Export-Excel -Path $xlFile1 -WorksheetName Target3 + $data | Export-Excel -Path $xlFile1 -WorksheetName Sheet1 + + $xlFile2 = "$env:TEMP\RemoveWorsheet2.xlsx" + Remove-Item $xlFile2 -ErrorAction SilentlyContinue + + $data | Export-Excel -Path $xlFile2 -WorksheetName Target1 + $data | Export-Excel -Path $xlFile2 -WorksheetName Target2 + $data | Export-Excel -Path $xlFile2 -WorksheetName Target3 + $data | Export-Excel -Path $xlFile2 -WorksheetName Sheet1 + } + + it "Should throw about the Path" { + {Remove-WorkSheet} | Should throw 'Remove-WorkSheet requires the and Excel file' + } + + it "Should delete Target2" { + Remove-WorkSheet -Path $xlFile1 -WorksheetName Target2 + + $actual = Get-ExcelSheetInfo -Path $xlFile1 + + $actual.Count | Should Be 3 + $actual[0].Name | Should Be "Target1" + $actual[1].Name | Should Be "Target3" + $actual[2].Name | Should Be "Sheet1" + } + + it "Should delete Sheet1" { + Remove-WorkSheet -Path $xlFile1 + + $actual = Get-ExcelSheetInfo -Path $xlFile1 + + $actual.Count | Should Be 3 + $actual[0].Name | Should Be "Target1" + $actual[1].Name | Should Be "Target2" + $actual[2].Name | Should Be "Target3" + } + + it "Should delete multiple sheets" { + Remove-WorkSheet -Path $xlFile1 -WorksheetName Target1, Sheet1 + + $actual = Get-ExcelSheetInfo -Path $xlFile1 + + $actual.Count | Should Be 2 + $actual[0].Name | Should Be "Target2" + $actual[1].Name | Should Be "Target3" + } + + it "Should delete sheet from multiple workbooks" { + + Get-ChildItem "$env:TEMP\RemoveWorsheet*.xlsx" | Remove-WorkSheet + + $actual = Get-ExcelSheetInfo -Path $xlFile1 + + $actual.Count | Should Be 3 + $actual[0].Name | Should Be "Target1" + $actual[1].Name | Should Be "Target2" + $actual[2].Name | Should Be "Target3" + } + } +} \ 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 f879b2a..7f0248f 100644 --- a/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 +++ b/__tests__/Set-Row_Set-Column-SetFormat.tests.ps1 @@ -34,7 +34,7 @@ Describe "Number format expansion and setting" { $x.ListItemText | Should be "Percentage" } } - Context "Expand-NumberFormat function" { + Context "Expand-NumberFormat function" { It "Expanded named number formats as expected " { $r = [regex]::Escape([cultureinfo]::CurrentCulture.NumberFormat.CurrencySymbol) Expand-NumberFormat 'Currency' | Should match "^[$r\(\)\[\] RED0#\?\-;,.]+$" @@ -54,8 +54,8 @@ Describe "Number format expansion and setting" { Remove-Item -Path $path -ErrorAction SilentlyContinue $n = [datetime]::Now.ToOADate() - $excel = 1..32 | ForEach-Object {$n} | Export-Excel -Path $path -WorksheetName s2 -PassThru - $ws = $excel.Workbook.Worksheets[1] + $excel = 1..32 | ForEach-Object {$n} | Export-Excel -Path $path -show -WorksheetName s2 -PassThru + $ws = $excel.Workbook.Worksheets[1] Set-ExcelRange -WorkSheet $ws -Range "A1" -numberFormat 'General' Set-ExcelRange -WorkSheet $ws -Range "A2" -numberFormat 'Number' Set-ExcelRange -WorkSheet $ws -Range "A3" -numberFormat 'Percentage' @@ -91,40 +91,40 @@ Describe "Number format expansion and setting" { Close-ExcelPackage -ExcelPackage $excel $excel = Open-ExcelPackage -Path $path - $ws = $excel.Workbook.Worksheets[1] + $ws = $excel.Workbook.Worksheets[1] } It "Set formats which translate to the correct format ID " { - $ws.Cells[ 1,1].Style.Numberformat.NumFmtID | Should be 0 # Set as General - $ws.Cells[20,1].Style.Numberformat.NumFmtID | Should be 1 # Set as 0 - $ws.Cells[ 2,1].Style.Numberformat.NumFmtID | Should be 2 # Set as "Number" - $ws.Cells[21,1].Style.Numberformat.NumFmtID | Should be 2 # Set as 0.00 - $ws.Cells[22,1].Style.Numberformat.NumFmtID | Should be 3 # Set as #,##0 - $ws.Cells[23,1].Style.Numberformat.NumFmtID | Should be 4 # Set as #,##0.00 - $ws.Cells[26,1].Style.Numberformat.NumFmtID | Should be 9 # Set as 0% - $ws.Cells[27,1].Style.Numberformat.NumFmtID | Should be 10 # Set as 0.00% - $ws.Cells[ 3,1].Style.Numberformat.NumFmtID | Should be 10 # Set as "Percentage" - $ws.Cells[28,1].Style.Numberformat.NumFmtID | Should be 11 # Set as 0.00E+00 - $ws.Cells[ 4,1].Style.Numberformat.NumFmtID | Should be 11 # Set as "Scientific" - $ws.Cells[ 5,1].Style.Numberformat.NumFmtID | Should be 12 # Set as "Fraction" - $ws.Cells[29,1].Style.Numberformat.NumFmtID | Should be 12 # Set as # ?/? - $ws.Cells[30,1].Style.Numberformat.NumFmtID | Should be 13 # Set as # ??/? - $ws.Cells[ 6,1].Style.Numberformat.NumFmtID | Should be 14 # Set as "Short date" - $ws.Cells[17,1].Style.Numberformat.NumFmtID | Should be 15 # Set as d-mmm-yy - $ws.Cells[18,1].Style.Numberformat.NumFmtID | Should be 16 # Set as d-mmm - $ws.Cells[19,1].Style.Numberformat.NumFmtID | Should be 17 # Set as mmm-yy - $ws.Cells[12,1].Style.Numberformat.NumFmtID | Should be 18 # Set as h:mm AM/PM - $ws.Cells[13,1].Style.Numberformat.NumFmtID | Should be 19 # Set as h:mm:ss AM/PM - $ws.Cells[ 7,1].Style.Numberformat.NumFmtID | Should be 20 # Set as "Short time" - $ws.Cells[ 8,1].Style.Numberformat.NumFmtID | Should be 21 # Set as "Long time" - $ws.Cells[ 9,1].Style.Numberformat.NumFmtID | Should be 22 # Set as "Date-time" - $ws.Cells[14,1].Style.Numberformat.NumFmtID | Should be 45 # Set as mm:ss - $ws.Cells[15,1].Style.Numberformat.NumFmtID | Should be 46 # Set as [h]:mm:ss - $ws.Cells[16,1].Style.Numberformat.NumFmtID | Should be 47 # Set as mmss.0 - $ws.Cells[11,1].Style.Numberformat.NumFmtID | Should be 49 # Set as "Text" - $ws.Cells[31,1].Style.Numberformat.NumFmtID | Should be 49 # Set as @ - $ws.Cells[24,1].Style.Numberformat.Format | Should be '#,' # Whole thousands - $ws.Cells[25,1].Style.Numberformat.Format | Should be '#.0,,' # Millions + $ws.Cells[ 1, 1].Style.Numberformat.NumFmtID | Should be 0 # Set as General + $ws.Cells[20, 1].Style.Numberformat.NumFmtID | Should be 1 # Set as 0 + $ws.Cells[ 2, 1].Style.Numberformat.NumFmtID | Should be 2 # Set as "Number" + $ws.Cells[21, 1].Style.Numberformat.NumFmtID | Should be 2 # Set as 0.00 + $ws.Cells[22, 1].Style.Numberformat.NumFmtID | Should be 3 # Set as #,##0 + $ws.Cells[23, 1].Style.Numberformat.NumFmtID | Should be 4 # Set as #,##0.00 + $ws.Cells[26, 1].Style.Numberformat.NumFmtID | Should be 9 # Set as 0% + $ws.Cells[27, 1].Style.Numberformat.NumFmtID | Should be 10 # Set as 0.00% + $ws.Cells[ 3, 1].Style.Numberformat.NumFmtID | Should be 10 # Set as "Percentage" + $ws.Cells[28, 1].Style.Numberformat.NumFmtID | Should be 11 # Set as 0.00E+00 + $ws.Cells[ 4, 1].Style.Numberformat.NumFmtID | Should be 11 # Set as "Scientific" + $ws.Cells[ 5, 1].Style.Numberformat.NumFmtID | Should be 12 # Set as "Fraction" + $ws.Cells[29, 1].Style.Numberformat.NumFmtID | Should be 12 # Set as # ?/? + $ws.Cells[30, 1].Style.Numberformat.NumFmtID | Should be 13 # Set as # ??/? + $ws.Cells[ 6, 1].Style.Numberformat.NumFmtID | Should be 14 # Set as "Short date" + $ws.Cells[17, 1].Style.Numberformat.NumFmtID | Should be 15 # Set as d-mmm-yy + $ws.Cells[18, 1].Style.Numberformat.NumFmtID | Should be 16 # Set as d-mmm + $ws.Cells[19, 1].Style.Numberformat.NumFmtID | Should be 17 # Set as mmm-yy + $ws.Cells[12, 1].Style.Numberformat.NumFmtID | Should be 18 # Set as h:mm AM/PM + $ws.Cells[13, 1].Style.Numberformat.NumFmtID | Should be 19 # Set as h:mm:ss AM/PM + $ws.Cells[ 7, 1].Style.Numberformat.NumFmtID | Should be 20 # Set as "Short time" + $ws.Cells[ 8, 1].Style.Numberformat.NumFmtID | Should be 21 # Set as "Long time" + $ws.Cells[ 9, 1].Style.Numberformat.NumFmtID | Should be 22 # Set as "Date-time" + $ws.Cells[14, 1].Style.Numberformat.NumFmtID | Should be 45 # Set as mm:ss + $ws.Cells[15, 1].Style.Numberformat.NumFmtID | Should be 46 # Set as [h]:mm:ss + $ws.Cells[16, 1].Style.Numberformat.NumFmtID | Should be 47 # Set as mmss.0 + $ws.Cells[11, 1].Style.Numberformat.NumFmtID | Should be 49 # Set as "Text" + $ws.Cells[31, 1].Style.Numberformat.NumFmtID | Should be 49 # Set as @ + $ws.Cells[24, 1].Style.Numberformat.Format | Should be '#,' # Whole thousands + $ws.Cells[25, 1].Style.Numberformat.Format | Should be '#.0,,' # Millions } } } @@ -162,7 +162,7 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" { Context "Set-ExcelRow and Set-ExcelColumn" { it "Set a row and a column to have zero width/height " { $r | Should not beNullorEmpty - # $c | Should not beNullorEmpty ## can't see why but this test breaks in appveyor + # $c | Should not beNullorEmpty ## can't see why but this test breaks in appveyor $ws.Column(1).width | Should be 0 $ws.Row(5).height | Should be 0 } @@ -239,10 +239,10 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" { $c = Set-ExcelColumn -PassThru -Worksheet $ws -Heading "NextBirthday" -Value { $bmonth = $worksheet.Cells["C$Row"].value.month ; $bDay = $worksheet.Cells["C$Row"].value.day $cMonth = [datetime]::Now.Month ; $cday = [datetime]::Now.day ; $cyear = [datetime]::Now.Year - if (($cmonth -gt $bmonth) -or (($cMonth -eq $bmonth) -and ($cday -ge $bDay))){ - [datetime]::new($cyear+1, $bmonth, $bDay) + if (($cmonth -gt $bmonth) -or (($cMonth -eq $bmonth) -and ($cday -ge $bDay))) { + [datetime]::new($cyear + 1, $bmonth, $bDay) } - else {[datetime]::new($cyear, $bmonth, $bday) } + else {[datetime]::new($cyear, $bmonth, $bday) } } Set-ExcelColumn -Worksheet $ws -Heading "Age" -Value "=INT((NOW()-DateOfBirth)/365)" # Test Piping column Numbers into Set excelColumn @@ -253,7 +253,7 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" { Close-ExcelPackage -ExcelPackage $excel -Calculate $excel = Open-ExcelPackage $path $ws = $excel.Workbook.Worksheets["Sheet1"] - } + } It "Inserted Hyperlinks " { $ws.Cells["D2"].Hyperlink | Should not beNullorEmpty $ws.Cells["D2"].Style.Font.UnderLine | Should be $true @@ -281,14 +281,14 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" { } } -Describe "Conditional Formatting" { +Describe "Conditional Formatting" { BeforeAll { - Remove-Item $path - $data = Get-Process | Where-Object company | Select-Object company,name,pm,handles,*mem* - $cfmt = New-ConditionalFormattingIconSet -Range "c:c" -ConditionalFormat ThreeIconSet -IconType Arrows - $data | Export-Excel -path $Path -AutoSize -ConditionalFormat $cfmt - $excel = Open-ExcelPackage -Path $path - $ws = $excel.Workbook.Worksheets[1] + Remove-Item $path + $data = Get-Process | Where-Object company | Select-Object company, name, pm, handles, *mem* + $cfmt = New-ConditionalFormattingIconSet -Range "c:c" -ConditionalFormat ThreeIconSet -IconType Arrows + $data | Export-Excel -path $Path -AutoSize -ConditionalFormat $cfmt + $excel = Open-ExcelPackage -Path $path + $ws = $excel.Workbook.Worksheets[1] } Context "Using a pre-prepared 3 Arrows rule" { it "Set the right type, IconSet and range " { @@ -318,23 +318,61 @@ ID,Product,Quantity,Price,Total 12012,Pliers,3,14.99,44.97 "@ -Describe "Table Formatting" { +Describe "AutoNameRange data with a single property name" { + BeforeEach { + $xlfile = "$Env:TEMP\testNamedRange.xlsx" + rm $xlfile -ErrorAction SilentlyContinue + } + + it "Should have a single item as a named range" { + $excel = ConvertFrom-Csv @" +Sold +1 +2 +3 +4 +"@ | Export-Excel $xlfile -PassThru -AutoNameRange + + $ws = $excel.Workbook.Worksheets["Sheet1"] + + $ws.Names.Count | Should Be 1 + $ws.Names[0].Name | Should Be 'Sold' + } + + it "Should have a more than a single item as a named range" { + $excel = ConvertFrom-Csv @" +Sold,ID +1,a +2,b +3,c +4,d +"@ | Export-Excel $xlfile -PassThru -AutoNameRange + + $ws = $excel.Workbook.Worksheets["Sheet1"] + + $ws.Names.Count | Should Be 2 + $ws.Names[0].Name | Should Be 'Sold' + $ws.Names[1].Name | Should Be 'ID' + } +} + +Describe "Table Formatting" { BeforeAll { Remove-Item $path $excel = $data2 | Export-excel -path $path -WorksheetName Hardware -AutoNameRange -AutoSize -BoldTopRow -FreezeTopRow -PassThru $ws = $excel.Workbook.Worksheets[1] #test showfilter & TotalSettings - $Table = Add-ExcelTable -PassThru -Range $ws.Cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName HardwareTable -TotalSettings @{"Total"="Sum"} -ShowFirstColumn -ShowFilter:$false + $Table = Add-ExcelTable -PassThru -Range $ws.Cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName HardwareTable -TotalSettings @{"Total" = "Sum"} -ShowFirstColumn -ShowFilter:$false #test expnading named number formats Set-ExcelColumn -Worksheet $ws -Column 4 -NumberFormat 'Currency' Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'Currency' - $PtDef =New-PivotTableDefinition -PivotTableName Totals -PivotRows Product -PivotData @{"Total"="Sum"} -PivotNumberFormat Currency -PivotTotals None -PivotTableStyle Dark2 + $PtDef = New-PivotTableDefinition -PivotTableName Totals -PivotRows Product -PivotData @{"Total" = "Sum"} -PivotNumberFormat Currency -PivotTotals None -PivotTableStyle Dark2 Export-excel -ExcelPackage $excel -WorksheetName Hardware -PivotTableDefinition $PtDef - $excel= Open-ExcelPackage -Path $path - $ws1 = $excel.Workbook.Worksheets["Hardware"] - $ws2 = $excel.Workbook.Worksheets["Totals"] + $excel = Open-ExcelPackage -Path $path + $ws1 = $excel.Workbook.Worksheets["Hardware"] + $ws2 = $excel.Workbook.Worksheets["Totals"] } - Context "Setting and not clearing when Export-Excel touches the file again."{ + Context "Setting and not clearing when Export-Excel touches the file again." { it "Set the Table Options " { $ws1.Tables[0].Address.Address | should be "A1:E16" $ws1.Tables[0].Name | should be "HardwareTable" @@ -352,8 +390,4 @@ Describe "Table Formatting" { $ws2.PivotTables[0].StyleName | Should be "PivotStyleDark2" } } -} - - - - +} \ No newline at end of file