mirror of
https://github.com/dfinke/ImportExcel.git
synced 2025-12-06 00:23:20 +00:00
All new Copy-ExcelWorksheet (+tests); fix sort in merge-Multiple
This commit is contained in:
@@ -1,22 +1,110 @@
|
|||||||
function Copy-ExcelWorkSheet {
|
function Copy-ExcelWorkSheet {
|
||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
|
<#
|
||||||
|
.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.
|
||||||
|
.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"
|
||||||
|
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
|
||||||
|
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:\> 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
|
||||||
|
|
||||||
|
#>
|
||||||
param(
|
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,
|
$SourceWorkbook,
|
||||||
[Parameter(Mandatory=$true)]
|
#Name or number (starting from 1) of the worksheet in the source workbook (defaults to 1).
|
||||||
$SourceWorkSheet,
|
$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,
|
$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
|
[Switch]$Show
|
||||||
)
|
)
|
||||||
|
#Special case - give the same path for source and destination worksheet
|
||||||
Write-Verbose "Copying $($SourceWorkSheet) from $($SourceWorkbook) to $($DestinationWorkSheet) in $($DestinationWorkbook)"
|
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}
|
||||||
if(!$DestinationWorkSheet) {
|
else {
|
||||||
$DestinationWorkSheet = $SourceWorkSheet
|
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
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname $DestinationWorkSheet -CopySource ($excel.Workbook.Worksheets[$SourceWorkSheet])
|
||||||
|
Close-ExcelPackage -ExcelPackage $excel -Show:$Show
|
||||||
|
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 ($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}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Import-Excel -Path $SourceWorkbook -WorkSheetname $SourceWorkSheet |
|
|
||||||
Export-Excel -Path $DestinationWorkbook -WorkSheetname $DestinationWorkSheet -Show:$Show
|
|
||||||
}
|
}
|
||||||
@@ -406,8 +406,9 @@ Function Merge-MultipleSheets {
|
|||||||
#if the process didn't return data then abandon now.
|
#if the process didn't return data then abandon now.
|
||||||
if (-not $merged) {Write-Warning -Message "The merge operation did not return any data."; return }
|
if (-not $merged) {Write-Warning -Message "The merge operation did not return any data."; return }
|
||||||
|
|
||||||
|
$orderByProperties = $merged[0].psobject.properties.where({$_.name -match "row$"}).name
|
||||||
Write-Progress -Activity "Merging sheets" -CurrentOperation "Creating output sheet '$OutputSheetName' in $OutputFile"
|
Write-Progress -Activity "Merging sheets" -CurrentOperation "Creating output sheet '$OutputSheetName' in $OutputFile"
|
||||||
$excel = $merged | Sort-Object "_row" | Update-FirstObjectProperties |
|
$excel = $merged | Sort-Object -Property $orderByProperties | Update-FirstObjectProperties |
|
||||||
Export-Excel -Path $OutputFile -WorkSheetname $OutputSheetName -ClearSheet -BoldTopRow -AutoFilter -PassThru
|
Export-Excel -Path $OutputFile -WorkSheetname $OutputSheetName -ClearSheet -BoldTopRow -AutoFilter -PassThru
|
||||||
$sheet = $excel.Workbook.Worksheets[$OutputSheetName]
|
$sheet = $excel.Workbook.Worksheets[$OutputSheetName]
|
||||||
|
|
||||||
|
|||||||
86
__tests__/Copy-ExcelWorksheet.Tests.ps1
Normal file
86
__tests__/Copy-ExcelWorksheet.Tests.ps1
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
$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
|
||||||
|
|
||||||
|
if ((Get-Culture).NumberFormat.CurrencySymbol -eq "£") {$OtherCurrencySymbol = "$"}
|
||||||
|
else {$OtherCurrencySymbol = "£"}
|
||||||
|
[PSCustOmobject][Ordered]@{
|
||||||
|
Date = Get-Date
|
||||||
|
Formula1 = '=SUM(F2:G2)'
|
||||||
|
String1 = 'My String'
|
||||||
|
Float = [math]::pi
|
||||||
|
IPAddress = '10.10.25.5'
|
||||||
|
StrLeadZero = '07670'
|
||||||
|
StrComma = '0,26'
|
||||||
|
StrEngThousand = '1,234.56'
|
||||||
|
StrEuroThousand = '1.555,83'
|
||||||
|
StrDot = '1.2'
|
||||||
|
StrNegInt = '-31'
|
||||||
|
StrTrailingNeg = '31-'
|
||||||
|
StrParens = '(123)'
|
||||||
|
strLocalCurrency = ('{0}123.45' -f (Get-Culture).NumberFormat.CurrencySymbol )
|
||||||
|
strOtherCurrency = ('{0}123.45' -f $OtherCurrencySymbol )
|
||||||
|
StrE164Phone = '+32 (444) 444 4444'
|
||||||
|
StrAltPhone1 = '+32 4 4444 444'
|
||||||
|
StrAltPhone2 = '+3244444444'
|
||||||
|
StrLeadSpace = ' 123'
|
||||||
|
StrTrailSpace = '123 '
|
||||||
|
Link1 = [uri]"https://github.com/dfinke/ImportExcel"
|
||||||
|
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"{
|
||||||
|
BeforeAll {
|
||||||
|
Copy-ExcelWorkSheet -SourceWorkbook $path1 -DestinationWorkbook $path2
|
||||||
|
$excel = Open-ExcelPackage -Path $path2
|
||||||
|
$ws = $excel.Workbook.Worksheets["Processes"]
|
||||||
|
}
|
||||||
|
it "inserted a worksheet " {
|
||||||
|
$Excel.Workbook.Worksheets.count | Should be 2
|
||||||
|
$ws | Should not benullorEmpty
|
||||||
|
$ws.Dimension.Address | should be $ProcRange
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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]
|
||||||
|
}
|
||||||
|
it "inserted a worksheet with the expected name, number of rows and number of columns " {
|
||||||
|
$Excel.Workbook.Worksheets.count | Should be 3
|
||||||
|
$ws | Should not benullorEmpty
|
||||||
|
$ws.Name | Should be "CopyOfMixedTypes"
|
||||||
|
$ws.Dimension.Columns | Should be 22
|
||||||
|
$ws.Dimension.Rows | Should be 2
|
||||||
|
$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, 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
|
||||||
|
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'
|
||||||
|
}
|
||||||
|
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, 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -63,7 +63,7 @@ Describe ExportExcel {
|
|||||||
$ws.cells[$IDcell].Style.Numberformat.NumFmtID | Should be 0
|
$ws.cells[$IDcell].Style.Numberformat.NumFmtID | Should be 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Context " # NoAliasOrScriptPropeties -ExcludeProperty and -DisplayPropertySet work" {
|
Context " # NoAliasOrScriptPropeties -ExcludeProperty and -DisplayPropertySet work" {
|
||||||
$path = "$env:TEMP\Test.xlsx"
|
$path = "$env:TEMP\Test.xlsx"
|
||||||
Remove-item -Path $path -ErrorAction SilentlyContinue
|
Remove-item -Path $path -ErrorAction SilentlyContinue
|
||||||
|
|||||||
Reference in New Issue
Block a user