mirror of
https://github.com/dfinke/ImportExcel.git
synced 2025-12-06 00:23:20 +00:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b82888527f | ||
|
|
a3c71de190 | ||
|
|
f3a99f04ce | ||
|
|
f631a20269 | ||
|
|
dbd35721ee | ||
|
|
8759070636 | ||
|
|
6259b8d091 | ||
|
|
7086c3707c | ||
|
|
8b28172616 | ||
|
|
abdd37b09e | ||
|
|
e1e855a823 | ||
|
|
585d9686a6 | ||
|
|
e87a6bdaf5 | ||
|
|
5ded5111b4 | ||
|
|
914c61048b | ||
|
|
25fb76d9b7 | ||
|
|
7faa27a3b3 | ||
|
|
5700be0684 | ||
|
|
6d86108060 | ||
|
|
4581c2b3e9 | ||
|
|
142c31ccc1 | ||
|
|
b99b7ba799 | ||
|
|
17b5d2caec | ||
|
|
6add16aa9f | ||
|
|
9aa0192ee6 | ||
|
|
fa25d1ac06 | ||
|
|
8131eee50f | ||
|
|
3ce485a144 |
@@ -3,24 +3,27 @@
|
||||
.SYNOPSIS
|
||||
Copies a worksheet between workbooks or within the same workbook.
|
||||
.DESCRIPTION
|
||||
Copy-ExcelWorkSheet takes Source and Destination workbook parameters; each can be the path to an XLSx file, an ExcelPackage object or an ExcelWorkbook object.
|
||||
The Source worksheet is specified by name or number (starting from 1), and the destination worksheet can be explicitly named,
|
||||
or will follow the name of the source if no name is specified.
|
||||
Copy-ExcelWorkSheet takes a Source object which is either a worksheet,
|
||||
or a package, Workbook or path, in which case the source worksheet can be specified
|
||||
by name or number (starting from 1).
|
||||
The destination worksheet can be explicitly named, or will follow the name of the source if no name is specified.
|
||||
The Destination workbook can be given as the path to an XLSx file, an ExcelPackage object or an ExcelWorkbook object.
|
||||
|
||||
.EXAMPLE
|
||||
C:\> Copy-ExcelWorkSheet -SourceWorkbook Test1.xlsx -DestinationWorkbook Test2.xlsx
|
||||
This is the simplest version of the command: no source worksheet is specified so Copy-ExcelWorksheet uses the first sheet in the workbook
|
||||
No Destination sheet is specified so the new worksheet will be the same as the one which is being copied.
|
||||
.EXAMPLE
|
||||
C:\> Copy-ExcelWorkSheet -SourceWorkbook Server1.xlsx -sourceWorksheet "Settings" -DestinationWorkbook Settings.xlsx -DestinationWorkSheet "Server1"
|
||||
C:\> Copy-ExcelWorkSheet -SourceWorkbook Server1.xlsx -sourceWorksheet "Settings" -DestinationWorkbook Settings.xlsx -DestinationWorksheet "Server1"
|
||||
Here the Settings page from Server1's workbook is copied to the 'Server1" page of a "Settings" workbook.
|
||||
.EXAMPLE
|
||||
C:\> $excel = Open-ExcelPackage .\test.xlsx
|
||||
C:\> Copy-ExcelWorkSheet -SourceWorkbook $excel -SourceWorkSheet "first" -DestinationWorkbook $excel -Show -DestinationWorkSheet Duplicate
|
||||
C:\> Copy-ExcelWorkSheet -SourceWorkbook $excel -SourceWorkSheet "first" -DestinationWorkbook $excel -Show -DestinationWorksheet Duplicate
|
||||
This opens the workbook test.xlsx and copies the worksheet named "first" to a new worksheet named "Duplicate",
|
||||
because -Show is specified the file is saved and opened in Excel
|
||||
.EXAMPLE
|
||||
C:\> $excel = Open-ExcelPackage .\test.xlsx
|
||||
C:\> Copy-ExcelWorkSheet -SourceWorkbook $excel -SourceWorkSheet 1 -DestinationWorkbook $excel -DestinationWorkSheet Duplicate
|
||||
C:\> Copy-ExcelWorkSheet -SourceWorkbook $excel -SourceWorkSheet 1 -DestinationWorkbook $excel -DestinationWorksheet Duplicate
|
||||
C:\> Close-ExcelPackage $excel
|
||||
This is almost the same as the previous example, except source sheet is specified by position rather than name and
|
||||
because -Show is not specified, so other steps can be carried using the package object, at the end the file is saved by Close-ExcelPackage
|
||||
@@ -29,83 +32,99 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
#An ExcelWorkbook or ExcelPackage object or the path to an XLSx file where the data is found.
|
||||
[Parameter(Mandatory = $true)]
|
||||
$SourceWorkbook,
|
||||
[Parameter(Mandatory = $true,ValueFromPipeline=$true)]
|
||||
[Alias('SourceWorkbook')]
|
||||
$SourceObject,
|
||||
#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)]
|
||||
$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,
|
||||
$DestinationWorksheet,
|
||||
#if the destination is an excel package or a path, launch excel and open the file on completion.
|
||||
[Switch]$Show
|
||||
)
|
||||
#Special case - give the same path for source and destination worksheet
|
||||
if ($SourceWorkbook -is [System.String] -and $SourceWorkbook -eq $DestinationWorkbook) {
|
||||
if (-not $DestinationWorkSheet) {Write-Warning -Message "You must specify a destination worksheet name if copying within the same workbook."; return}
|
||||
else {
|
||||
Write-Verbose -Message "Copying "
|
||||
$excel = Open-ExcelPackage -Path $SourceWorkbook
|
||||
if (-not $excel.Workbook.Worksheets[$Sourceworksheet]) {
|
||||
Write-Warning -Message "Could not find Worksheet $sourceWorksheet in $sourceWorkbook"
|
||||
Close-ExcelPackage -ExcelPackage $excel -NoSave
|
||||
return
|
||||
}
|
||||
elseif ($excel.Workbook.Worksheets[$Sourceworksheet].name -eq $DestinationWorkSheet) {
|
||||
Write-Warning -Message "The destination worksheet name is the same as the source. "
|
||||
Close-ExcelPackage -ExcelPackage $excel -NoSave
|
||||
return
|
||||
}
|
||||
begin {
|
||||
#For the case where we are piped multiple sheets, we want to open the destination in the begin and close it in the end.
|
||||
if ($DestinationWorkbook -is [OfficeOpenXml.ExcelPackage] ) {
|
||||
if ($Show) {$package2 = $DestinationWorkbook}
|
||||
$DestinationWorkbook = $DestinationWorkbook.Workbook
|
||||
}
|
||||
elseif ($DestinationWorkbook -is [string] -and ($DestinationWorkbook -ne $SourceObject)) {
|
||||
$package2 = Open-ExcelPackage -Create -Path $DestinationWorkbook
|
||||
$DestinationWorkbook = $package2.Workbook
|
||||
}
|
||||
}
|
||||
process {
|
||||
#Special case - given the same path for source and destination worksheet
|
||||
if ($SourceObject -is [System.String] -and $SourceObject -eq $DestinationWorkbook) {
|
||||
if (-not $DestinationWorksheet) {Write-Warning -Message "You must specify a destination worksheet name if copying within the same workbook."; return}
|
||||
else {
|
||||
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname $DestinationWorkSheet -CopySource ($excel.Workbook.Worksheets[$SourceWorkSheet])
|
||||
Close-ExcelPackage -ExcelPackage $excel -Show:$Show
|
||||
return
|
||||
Write-Verbose -Message "Copying "
|
||||
$excel = Open-ExcelPackage -Path $SourceObject
|
||||
if (-not $excel.Workbook.Worksheets[$Sourceworksheet]) {
|
||||
Write-Warning -Message "Could not find Worksheet $sourceWorksheet in $SourceObject"
|
||||
Close-ExcelPackage -ExcelPackage $excel -NoSave
|
||||
return
|
||||
}
|
||||
elseif ($excel.Workbook.Worksheets[$Sourceworksheet].name -eq $DestinationWorksheet) {
|
||||
Write-Warning -Message "The destination worksheet name is the same as the source. "
|
||||
Close-ExcelPackage -ExcelPackage $excel -NoSave
|
||||
return
|
||||
}
|
||||
else {
|
||||
$null = Add-WorkSheet -ExcelPackage $excel -WorkSheetname $DestinationWorksheet -CopySource ($excel.Workbook.Worksheets[$SourceWorkSheet])
|
||||
Close-ExcelPackage -ExcelPackage $excel -Show:$Show
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($SourceObject -is [OfficeOpenXml.ExcelWorksheet]) {$sourceWs = $SourceObject}
|
||||
elseif ($SourceObject -is [OfficeOpenXml.ExcelWorkbook]) {$sourceWs = $SourceObject.Worksheets[$SourceWorkSheet]}
|
||||
elseif ($SourceObject -is [OfficeOpenXml.ExcelPackage] ) {$sourceWs = $SourceObject.Workbook.Worksheets[$SourceWorkSheet]}
|
||||
else {
|
||||
$SourceObject = (Resolve-Path $SourceObject).ProviderPath
|
||||
try {
|
||||
Write-Verbose "Opening worksheet '$Worksheetname' in Excel workbook '$SourceObject'."
|
||||
$stream = New-Object -TypeName System.IO.FileStream -ArgumentList $SourceObject, 'Open', 'Read' , 'ReadWrite'
|
||||
$package1 = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream
|
||||
$sourceWs = $Package1.Workbook.Worksheets[$SourceWorkSheet]
|
||||
}
|
||||
catch {Write-Warning -Message "Could not open $SourceObject - the error was '$($_.exception.message)' " ; return}
|
||||
}
|
||||
if (-not $sourceWs) {Write-Warning -Message "Could not find worksheet '$Sourceworksheet' in the source workbook." ; return}
|
||||
else {
|
||||
try {
|
||||
if ($DestinationWorkbook -isnot [OfficeOpenXml.ExcelWorkbook]) {
|
||||
Write-Warning "Not a valid workbook" ; return
|
||||
}
|
||||
#check if we have a destination sheet name and set one if not. Because we might loop round check $psBoundParameters, not the variable.
|
||||
if (-not $PSBoundParameters['DestinationWorksheet']) {
|
||||
#if we are piped files, use the file name without the extension as the destination sheet name, Otherwise use the source sheet name
|
||||
if ($_ -is [System.IO.FileInfo]) {$DestinationWorksheet = $_.name -replace '\.xlsx$', '' }
|
||||
else { $DestinationWorksheet = $sourceWs.Name}
|
||||
}
|
||||
if ($DestinationWorkbook.Worksheets[$DestinationWorksheet]) {
|
||||
Write-Verbose "Destination workbook already has a sheet named '$DestinationWorksheet', deleting it."
|
||||
$DestinationWorkbook.Worksheets.Delete($DestinationWorksheet)
|
||||
}
|
||||
Write-Verbose "Copying '$($sourcews.name)' from $($SourceObject) to '$($DestinationWorksheet)' in $($PSBoundParameters['DestinationWorkbook'])"
|
||||
$null = Add-WorkSheet -ExcelWorkbook $DestinationWorkbook -WorkSheetname $DestinationWorksheet -CopySource $sourceWs
|
||||
#Leave the destination open but close the source - if we're copying more than one sheet we'll re-open it and live with the inefficiency
|
||||
if ($stream) {$stream.Close() }
|
||||
if ($package1) {Close-ExcelPackage -ExcelPackage $package1 -NoSave }
|
||||
}
|
||||
catch {Write-Warning -Message "Could not write to sheet '$DestinationWorksheet' in the destination workbook. Error was '$($_.exception.message)'" ; return}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
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}
|
||||
}
|
||||
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 ($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}
|
||||
end {
|
||||
#OK Now we can close the destination package
|
||||
if ($package2) {Close-ExcelPackage -ExcelPackage $package2 -Show:$Show }
|
||||
if ($Show -and -not $package2) {
|
||||
Write-Warning -Message "-Show only works if the Destination workbook is given as a file path or an ExcelPackage object."
|
||||
}
|
||||
}
|
||||
}
|
||||
21
Examples/Charts/ChartAndTrendlines.ps1
Normal file
21
Examples/Charts/ChartAndTrendlines.ps1
Normal file
@@ -0,0 +1,21 @@
|
||||
# Creates a worksheet, addes a chart and then a Linear trendline
|
||||
|
||||
$xlfile = "$env:TEMP\trendLine.xlsx"
|
||||
Remove-Item $xlfile -ErrorAction SilentlyContinue
|
||||
|
||||
$data = ConvertFrom-Csv @"
|
||||
Region,Item,TotalSold
|
||||
West,screws,60
|
||||
South,lemon,48
|
||||
South,apple,71
|
||||
East,screwdriver,70
|
||||
East,kiwi,32
|
||||
West,screwdriver,1
|
||||
South,melon,21
|
||||
East,apple,79
|
||||
South,apple,68
|
||||
South,avocado,73
|
||||
"@
|
||||
|
||||
$cd = New-ExcelChartDefinition -XRange Region -YRange TotalSold -ChartType ColumnClustered -ChartTrendLine Linear
|
||||
$data | Export-Excel $xlfile -ExcelChartDefinition $cd -AutoNameRange -Show
|
||||
27
Examples/Charts/NumberOfVisitors.ps1
Normal file
27
Examples/Charts/NumberOfVisitors.ps1
Normal file
@@ -0,0 +1,27 @@
|
||||
$xlfile = "$env:TEMP\visitors.xlsx"
|
||||
Remove-Item $xlfile -ErrorAction SilentlyContinue
|
||||
|
||||
$data = ConvertFrom-Csv @"
|
||||
Week, TotalVisitors
|
||||
1,11916
|
||||
2,11665
|
||||
3,13901
|
||||
4,15444
|
||||
5,21592
|
||||
6,15057
|
||||
7,26187
|
||||
8,20662
|
||||
9,28935
|
||||
10,32443
|
||||
"@
|
||||
|
||||
$cd = New-ExcelChartDefinition `
|
||||
-XRange Week `
|
||||
-YRange TotalVisitors `
|
||||
-Title "No. Of Visitors" `
|
||||
-ChartType ColumnClustered `
|
||||
-NoLegend `
|
||||
-ChartTrendLine Linear
|
||||
|
||||
$data | Export-Excel $xlfile -Show -AutoNameRange -AutoSize -TableName Visitors -ExcelChartDefinition $cd
|
||||
|
||||
@@ -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", "AutoFiler" and "Show", and opens the file immediately.
|
||||
The -Now switch is a shortcut that automatically creates a temporary file, enables "AutoSize", "AutoFilter" and "Show", and opens the file immediately.
|
||||
.PARAMETER NumberFormat
|
||||
Formats all values that can be converted to a number to the format specified.
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
RootModule = 'ImportExcel.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '6.2.0'
|
||||
ModuleVersion = '6.2.3'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '60dd4136-feff-401a-ba27-a84458c57ede'
|
||||
|
||||
@@ -48,7 +48,7 @@ if ($PSVersionTable.PSVersion.Major -ge 5) {
|
||||
. $PSScriptRoot\plot.ps1
|
||||
|
||||
Function New-Plot {
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification='New-Plot does not change system state')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'New-Plot does not change system state')]
|
||||
Param()
|
||||
|
||||
[PSPlot]::new()
|
||||
@@ -269,7 +269,6 @@ function Import-Excel {
|
||||
[Parameter(ParameterSetName = "PathA", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )]
|
||||
[Parameter(ParameterSetName = "PathB", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )]
|
||||
[Parameter(ParameterSetName = "PathC", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )]
|
||||
[ValidateScript( {(Test-Path -Path $_ -PathType Leaf) -and ($_ -match '.xls$|.xlsx$|.xlsm$')})]
|
||||
[String]$Path,
|
||||
[Parameter(ParameterSetName = "PackageA", Mandatory)]
|
||||
[Parameter(ParameterSetName = "PackageB", Mandatory)]
|
||||
@@ -300,12 +299,13 @@ function Import-Excel {
|
||||
)
|
||||
begin {
|
||||
$sw = [System.Diagnostics.Stopwatch]::StartNew()
|
||||
|
||||
Function Get-PropertyNames {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Create objects containing the column number and the column name for each of the different header types.
|
||||
#>
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification="Name would be incorrect, and command is not exported")]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = "Name would be incorrect, and command is not exported")]
|
||||
Param (
|
||||
[Parameter(Mandatory)]
|
||||
[Int[]]$Columns,
|
||||
@@ -318,13 +318,13 @@ function Import-Excel {
|
||||
$i = 0
|
||||
foreach ($C in $Columns) {
|
||||
$i++
|
||||
$C | Select-Object @{N = 'Column'; E = {$_}}, @{N = 'Value'; E = {'P' + $i}}
|
||||
$C | Select-Object @{N = 'Column'; E = { $_ } }, @{N = 'Value'; E = { 'P' + $i } }
|
||||
}
|
||||
}
|
||||
elseif ($HeaderName) {
|
||||
$i = 0
|
||||
foreach ($H in $HeaderName) {
|
||||
$H | Select-Object @{N = 'Column'; E = {$Columns[$i]}}, @{N = 'Value'; E = {$H}}
|
||||
$H | Select-Object @{N = 'Column'; E = { $Columns[$i] } }, @{N = 'Value'; E = { $H } }
|
||||
$i++
|
||||
}
|
||||
}
|
||||
@@ -334,7 +334,7 @@ function Import-Excel {
|
||||
}
|
||||
|
||||
foreach ($C in $Columns) {
|
||||
$Worksheet.Cells[$StartRow, $C] | Where-Object {$_.Value} | Select-Object @{N = 'Column'; E = {$C}}, Value
|
||||
$Worksheet.Cells[$StartRow, $C] | Where-Object { $_.Value } | Select-Object @{N = 'Column'; E = { $C } }, Value
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -346,43 +346,57 @@ function Import-Excel {
|
||||
|
||||
process {
|
||||
if ($path) {
|
||||
$extension = [System.IO.Path]::GetExtension($Path)
|
||||
if ($extension -notmatch '.xlsx$|.xlsm$') {
|
||||
throw "Import-Excel does not support reading this extension type $($extension)"
|
||||
}
|
||||
|
||||
$resolvedPath = (Resolve-Path $Path -ErrorAction SilentlyContinue)
|
||||
if ($resolvedPath) {
|
||||
$Path = $resolvedPath.ProviderPath
|
||||
}
|
||||
else {
|
||||
throw "'$($Path)' file not found"
|
||||
}
|
||||
|
||||
$stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path, 'Open', 'Read', 'ReadWrite'
|
||||
if ($Password) {$ExcelPackage = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream , $Password }
|
||||
else {$ExcelPackage = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream}
|
||||
$ExcelPackage = New-Object -TypeName OfficeOpenXml.ExcelPackage
|
||||
if ($Password) { $ExcelPackage.Load($stream,$Password)}
|
||||
else { $ExcelPackage.Load($stream) }
|
||||
}
|
||||
try {
|
||||
#Select worksheet
|
||||
if (-not $WorksheetName) { $Worksheet = $ExcelPackage.Workbook.Worksheets[1] }
|
||||
elseif(-not ($Worksheet = $ExcelPackage.Workbook.Worksheets[$WorkSheetName])) {
|
||||
throw "Worksheet '$WorksheetName' not found, the workbook only contains the worksheets '$($ExcelPackage.Workbook.Worksheets)'. If you only wish to select the first worksheet, please remove the '-WorksheetName' parameter." ; return
|
||||
elseif (-not ($Worksheet = $ExcelPackage.Workbook.Worksheets[$WorkSheetName])) {
|
||||
throw "Worksheet '$WorksheetName' not found, the workbook only contains the worksheets '$($ExcelPackage.Workbook.Worksheets)'. If you only wish to select the first worksheet, please remove the '-WorksheetName' parameter." ; return
|
||||
}
|
||||
|
||||
Write-Debug $sw.Elapsed.TotalMilliseconds
|
||||
#region Get rows and columns
|
||||
#If we are doing dataonly it is quicker to work out which rows to ignore before processing the cells.
|
||||
if (-not $EndRow ) {$EndRow = $Worksheet.Dimension.End.Row }
|
||||
if (-not $EndColumn) {$EndColumn = $Worksheet.Dimension.End.Column }
|
||||
if (-not $EndRow ) { $EndRow = $Worksheet.Dimension.End.Row }
|
||||
if (-not $EndColumn) { $EndColumn = $Worksheet.Dimension.End.Column }
|
||||
$endAddress = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[$EndRow]C[$EndColumn]", 0, 0)
|
||||
if ($DataOnly) {
|
||||
#If we are using headers startrow will be the header-row so examine data from startRow + 1,
|
||||
if ($NoHeader) {$range = "A" + ($StartRow ) + ":" + $endAddress }
|
||||
else {$range = "A" + ($StartRow + 1 ) + ":" + $endAddress }
|
||||
if ($NoHeader) { $range = "A" + ($StartRow ) + ":" + $endAddress }
|
||||
else { $range = "A" + ($StartRow + 1 ) + ":" + $endAddress }
|
||||
#We're going to look at every cell and build 2 hash tables holding rows & columns which contain data.
|
||||
#Want to Avoid 'select unique' operations & large Sorts, becuse time time taken increases with square
|
||||
#of number of items (PS uses heapsort at large size). Instead keep a list of what we have seen,
|
||||
#using Hash tables: "we've seen it" is all we need, no need to worry about "seen it before" / "Seen it many times".
|
||||
$colHash = @{}
|
||||
$rowHash = @{}
|
||||
$colHash = @{ }
|
||||
$rowHash = @{ }
|
||||
foreach ($cell in $Worksheet.Cells[$range]) {
|
||||
if ($null -ne $cell.Value ) {$colHash[$cell.Start.Column] = 1; $rowHash[$cell.Start.row] = 1 }
|
||||
if ($null -ne $cell.Value ) { $colHash[$cell.Start.Column] = 1; $rowHash[$cell.Start.row] = 1 }
|
||||
}
|
||||
$rows = ( $StartRow..$EndRow ).Where( {$rowHash[$_]})
|
||||
$columns = ($StartColumn..$EndColumn).Where( {$colHash[$_]})
|
||||
$rows = ( $StartRow..$EndRow ).Where( { $rowHash[$_] })
|
||||
$columns = ($StartColumn..$EndColumn).Where( { $colHash[$_] })
|
||||
}
|
||||
else {
|
||||
$Columns = $StartColumn .. $EndColumn ; if ($StartColumn -gt $EndColumn) {Write-Warning -Message "Selecting columns $StartColumn to $EndColumn might give odd results."}
|
||||
if ($NoHeader) {$Rows = $StartRow..$EndRow ; if ($StartRow -gt $EndRow) {Write-Warning -Message "Selecting rows $StartRow to $EndRow might give odd results."} }
|
||||
else {$Rows = (1 + $StartRow)..$EndRow ; if ($StartRow -ge $EndRow) {Write-Warning -Message "Selecting $StartRow as the header with data in $(1+$StartRow) to $EndRow might give odd results."}}
|
||||
$Columns = $StartColumn .. $EndColumn ; if ($StartColumn -gt $EndColumn) { Write-Warning -Message "Selecting columns $StartColumn to $EndColumn might give odd results." }
|
||||
if ($NoHeader) { $Rows = $StartRow..$EndRow ; if ($StartRow -gt $EndRow) { Write-Warning -Message "Selecting rows $StartRow to $EndRow might give odd results." } }
|
||||
else { $Rows = (1 + $StartRow)..$EndRow } # ; if ($StartRow -ge $EndRow) { Write-Warning -Message "Selecting $StartRow as the header with data in $(1+$StartRow) to $EndRow might give odd results." } }
|
||||
}
|
||||
#endregion
|
||||
#region Create property names
|
||||
@@ -402,7 +416,7 @@ function Import-Excel {
|
||||
foreach ($R in $Rows) {
|
||||
#Disabled write-verbose for speed
|
||||
# Write-Verbose "Import row '$R'"
|
||||
$NewRow = [Ordered]@{}
|
||||
$NewRow = [Ordered]@{ }
|
||||
|
||||
foreach ($P in $PropertyNames) {
|
||||
$NewRow[$P.Value] = $Worksheet.Cells[$R, $P.Column].Value
|
||||
@@ -417,7 +431,7 @@ function Import-Excel {
|
||||
}
|
||||
catch { throw "Failed importing the Excel workbook '$Path' with worksheet '$Worksheetname': $_"; return }
|
||||
finally {
|
||||
if ($Path) {$stream.close(); $ExcelPackage.Dispose() }
|
||||
if ($Path) { $stream.close(); $ExcelPackage.Dispose() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -463,9 +477,9 @@ function ConvertFrom-ExcelSheet {
|
||||
$xl = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Stream
|
||||
$workbook = $xl.Workbook
|
||||
|
||||
$targetSheets = $workbook.Worksheets | Where-Object {$_.Name -like $SheetName}
|
||||
$targetSheets = $workbook.Worksheets | Where-Object { $_.Name -like $SheetName }
|
||||
|
||||
$params = @{} + $PSBoundParameters
|
||||
$params = @{ } + $PSBoundParameters
|
||||
$params.Remove("OutputPath")
|
||||
$params.Remove("SheetName")
|
||||
$params.Remove('Extension')
|
||||
@@ -496,7 +510,7 @@ function Export-MultipleExcelSheets {
|
||||
[Switch]$AutoSize
|
||||
)
|
||||
|
||||
$parameters = @{} + $PSBoundParameters
|
||||
$parameters = @{ } + $PSBoundParameters
|
||||
$parameters.Remove("InfoMap")
|
||||
$parameters.Remove("Show")
|
||||
|
||||
@@ -509,7 +523,7 @@ function Export-MultipleExcelSheets {
|
||||
& $entry.Value | Export-Excel @parameters
|
||||
}
|
||||
|
||||
if ($Show) {Invoke-Item $Path}
|
||||
if ($Show) { Invoke-Item $Path }
|
||||
}
|
||||
|
||||
Function WorksheetArgumentCompleter {
|
||||
@@ -519,7 +533,7 @@ Function WorksheetArgumentCompleter {
|
||||
$xlpkg = Open-ExcelPackage -ReadOnly -Path $xlPath
|
||||
$WorksheetNames = $xlPkg.Workbook.Worksheets.Name
|
||||
Close-ExcelPackage -nosave -ExcelPackage $xlpkg
|
||||
$WorksheetNames.where( {$_ -like "*$wordToComplete*"}) | foreach-object {
|
||||
$WorksheetNames.where( { $_ -like "*$wordToComplete*" }) | foreach-object {
|
||||
New-Object -TypeName System.Management.Automation.CompletionResult -ArgumentList "'$_'",
|
||||
$_ , ([System.Management.Automation.CompletionResultType]::ParameterValue) , $_
|
||||
}
|
||||
|
||||
@@ -97,11 +97,12 @@
|
||||
#>
|
||||
[Alias("New-ExcelChart")] #This was the former name. The new name reflects that we are defining a chart, not making one in the workbook.
|
||||
[cmdletbinding()]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '',Justification='Does not change system State')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Does not change system State')]
|
||||
param(
|
||||
$Title = "Chart Title",
|
||||
$Header,
|
||||
[OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = "ColumnStacked",
|
||||
[OfficeOpenXml.Drawing.Chart.eTrendLine[]]$ChartTrendLine,
|
||||
$XRange,
|
||||
$YRange,
|
||||
$Width = 500,
|
||||
@@ -138,11 +139,12 @@
|
||||
$YMinValue,
|
||||
[OfficeOpenXml.Drawing.Chart.eAxisPosition]$YAxisPosition
|
||||
)
|
||||
if ( $Header ) {Write-Warning "The header parameter is ignored."} #Nothing was done with it when creating a chart.
|
||||
if ( $Header ) { Write-Warning "The header parameter is ignored." } #Nothing was done with it when creating a chart.
|
||||
#might be able to do [PSCustomObject]$PsboundParameters, the defaults here match those in Add-Excel Chart
|
||||
[PSCustomObject]@{
|
||||
Title = $Title
|
||||
ChartType = $ChartType
|
||||
ChartTrendLine = $ChartTrendLine
|
||||
XRange = $XRange
|
||||
YRange = $YRange
|
||||
Width = $Width
|
||||
@@ -151,14 +153,14 @@
|
||||
RowOffSetPixels = $RowOffSetPixels
|
||||
Column = $Column
|
||||
ColumnOffSetPixels = $ColumnOffSetPixels
|
||||
LegendPosition = $LegendPosition
|
||||
LegendPosition = $LegendPosition
|
||||
LegendSize = $LegendSize
|
||||
Legendbold = $LegendBold
|
||||
NoLegend = $NoLegend -as [Boolean]
|
||||
NoLegend = $NoLegend -as [Boolean]
|
||||
ShowCategory = $ShowCategory -as [Boolean]
|
||||
ShowPercent = $ShowPercent -as [Boolean]
|
||||
ShowPercent = $ShowPercent -as [Boolean]
|
||||
SeriesHeader = $SeriesHeader
|
||||
TitleBold = $TitleBold -as [Boolean]
|
||||
TitleBold = $TitleBold -as [Boolean]
|
||||
TitleSize = $TitleSize
|
||||
XAxisTitleText = $XAxisTitleText
|
||||
XAxisTitleBold = $XAxisTitleBold -as [Boolean]
|
||||
@@ -170,7 +172,7 @@
|
||||
XMinValue = $XMinValue
|
||||
XAxisPosition = $XAxisPosition
|
||||
YAxisTitleText = $YAxisTitleText
|
||||
YAxisTitleBold = $YAxisTitleBold -as [Boolean]
|
||||
YAxisTitleBold = $YAxisTitleBold -as [Boolean]
|
||||
YAxisTitleSize = $YAxisTitleSize
|
||||
YAxisNumberformat = $YAxisNumberformat
|
||||
YMajorUnit = $YMajorUnit
|
||||
@@ -326,24 +328,25 @@ function Add-ExcelChart {
|
||||
and is marked off in units of 0.25 shown to two decimal places.
|
||||
The key will for the chart will be at the bottom in 8 point bold type and the line will be named "Sin(x)".
|
||||
#>
|
||||
[cmdletbinding(DefaultParameterSetName='Worksheet')]
|
||||
[cmdletbinding(DefaultParameterSetName = 'Worksheet')]
|
||||
[OutputType([OfficeOpenXml.Drawing.Chart.ExcelChart])]
|
||||
param(
|
||||
[Parameter(ParameterSetName='Workshet',Mandatory=$true)]
|
||||
[Parameter(ParameterSetName = 'Workshet', Mandatory = $true)]
|
||||
[OfficeOpenXml.ExcelWorksheet]$Worksheet,
|
||||
[Parameter(ParameterSetName='PivotTable',Mandatory=$true)]
|
||||
[Parameter(ParameterSetName = 'PivotTable', Mandatory = $true)]
|
||||
[OfficeOpenXml.Table.PivotTable.ExcelPivotTable]$PivotTable ,
|
||||
[String]$Title,
|
||||
#$Header, Not used but referenced previously
|
||||
[OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = "ColumnStacked",
|
||||
[OfficeOpenXml.Drawing.Chart.eTrendLine[]]$ChartTrendLine,
|
||||
$XRange,
|
||||
$YRange,
|
||||
[int]$Width = 500,
|
||||
[int]$Height = 350,
|
||||
[int]$Row = 0,
|
||||
[int]$RowOffSetPixels = 10,
|
||||
[int]$Column = 6,
|
||||
[int]$ColumnOffSetPixels = 5,
|
||||
[int]$Width = 500,
|
||||
[int]$Height = 350,
|
||||
[int]$Row = 0,
|
||||
[int]$RowOffSetPixels = 10,
|
||||
[int]$Column = 6,
|
||||
[int]$ColumnOffSetPixels = 5,
|
||||
[OfficeOpenXml.Drawing.Chart.eLegendPosition]$LegendPosition,
|
||||
$LegendSize,
|
||||
[Switch]$LegendBold,
|
||||
@@ -372,11 +375,11 @@ function Add-ExcelChart {
|
||||
$YMinValue,
|
||||
[OfficeOpenXml.Drawing.Chart.eAxisPosition]$YAxisPosition,
|
||||
[Switch]$PassThru
|
||||
)
|
||||
)
|
||||
try {
|
||||
if ($PivotTable) {
|
||||
$Worksheet = $PivotTable.WorkSheet
|
||||
$chart = $Worksheet.Drawings.AddChart(("Chart" + $PivotTable.Name ),$ChartType,$PivotTable)
|
||||
$chart = $Worksheet.Drawings.AddChart(("Chart" + $PivotTable.Name ), $ChartType, $PivotTable)
|
||||
}
|
||||
else {
|
||||
$ChartName = 'Chart' + (Split-Path -Leaf ([System.IO.path]::GetTempFileName())) -replace 'tmp|\.', ''
|
||||
@@ -384,75 +387,85 @@ function Add-ExcelChart {
|
||||
$chartDefCount = @($YRange).Count
|
||||
if ($chartDefCount -eq 1) {
|
||||
$Series = $chart.Series.Add($YRange, $XRange)
|
||||
if ($SeriesHeader) { $Series.Header = $SeriesHeader}
|
||||
else { $Series.Header = 'Series 1'}
|
||||
if ($ChartTrendLine) {
|
||||
if ($ChartType -notmatch "stacked|3D$|pie|Doughnut|Cone|Cylinder|Pyramid") {
|
||||
foreach ($trendLine in $ChartTrendLine) {
|
||||
$null = $Series.TrendLines.Add($trendLine)
|
||||
}
|
||||
}
|
||||
else {
|
||||
Write-Warning "Chart trend line is not supported for chart type: $ChartType"
|
||||
}
|
||||
}
|
||||
if ($SeriesHeader) { $Series.Header = $SeriesHeader }
|
||||
else { $Series.Header = 'Series 1' }
|
||||
}
|
||||
else {
|
||||
for ($idx = 0; $idx -lt $chartDefCount; $idx += 1) {
|
||||
if ($Yrange.count -eq $xrange.count) {
|
||||
$Series = $chart.Series.Add($YRange[$idx], $XRange[$idx])
|
||||
$Series = $chart.Series.Add($YRange[$idx], $XRange[$idx])
|
||||
}
|
||||
else {
|
||||
$Series = $chart.Series.Add($YRange[$idx], $XRange)
|
||||
$Series = $chart.Series.Add($YRange[$idx], $XRange)
|
||||
}
|
||||
if ($SeriesHeader.Count -gt 0) {
|
||||
if ($SeriesHeader[$idx] -match '^=') {$Series.HeaderAddress = $SeriesHeader[$idx] -replace '^=',''}
|
||||
else {$Series.Header = $SeriesHeader[$idx] }
|
||||
if ($SeriesHeader[$idx] -match '^=') { $Series.HeaderAddress = $SeriesHeader[$idx] -replace '^=', '' }
|
||||
else { $Series.Header = $SeriesHeader[$idx] }
|
||||
}
|
||||
else { $Series.Header = "Series $($idx)"}
|
||||
else { $Series.Header = "Series $($idx)" }
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($Title) {
|
||||
$chart.Title.Text = $Title
|
||||
if ($TitleBold) {$chart.Title.Font.Bold = $true}
|
||||
if ($TitleSize) {$chart.Title.Font.Size = $TitleSize}
|
||||
if ($TitleBold) { $chart.Title.Font.Bold = $true }
|
||||
if ($TitleSize) { $chart.Title.Font.Size = $TitleSize }
|
||||
}
|
||||
if ($NoLegend) { $chart.Legend.Remove() }
|
||||
else {
|
||||
if ($PSBoundParameters.ContainsKey('LegendPosition')) {$chart.Legend.Position = $LegendPosition}
|
||||
if ($PSBoundParameters.ContainsKey('LegendBold')) {$chart.Legend.Font.Bold = [boolean]$LegendBold}
|
||||
if ($LegendSize) {$chart.Legend.Font.Size = $LegendSize}
|
||||
if ($PSBoundParameters.ContainsKey('LegendPosition')) { $chart.Legend.Position = $LegendPosition }
|
||||
if ($PSBoundParameters.ContainsKey('LegendBold')) { $chart.Legend.Font.Bold = [boolean]$LegendBold }
|
||||
if ($LegendSize) { $chart.Legend.Font.Size = $LegendSize }
|
||||
}
|
||||
|
||||
if ($XAxisTitleText) {
|
||||
if ($XAxisTitleText) {
|
||||
$chart.XAxis.Title.Text = $XAxisTitleText
|
||||
if ($PSBoundParameters.ContainsKey('XAxisTitleBold')) {
|
||||
$chart.XAxis.Title.Font.Bold = [boolean]$XAxisTitleBold
|
||||
if ($PSBoundParameters.ContainsKey('XAxisTitleBold')) {
|
||||
$chart.XAxis.Title.Font.Bold = [boolean]$XAxisTitleBold
|
||||
}
|
||||
if ($XAxisTitleSize) {$chart.XAxis.Title.Font.Size = $XAxisTitleSize}
|
||||
if ($XAxisTitleSize) { $chart.XAxis.Title.Font.Size = $XAxisTitleSize }
|
||||
}
|
||||
if ($XAxisPosition) {Write-Warning "X-axis position is not being set propertly at the moment, parameter ignored" }
|
||||
#$chart.ChartXml.chartSpace.chart.plotArea.catAx.axPos.val = $XAxisPosition.ToString().substring(0,1)}
|
||||
if ($XMajorUnit) {$chart.XAxis.MajorUnit = $XMajorUnit}
|
||||
if ($XMinorUnit) {$chart.XAxis.MinorUnit = $XMinorUnit}
|
||||
if ($null -ne $XMinValue) {$chart.XAxis.MinValue = $XMinValue}
|
||||
if ($null -ne $XMaxValue) {$chart.XAxis.MaxValue = $XMaxValue}
|
||||
if ($XAxisNumberformat) {$chart.XAxis.Format = (Expand-NumberFormat $XAxisNumberformat)}
|
||||
if ($XAxisPosition) { Write-Warning "X-axis position is not being set propertly at the moment, parameter ignored" }
|
||||
#$chart.ChartXml.chartSpace.chart.plotArea.catAx.axPos.val = $XAxisPosition.ToString().substring(0,1)}
|
||||
if ($XMajorUnit) { $chart.XAxis.MajorUnit = $XMajorUnit }
|
||||
if ($XMinorUnit) { $chart.XAxis.MinorUnit = $XMinorUnit }
|
||||
if ($null -ne $XMinValue) { $chart.XAxis.MinValue = $XMinValue }
|
||||
if ($null -ne $XMaxValue) { $chart.XAxis.MaxValue = $XMaxValue }
|
||||
if ($XAxisNumberformat) { $chart.XAxis.Format = (Expand-NumberFormat $XAxisNumberformat) }
|
||||
|
||||
if ($YAxisTitleText) {
|
||||
if ($YAxisTitleText) {
|
||||
$chart.YAxis.Title.Text = $YAxisTitleText
|
||||
if ($PSBoundParameters.ContainsKey('YAxisTitleBold')) {
|
||||
$chart.YAxis.Title.Font.Bold = [boolean]$YAxisTitleBold
|
||||
$chart.YAxis.Title.Font.Bold = [boolean]$YAxisTitleBold
|
||||
}
|
||||
if ($YAxisTitleSize) {$chart.YAxis.Title.Font.Size = $YAxisTitleSize}
|
||||
if ($YAxisTitleSize) { $chart.YAxis.Title.Font.Size = $YAxisTitleSize }
|
||||
}
|
||||
if ($YAxisPosition) {Write-Warning "Y-axis position is not being set propertly at the moment, parameter ignored" }
|
||||
#$chart.ChartXml.chartSpace.chart.plotArea.valAx.axPos.val= $YAxisPosition.ToString().substring(0,1)}
|
||||
if ($YMajorUnit) {$chart.YAxis.MajorUnit = $YMajorUnit}
|
||||
if ($YMinorUnit) {$chart.YAxis.MinorUnit = $YMinorUnit}
|
||||
if ($null -ne $YMinValue){$chart.YAxis.MinValue = $YMinValue}
|
||||
if ($null -ne $YMaxValue){$chart.YAxis.MaxValue = $YMaxValue}
|
||||
if ($YAxisNumberformat) {$chart.YAxis.Format = (Expand-NumberFormat $YAxisNumberformat)}
|
||||
if ($YAxisPosition) { Write-Warning "Y-axis position is not being set propertly at the moment, parameter ignored" }
|
||||
#$chart.ChartXml.chartSpace.chart.plotArea.valAx.axPos.val= $YAxisPosition.ToString().substring(0,1)}
|
||||
if ($YMajorUnit) { $chart.YAxis.MajorUnit = $YMajorUnit }
|
||||
if ($YMinorUnit) { $chart.YAxis.MinorUnit = $YMinorUnit }
|
||||
if ($null -ne $YMinValue) { $chart.YAxis.MinValue = $YMinValue }
|
||||
if ($null -ne $YMaxValue) { $chart.YAxis.MaxValue = $YMaxValue }
|
||||
if ($YAxisNumberformat) { $chart.YAxis.Format = (Expand-NumberFormat $YAxisNumberformat) }
|
||||
if ($null -ne $chart.Datalabel) {
|
||||
$chart.Datalabel.ShowCategory = [boolean]$ShowCategory
|
||||
$chart.Datalabel.ShowPercent = [boolean]$ShowPercent
|
||||
$chart.Datalabel.ShowCategory = [boolean]$ShowCategory
|
||||
$chart.Datalabel.ShowPercent = [boolean]$ShowPercent
|
||||
}
|
||||
|
||||
$chart.SetPosition($Row, $RowOffsetPixels, $Column, $ColumnOffsetPixels)
|
||||
$chart.SetSize($Width, $Height)
|
||||
|
||||
if ($PassThru) {return $chart}
|
||||
if ($PassThru) { return $chart }
|
||||
}
|
||||
catch {Write-Warning -Message "Failed adding Chart to worksheet '$($WorkSheet).name': $_"}
|
||||
catch { Write-Warning -Message "Failed adding Chart to worksheet '$($WorkSheet).name': $_" }
|
||||
}
|
||||
|
||||
17
README.md
17
README.md
@@ -52,6 +52,23 @@ Install-Module ImportExcel -scope CurrentUser
|
||||
```PowerShell
|
||||
Install-Module ImportExcel
|
||||
```
|
||||
# What's new 6.2.3
|
||||
|
||||
Thank you [jhoneill](https://github.com/jhoneill).
|
||||
|
||||
- Refactored copy sheet and added pipe support
|
||||
- Add `ClearAll` to `Set-ExcelRange`
|
||||
- Fix broken test & regression for `passwords`
|
||||
- **Note**: Passwords do not work on `pwsh`. The EPPlus library does not support these dotnet core APIs at this time.
|
||||
|
||||
# What's new 6.2.2
|
||||
|
||||
- Added requested feature, chart trendlines.
|
||||
- [Example PowerShell script](https://github.com/dfinke/ImportExcel/blob/master/Examples/Charts/NumberOfVisitors.ps1)
|
||||
|
||||

|
||||
|
||||
- Fixed Import-Excel and relative path issue, added unit tests.
|
||||
|
||||
# What's new 6.2.0
|
||||
Thank you to [James O'Neill](https://github.com/jhoneill)
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
Set-ExcelRow -Worksheet $ws -Heading Total -Value {"=sum($columnName`2:$columnName$endrow)" }
|
||||
|
||||
$Ws contains a worksheet object, and no Row number is specified so
|
||||
Set-ExcelRow will select the next row after the endof the data in
|
||||
Set-ExcelRow will select the next row after the end of the data in
|
||||
the sheet. The first cell in the row will contain "Total", and
|
||||
each of the other cells will contain
|
||||
=Sum(xx2:xx99)
|
||||
|
||||
@@ -124,7 +124,10 @@
|
||||
$Range = $WorkSheet.Cells[$Range]
|
||||
}
|
||||
elseif ($Range -is [string]) {Write-Warning -Message "The range pararameter you have specified also needs a worksheet parameter." ;return}
|
||||
#else we assume Range is a range.
|
||||
#else we assume $Range is a range.
|
||||
if ($ClearAll) {
|
||||
$Range.Clear()
|
||||
}
|
||||
if ($ResetFont) {
|
||||
$Range.Style.Font.Color.SetColor( ([System.Drawing.Color]::Black))
|
||||
$Range.Style.Font.Bold = $false
|
||||
@@ -332,6 +335,7 @@ if (Get-Command -ErrorAction SilentlyContinue -name Register-ArgumentCompleter)
|
||||
Register-ArgumentCompleter -CommandName Set-ExcelRange -ParameterName FontName -ScriptBlock $Function:ListFonts
|
||||
Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName FontName -ScriptBlock $Function:ListFonts
|
||||
}
|
||||
|
||||
function Expand-NumberFormat {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
|
||||
49
__tests__/AddTrendlinesToAChart.tests.ps1
Normal file
49
__tests__/AddTrendlinesToAChart.tests.ps1
Normal file
@@ -0,0 +1,49 @@
|
||||
Describe "Test adding trendlines to charts" {
|
||||
BeforeAll {
|
||||
$script:data = ConvertFrom-Csv @"
|
||||
Region,Item,TotalSold
|
||||
West,screws,60
|
||||
South,lemon,48
|
||||
South,apple,71
|
||||
East,screwdriver,70
|
||||
East,kiwi,32
|
||||
West,screwdriver,1
|
||||
South,melon,21
|
||||
East,apple,79
|
||||
South,apple,68
|
||||
South,avocado,73
|
||||
"@
|
||||
|
||||
}
|
||||
|
||||
BeforeEach {
|
||||
$xlfile = "$env:TEMP\trendLine.xlsx"
|
||||
Remove-Item $xlfile -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
It "Should add a linear trendline" {
|
||||
|
||||
$cd = New-ExcelChartDefinition -XRange Region -YRange TotalSold -ChartType ColumnClustered -ChartTrendLine Linear
|
||||
$data | Export-Excel $xlfile -ExcelChartDefinition $cd -AutoNameRange
|
||||
|
||||
$excel = Open-ExcelPackage -Path $xlfile
|
||||
$ws = $excel.Workbook.Worksheets["Sheet1"]
|
||||
|
||||
$ws.Drawings[0].Series.TrendLines.Type | Should Be 'Linear'
|
||||
|
||||
Close-ExcelPackage $excel
|
||||
}
|
||||
|
||||
It "Should add a MovingAvgerage trendline" {
|
||||
|
||||
$cd = New-ExcelChartDefinition -XRange Region -YRange TotalSold -ChartType ColumnClustered -ChartTrendLine MovingAvgerage
|
||||
$data | Export-Excel $xlfile -ExcelChartDefinition $cd -AutoNameRange
|
||||
|
||||
$excel = Open-ExcelPackage -Path $xlfile
|
||||
$ws = $excel.Workbook.Worksheets["Sheet1"]
|
||||
|
||||
$ws.Drawings[0].Series.TrendLines.Type | Should Be 'MovingAvgerage'
|
||||
|
||||
Close-ExcelPackage $excel
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#Requires -Modules Pester
|
||||
Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force
|
||||
if ($PSVersionTable.PSVersion.Major -gt 5) { Write-Warning "Can't test grid view on V6" }
|
||||
if ($PSVersionTable.PSVersion.Major -gt 5) { Write-Warning "Can't test grid view on V6 and later" }
|
||||
else {Add-Type -AssemblyName System.Windows.Forms }
|
||||
Describe "Compare Worksheet" {
|
||||
Context "Simple comparison output" {
|
||||
|
||||
@@ -60,29 +60,29 @@ 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 -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
|
||||
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, 8].Value -is [valuetype] ) | Should be $true
|
||||
$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, 9].Value -is [valuetype] ) | Should be $true
|
||||
$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, 19].Value -is [valuetype] ) | Should be $true
|
||||
($ws.Cells[2, 20].Value -is [valuetype] ) | Should be $true
|
||||
($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, 19].Value -is [valuetype] ) | Should be $true
|
||||
($ws.Cells[2, 20].Value -is [valuetype] ) | Should be $true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ Describe "Copy-Worksheet" {
|
||||
}
|
||||
}
|
||||
|
||||
it "Should copy and remove sheets" {
|
||||
it "Should copy and remove sheets " {
|
||||
$targetSheets = echo 1.1.2019 1.4.2019
|
||||
|
||||
$targetSheets | ForEach-Object {
|
||||
@@ -113,4 +113,28 @@ Describe "Copy-Worksheet" {
|
||||
(Get-ExcelSheetInfo -Path $xlfile ).Count | Should Be 3
|
||||
}
|
||||
}
|
||||
|
||||
Context "Copy worksheet should support piped input" {
|
||||
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 $_
|
||||
}
|
||||
$e = Open-ExcelPackage $xlfile
|
||||
$e.Workbook.Worksheets | Copy-ExcelWorkSheet -DestinationWorkbook $xlfileArchive
|
||||
Close-ExcelPackage -NoSave $e
|
||||
}
|
||||
it "Should copy sheets piped into the command " {
|
||||
$excel = Open-ExcelPackage $xlfileArchive
|
||||
$excel.Workbook.Worksheets.Count | should be 5
|
||||
$excel.Workbook.Worksheets['1.3.2019'].Cells['A1'].Value | should be 'Hello World'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,28 @@
|
||||
Describe "Password Support" {
|
||||
Context "Password protected sheet" {
|
||||
BeforeAll {
|
||||
$password = "YouMustRememberThis"
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
if ($PSVersionTable.PSVersion.Major -GT 5) {
|
||||
Write-Warning "Can't test passwords on V6 and later"
|
||||
return
|
||||
}
|
||||
|
||||
Describe "Password Support" {
|
||||
Context "Password protected sheet" {
|
||||
BeforeAll {
|
||||
$password = "YouMustRememberThis"
|
||||
$path = "$env:TEMP\Test.xlsx"
|
||||
Remove-Item $path -ErrorAction SilentlyContinue
|
||||
Get-Service | Select-Object -First 10 | Export-excel -password $password -Path $Path -DisplayPropertySet
|
||||
Get-Service | Select-Object -First 10 | Export-excel -password $password -Path $Path -DisplayPropertySet
|
||||
}
|
||||
it "Threw an error when the password was omitted " {
|
||||
{Open-ExcelPackage -Path $path } | should throw
|
||||
}
|
||||
it "Was able to append when the password was included " {
|
||||
{Get-Service | Select-Object -First 10 |
|
||||
{Get-Service | Select-Object -First 10 |
|
||||
Export-excel -password $password -Path $Path -Append } | should not throw
|
||||
}
|
||||
it "Kept the password on the file when it was saved " {
|
||||
{Import-Excel $Path } | should throw
|
||||
{Import-Excel $Path } | should throw
|
||||
}
|
||||
it "Could read the file when the password was included " {
|
||||
(import-excel $path -Password $password).count | should be 20
|
||||
it "Could read the file when the password was included " {
|
||||
(import-excel $path -Password $password).count | should be 20
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
38
__tests__/Path.tests.ps1
Normal file
38
__tests__/Path.tests.ps1
Normal file
@@ -0,0 +1,38 @@
|
||||
Describe "Test reading relative paths" {
|
||||
BeforeAll {
|
||||
$script:xlfileName = "TestR.xlsx"
|
||||
@{data = 1 } | Export-Excel "$pwd\TestR.xlsx"
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
Remove-Item "$pwd\$($script:xlfileName)"
|
||||
}
|
||||
|
||||
It "Should read local file" {
|
||||
$actual = Import-Excel -Path ".\$($script:xlfileName)"
|
||||
$actual | Should Not Be $null
|
||||
$actual.Count | Should Be 1
|
||||
}
|
||||
|
||||
It "Should read with pwd" {
|
||||
$actual = Import-Excel -Path "$pwd\$($script:xlfileName)"
|
||||
$actual | Should Not Be $null
|
||||
}
|
||||
|
||||
It "Should read with just a file name and resolve to cwd" {
|
||||
$actual = Import-Excel -Path "$($script:xlfileName)"
|
||||
$actual | Should Not Be $null
|
||||
}
|
||||
|
||||
It "Should fail for not found" {
|
||||
{ Import-Excel -Path "ExcelFileDoesNotExist.xlsx" } | Should Throw "'ExcelFileDoesNotExist.xlsx' file not found"
|
||||
}
|
||||
|
||||
It "Should fail for xls extension" {
|
||||
{ Import-Excel -Path "ExcelFileDoesNotExist.xls" } | Should Throw "Import-Excel does not support reading this extension type .xls"
|
||||
}
|
||||
|
||||
It "Should fail for xlsxs extension" {
|
||||
{ Import-Excel -Path "ExcelFileDoesNotExist.xlsxs" } | Should Throw "Import-Excel does not support reading this extension type .xlsxs"
|
||||
}
|
||||
}
|
||||
BIN
__tests__/testRelative.xlsx
Normal file
BIN
__tests__/testRelative.xlsx
Normal file
Binary file not shown.
BIN
images/ChartTrendlines.png
Normal file
BIN
images/ChartTrendlines.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 96 KiB |
Reference in New Issue
Block a user