mirror of
https://github.com/dfinke/ImportExcel.git
synced 2025-12-15 07:43:23 +00:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
050613eede | ||
|
|
84f51c4823 | ||
|
|
f2544ed1ec | ||
|
|
45449650c7 | ||
|
|
d7348250fc | ||
|
|
b53881fd02 | ||
|
|
632bb263cc | ||
|
|
658a6b543a | ||
|
|
0f301ff619 | ||
|
|
115fbb23a7 | ||
|
|
2b30537c20 | ||
|
|
22f50d2659 | ||
|
|
f0a2d076e3 | ||
|
|
835a11bbb3 | ||
|
|
701b8e2062 | ||
|
|
6f2bfaff4e | ||
|
|
ba6cee12d9 | ||
|
|
5d36945708 | ||
|
|
6cbf4efd1d | ||
|
|
4feaee46d2 | ||
|
|
89f90b77fb | ||
|
|
98256c61e8 | ||
|
|
ebde9269aa | ||
|
|
e3149b7b40 | ||
|
|
64ff97b486 | ||
|
|
12f1f23d51 | ||
|
|
e279cd785e | ||
|
|
04b5a9a096 | ||
|
|
c6a06cc325 | ||
|
|
a4bed31e1e | ||
|
|
c385ca9012 | ||
|
|
2a8cbbba7c | ||
|
|
b789db9ba3 | ||
|
|
89a4cfde0d | ||
|
|
ab56ae4409 | ||
|
|
ef35c4fca8 | ||
|
|
9fad33c7a6 | ||
|
|
8bb3d50052 | ||
|
|
d5b807d3cb | ||
|
|
e2053e4998 | ||
|
|
8c6c7eeaf6 | ||
|
|
31abd215dc | ||
|
|
cafaafd53d | ||
|
|
ee3c8e7680 | ||
|
|
0b207548e0 | ||
|
|
6628b55ce5 | ||
|
|
f6bfabd96a | ||
|
|
980631df8b | ||
|
|
4f9b83f0e6 | ||
|
|
59cf89b451 | ||
|
|
5777d907c4 | ||
|
|
d7c516d35e | ||
|
|
27d69e7531 | ||
|
|
8ae92fba54 | ||
|
|
aa0f0cf4e2 | ||
|
|
6e38d97498 | ||
|
|
ef7c8331f5 | ||
|
|
267d15f99a | ||
|
|
390aca0496 | ||
|
|
4fa34ae257 | ||
|
|
0b3b382c4e | ||
|
|
415be5bca3 | ||
|
|
f348088b62 |
27
.github/workflows/ci.yml
vendored
Normal file
27
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- Set-up-GHA-CI/CD
|
||||
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Run Continuous Integration
|
||||
shell: pwsh
|
||||
run : |
|
||||
if($PSVersionTable.Platform -eq 'Win32NT') {
|
||||
$null = mkdir ./ace
|
||||
Invoke-Restmethod https://download.microsoft.com/download/3/5/C/35C84C36-661A-44E6-9324-8786B8DBE231/accessdatabaseengine_X64.exe -OutFile ./ace/ace.exe
|
||||
Start-Process ./ace/ace.exe -Wait -ArgumentList "/quiet /passive /norestart"
|
||||
}
|
||||
|
||||
cd ./__tests__
|
||||
Invoke-Pester -Output Detailed
|
||||
26
Examples/ConditionalFormatting/Highlight-DiffCells.ps1
Normal file
26
Examples/ConditionalFormatting/Highlight-DiffCells.ps1
Normal file
@@ -0,0 +1,26 @@
|
||||
try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return }
|
||||
|
||||
# Get rid of pre-exisiting sheet
|
||||
$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx"
|
||||
|
||||
Write-Verbose -Verbose -Message "Save location: $xlSourcefile"
|
||||
Remove-Item $xlSourcefile -ErrorAction Ignore
|
||||
|
||||
$data = ConvertFrom-Csv @"
|
||||
Region,State,Units2021,Units2022
|
||||
West,Texas,927,925
|
||||
North,Tennessee,466,466
|
||||
East,Florida,520,458
|
||||
East,Maine,828,661
|
||||
West,Virginia,465,465
|
||||
North,Missouri,436,235
|
||||
South,Kansas,214,214
|
||||
North,North Dakota,789,640
|
||||
South,Delaware,712,508
|
||||
"@
|
||||
|
||||
$excel = $data | Export-Excel $xlSourcefile -AutoSize -PassThru
|
||||
|
||||
Add-ConditionalFormatting -Worksheet $excel.sheet1 -Range "C2:C10" -ConditionValue '=C2=D2' -RuleType Expression -BackgroundColor Cyan
|
||||
|
||||
Close-ExcelPackage $excel -Show
|
||||
23
Examples/CustomNumbers/ShortenNumbers.ps1
Normal file
23
Examples/CustomNumbers/ShortenNumbers.ps1
Normal file
@@ -0,0 +1,23 @@
|
||||
# How to convert abbreviate or shorten long numbers in Excel
|
||||
|
||||
Remove-Item .\custom.xlsx -ErrorAction SilentlyContinue
|
||||
|
||||
$data = $(
|
||||
12000
|
||||
1000
|
||||
2000
|
||||
3000
|
||||
2400
|
||||
3600
|
||||
6000
|
||||
13000
|
||||
40000
|
||||
400000
|
||||
1000000
|
||||
)
|
||||
|
||||
$excel = $data | Export-Excel .\custom.xlsx -PassThru
|
||||
|
||||
Set-ExcelRange -Worksheet $excel.Sheet1 -Range "A:A" -NumberFormat '[>999999]#,,"M";#,"K"'
|
||||
|
||||
Close-ExcelPackage $excel -Show
|
||||
@@ -15,6 +15,6 @@ param(
|
||||
$galleryUrl = "https://www.powershellgallery.com/packages/$moduleName"
|
||||
$nolegend = '-nolegend'
|
||||
if($chartType -eq 'pie') {$nolegend = $null}
|
||||
$code = "$($chartType)Chart (Get-HtmlTable $galleryUrl 0 | sort lastupdated -desc) -title 'Download stats for $moduleName' $nolegend"
|
||||
$code = "$($chartType)Chart (Get-HtmlTable $galleryUrl -FirstDataRow 1 | sort lastupdated -desc) -title 'Download stats for $moduleName' $nolegend"
|
||||
|
||||
$code | Invoke-Expression
|
||||
@@ -2,6 +2,6 @@ Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force
|
||||
|
||||
$xlfile = "$PSScriptRoot\yearlySales.xlsx"
|
||||
|
||||
$result = Import-Excel -Path $xlfile -WorksheetName * -NotAsDictionary
|
||||
$result = Import-Excel -Path $xlfile -WorksheetName * -Raw
|
||||
|
||||
$result | Measure-Object
|
||||
BIN
Examples/ImportByColumns/FruitCity.xlsx
Normal file
BIN
Examples/ImportByColumns/FruitCity.xlsx
Normal file
Binary file not shown.
BIN
Examples/ImportByColumns/VM_Build_Example.xlsx
Normal file
BIN
Examples/ImportByColumns/VM_Build_Example.xlsx
Normal file
Binary file not shown.
146
Examples/ImportByColumns/import-by-columns.ps1
Normal file
146
Examples/ImportByColumns/import-by-columns.ps1
Normal file
@@ -0,0 +1,146 @@
|
||||
function Import-ByColumns {
|
||||
<#
|
||||
.synopsis
|
||||
Works like Import-Excel but with data in columns instead of the conventional rows.
|
||||
.Description.
|
||||
Import-excel will read the sample file in this folder like this
|
||||
> Import-excel FruitCity.xlsx | ft *
|
||||
GroupAs Apple Orange Banana
|
||||
------- ----- ------ ------
|
||||
London 1 4 9
|
||||
Paris 2 4 10
|
||||
NewYork 6 5 11
|
||||
Munich 7 8 12
|
||||
Import-ByColumns transposes it
|
||||
> Import-Bycolumns FruitCity.xlsx | ft *
|
||||
GroupAs London Paris NewYork Munich
|
||||
------- ------ ----- ------- ------
|
||||
Apple 1 2 6 7
|
||||
Orange 4 4 5 8
|
||||
Banana 9 10 11 12
|
||||
.Example
|
||||
C:\> Import-Bycolumns -path .\VM_Build_Example.xlsx -StartRow 7 -EndRow 21 -EndColumn 7 -HeaderName Desc,size,type,
|
||||
cpu,ram,NetAcc,OS,OSDiskSize,DataDiskSize,LogDiskSize,TempDbDiskSize,BackupDiskSize,ImageDiskDize,AzureBackup,AzureReplication | ft -a *
|
||||
|
||||
This reads a spreadsheet which has a block from row 7 to 21 containing 14 properties of virtual machines.
|
||||
The properties names are in column A and the 6 VMS are in columns B-G
|
||||
Because the property names are written for easy reading by the person completing the spreadsheet, they are replaced with new names.
|
||||
All the parameters work as they would for Import-Excel
|
||||
#>
|
||||
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")]
|
||||
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,
|
||||
|
||||
[Parameter(ParameterSetName = "PackageA", Mandatory)]
|
||||
[Parameter(ParameterSetName = "PackageB", Mandatory)]
|
||||
[Parameter(ParameterSetName = "PackageC", Mandatory)]
|
||||
[OfficeOpenXml.ExcelPackage]$ExcelPackage,
|
||||
|
||||
[Alias('Sheet')]
|
||||
[Parameter(Position = 1)]
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]$WorksheetName,
|
||||
|
||||
[Parameter(ParameterSetName = 'PathB' , Mandatory)]
|
||||
[Parameter(ParameterSetName = 'PackageB', Mandatory)]
|
||||
[String[]]$HeaderName ,
|
||||
[Parameter(ParameterSetName = 'PathC' , Mandatory)]
|
||||
[Parameter(ParameterSetName = 'PackageC', Mandatory)]
|
||||
[Switch]$NoHeader,
|
||||
|
||||
[Alias('TopRow')]
|
||||
[ValidateRange(1, 9999)]
|
||||
[Int]$StartRow = 1,
|
||||
|
||||
[Alias('StopRow', 'BottomRow')]
|
||||
[Int]$EndRow ,
|
||||
|
||||
[Alias('LeftColumn','LabelColumn')]
|
||||
[Int]$StartColumn = 1,
|
||||
|
||||
[Int]$EndColumn,
|
||||
[switch]$DataOnly,
|
||||
[switch]$AsHash,
|
||||
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]$Password
|
||||
)
|
||||
function Get-PropertyNames {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Create objects containing the row number and the row 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[]]$Rows,
|
||||
[Parameter(Mandatory)]
|
||||
[Int]$StartColumn
|
||||
)
|
||||
if ($HeaderName) {
|
||||
$i = 0
|
||||
foreach ($h in $HeaderName) {
|
||||
$h | Select-Object @{n='Row'; e={$rows[$i]}}, @{n='Value'; e={$h} }
|
||||
$i++
|
||||
}
|
||||
}
|
||||
elseif ($NoHeader) {
|
||||
$i = 0
|
||||
foreach ($r in $rows) {
|
||||
$i++
|
||||
$r | Select-Object @{n='Row'; e={$_}}, @{n='Value'; e={"P$i"} }
|
||||
}
|
||||
}
|
||||
else {
|
||||
foreach ($r in $Rows) {
|
||||
#allow "False" or "0" to be headings
|
||||
$Worksheet.Cells[$r, $StartColumn] | Where-Object {-not [string]::IsNullOrEmpty($_.Value) } | Select-Object @{n='Row'; e={$r} }, Value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region open file if necessary, find worksheet and ensure we have start/end row/columns
|
||||
if ($Path -and -not $ExcelPackage -and $Password) {
|
||||
$ExcelPackage = Open-ExcelPackage -Path $Path -Password $Password
|
||||
}
|
||||
elseif ($Path -and -not $ExcelPackage ) {
|
||||
$ExcelPackage = Open-ExcelPackage -Path $Path
|
||||
}
|
||||
if (-not $ExcelPackage) {
|
||||
throw 'Could not get an Excel workbook to work on' ; return
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if (-not $EndRow ) { $EndRow = $Worksheet.Dimension.End.Row }
|
||||
if (-not $EndColumn) { $EndColumn = $Worksheet.Dimension.End.Column }
|
||||
#endregion
|
||||
|
||||
$Rows = $Startrow .. $EndRow ;
|
||||
$Columns = (1 + $StartColumn)..$EndColumn
|
||||
|
||||
if ((-not $rows) -or (-not ($PropertyNames = Get-PropertyNames -Rows $Rows -StartColumn $StartColumn))) {
|
||||
throw "No headers found in left coulmn '$Startcolumn'. "; return
|
||||
}
|
||||
if (-not $Columns) {
|
||||
Write-Warning "Worksheet '$WorksheetName' in workbook contains no data in the rows after left column '$StartColumn'"
|
||||
}
|
||||
else {
|
||||
foreach ($c in $Columns) {
|
||||
$NewColumn = [Ordered]@{ }
|
||||
foreach ($p in $PropertyNames) {
|
||||
$NewColumn[$p.Value] = $Worksheet.Cells[$p.row,$c].text
|
||||
}
|
||||
if ($AsHash) {$NewColumn}
|
||||
elseif (($NewColumn.Values -ne "") -or -not $dataonly) {[PSCustomObject]$NewColumn}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
|
||||
Function Import-Bycolumns {
|
||||
Param(
|
||||
[Parameter(Mandatory=$true)]
|
||||
[OfficeOpenXml.ExcelPackage]$ExcelPackage,
|
||||
[Int]$StartRow = 1,
|
||||
[String]$WorksheetName,
|
||||
[Int]$EndRow ,
|
||||
[Int]$StartColumn = 1,
|
||||
[Int]$EndColumn
|
||||
)
|
||||
Function Get-RowNames {
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = "Name would be incorrect, and command is not exported")]
|
||||
param(
|
||||
[Parameter(Mandatory)]
|
||||
[Int[]]$Rows,
|
||||
[Parameter(Mandatory)]
|
||||
[Int]$StartColumn
|
||||
)
|
||||
foreach ($R in $Rows) {
|
||||
#allow "False" or "0" to be headings
|
||||
$Worksheet.Cells[$R, $StartColumn] | Where-Object {-not [string]::IsNullOrEmpty($_.Value) } | Select-Object @{N = 'Row'; E = { $R } }, Value
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
if (-not $EndRow ) { $EndRow = $Worksheet.Dimension.End.Row }
|
||||
if (-not $EndColumn) { $EndColumn = $Worksheet.Dimension.End.Column }
|
||||
|
||||
$Rows = $Startrow .. $EndRow ;
|
||||
$Columns = (1 + $StartColumn)..$EndColumn
|
||||
|
||||
if ((-not $rows) -or (-not ($PropertyNames = Get-RowNames -Rows $Rows -StartColumn $StartColumn))) {
|
||||
throw "No headers found in left coulmn '$Startcolumn'. "; return
|
||||
}
|
||||
if (-not $Columns) {
|
||||
Write-Warning "Worksheet '$WorksheetName' in workbook contains no data in the rows after left column '$StartColumn'"
|
||||
}
|
||||
else {
|
||||
foreach ($c in $Columns) {
|
||||
$NewColumn = [Ordered]@{ }
|
||||
foreach ($p in $PropertyNames) {
|
||||
$NewColumn[$p.Value] = $Worksheet.Cells[$p.row,$c].text
|
||||
}
|
||||
[PSCustomObject]$NewColumn
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@
|
||||
RootModule = 'ImportExcel.psm1'
|
||||
|
||||
# Version number of this module.
|
||||
ModuleVersion = '7.5.1'
|
||||
ModuleVersion = '7.7.0'
|
||||
|
||||
# ID used to uniquely identify this module
|
||||
GUID = '60dd4136-feff-401a-ba27-a84458c57ede'
|
||||
@@ -131,9 +131,8 @@ Check out the How To Videos https://www.youtube.com/watch?v=U3Ne_yX4tYo&list=PL5
|
||||
'.\Charting\Charting.ps1',
|
||||
'.\InferData\InferData.ps1',
|
||||
'.\Pivot\Pivot.ps1',
|
||||
'.\spikes\ConvertFrom-ExcelColumnName.ps1',
|
||||
'.\Examples', '.\images', '.\Testimonials'
|
||||
|
||||
'.\Examples',
|
||||
'.\Testimonials'
|
||||
)
|
||||
|
||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||
|
||||
@@ -7,5 +7,5 @@ if (-not $fullPath) {
|
||||
$fullPath = Join-Path $fullPath -ChildPath "ImportExcel"
|
||||
}
|
||||
Push-location $PSScriptRoot
|
||||
Robocopy . $fullPath /mir /XD .vscode .git CI __tests__ data mdHelp /XF appveyor.yml azure-pipelines.yml .gitattributes .gitignore filelist.txt install.ps1 InstallModule.ps1
|
||||
Robocopy . $fullPath /mir /XD .vscode images .git .github CI __tests__ data mdHelp spikes /XF README.md README.original.md appveyor.yml azure-pipelines.yml .gitattributes .gitignore filelist.txt install.ps1 InstallModule.ps1 PublishToGallery.ps1
|
||||
Pop-Location
|
||||
@@ -9,36 +9,75 @@ function Get-HtmlTable {
|
||||
[int]$FirstDataRow=0,
|
||||
[Switch]$UseDefaultCredentials
|
||||
)
|
||||
if ($PSVersionTable.PSVersion.Major -gt 5 -and -not (Get-Command ConvertFrom-Html -ErrorAction SilentlyContinue)) {
|
||||
# Invoke-WebRequest on .NET core doesn't have ParsedHtml so we need HtmlAgilityPack or similiar Justin Grote's PowerHTML wraps that nicely
|
||||
throw "This version of PowerShell needs the PowerHTML module to process HTML Tables."
|
||||
}
|
||||
|
||||
$r = Invoke-WebRequest $Url -UseDefaultCredentials: $UseDefaultCredentials
|
||||
$propertyNames = $Header
|
||||
|
||||
$table = $r.ParsedHtml.getElementsByTagName("table")[$TableIndex]
|
||||
$propertyNames=$Header
|
||||
$totalRows=@($table.rows).count
|
||||
if ($PSVersionTable.PSVersion.Major -le 5) {
|
||||
$table = $r.ParsedHtml.getElementsByTagName("table")[$TableIndex]
|
||||
$totalRows=@($table.rows).count
|
||||
|
||||
for ($idx = $FirstDataRow; $idx -lt $totalRows; $idx++) {
|
||||
for ($idx = $FirstDataRow; $idx -lt $totalRows; $idx++) {
|
||||
|
||||
$row = $table.rows[$idx]
|
||||
$cells = @($row.cells)
|
||||
$row = $table.rows[$idx]
|
||||
$cells = @($row.cells)
|
||||
|
||||
if(!$propertyNames) {
|
||||
if($cells[0].tagName -eq 'th') {
|
||||
$propertyNames = @($cells | ForEach-Object {$_.innertext -replace ' ',''})
|
||||
} else {
|
||||
$propertyNames = @(1..($cells.Count + 2) | Foreach-Object { "P$_" })
|
||||
if(!$propertyNames) {
|
||||
if($cells[0].tagName -eq 'th') {
|
||||
$propertyNames = @($cells | ForEach-Object {$_.innertext -replace ' ',''})
|
||||
} else {
|
||||
$propertyNames = @(1..($cells.Count + 2) | Foreach-Object { "P$_" })
|
||||
}
|
||||
continue
|
||||
}
|
||||
continue
|
||||
|
||||
$result = [ordered]@{}
|
||||
|
||||
for($counter = 0; $counter -lt $cells.Count; $counter++) {
|
||||
$propertyName = $propertyNames[$counter]
|
||||
|
||||
if(!$propertyName) { $propertyName= '[missing]'}
|
||||
$result.$propertyName= $cells[$counter].InnerText
|
||||
}
|
||||
|
||||
[PSCustomObject]$result
|
||||
}
|
||||
|
||||
$result = [ordered]@{}
|
||||
|
||||
for($counter = 0; $counter -lt $cells.Count; $counter++) {
|
||||
$propertyName = $propertyNames[$counter]
|
||||
|
||||
if(!$propertyName) { $propertyName= '[missing]'}
|
||||
$result.$propertyName= $cells[$counter].InnerText
|
||||
}
|
||||
else {
|
||||
$h = ConvertFrom-Html -Content $r.Content
|
||||
if ($TableIndex -is [valuetype]) { $TableIndex += 1}
|
||||
$rows = $h.SelectNodes("//table[$TableIndex]//tr")
|
||||
if (-not $rows) {Write-Warning "Could not find rows for `"//table[$TableIndex]`" in $Url ."}
|
||||
if ( -not $propertyNames) {
|
||||
if ( $tableHeaders = $rows[$FirstDataRow].SelectNodes("th")) {
|
||||
$propertyNames = $tableHeaders.foreach({[System.Web.HttpUtility]::HtmlDecode( $_.innerText ) -replace '\W+','_' -replace '(\w)_+$','$1' })
|
||||
$FirstDataRow += 1
|
||||
}
|
||||
else {
|
||||
$c = 0
|
||||
$propertyNames = $rows[$FirstDataRow].SelectNodes("td") | Foreach-Object { "P$c" ; $c ++ }
|
||||
}
|
||||
}
|
||||
Write-Verbose ("Property names: " + ($propertyNames -join ","))
|
||||
foreach ($n in $FirstDataRow..($rows.Count-1)) {
|
||||
$r = $rows[$n].SelectNodes("td|th")
|
||||
if ($r -and $r.innerText -ne "" -and $r.count -gt $rows[$n].SelectNodes("th").count ) {
|
||||
$c = 0
|
||||
$newObj = [ordered]@{}
|
||||
foreach ($p in $propertyNames) {
|
||||
$n = $null
|
||||
#Join descentandts for cases where the text in the cell is split (e.g with a <BR> ). We also want to remove HTML codes, trim and convert unicode minus sign to "-"
|
||||
$cellText = $r[$c].Descendants().where({$_.NodeType -eq "Text"}).foreach({[System.Web.HttpUtility]::HtmlDecode( $_.innerText ).Trim()}) -Join " " -replace "\u2212","-"
|
||||
if ([double]::TryParse($cellText, [ref]$n)) {$newObj[$p] = $n }
|
||||
else {$newObj[$p] = $cellText }
|
||||
$c ++
|
||||
}
|
||||
[pscustomObject]$newObj
|
||||
}
|
||||
}
|
||||
|
||||
[PSCustomObject]$result
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
[ValidateNotNullOrEmpty()]
|
||||
[String]$Password,
|
||||
[Int[]]$ImportColumns,
|
||||
[Switch]$NotAsDictionary
|
||||
[Switch]$Raw
|
||||
)
|
||||
end {
|
||||
$sw = [System.Diagnostics.Stopwatch]::StartNew()
|
||||
@@ -134,8 +134,16 @@
|
||||
|
||||
$xlBook = [Ordered]@{}
|
||||
foreach ($sheet in $Worksheet) {
|
||||
$EndRow = 0
|
||||
$EndColumn = 0
|
||||
if ($Worksheet.Count -gt 1 -or $Paths.Count -gt 1) {
|
||||
<#
|
||||
Needed under these conditions to handle sheets of different number of Row/Col
|
||||
- When reading more than one xlsx file
|
||||
- When reading more than one worksheet in the same file
|
||||
#>
|
||||
$EndRow = $null
|
||||
$EndColumn = $null
|
||||
}
|
||||
|
||||
$targetSheetname = $sheet.Name
|
||||
$xlBook["$targetSheetname"] = @()
|
||||
#region Get rows and columns
|
||||
@@ -239,7 +247,7 @@
|
||||
# $EndColumn = 0
|
||||
if ($Path) { $stream.close(); $ExcelPackage.Dispose() }
|
||||
|
||||
if ($NotAsDictionary) {
|
||||
if ($Raw) {
|
||||
foreach ($entry in $xlbook.GetEnumerator()) {
|
||||
$entry.Value
|
||||
}
|
||||
|
||||
@@ -3,13 +3,13 @@ function Import-Html {
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
$Url,
|
||||
$Index,
|
||||
[int]$Index = 0,
|
||||
$Header,
|
||||
[int]$FirstDataRow=0,
|
||||
[int]$FirstDataRow = 0,
|
||||
[Switch]$UseDefaultCredentials
|
||||
)
|
||||
|
||||
$xlFile = [System.IO.Path]::GetTempFileName() -replace "tmp","xlsx"
|
||||
$xlFile = [System.IO.Path]::GetTempFileName() -replace "tmp", "xlsx"
|
||||
Remove-Item $xlFile -ErrorAction Ignore
|
||||
|
||||
Write-Verbose "Exporting to Excel file $($xlFile)"
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
|
||||
#region Apply formatting
|
||||
$params = @{}
|
||||
foreach ($p in @('Underline','Bold','Italic','StrikeThru', 'FontName', 'FontSize','FontShift','NumberFormat','TextRotation',
|
||||
foreach ($p in @('Underline','UnderLineType','Bold','Italic','StrikeThru', 'FontName', 'FontSize','FontShift','NumberFormat','TextRotation',
|
||||
'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Autosize', 'Width', 'FontColor'
|
||||
'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) {
|
||||
if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]}
|
||||
|
||||
1248
README.original.md
Normal file
1248
README.original.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
#Requires -Modules Pester
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments','',Justification='False Positives')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable','',Justification='Only executes on versions without the automatic variable')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')]
|
||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable', '', Justification = 'Only executes on versions without the automatic variable')]
|
||||
param()
|
||||
Describe ExportExcel -Tag "ExportExcel" {
|
||||
BeforeAll {
|
||||
@@ -8,7 +8,7 @@ Describe ExportExcel -Tag "ExportExcel" {
|
||||
$WarningAction = "SilentlyContinue"
|
||||
. "$PSScriptRoot\Samples\Samples.ps1"
|
||||
if (-not (Get-command Get-Service -ErrorAction SilentlyContinue)) {
|
||||
Function Get-Service {Import-Clixml $PSScriptRoot\Mockservices.xml}
|
||||
Function Get-Service { Import-Clixml $PSScriptRoot\Mockservices.xml }
|
||||
}
|
||||
if (Get-process -Name Excel, xlim -ErrorAction SilentlyContinue) {
|
||||
It "Excel is open" {
|
||||
@@ -389,7 +389,7 @@ Describe ExportExcel -Tag "ExportExcel" {
|
||||
}
|
||||
}
|
||||
|
||||
Context "#Example 5 # Adding a single conditional format "{
|
||||
Context "#Example 5 # Adding a single conditional format " {
|
||||
BeforeEach {
|
||||
#Test New-ConditionalText builds correctly
|
||||
$ct = New-ConditionalText -ConditionalType GreaterThan 525 -ConditionalTextColor ([System.Drawing.Color]::DarkRed) -BackgroundColor ([System.Drawing.Color]::LightPink)
|
||||
@@ -491,7 +491,7 @@ Describe ExportExcel -Tag "ExportExcel" {
|
||||
}
|
||||
}
|
||||
|
||||
Context "#Examples 8 & 9 # Adding Pivot tables and charts from parameters" {
|
||||
Context "#Examples 8 & 9 # Adding Pivot tables and charts from parameters" {
|
||||
BeforeAll {
|
||||
$path = "TestDrive:\test.xlsx"
|
||||
#Test -passthru and -worksheetName creating a new, named, sheet in an existing file.
|
||||
@@ -544,7 +544,7 @@ Describe ExportExcel -Tag "ExportExcel" {
|
||||
#Test appending data extends pivot chart (with a warning) .
|
||||
$warnVar = $null
|
||||
Get-Process | Select-Object -Last 20 -Property Name, cpu, pm, handles, company |
|
||||
Export-Excel $path -WorkSheetname Processes -Append -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -WarningAction SilentlyContinue -WarningVariable warnvar
|
||||
Export-Excel $path -WorkSheetname Processes -Append -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -WarningAction SilentlyContinue -WarningVariable warnvar
|
||||
$Excel = Open-ExcelPackage $path
|
||||
$pt = $Excel.Workbook.Worksheets["ProcessesPivotTable"].PivotTables[0]
|
||||
|
||||
@@ -557,12 +557,12 @@ Describe ExportExcel -Tag "ExportExcel" {
|
||||
}
|
||||
}
|
||||
|
||||
Context " # Add-Worksheet inserted sheets, moved them correctly, and copied a sheet" {
|
||||
Context " # Add-Worksheet inserted sheets, moved them correctly, and copied a sheet" {
|
||||
BeforeAll {
|
||||
$path = "TestDrive:\test.xlsx"
|
||||
#Test the -CopySource and -Movexxxx parameters for Add-Worksheet
|
||||
$Excel = Get-Process | Select-Object -first 20 -Property Name, cpu, pm, handles, company |
|
||||
Export-Excel $path -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -NoTotalsInPivot -PivotDataToColumn -Activate
|
||||
Export-Excel $path -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -NoTotalsInPivot -PivotDataToColumn -Activate
|
||||
|
||||
$Excel = Open-ExcelPackage $path
|
||||
#At this point Sheets Should be in the order Sheet1, Processes, ProcessesPivotTable
|
||||
@@ -1081,4 +1081,55 @@ Describe ExportExcel -Tag "ExportExcel" {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Context " # Check UnderLineType" -Tag CheckUnderLineType {
|
||||
BeforeAll {
|
||||
$Path = Join-Path (Resolve-Path 'TestDrive:').ProviderPath "testUnderLineType.xlsx"
|
||||
Remove-Item -Path $Path -ErrorAction SilentlyContinue
|
||||
|
||||
$data = "
|
||||
Set-ExcelRange,Set-ExcelColumn
|
||||
Should be double underlined,Should be double underlined
|
||||
Should be double underlined,Should be double underlined
|
||||
" | ConvertFrom-Csv
|
||||
|
||||
$data | Export-Excel $Path -AutoSize
|
||||
|
||||
$excel = Open-ExcelPackage $Path
|
||||
$ws = $excel.Workbook.Worksheets["sheet1"]
|
||||
|
||||
Set-ExcelRange -Range $ws.Cells["A2:A3"] -Underline -UnderLineType "Double"
|
||||
Set-ExcelColumn -Worksheet $ws -Column 2 -StartRow 2 -Underline -UnderLineType "Double"
|
||||
|
||||
Close-ExcelPackage $excel
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
Remove-Item -Path $Path -ErrorAction SilentlyContinue
|
||||
}
|
||||
|
||||
it "Check Cell Style Font via Set-ExcelColumn".PadRight(87) {
|
||||
$excel = Open-ExcelPackage $Path
|
||||
$cell = $excel.Sheet1.Cells["B2"]
|
||||
|
||||
$actual = $cell.Style.Font
|
||||
|
||||
$actual.Underline | Should -BeTrue
|
||||
$actual.UnderlineType | Should -Be "Double"
|
||||
|
||||
Close-ExcelPackage $excel -NoSave
|
||||
}
|
||||
|
||||
it "Check Cell Style Font via Set-ExcelRange".PadRight(87) {
|
||||
$excel = Open-ExcelPackage $Path
|
||||
$cell = $excel.Sheet1.Cells["A2"]
|
||||
|
||||
$actual = $cell.Style.Font
|
||||
|
||||
$actual.Underline | Should -BeTrue
|
||||
$actual.UnderlineType | Should -Be "Double"
|
||||
|
||||
Close-ExcelPackage $excel -NoSave
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
__tests__/ImportExcelTests/DataInDiffRowCol.xlsx
Normal file
BIN
__tests__/ImportExcelTests/DataInDiffRowCol.xlsx
Normal file
Binary file not shown.
BIN
__tests__/ImportExcelTests/DataInDiffRowColMultipleSheets.xlsx
Normal file
BIN
__tests__/ImportExcelTests/DataInDiffRowColMultipleSheets.xlsx
Normal file
Binary file not shown.
@@ -0,0 +1,51 @@
|
||||
Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force
|
||||
|
||||
Describe 'Test' -Tag ImportExcelEndRowAndCols {
|
||||
BeforeAll {
|
||||
$script:xlFilename = "$PSScriptRoot\DataInDiffRowCol.xlsx"
|
||||
}
|
||||
|
||||
Context 'Test reading a partial sheet' {
|
||||
It 'Should read 2 rows and first 3 columns' {
|
||||
$actual = Import-Excel $xlFilename -StartRow 5 -EndRow 7 -StartColumn 3 -EndColumn 5
|
||||
|
||||
# $actual | out-host
|
||||
$actual.Count | Should -Be 2
|
||||
|
||||
$colNames = $actual[0].psobject.properties.Name
|
||||
$colNames.Count | Should -Be 3
|
||||
|
||||
$colNames[0] | Should -Be 'Region'
|
||||
$colNames[1] | Should -Be 'State'
|
||||
$colNames[2] | Should -Be 'Units'
|
||||
}
|
||||
|
||||
It 'Should read second 2 rows and last 2 columns' {
|
||||
$actual = Import-Excel $xlFilename -StartRow 8 -EndRow 9 -StartColumn 5 -EndColumn 6 -HeaderName 'Units', 'Price'
|
||||
|
||||
# $actual | out-host
|
||||
$actual.Count | Should -Be 2
|
||||
|
||||
$colNames = $actual[0].psobject.properties.Name
|
||||
$colNames.Count | Should -Be 2
|
||||
|
||||
$colNames[0] | Should -Be 'Units'
|
||||
$colNames[1] | Should -Be 'Price'
|
||||
}
|
||||
}
|
||||
|
||||
Context 'Test reading multiple sheets with data in differnt rows and columns' {
|
||||
It 'Should read 2 sheets same StartRow different dimensions' {
|
||||
$xlFilename = "$PSScriptRoot\DataInDiffRowColMultipleSheets.xlsx"
|
||||
|
||||
$actual = Import-Excel $xlFilename -StartRow 5 -WorksheetName *
|
||||
|
||||
$actual.Keys.Count | Should -Be 2
|
||||
$actual.Contains('Sheet1') | Should -BeTrue
|
||||
$actual.Contains('Sheet2') | Should -BeTrue
|
||||
|
||||
$actual['Sheet1'].Count | Should -Be 9
|
||||
$actual['Sheet2'].Count | Should -Be 12
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,7 @@ Describe 'Different ways to import sheets' -Tag ImportExcelReadSheets {
|
||||
}
|
||||
|
||||
It 'Should return an array not a dictionary' {
|
||||
$actual = Import-Excel $xlFilename april, june -NotAsDictionary
|
||||
$actual = Import-Excel $xlFilename april, june -Raw
|
||||
|
||||
$actual.Count | Should -Be 200
|
||||
$group = $actual | Group-Object month -NoElement
|
||||
@@ -69,5 +69,14 @@ Describe 'Different ways to import sheets' -Tag ImportExcelReadSheets {
|
||||
$actual["2015"].Count | Should -Be 12
|
||||
$actual["2016"].Count | Should -Be 1
|
||||
}
|
||||
|
||||
It "Should read multiple sheets with diff number of rows correctly and flatten it" {
|
||||
$xlFilename = "$PSScriptRoot\construction.xlsx"
|
||||
|
||||
$actual = Import-Excel $xlFilename 2015, 2016 -Raw
|
||||
|
||||
$actual.Count | Should -Be 13
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ Param()
|
||||
|
||||
Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force
|
||||
|
||||
Describe "Test reading multiple XLSX files of differernt row count" -Tag ReadMultipleXLSX {
|
||||
Describe "Test reading multiple XLSX files of different row count" -Tag ReadMultipleXLSX {
|
||||
It "Should find these xlsx files" {
|
||||
Test-Path -Path $PSScriptRoot\rows05.xlsx | Should -BeTrue
|
||||
Test-Path -Path $PSScriptRoot\rows10.xlsx | Should -BeTrue
|
||||
|
||||
23
changelog.md
23
changelog.md
@@ -1,3 +1,26 @@
|
||||
# 7.7.0
|
||||
|
||||
- Fix a bug with `-UnderLineType parameter is ignored in Set-ExcelColumn` [#1204](https://github.com/dfinke/ImportExcel/issues/1204)
|
||||
|
||||
# Example added
|
||||
|
||||
Thank you [@kkazala](https://github.com/kkazala)
|
||||
- Added an example showing `ConditionalFormatting` using the `RuleType` `Expression` with a formula
|
||||
- [Highlight-DiffCells.ps1](https://github.dev/kkazala/ImportExcel/blob/b53881fd023c052da1acc7812511da223bb2e40c/Examples/ConditionalFormatting/Highlight-DiffCells.ps1)
|
||||
|
||||
# 7.6.0
|
||||
|
||||
- **_[Under investigation]_** Fix -StartRow and -StartColumn being ignored.
|
||||
- James O'Neill:
|
||||
- Update Get-HtmlTable to support to use PowerHTML (maintained by [Justin Grote](https://twitter.com/JustinWGrote)).
|
||||
- Added example to including a new function Import-ByColumn. Works like Import-Excel but with data in columns instead of the conventional rows.
|
||||
- Update Import-HTML with better defaults
|
||||
- Fixed example `Get-ModuleStats.ps1` which reads the PowerShell Gallery page and extracts the stats table
|
||||
|
||||
|
||||
# v7.5.2
|
||||
- Changed the switch `-NotAsDictionary` to `-Raw`. Works with `-Worksheetname *` reads all the sheets in the xlsx file and returns an array.
|
||||
|
||||
# v7.5.1
|
||||
- Fixed `Import-Excel` - Reset `EndRow` and `EndColumn` in the correct place.
|
||||
# v7.5.0
|
||||
|
||||
BIN
images/SalesData.png
Normal file
BIN
images/SalesData.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
BIN
images/SalesDataChart.png
Normal file
BIN
images/SalesDataChart.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
BIN
images/SalesDataChartPivotTable.png
Normal file
BIN
images/SalesDataChartPivotTable.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 238 KiB |
BIN
images/logo.png
Normal file
BIN
images/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
images/logoWithInstall.png
Normal file
BIN
images/logoWithInstall.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
Reference in New Issue
Block a user