Compare commits

..

12 Commits

Author SHA1 Message Date
dfinke
abdd37b09e Updated readme and bumped version 2019-07-04 16:20:19 -04:00
Doug Finke
e1e855a823 Merge pull request #628 from dfinke/RelativePath
Added resolve-path and tests. #627; Commented out write-warning
2019-07-04 16:18:14 -04:00
dfinke
585d9686a6 Remove firstTimeThru check 2019-07-04 16:14:36 -04:00
dfinke
e87a6bdaf5 Add extension test back in 2019-07-04 12:16:44 -04:00
dfinke
5ded5111b4 Rename test 2019-07-04 12:16:34 -04:00
dfinke
914c61048b Moved back, CI has issues with $psscriptroot for xlsx 2019-07-04 12:03:05 -04:00
dfinke
25fb76d9b7 Remove test, put check in begin block 2019-07-04 11:59:15 -04:00
dfinke
7faa27a3b3 create xlsx before all in cwd 2019-07-04 11:53:59 -04:00
dfinke
5700be0684 works locally, not in the CI tho 2019-07-04 11:45:42 -04:00
dfinke
6d86108060 wip: remove param validation 2019-07-04 11:40:02 -04:00
dfinke
4581c2b3e9 Added resolve-path and tests. #627; Commented out write-warning 2019-07-04 11:18:28 -04:00
dfinke
142c31ccc1 Added image to readme 2019-06-18 14:56:00 -04:00
6 changed files with 92 additions and 30 deletions

View File

@@ -4,7 +4,7 @@
RootModule = 'ImportExcel.psm1' RootModule = 'ImportExcel.psm1'
# Version number of this module. # Version number of this module.
ModuleVersion = '6.2.1' ModuleVersion = '6.2.2'
# ID used to uniquely identify this module # ID used to uniquely identify this module
GUID = '60dd4136-feff-401a-ba27-a84458c57ede' GUID = '60dd4136-feff-401a-ba27-a84458c57ede'

View File

