mirror of
https://github.com/dfinke/ImportExcel.git
synced 2025-12-15 15:53:32 +00:00
Compare commits
60 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 | ||
|
|
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"
|
$galleryUrl = "https://www.powershellgallery.com/packages/$moduleName"
|
||||||
$nolegend = '-nolegend'
|
$nolegend = '-nolegend'
|
||||||
if($chartType -eq 'pie') {$nolegend = $null}
|
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
|
$code | Invoke-Expression
|
||||||
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'
|
RootModule = 'ImportExcel.psm1'
|
||||||
|
|
||||||
# Version number of this module.
|
# Version number of this module.
|
||||||
ModuleVersion = '7.5.2'
|
ModuleVersion = '7.7.0'
|
||||||
|
|
||||||
# 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'
|
||||||
@@ -131,9 +131,8 @@ Check out the How To Videos https://www.youtube.com/watch?v=U3Ne_yX4tYo&list=PL5
|
|||||||
'.\Charting\Charting.ps1',
|
'.\Charting\Charting.ps1',
|
||||||
'.\InferData\InferData.ps1',
|
'.\InferData\InferData.ps1',
|
||||||
'.\Pivot\Pivot.ps1',
|
'.\Pivot\Pivot.ps1',
|
||||||
'.\spikes\ConvertFrom-ExcelColumnName.ps1',
|
'.\Examples',
|
||||||
'.\Examples', '.\images', '.\Testimonials'
|
'.\Testimonials'
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
# Private data to pass to the module specified in RootModule/ModuleToProcess
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ if (-not $fullPath) {
|
|||||||
$fullPath = Join-Path $fullPath -ChildPath "ImportExcel"
|
$fullPath = Join-Path $fullPath -ChildPath "ImportExcel"
|
||||||
}
|
}
|
||||||
Push-location $PSScriptRoot
|
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
|
Pop-Location
|
||||||
@@ -9,36 +9,75 @@ function Get-HtmlTable {
|
|||||||
[int]$FirstDataRow=0,
|
[int]$FirstDataRow=0,
|
||||||
[Switch]$UseDefaultCredentials
|
[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
|
$r = Invoke-WebRequest $Url -UseDefaultCredentials: $UseDefaultCredentials
|
||||||
|
$propertyNames = $Header
|
||||||
|
|
||||||
$table = $r.ParsedHtml.getElementsByTagName("table")[$TableIndex]
|
if ($PSVersionTable.PSVersion.Major -le 5) {
|
||||||
$propertyNames=$Header
|
$table = $r.ParsedHtml.getElementsByTagName("table")[$TableIndex]
|
||||||
$totalRows=@($table.rows).count
|
$totalRows=@($table.rows).count
|
||||||
|
|
||||||
for ($idx = $FirstDataRow; $idx -lt $totalRows; $idx++) {
|
for ($idx = $FirstDataRow; $idx -lt $totalRows; $idx++) {
|
||||||
|
|
||||||
$row = $table.rows[$idx]
|
$row = $table.rows[$idx]
|
||||||
$cells = @($row.cells)
|
$cells = @($row.cells)
|
||||||
|
|
||||||
if(!$propertyNames) {
|
if(!$propertyNames) {
|
||||||
if($cells[0].tagName -eq 'th') {
|
if($cells[0].tagName -eq 'th') {
|
||||||
$propertyNames = @($cells | ForEach-Object {$_.innertext -replace ' ',''})
|
$propertyNames = @($cells | ForEach-Object {$_.innertext -replace ' ',''})
|
||||||
} else {
|
} else {
|
||||||
$propertyNames = @(1..($cells.Count + 2) | Foreach-Object { "P$_" })
|
$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]@{}
|
else {
|
||||||
|
$h = ConvertFrom-Html -Content $r.Content
|
||||||
for($counter = 0; $counter -lt $cells.Count; $counter++) {
|
if ($TableIndex -is [valuetype]) { $TableIndex += 1}
|
||||||
$propertyName = $propertyNames[$counter]
|
$rows = $h.SelectNodes("//table[$TableIndex]//tr")
|
||||||
|
if (-not $rows) {Write-Warning "Could not find rows for `"//table[$TableIndex]`" in $Url ."}
|
||||||
if(!$propertyName) { $propertyName= '[missing]'}
|
if ( -not $propertyNames) {
|
||||||
$result.$propertyName= $cells[$counter].InnerText
|
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -134,8 +134,16 @@
|
|||||||
|
|
||||||
$xlBook = [Ordered]@{}
|
$xlBook = [Ordered]@{}
|
||||||
foreach ($sheet in $Worksheet) {
|
foreach ($sheet in $Worksheet) {
|
||||||
$EndRow = 0
|
if ($Worksheet.Count -gt 1 -or $Paths.Count -gt 1) {
|
||||||
$EndColumn = 0
|
<#
|
||||||
|
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
|
$targetSheetname = $sheet.Name
|
||||||
$xlBook["$targetSheetname"] = @()
|
$xlBook["$targetSheetname"] = @()
|
||||||
#region Get rows and columns
|
#region Get rows and columns
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ function Import-Html {
|
|||||||
[CmdletBinding()]
|
[CmdletBinding()]
|
||||||
param(
|
param(
|
||||||
$Url,
|
$Url,
|
||||||
$Index,
|
[int]$Index = 0,
|
||||||
$Header,
|
$Header,
|
||||||
[int]$FirstDataRow=0,
|
[int]$FirstDataRow = 0,
|
||||||
[Switch]$UseDefaultCredentials
|
[Switch]$UseDefaultCredentials
|
||||||
)
|
)
|
||||||
|
|
||||||
$xlFile = [System.IO.Path]::GetTempFileName() -replace "tmp","xlsx"
|
$xlFile = [System.IO.Path]::GetTempFileName() -replace "tmp", "xlsx"
|
||||||
Remove-Item $xlFile -ErrorAction Ignore
|
Remove-Item $xlFile -ErrorAction Ignore
|
||||||
|
|
||||||
Write-Verbose "Exporting to Excel file $($xlFile)"
|
Write-Verbose "Exporting to Excel file $($xlFile)"
|
||||||
|
|||||||
@@ -110,7 +110,7 @@
|
|||||||
|
|
||||||
#region Apply formatting
|
#region Apply formatting
|
||||||
$params = @{}
|
$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'
|
'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Autosize', 'Width', 'FontColor'
|
||||||
'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) {
|
'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) {
|
||||||
if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]}
|
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
|
#Requires -Modules Pester
|
||||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments','',Justification='False Positives')]
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')]
|
||||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable','',Justification='Only executes on versions without the automatic variable')]
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable', '', Justification = 'Only executes on versions without the automatic variable')]
|
||||||
param()
|
param()
|
||||||
Describe ExportExcel -Tag "ExportExcel" {
|
Describe ExportExcel -Tag "ExportExcel" {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
@@ -8,7 +8,7 @@ Describe ExportExcel -Tag "ExportExcel" {
|
|||||||
$WarningAction = "SilentlyContinue"
|
$WarningAction = "SilentlyContinue"
|
||||||
. "$PSScriptRoot\Samples\Samples.ps1"
|
. "$PSScriptRoot\Samples\Samples.ps1"
|
||||||
if (-not (Get-command Get-Service -ErrorAction SilentlyContinue)) {
|
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) {
|
if (Get-process -Name Excel, xlim -ErrorAction SilentlyContinue) {
|
||||||
It "Excel is open" {
|
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 {
|
BeforeEach {
|
||||||
#Test New-ConditionalText builds correctly
|
#Test New-ConditionalText builds correctly
|
||||||
$ct = New-ConditionalText -ConditionalType GreaterThan 525 -ConditionalTextColor ([System.Drawing.Color]::DarkRed) -BackgroundColor ([System.Drawing.Color]::LightPink)
|
$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 {
|
BeforeAll {
|
||||||
$path = "TestDrive:\test.xlsx"
|
$path = "TestDrive:\test.xlsx"
|
||||||
#Test -passthru and -worksheetName creating a new, named, sheet in an existing file.
|
#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) .
|
#Test appending data extends pivot chart (with a warning) .
|
||||||
$warnVar = $null
|
$warnVar = $null
|
||||||
Get-Process | Select-Object -Last 20 -Property Name, cpu, pm, handles, company |
|
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
|
$Excel = Open-ExcelPackage $path
|
||||||
$pt = $Excel.Workbook.Worksheets["ProcessesPivotTable"].PivotTables[0]
|
$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 {
|
BeforeAll {
|
||||||
$path = "TestDrive:\test.xlsx"
|
$path = "TestDrive:\test.xlsx"
|
||||||
#Test the -CopySource and -Movexxxx parameters for Add-Worksheet
|
#Test the -CopySource and -Movexxxx parameters for Add-Worksheet
|
||||||
$Excel = Get-Process | Select-Object -first 20 -Property Name, cpu, pm, handles, company |
|
$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
|
$Excel = Open-ExcelPackage $path
|
||||||
#At this point Sheets Should be in the order Sheet1, Processes, ProcessesPivotTable
|
#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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ Param()
|
|||||||
|
|
||||||
Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force
|
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" {
|
It "Should find these xlsx files" {
|
||||||
Test-Path -Path $PSScriptRoot\rows05.xlsx | Should -BeTrue
|
Test-Path -Path $PSScriptRoot\rows05.xlsx | Should -BeTrue
|
||||||
Test-Path -Path $PSScriptRoot\rows10.xlsx | Should -BeTrue
|
Test-Path -Path $PSScriptRoot\rows10.xlsx | Should -BeTrue
|
||||||
|
|||||||
20
changelog.md
20
changelog.md
@@ -1,3 +1,23 @@
|
|||||||
|
# 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
|
# v7.5.2
|
||||||
- Changed the switch `-NotAsDictionary` to `-Raw`. Works with `-Worksheetname *` reads all the sheets in the xlsx file and returns an array.
|
- Changed the switch `-NotAsDictionary` to `-Raw`. Works with `-Worksheetname *` reads all the sheets in the xlsx file and returns an array.
|
||||||
|
|
||||||
|
|||||||
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