From f6c66e21a757cddbb4dd6eea09d5bd0625cb1fbf Mon Sep 17 00:00:00 2001 From: jhoneill Date: Sat, 23 Nov 2019 16:12:29 +0000 Subject: [PATCH] Sync to Doug's 6.5.3 release --- ExportedCommands/Import-Excel.ps1 | 106 +++++++++++--------- ImportExcel.psd1 | 2 +- README.md | 13 +++ __tests__/ImportExcelTests/Simple.tests.ps1 | 21 ++++ __tests__/ImportExcelTests/TestData1.xlsx | Bin 0 -> 8626 bytes __tests__/ImportExcelTests/TestData2.xlsx | Bin 0 -> 8624 bytes 6 files changed, 91 insertions(+), 51 deletions(-) create mode 100644 __tests__/ImportExcelTests/TestData1.xlsx create mode 100644 __tests__/ImportExcelTests/TestData2.xlsx diff --git a/ExportedCommands/Import-Excel.ps1 b/ExportedCommands/Import-Excel.ps1 index 7f5c5a9..94ec48f 100644 --- a/ExportedCommands/Import-Excel.ps1 +++ b/ExportedCommands/Import-Excel.ps1 @@ -1,14 +1,13 @@ function Import-Excel { - - [CmdLetBinding()] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSPossibleIncorrectUsageOfAssignmentOperator', '', Justification = 'Intentional')] - Param ( + [CmdLetBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSPossibleIncorrectUsageOfAssignmentOperator', '', Justification = 'Intentional')] + param ( [Alias('FullName')] [Parameter(ParameterSetName = "PathA", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] [Parameter(ParameterSetName = "PathB", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] [Parameter(ParameterSetName = "PathC", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] - [String]$Path, + [String[]]$Path, [Parameter(ParameterSetName = "PackageA", Mandatory)] [Parameter(ParameterSetName = "PackageB", Mandatory)] [Parameter(ParameterSetName = "PackageC", Mandatory)] @@ -37,55 +36,61 @@ [ValidateNotNullOrEmpty()] [String]$Password ) - begin { - $sw = [System.Diagnostics.Stopwatch]::StartNew() + end { + $sw = [System.Diagnostics.Stopwatch]::StartNew() + if ($input) { + $Paths = $input + } + elseif ($Path) { + $Paths = $Path + } + else { + $Paths = '' + } + 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")] + Param ( + [Parameter(Mandatory)] + [Int[]]$Columns, + [Parameter(Mandatory)] + [Int]$StartRow + ) - 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")] - Param ( - [Parameter(Mandatory)] - [Int[]]$Columns, - [Parameter(Mandatory)] - [Int]$StartRow - ) - - Try { - if ($HeaderName) { - $i = 0 - foreach ($H in $HeaderName) { - $H | Select-Object @{N = 'Column'; E = { $Columns[$i] } }, @{N = 'Value'; E = { $H } } - $i++ - } - } - elseif ($NoHeader) { - $i = 0 - foreach ($C in $Columns) { - $i++ - $C | Select-Object @{N = 'Column'; E = { $_ } }, @{N = 'Value'; E = { 'P' + $i } } - } - } - - else { - if ($StartRow -lt 1) { - throw 'The top row can never be less than 1 when we need to retrieve headers from the worksheet.' ; return - } - - foreach ($C in $Columns) { - $Worksheet.Cells[$StartRow, $C] | Where-Object { $_.Value } | Select-Object @{N = 'Column'; E = { $C } }, Value - } + Try { + if ($HeaderName) { + $i = 0 + foreach ($H in $HeaderName) { + $H | Select-Object @{N = 'Column'; E = { $Columns[$i] } }, @{N = 'Value'; E = { $H } } + $i++ } } - Catch { - throw "Failed creating property names: $_" ; return + elseif ($NoHeader) { + $i = 0 + foreach ($C in $Columns) { + $i++ + $C | Select-Object @{N = 'Column'; E = { $_ } }, @{N = 'Value'; E = { 'P' + $i } } + } + } + + else { + if ($StartRow -lt 1) { + throw 'The top row can never be less than 1 when we need to retrieve headers from the worksheet.' ; return + } + + foreach ($C in $Columns) { + $Worksheet.Cells[$StartRow, $C] | Where-Object { $_.Value } | Select-Object @{N = 'Column'; E = { $C } }, Value + } } } + Catch { + throw "Failed creating property names: $_" ; return + } } - - process { + foreach ($Path in $Paths) { if ($path) { $extension = [System.IO.Path]::GetExtension($Path) if ($extension -notmatch '.xlsx$|.xlsm$') { @@ -193,4 +198,5 @@ if ($Path) { $stream.close(); $ExcelPackage.Dispose() } } } -} + } +} \ No newline at end of file diff --git a/ImportExcel.psd1 b/ImportExcel.psd1 index c602500..6288b3d 100644 --- a/ImportExcel.psd1 +++ b/ImportExcel.psd1 @@ -4,7 +4,7 @@ RootModule = 'ImportExcel.psm1' # Version number of this module. - ModuleVersion = '6.5.2' + ModuleVersion = '6.5.3' # ID used to uniquely identify this module GUID = '60dd4136-feff-401a-ba27-a84458c57ede' diff --git a/README.md b/README.md index e5f7f52..dba7450 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,19 @@ Plus, wiring the [PowerShell ScriptAnalyzer Excel report](https://github.com/dfi ![](./images/ScriptAnalyzerReport.png) +# What's new 6.5.3 + +Thanks again to the community for making this module even better. + +- [Fix import excel headers](https://github.com/dfinke/ImportExcel/pull/713) +- Numerous improvements for DataTables and exporting it to Excel [James O'Neill](https://twitter.com/jamesoneill) + - Names, styles, proper appending +- Handles marking the empty row on an empty table as dummy row +- Re-work code based on linting recommendations +- Update existing tests and add more +- Support PipelineVariable thanks to [Luc Dekens](https://twitter.com/LucD22) for reporting and [Ili](https://twitter.com/ili_z) for the PR +- Fix quoting in ConvertFromExcelToSQLInsert [beckerben](https://github.com/beckerben) + # What's new 6.5.2 Thank you [uSlackr](https://github.com/uSlackr)ill diff --git a/__tests__/ImportExcelTests/Simple.tests.ps1 b/__tests__/ImportExcelTests/Simple.tests.ps1 index 12049ec..a8a48fe 100644 --- a/__tests__/ImportExcelTests/Simple.tests.ps1 +++ b/__tests__/ImportExcelTests/Simple.tests.ps1 @@ -42,4 +42,25 @@ Describe "Tests" { $data[0].p1 | Should be "a" $data[1].p1 | Should be "b" } + + It "Should take Paths from parameter".PadRight(90) { + $data = Import-Excel -Path (Get-ChildItem -Path $PSScriptRoot -Filter "TestData?.xlsx").FullName + $data.count | Should be 4 + $data[0].cola | Should be 1 + $data[2].cola | Should be 5 + } + + It "Should take Paths from pipeline".PadRight(90) { + $data = (Get-ChildItem -Path $PSScriptRoot -Filter "TestData?.xlsx").FullName | Import-Excel + $data.count | Should be 4 + $data[0].cola | Should be 1 + $data[2].cola | Should be 5 + } + + It "Should support PipelineVariable".PadRight(90) { + $data = Import-Excel $PSScriptRoot\Simple.xlsx -PipelineVariable 'Pv' | ForEach-Object { $Pv.p1 } + $data.count | Should be 2 + $data[0] | Should be "a" + $data[1] | Should be "b" + } } \ No newline at end of file diff --git a/__tests__/ImportExcelTests/TestData1.xlsx b/__tests__/ImportExcelTests/TestData1.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..7f554adb7cb810a4ef8ea8fc1d14f74bb68a30a8 GIT binary patch literal 8626 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 literal 0 HcmV?d00001 diff --git a/__tests__/ImportExcelTests/TestData2.xlsx b/__tests__/ImportExcelTests/TestData2.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..fd7996700553b2b6158ada76a4b7bf7aa8a9d57c GIT binary patch literal 8624 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 literal 0 HcmV?d00001