@@ -48,7 +48,7 @@ if ($PSVersionTable.PSVersion.Major -ge 5) {
. $PSScriptRoot\plot.ps1 . $PSScriptRoot\plot.ps1
Function New-Plot { 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() Param()
[PSPlot]::new() [PSPlot]::new()
@@ -269,7 +269,6 @@ function Import-Excel {
[Parameter(ParameterSetName = "PathA", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] [Parameter(ParameterSetName = "PathA", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )]
[Parameter(ParameterSetName = "PathB", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )] [Parameter(ParameterSetName = "PathB", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )]
[Parameter(ParameterSetName = "PathC", 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, [String]$Path,
[Parameter(ParameterSetName = "PackageA", Mandatory)] [Parameter(ParameterSetName = "PackageA", Mandatory)]
[Parameter(ParameterSetName = "PackageB", Mandatory)] [Parameter(ParameterSetName = "PackageB", Mandatory)]
@@ -300,12 +299,13 @@ function Import-Excel {
) )
begin { begin {
$sw = [System.Diagnostics.Stopwatch]::StartNew() $sw = [System.Diagnostics.Stopwatch]::StartNew()
Function Get-PropertyNames { Function Get-PropertyNames {
<# <#
.SYNOPSIS .SYNOPSIS
Create objects containing the column number and the column name for each of the different header types. 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 ( Param (
[Parameter(Mandatory)] [Parameter(Mandatory)]
[Int[]]$Columns, [Int[]]$Columns,
@@ -318,13 +318,13 @@ function Import-Excel {
$i = 0 $i = 0
foreach ($C in $Columns) { foreach ($C in $Columns) {
$i++ $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) { elseif ($HeaderName) {
$i = 0 $i = 0
foreach ($H in $HeaderName) { 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++ $i++
} }
} }
@@ -334,7 +334,7 @@ function Import-Excel {
} }
foreach ($C in $Columns) { 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,56 @@ function Import-Excel {
process { process {
if ($path) { 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' $stream = New-Object -TypeName System.IO.FileStream -ArgumentList $Path, 'Open', 'Read', 'ReadWrite'
if ($Password) {$ExcelPackage = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream , $Password } if ($Password) { $ExcelPackage = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream , $Password }
else {$ExcelPackage = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream} else { $ExcelPackage = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $stream }
} }
try { try {
#Select worksheet #Select worksheet
if (-not $WorksheetName) { $Worksheet = $ExcelPackage.Workbook.Worksheets[1] } if (-not $WorksheetName) { $Worksheet = $ExcelPackage.Workbook.Worksheets[1] }
elseif(-not ($Worksheet = $ExcelPackage.Workbook.Worksheets[$WorkSheetName])) { 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 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 Write-Debug $sw.Elapsed.TotalMilliseconds
#region Get rows and columns #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 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 $EndRow ) { $EndRow = $Worksheet.Dimension.End.Row }
if (-not $EndColumn) {$EndColumn = $Worksheet.Dimension.End.Column } if (-not $EndColumn) { $EndColumn = $Worksheet.Dimension.End.Column }
$endAddress = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[$EndRow]C[$EndColumn]", 0, 0) $endAddress = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[$EndRow]C[$EndColumn]", 0, 0)
if ($DataOnly) { if ($DataOnly) {
#If we are using headers startrow will be the header-row so examine data from startRow + 1, #If we are using headers startrow will be the header-row so examine data from startRow + 1,
if ($NoHeader) {$range = "A" + ($StartRow ) + ":" + $endAddress } if ($NoHeader) { $range = "A" + ($StartRow ) + ":" + $endAddress }
else {$range = "A" + ($StartRow + 1 ) + ":" + $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. #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 #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, #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". #using Hash tables: "we've seen it" is all we need, no need to worry about "seen it before" / "Seen it many times".
$colHash = @{} $colHash = @{ }
$rowHash = @{} $rowHash = @{ }
foreach ($cell in $Worksheet.Cells[$range]) { 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[$_]}) $rows = ( $StartRow..$EndRow ).Where( { $rowHash[$_] })
$columns = ($StartColumn..$EndColumn).Where( {$colHash[$_]}) $columns = ($StartColumn..$EndColumn).Where( { $colHash[$_] })
} }
else { else {
$Columns = $StartColumn .. $EndColumn ; if ($StartColumn -gt $EndColumn) {Write-Warning -Message "Selecting columns $StartColumn to $EndColumn 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."} } 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."}} 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 #endregion
#region Create property names #region Create property names
@@ -402,7 +415,7 @@ function Import-Excel {
foreach ($R in $Rows) { foreach ($R in $Rows) {
#Disabled write-verbose for speed #Disabled write-verbose for speed
# Write-Verbose "Import row '$R'" # Write-Verbose "Import row '$R'"
$NewRow = [Ordered]@{} $NewRow = [Ordered]@{ }
foreach ($P in $PropertyNames) { foreach ($P in $PropertyNames) {
$NewRow[$P.Value] = $Worksheet.Cells[$R, $P.Column].Value $NewRow[$P.Value] = $Worksheet.Cells[$R, $P.Column].Value
@@ -417,7 +430,7 @@ function Import-Excel {
} }
catch { throw "Failed importing the Excel workbook '$Path' with worksheet '$Worksheetname': $_"; return } catch { throw "Failed importing the Excel workbook '$Path' with worksheet '$Worksheetname': $_"; return }
finally { finally {
if ($Path) {$stream.close(); $ExcelPackage.Dispose() } if ($Path) { $stream.close(); $ExcelPackage.Dispose() }
} }
} }
} }
@@ -463,9 +476,9 @@ function ConvertFrom-ExcelSheet {
$xl = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Stream $xl = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Stream
$workbook = $xl.Workbook $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("OutputPath")
$params.Remove("SheetName") $params.Remove("SheetName")
$params.Remove('Extension') $params.Remove('Extension')
@@ -496,7 +509,7 @@ function Export-MultipleExcelSheets {
[Switch]$AutoSize [Switch]$AutoSize
) )
$parameters = @{} + $PSBoundParameters $parameters = @{ } + $PSBoundParameters
$parameters.Remove("InfoMap") $parameters.Remove("InfoMap")
$parameters.Remove("Show") $parameters.Remove("Show")
@@ -509,7 +522,7 @@ function Export-MultipleExcelSheets {
& $entry.Value | Export-Excel @parameters & $entry.Value | Export-Excel @parameters
} }
if ($Show) {Invoke-Item $Path} if ($Show) { Invoke-Item $Path }
} }
Function WorksheetArgumentCompleter { Function WorksheetArgumentCompleter {
@@ -519,7 +532,7 @@ Function WorksheetArgumentCompleter {
$xlpkg = Open-ExcelPackage -ReadOnly -Path $xlPath $xlpkg = Open-ExcelPackage -ReadOnly -Path $xlPath
$WorksheetNames = $xlPkg.Workbook.Worksheets.Name $WorksheetNames = $xlPkg.Workbook.Worksheets.Name
Close-ExcelPackage -nosave -ExcelPackage $xlpkg 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 "'$_'", New-Object -TypeName System.Management.Automation.CompletionResult -ArgumentList "'$_'",
$_ , ([System.Management.Automation.CompletionResultType]::ParameterValue) , $_ $_ , ([System.Management.Automation.CompletionResultType]::ParameterValue) , $_
} }

View File

@@ -53,6 +53,17 @@ Install-Module ImportExcel -scope CurrentUser
Install-Module ImportExcel Install-Module ImportExcel
``` ```
# What's new 6.2.1
- Added requested feature, chart trendlines.
- [Example PowerShell script](https://github.com/dfinke/ImportExcel/blob/master/Examples/Charts/NumberOfVisitors.ps1)
![](/images/ChartTrendlines.png)
# What's new 6.2.2
- Fixed Import-Excel and relative path issue, added unit tests.
# What's new 6.2.0 # What's new 6.2.0
Thank you to [James O'Neill](https://github.com/jhoneill) Thank you to [James O'Neill](https://github.com/jhoneill)

38
__tests__/Path.tests.ps1 Normal file
View 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

Binary file not shown.

BIN
images/ChartTrendlines.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB