mirror of
https://github.com/dfinke/ImportExcel.git
synced 2026-01-01 08:03:27 +00:00
Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
91b0e8b0ed | ||
|
|
b997e90e78 | ||
|
|
4d8710d017 | ||
|
|
0929a442a5 | ||
|
|
895a5c0cb2 | ||
|
|
d7901af8f3 | ||
|
|
34f55a3659 | ||
|
|
606988bcf6 | ||
|
|
441f2ada22 | ||
|
|
29ea7012d7 | ||
|
|
67ac63ddcf | ||
|
|
c939c6ecb0 | ||
|
|
96493e059b | ||
|
|
cb7f2a06f4 | ||
|
|
99beda7a10 | ||
|
|
0c8bb2300a | ||
|
|
c09083d350 | ||
|
|
556f0ac51e | ||
|
|
1e4fc59a25 | ||
|
|
5ab6a9116d | ||
|
|
f33215382a | ||
|
|
cf5d3f83d6 | ||
|
|
91da711635 | ||
|
|
eec5e343d4 | ||
|
|
d69b640edc | ||
|
|
2ca870a889 | ||
|
|
a320cfd28c | ||
|
|
aa1b042767 | ||
|
|
7e8416d67c | ||
|
|
229b60b25d | ||
|
|
5700989321 | ||
|
|
56e1704e7e | ||
|
|
8268bbc2e1 | ||
|
|
5657659331 | ||
|
|
0d4a32e266 | ||
|
|
1c8f8d2a3d | ||
|
|
f6a65677df | ||
|
|
86a7865fb2 | ||
|
|
8b3bf4f14f | ||
|
|
4d6193f549 | ||
|
|
6ebac7b6dc | ||
|
|
d71dd36d56 | ||
|
|
3697cdfeee | ||
|
|
1e172cf21f | ||
|
|
6da7553c98 | ||
|
|
5a444c620b | ||
|
|
4a09fc3570 | ||
|
|
d706a10276 | ||
|
|
1fd2f422cd | ||
|
|
283e50547d | ||
|
|
15211a6297 | ||
|
|
8905b8d401 | ||
|
|
e9b437af4e | ||
|
|
330e237727 | ||
|
|
c56b2cd33a | ||
|
|
1aa5c6da45 | ||
|
|
9eb894cf59 |
119
Examples/AddImage/Add-ExcelImage.ps1
Normal file
119
Examples/AddImage/Add-ExcelImage.ps1
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
function Add-ExcelImage {
|
||||||
|
<#
|
||||||
|
.SYNOPSIS
|
||||||
|
Adds an image to a worksheet in an Excel package.
|
||||||
|
.DESCRIPTION
|
||||||
|
Adds an image to a worksheet in an Excel package using the
|
||||||
|
`WorkSheet.Drawings.AddPicture(name, image)` method, and places the
|
||||||
|
image at the location specified by the Row and Column parameters.
|
||||||
|
|
||||||
|
Additional position adjustment can be made by providing RowOffset and
|
||||||
|
ColumnOffset values in pixels.
|
||||||
|
.EXAMPLE
|
||||||
|
$image = [System.Drawing.Image]::FromFile($octocat)
|
||||||
|
$xlpkg = $data | Export-Excel -Path $path -PassThru
|
||||||
|
$xlpkg.Sheet1 | Add-ExcelImage -Image $image -Row 4 -Column 6 -ResizeCell
|
||||||
|
|
||||||
|
Where $octocat is a path to an image file, and $data is a collection of
|
||||||
|
data to be exported, and $path is the output path for the Excel document,
|
||||||
|
Add-Excel places the image at row 4 and column 6, resizing the column
|
||||||
|
and row as needed to fit the image.
|
||||||
|
.INPUTS
|
||||||
|
[OfficeOpenXml.ExcelWorksheet]
|
||||||
|
.OUTPUTS
|
||||||
|
None
|
||||||
|
#>
|
||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
# Specifies the worksheet to add the image to.
|
||||||
|
[Parameter(Mandatory, ValueFromPipeline)]
|
||||||
|
[OfficeOpenXml.ExcelWorksheet]
|
||||||
|
$WorkSheet,
|
||||||
|
|
||||||
|
# Specifies the Image to be added to the worksheet.
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[System.Drawing.Image]
|
||||||
|
$Image,
|
||||||
|
|
||||||
|
# Specifies the row where the image will be placed. Rows are counted from 1.
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[ValidateRange(1, [int]::MaxValue)]
|
||||||
|
[int]
|
||||||
|
$Row,
|
||||||
|
|
||||||
|
# Specifies the column where the image will be placed. Columns are counted from 1.
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[ValidateRange(1, [int]::MaxValue)]
|
||||||
|
[int]
|
||||||
|
$Column,
|
||||||
|
|
||||||
|
# Specifies the name to associate with the image. Names must be unique per sheet.
|
||||||
|
# Omit the name and a GUID will be used instead.
|
||||||
|
[Parameter()]
|
||||||
|
[string]
|
||||||
|
$Name,
|
||||||
|
|
||||||
|
# Specifies the number of pixels to offset the image on the Y-axis. A
|
||||||
|
# positive number moves the image down by the specified number of pixels
|
||||||
|
# from the top border of the cell.
|
||||||
|
[Parameter()]
|
||||||
|
[int]
|
||||||
|
$RowOffset = 1,
|
||||||
|
|
||||||
|
# Specifies the number of pixels to offset the image on the X-axis. A
|
||||||
|
# positive number moves the image to the right by the specified number
|
||||||
|
# of pixels from the left border of the cell.
|
||||||
|
[Parameter()]
|
||||||
|
[int]
|
||||||
|
$ColumnOffset = 1,
|
||||||
|
|
||||||
|
# Increase the column width and row height to fit the image if the current
|
||||||
|
# dimensions are smaller than the image provided.
|
||||||
|
[Parameter()]
|
||||||
|
[switch]
|
||||||
|
$ResizeCell
|
||||||
|
)
|
||||||
|
|
||||||
|
begin {
|
||||||
|
if ($IsWindows -eq $false) {
|
||||||
|
throw "This only works on Windows and won't run on $([environment]::OSVersion)"
|
||||||
|
}
|
||||||
|
|
||||||
|
<#
|
||||||
|
These ratios work on my machine but it feels fragile. Need to better
|
||||||
|
understand how row and column sizing works in Excel and what the
|
||||||
|
width and height units represent.
|
||||||
|
#>
|
||||||
|
$widthFactor = 1 / 7
|
||||||
|
$heightFactor = 3 / 4
|
||||||
|
}
|
||||||
|
|
||||||
|
process {
|
||||||
|
if ([string]::IsNullOrWhiteSpace($Name)) {
|
||||||
|
$Name = (New-Guid).ToString()
|
||||||
|
}
|
||||||
|
if ($null -ne $WorkSheet.Drawings[$Name]) {
|
||||||
|
Write-Error "A picture with the name `"$Name`" already exists in worksheet $($WorkSheet.Name)."
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
<#
|
||||||
|
The row and column offsets of 1 ensures that the image lands just
|
||||||
|
inside the gray cell borders at the top left.
|
||||||
|
#>
|
||||||
|
$picture = $WorkSheet.Drawings.AddPicture($Name, $Image)
|
||||||
|
$picture.SetPosition($Row - 1, $RowOffset, $Column - 1, $ColumnOffset)
|
||||||
|
|
||||||
|
if ($ResizeCell) {
|
||||||
|
<#
|
||||||
|
Adding 1 to the image height and width ensures that when the
|
||||||
|
row and column are resized, the bottom right of the image lands
|
||||||
|
just inside the gray cell borders at the bottom right.
|
||||||
|
#>
|
||||||
|
$width = $widthFactor * ($Image.Width + 1)
|
||||||
|
$height = $heightFactor * ($Image.Height + 1)
|
||||||
|
$WorkSheet.Column($Column).Width = [Math]::Max($width, $WorkSheet.Column($Column).Width)
|
||||||
|
$WorkSheet.Row($Row).Height = [Math]::Max($height, $WorkSheet.Row($Row).Height)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
Examples/AddImage/AddImage.ps1
Normal file
39
Examples/AddImage/AddImage.ps1
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
if ($IsWindows -eq $false) {
|
||||||
|
throw "This only works on Windows and won't run on $([environment]::OSVersion)"
|
||||||
|
}
|
||||||
|
|
||||||
|
Add-Type -AssemblyName System.Drawing
|
||||||
|
|
||||||
|
. $PSScriptRoot\Add-ExcelImage.ps1
|
||||||
|
|
||||||
|
$data = ConvertFrom-Csv @"
|
||||||
|
Region,State,Units,Price
|
||||||
|
West,Texas,927,923.71
|
||||||
|
North,Tennessee,466,770.67
|
||||||
|
East,Florida,520,458.68
|
||||||
|
East,Maine,828,661.24
|
||||||
|
West,Virginia,465,053.58
|
||||||
|
North,Missouri,436,235.67
|
||||||
|
South,Kansas,214,992.47
|
||||||
|
North,North Dakota,789,640.72
|
||||||
|
South,Delaware,712,508.55
|
||||||
|
"@
|
||||||
|
|
||||||
|
$path = "$PSScriptRoot/Add-Picture-test.xlsx"
|
||||||
|
Remove-Item $path -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
$octocat = "$PSScriptRoot/Octocat.jpg"
|
||||||
|
$image = [System.Drawing.Image]::FromFile($octocat)
|
||||||
|
$xlpkg = $data | Export-Excel -Path $path -PassThru
|
||||||
|
$xlpkg.Sheet1 | Add-ExcelImage -Image $image -Row 4 -Column 6 -ResizeCell
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if ($image) {
|
||||||
|
$image.Dispose()
|
||||||
|
}
|
||||||
|
if ($xlpkg) {
|
||||||
|
Close-ExcelPackage -ExcelPackage $xlpkg -Show
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Examples/AddImage/Octocat.jpg
Normal file
BIN
Examples/AddImage/Octocat.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
33
Examples/AddImage/README.md
Normal file
33
Examples/AddImage/README.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# Add-ExcelImage Example
|
||||||
|
|
||||||
|
Adding pictures to an Excel worksheet is possible by calling the `AddPicture(name, image)`
|
||||||
|
method on the `Drawings` property of an `ExcelWorksheet` object.
|
||||||
|
|
||||||
|
The `Add-ExcelImage` example here demonstrates how to add a picture at a given
|
||||||
|
cell location, and optionally resize the row and column to fit the image.
|
||||||
|
|
||||||
|
## Running the example
|
||||||
|
|
||||||
|
To try this example, run the script `AddImage.ps1`. The `Add-ExcelImage`
|
||||||
|
function will be dot-sourced, and an Excel document will be created in the same
|
||||||
|
folder with a sample data set. The Octocat image will then be embedded into
|
||||||
|
Sheet1.
|
||||||
|
|
||||||
|
The creation of the Excel document and the `System.Drawing.Image` object
|
||||||
|
representing Octocat are properly disposed within a `finally` block to ensure
|
||||||
|
that the resources are released, even if an error occurs in the `try` block.
|
||||||
|
|
||||||
|
## Note about column and row sizing
|
||||||
|
|
||||||
|
Care has been taken in this example to get the image placement to be just inside
|
||||||
|
the cell border, and if the `-ResizeCell` switch is present, the height and width
|
||||||
|
of the row and column will be increased, if needed, so that the bottom right of
|
||||||
|
the image also lands just inside the cell border.
|
||||||
|
|
||||||
|
The Excel row and column sizes are measured in "point" units rather than pixels,
|
||||||
|
and a fixed multiplication factor is used to convert the size of the image in
|
||||||
|
pixels, to the corresponding height and width values in Excel.
|
||||||
|
|
||||||
|
It's possible that different DPI or text scaling options could result in
|
||||||
|
imperfect column and row sizing and if a better strategy is found for converting
|
||||||
|
the image dimensions to column and row sizes, this example will be updated.
|
||||||
54
Examples/Freeze/FreezePane.ps1
Normal file
54
Examples/Freeze/FreezePane.ps1
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
# Freeze the columns/rows to left and above the cell
|
||||||
|
|
||||||
|
$data = ConvertFrom-Csv @"
|
||||||
|
Region,State,Units,Price,Name,NA,EU,JP,Other
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
|
||||||
|
"@
|
||||||
|
|
||||||
|
$xlfilename = "test.xlsx"
|
||||||
|
Remove-Item $xlfilename -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
<#
|
||||||
|
Freezes the top two rows and the two leftmost column
|
||||||
|
#>
|
||||||
|
|
||||||
|
$data | Export-Excel $xlfilename -Show -Title 'Sales Data' -FreezePane 3, 3
|
||||||
64
Examples/VBA/AddModuleMultipleWorksheetVBA.ps1
Normal file
64
Examples/VBA/AddModuleMultipleWorksheetVBA.ps1
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
$xlfile = "$env:temp\test.xlsm"
|
||||||
|
Remove-Item $xlfile -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
ConvertFrom-Csv @"
|
||||||
|
Region,Item,TotalSold
|
||||||
|
West,screwdriver,98
|
||||||
|
West,kiwi,19
|
||||||
|
North,kiwi,47
|
||||||
|
West,screws,48
|
||||||
|
West,avocado,52
|
||||||
|
East,avocado,40
|
||||||
|
South,drill,61
|
||||||
|
North,orange,92
|
||||||
|
South,drill,29
|
||||||
|
South,saw,36
|
||||||
|
"@ | Export-Excel $xlfile -TableName 'Sales' -WorksheetName 'Sales' -AutoSize
|
||||||
|
|
||||||
|
$Excel = ConvertFrom-Csv @"
|
||||||
|
Supplier,Item,TotalBought
|
||||||
|
Hardware,screwdriver,98
|
||||||
|
Groceries,kiwi,19
|
||||||
|
Hardware,screws,48
|
||||||
|
Groceries,avocado,52
|
||||||
|
Hardware,drill,61
|
||||||
|
Groceries,orange,92
|
||||||
|
Hardware,drill,29
|
||||||
|
HArdware,saw,36
|
||||||
|
"@ | Export-Excel $xlfile -TableName 'Purchases' -WorksheetName 'Purchases' -PassThru -AutoSize
|
||||||
|
|
||||||
|
$wb = $Excel.Workbook
|
||||||
|
$wb.CreateVBAProject()
|
||||||
|
|
||||||
|
# Create a module with a sub to highlight the selected row & column of the active table.
|
||||||
|
# https://docs.microsoft.com/en-gb/office/vba/excel/Concepts/Cells-and-Ranges/highlight-the-active-cell-row-or-column
|
||||||
|
$codeModule = @"
|
||||||
|
Public Sub HighlightSelection(ByVal Target As Range)
|
||||||
|
' Clear the color of all the cells
|
||||||
|
Cells.Interior.ColorIndex = 0
|
||||||
|
If Target.Cells.Count > 1 Then Exit Sub
|
||||||
|
Application.ScreenUpdating = False
|
||||||
|
With ActiveCell
|
||||||
|
' Highlight the row and column that contain the active cell, within the current region
|
||||||
|
Range(Cells(.Row, .CurrentRegion.Column), Cells(.Row, .CurrentRegion.Columns.Count + .CurrentRegion.Column - 1)).Interior.ColorIndex = 38
|
||||||
|
Range(Cells(.CurrentRegion.Row, .Column), Cells(.CurrentRegion.Rows.Count + .CurrentRegion.Row - 1, .Column)).Interior.ColorIndex = 24
|
||||||
|
End With
|
||||||
|
Application.ScreenUpdating = True
|
||||||
|
End Sub
|
||||||
|
"@
|
||||||
|
|
||||||
|
$module = $wb.VbaProject.Modules.AddModule("PSExcelModule")
|
||||||
|
$module.Code = $codeModule
|
||||||
|
|
||||||
|
# Add a call to the row & column highlight sub on each worksheet.
|
||||||
|
$codeSheet = @"
|
||||||
|
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
|
||||||
|
HighlightSelection Target
|
||||||
|
End Sub
|
||||||
|
"@
|
||||||
|
|
||||||
|
foreach ($sheet in $wb.Worksheets) {
|
||||||
|
$sheet.CodeModule.Code = $codeSheet
|
||||||
|
}
|
||||||
|
|
||||||
|
Close-ExcelPackage $Excel -Show
|
||||||
41
Examples/VBA/AddWorksheetVBA.ps1
Normal file
41
Examples/VBA/AddWorksheetVBA.ps1
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
$xlfile = "$env:temp\test.xlsm"
|
||||||
|
Remove-Item $xlfile -ErrorAction SilentlyContinue
|
||||||
|
|
||||||
|
$Excel = ConvertFrom-Csv @"
|
||||||
|
Region,Item,TotalSold
|
||||||
|
West,screwdriver,98
|
||||||
|
West,kiwi,19
|
||||||
|
North,kiwi,47
|
||||||
|
West,screws,48
|
||||||
|
West,avocado,52
|
||||||
|
East,avocado,40
|
||||||
|
South,drill,61
|
||||||
|
North,orange,92
|
||||||
|
South,drill,29
|
||||||
|
South,saw,36
|
||||||
|
"@ | Export-Excel $xlfile -TableName 'Sales' -WorksheetName 'Sales' -AutoSize -PassThru
|
||||||
|
|
||||||
|
$wb = $Excel.Workbook
|
||||||
|
$sheet = $wb.Worksheets["Sales"]
|
||||||
|
$wb.CreateVBAProject()
|
||||||
|
|
||||||
|
# Add a sub to the 'Worksheet_SelectionChange' event of the worksheet to highlight the selected row & column of the active table.
|
||||||
|
# https://docs.microsoft.com/en-gb/office/vba/excel/Concepts/Cells-and-Ranges/highlight-the-active-cell-row-or-column
|
||||||
|
$code = @"
|
||||||
|
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
|
||||||
|
' Clear the color of all the cells
|
||||||
|
Cells.Interior.ColorIndex = 0
|
||||||
|
If Target.Cells.Count > 1 Then Exit Sub
|
||||||
|
Application.ScreenUpdating = False
|
||||||
|
With ActiveCell
|
||||||
|
' Highlight the row and column that contain the active cell, within the current region
|
||||||
|
Range(Cells(.Row, .CurrentRegion.Column), Cells(.Row, .CurrentRegion.Columns.Count + .CurrentRegion.Column - 1)).Interior.ColorIndex = 38
|
||||||
|
Range(Cells(.CurrentRegion.Row, .Column), Cells(.CurrentRegion.Rows.Count + .CurrentRegion.Row - 1, .Column)).Interior.ColorIndex = 24
|
||||||
|
End With
|
||||||
|
Application.ScreenUpdating = True
|
||||||
|
End Sub
|
||||||
|
"@
|
||||||
|
|
||||||
|
$sheet.CodeModule.Code = $code
|
||||||
|
|
||||||
|
Close-ExcelPackage $Excel -Show
|
||||||
6
FAQ/How to Create an Empty Excel File.md
Normal file
6
FAQ/How to Create an Empty Excel File.md
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
# Create an Empty Excel File
|
||||||
|
Use an empty string to export to an excel file.
|
||||||
|
```powershell
|
||||||
|
#Build an Excel file named: "file.xlsx" containing a worksheet: "MyWorksheet"
|
||||||
|
"" | Export-Excel -Path "C:\Test\file.xlsx" -WorksheetName "MyWorksheet"
|
||||||
|
```
|
||||||
41
FAQ/How to Read an Existing Excel File.md
Normal file
41
FAQ/How to Read an Existing Excel File.md
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
# How to Read an Existing Excel File
|
||||||
|
## Enumerate the Excel File Contents
|
||||||
|
```powershell
|
||||||
|
#Load the Excel file into a PSCustomObject
|
||||||
|
$ExcelFile = Import-Excel "C:\Test\file.xlsx" -WorksheetName "Sheet1"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Visual of Data Structure
|
||||||
|
The File C:\Test\file.xlsx contains
|
||||||
|

|
||||||
|
|
||||||
|
After loading this data into ```$ExcelFile``` the data is stored like:
|
||||||
|

|
||||||
|
|
||||||
|
## Other Common Operations
|
||||||
|
|
||||||
|
### Load a Column
|
||||||
|
```powershell
|
||||||
|
$SpecificColumn = $ExcelFile."anotherHeader" #loads column with the header "anotherHeader" -- data stored in an array
|
||||||
|
```
|
||||||
|
|
||||||
|
### Load a Row
|
||||||
|
```powershell
|
||||||
|
$SpecificRow = $ExcelFile[1] #Loads row at index 1. Index 1 is the first row instead of 0.
|
||||||
|
```
|
||||||
|
|
||||||
|
### Map Contents to Hashtable to Interpret Data
|
||||||
|
Sometimes mapping to a Hashtable is more convenient to have access to common Hashtable operations. Enumerate a Hashtable with the row's data by:
|
||||||
|
```powershell
|
||||||
|
$HashTable = @{}
|
||||||
|
$SpecificRow= $ExcelFile[2]
|
||||||
|
$SpecificRow.psobject.properties | ForEach-Object {
|
||||||
|
$HashTable[$_.Name] = $_.Value
|
||||||
|
}
|
||||||
|
```
|
||||||
|
To then iterate through the enumerated Hashtable:
|
||||||
|
```powershell
|
||||||
|
ForEach ($Key in ($HashTable.GetEnumerator()) | Where-Object {$_.Value -eq "x"}){ #Only grabs a key where the value is "x"
|
||||||
|
#values accessible with $Key.Name or $Key.Value
|
||||||
|
}
|
||||||
|
```
|
||||||
34
FAQ/How to Write to an Existing Excel File.md
Normal file
34
FAQ/How to Write to an Existing Excel File.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# Write to an Existing Excel File
|
||||||
|
### Enumerate the Excel File
|
||||||
|
The cmdlets ```Open-ExcelPackage``` and ```Close-ExcelPackage``` allow for direct modification to Excel file contents.
|
||||||
|
```powershell
|
||||||
|
$ExcelPkg = Open-ExcelPackage -Path "C:\Test\file.xlsx"
|
||||||
|
```
|
||||||
|
Contents of file.xlsx:
|
||||||
|

|
||||||
|
### Enumerate the Worksheet to View or Modify the Data
|
||||||
|
```powershell
|
||||||
|
$WorkSheet = $ExcelPkg.Workbook.Worksheets["sheet1"].Cells #open excel worksheet cells from worksheet "sheet1"
|
||||||
|
```
|
||||||
|
Visual of data structure:
|
||||||
|

|
||||||
|
A1 contains "someHeader", A2 contains "data1" etc.
|
||||||
|
### Modify a Specific Value in a File
|
||||||
|
Values can be accessed by row, column. Similar to a 2D array.
|
||||||
|
```powershell
|
||||||
|
$WorkSheet[1,4].Value = "New Column Header" #Starts at index 1 not 0
|
||||||
|
```
|
||||||
|
Contents of file.xlsx after modifying:
|
||||||
|

|
||||||
|
### Load Value at Specific Index
|
||||||
|
```powershell
|
||||||
|
$ValueAtIndex = $WorkSheet[2,1].Value #Loads the value at row 2, column A
|
||||||
|
```
|
||||||
|
```$ValueAtIndex``` now contains: 
|
||||||
|
### Save File After Modifying
|
||||||
|
The changes will not display in the Excel file until Close-ExcelPackage is called.
|
||||||
|
```powershell
|
||||||
|
Close-ExcelPackage $ExcelPkg #close and save changes made to the Excel file.
|
||||||
|
```
|
||||||
|
**Note**: If the file is currently in use, Close-ExcelPackage will return an error and will not save the information.
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
RootModule = 'ImportExcel.psm1'
|
RootModule = 'ImportExcel.psm1'
|
||||||
|
|
||||||
# Version number of this module.
|
# Version number of this module.
|
||||||
ModuleVersion = '7.4.0'
|
ModuleVersion = '7.4.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'
|
||||||
|
|||||||
25
Private/Invoke-ExcelReZipFile.ps1
Normal file
25
Private/Invoke-ExcelReZipFile.ps1
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
function Invoke-ExcelReZipFile {
|
||||||
|
<#
|
||||||
|
#>
|
||||||
|
param(
|
||||||
|
[Parameter(Mandatory)]
|
||||||
|
[OfficeOpenXml.ExcelPackage]$ExcelPackage
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Verbose -Message "Re-Zipping $($ExcelPackage.file) using .NET ZIP library"
|
||||||
|
try {
|
||||||
|
Add-Type -AssemblyName 'System.IO.Compression.Filesystem' -ErrorAction stop
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-Error "The -ReZip parameter requires .NET Framework 4.5 or later to be installed. Recommend to install Powershell v4+"
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
$TempZipPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath ([System.IO.Path]::GetRandomFileName())
|
||||||
|
$null = [io.compression.zipfile]::ExtractToDirectory($ExcelPackage.File, $TempZipPath)
|
||||||
|
Remove-Item $ExcelPackage.File -Force
|
||||||
|
$null = [io.compression.zipfile]::CreateFromDirectory($TempZipPath, $ExcelPackage.File)
|
||||||
|
Remove-Item $TempZipPath -Recurse -Force
|
||||||
|
}
|
||||||
|
catch { throw "Error resizipping $path : $_" }
|
||||||
|
}
|
||||||
@@ -1,33 +1,38 @@
|
|||||||
function Close-ExcelPackage {
|
function Close-ExcelPackage {
|
||||||
[CmdLetBinding()]
|
[CmdLetBinding()]
|
||||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword","")]
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")]
|
||||||
param (
|
param (
|
||||||
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
|
[parameter(Mandatory = $true, ValueFromPipeline = $true)]
|
||||||
[OfficeOpenXml.ExcelPackage]$ExcelPackage,
|
[OfficeOpenXml.ExcelPackage]$ExcelPackage,
|
||||||
[switch]$Show,
|
[Switch]$Show,
|
||||||
[Switch]$NoSave,
|
[Switch]$NoSave,
|
||||||
$SaveAs,
|
$SaveAs,
|
||||||
[ValidateNotNullOrEmpty()]
|
[ValidateNotNullOrEmpty()]
|
||||||
[String]$Password,
|
[String]$Password,
|
||||||
[switch]$Calculate
|
[Switch]$Calculate,
|
||||||
|
[Switch]$ReZip
|
||||||
)
|
)
|
||||||
if ( $NoSave) {$ExcelPackage.Dispose()}
|
|
||||||
|
if ( $NoSave) { $ExcelPackage.Dispose() }
|
||||||
else {
|
else {
|
||||||
if ($Calculate) {
|
if ($Calculate) {
|
||||||
try { [OfficeOpenXml.CalculationExtension]::Calculate($ExcelPackage.Workbook) }
|
try { [OfficeOpenXml.CalculationExtension]::Calculate($ExcelPackage.Workbook) }
|
||||||
catch { Write-Warning "One or more errors occured while calculating, save will continue, but there may be errors in the workbook."}
|
catch { Write-Warning "One or more errors occured while calculating, save will continue, but there may be errors in the workbook." }
|
||||||
}
|
}
|
||||||
if ($SaveAs) {
|
if ($SaveAs) {
|
||||||
$SaveAs = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($SaveAs)
|
$SaveAs = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($SaveAs)
|
||||||
if ($Password) {$ExcelPackage.SaveAs( $SaveAs, $Password ) }
|
if ($Password) { $ExcelPackage.SaveAs( $SaveAs, $Password ) }
|
||||||
else {$ExcelPackage.SaveAs( $SaveAs)}
|
else { $ExcelPackage.SaveAs( $SaveAs) }
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ($Password) {$ExcelPackage.Save($Password) }
|
if ($Password) { $ExcelPackage.Save($Password) }
|
||||||
else {$ExcelPackage.Save() }
|
else { $ExcelPackage.Save() }
|
||||||
$SaveAs = $ExcelPackage.File.FullName
|
$SaveAs = $ExcelPackage.File.FullName
|
||||||
}
|
}
|
||||||
|
if ($ReZip) {
|
||||||
|
Invoke-ExcelReZipFile -ExcelPackage $ExcelPackage
|
||||||
|
}
|
||||||
$ExcelPackage.Dispose()
|
$ExcelPackage.Dispose()
|
||||||
if ($Show) {Start-Process -FilePath $SaveAs }
|
if ($Show) { Start-Process -FilePath $SaveAs }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,12 +16,15 @@ function ConvertFrom-ExcelToSQLInsert {
|
|||||||
[switch]$NoHeader,
|
[switch]$NoHeader,
|
||||||
[switch]$DataOnly,
|
[switch]$DataOnly,
|
||||||
[switch]$ConvertEmptyStringsToNull,
|
[switch]$ConvertEmptyStringsToNull,
|
||||||
[switch]$UseMsSqlSyntax
|
[switch]$UseMsSqlSyntax,
|
||||||
|
[Parameter(Mandatory = $false)]
|
||||||
|
$SingleQuoteStyle
|
||||||
)
|
)
|
||||||
|
|
||||||
$null = $PSBoundParameters.Remove('TableName')
|
$null = $PSBoundParameters.Remove('TableName')
|
||||||
$null = $PSBoundParameters.Remove('ConvertEmptyStringsToNull')
|
$null = $PSBoundParameters.Remove('ConvertEmptyStringsToNull')
|
||||||
$null = $PSBoundParameters.Remove('UseMsSqlSyntax')
|
$null = $PSBoundParameters.Remove('UseMsSqlSyntax')
|
||||||
|
$null = $PSBoundParameters.Remove('SingleQuoteStyle')
|
||||||
|
|
||||||
$params = @{} + $PSBoundParameters
|
$params = @{} + $PSBoundParameters
|
||||||
|
|
||||||
@@ -38,7 +41,12 @@ function ConvertFrom-ExcelToSQLInsert {
|
|||||||
'NULL'
|
'NULL'
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
"'" + $record.$propertyName + "'"
|
if ( $SingleQuoteStyle ) {
|
||||||
|
"'" + $record.$propertyName.ToString().Replace("'",${SingleQuoteStyle}) + "'"
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
"'" + $record.$propertyName + "'"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$targetValues = ($values -join ", ")
|
$targetValues = ($values -join ", ")
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
[Switch]$TitleBold,
|
[Switch]$TitleBold,
|
||||||
[Int]$TitleSize = 22,
|
[Int]$TitleSize = 22,
|
||||||
$TitleBackgroundColor,
|
$TitleBackgroundColor,
|
||||||
[parameter(DontShow=$true)]
|
[parameter(DontShow = $true)]
|
||||||
[Switch]$IncludePivotTable,
|
[Switch]$IncludePivotTable,
|
||||||
[String]$PivotTableName,
|
[String]$PivotTableName,
|
||||||
[String[]]$PivotRows,
|
[String[]]$PivotRows,
|
||||||
@@ -48,14 +48,14 @@
|
|||||||
[Switch]$BoldTopRow,
|
[Switch]$BoldTopRow,
|
||||||
[Switch]$NoHeader,
|
[Switch]$NoHeader,
|
||||||
[ValidateScript( {
|
[ValidateScript( {
|
||||||
if (-not $_) { throw 'RangeName is null or empty.' }
|
if (-not $_) { throw 'RangeName is null or empty.' }
|
||||||
elseif ($_[0] -notmatch '[a-z]') { throw 'RangeName starts with an invalid character.' }
|
elseif ($_[0] -notmatch '[a-z]') { throw 'RangeName starts with an invalid character.' }
|
||||||
else { $true }
|
else { $true }
|
||||||
})]
|
})]
|
||||||
[String]$RangeName,
|
[String]$RangeName,
|
||||||
[Alias('Table')]
|
[Alias('Table')]
|
||||||
$TableName,
|
$TableName,
|
||||||
[OfficeOpenXml.Table.TableStyles]$TableStyle = [OfficeOpenXml.Table.TableStyles]::Medium6,
|
[OfficeOpenXml.Table.TableStyles]$TableStyle = [OfficeOpenXml.Table.TableStyles]::Medium6,
|
||||||
[Switch]$Barchart,
|
[Switch]$Barchart,
|
||||||
[Switch]$PieChart,
|
[Switch]$PieChart,
|
||||||
[Switch]$LineChart ,
|
[Switch]$LineChart ,
|
||||||
@@ -88,7 +88,7 @@
|
|||||||
[Switch]$Now,
|
[Switch]$Now,
|
||||||
[Switch]$ReturnRange,
|
[Switch]$ReturnRange,
|
||||||
#By default PivotTables have Totals for each Row (on the right) and for each column at the bottom. This allows just one or neither to be selected.
|
#By default PivotTables have Totals for each Row (on the right) and for each column at the bottom. This allows just one or neither to be selected.
|
||||||
[ValidateSet("Both","Columns","Rows","None")]
|
[ValidateSet("Both", "Columns", "Rows", "None")]
|
||||||
[String]$PivotTotals = "Both",
|
[String]$PivotTotals = "Both",
|
||||||
#Included for compatibility - equivalent to -PivotTotals "None"
|
#Included for compatibility - equivalent to -PivotTotals "None"
|
||||||
[Switch]$NoTotalsInPivot,
|
[Switch]$NoTotalsInPivot,
|
||||||
@@ -98,13 +98,13 @@
|
|||||||
begin {
|
begin {
|
||||||
$numberRegex = [Regex]'\d'
|
$numberRegex = [Regex]'\d'
|
||||||
$isDataTypeValueType = $false
|
$isDataTypeValueType = $false
|
||||||
if ($NoClobber) {Write-Warning -Message "-NoClobber parameter is no longer used" }
|
if ($NoClobber) { Write-Warning -Message "-NoClobber parameter is no longer used" }
|
||||||
#Open the file, get the worksheet, and decide where in the sheet we are writing, and if there is a number format to apply.
|
#Open the file, get the worksheet, and decide where in the sheet we are writing, and if there is a number format to apply.
|
||||||
try {
|
try {
|
||||||
$script:Header = $null
|
$script:Header = $null
|
||||||
if ($Append -and $ClearSheet) {throw "You can't use -Append AND -ClearSheet." ; return}
|
if ($Append -and $ClearSheet) { throw "You can't use -Append AND -ClearSheet." ; return }
|
||||||
#To force -Now not to format as a table, allow $false in -TableName to be "No table"
|
#To force -Now not to format as a table, allow $false in -TableName to be "No table"
|
||||||
$TableName = if ($null -eq $TableName -or ($TableName -is [bool] -and $false -eq $TableName)) { $null } else {[String]$TableName}
|
$TableName = if ($null -eq $TableName -or ($TableName -is [bool] -and $false -eq $TableName)) { $null } else { [String]$TableName }
|
||||||
if ($Now -or (-not $Path -and -not $ExcelPackage) ) {
|
if ($Now -or (-not $Path -and -not $ExcelPackage) ) {
|
||||||
if (-not $PSBoundParameters.ContainsKey("Path")) { $Path = [System.IO.Path]::GetTempFileName() -replace '\.tmp', '.xlsx' }
|
if (-not $PSBoundParameters.ContainsKey("Path")) { $Path = [System.IO.Path]::GetTempFileName() -replace '\.tmp', '.xlsx' }
|
||||||
if (-not $PSBoundParameters.ContainsKey("Show")) { $Show = $true }
|
if (-not $PSBoundParameters.ContainsKey("Show")) { $Show = $true }
|
||||||
@@ -120,59 +120,59 @@
|
|||||||
$pkg = $ExcelPackage
|
$pkg = $ExcelPackage
|
||||||
$Path = $pkg.File
|
$Path = $pkg.File
|
||||||
}
|
}
|
||||||
Else { $pkg = Open-ExcelPackage -Path $Path -Create -KillExcel:$KillExcel -Password:$Password}
|
Else { $pkg = Open-ExcelPackage -Path $Path -Create -KillExcel:$KillExcel -Password:$Password }
|
||||||
}
|
}
|
||||||
catch {throw "Could not open Excel Package $path"}
|
catch { throw "Could not open Excel Package $path" }
|
||||||
try {
|
try {
|
||||||
$params = @{WorksheetName=$WorksheetName}
|
$params = @{WorksheetName = $WorksheetName }
|
||||||
foreach ($p in @("ClearSheet", "MoveToStart", "MoveToEnd", "MoveBefore", "MoveAfter", "Activate")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}}
|
foreach ($p in @("ClearSheet", "MoveToStart", "MoveToEnd", "MoveBefore", "MoveAfter", "Activate")) { if ($PSBoundParameters[$p]) { $params[$p] = $PSBoundParameters[$p] } }
|
||||||
$ws = $pkg | Add-Worksheet @params
|
$ws = $pkg | Add-Worksheet @params
|
||||||
if ($ws.Name -ne $WorksheetName) {
|
if ($ws.Name -ne $WorksheetName) {
|
||||||
Write-Warning -Message "The Worksheet name has been changed from $WorksheetName to $($ws.Name), this may cause errors later."
|
Write-Warning -Message "The Worksheet name has been changed from $WorksheetName to $($ws.Name), this may cause errors later."
|
||||||
$WorksheetName = $ws.Name
|
$WorksheetName = $ws.Name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {throw "Could not get worksheet $WorksheetName"}
|
catch { throw "Could not get worksheet $WorksheetName" }
|
||||||
try {
|
try {
|
||||||
if ($Append -and $ws.Dimension) {
|
if ($Append -and $ws.Dimension) {
|
||||||
#if there is a title or anything else above the header row, append needs to be combined wih a suitable startrow parameter
|
#if there is a title or anything else above the header row, append needs to be combined wih a suitable startrow parameter
|
||||||
$headerRange = $ws.Dimension.Address -replace "\d+$", $StartRow
|
$headerRange = $ws.Dimension.Address -replace "\d+$", $StartRow
|
||||||
#using a slightly odd syntax otherwise header ends up as a 2D array
|
#using a slightly odd syntax otherwise header ends up as a 2D array
|
||||||
$ws.Cells[$headerRange].Value | ForEach-Object -Begin {$Script:header = @()} -Process {$Script:header += $_ }
|
$ws.Cells[$headerRange].Value | ForEach-Object -Begin { $Script:header = @() } -Process { $Script:header += $_ }
|
||||||
$NoHeader = $true
|
$NoHeader = $true
|
||||||
#if we did not get AutoNameRange, but headers have ranges of the same name make autoNameRange True, otherwise make it false
|
#if we did not get AutoNameRange, but headers have ranges of the same name make autoNameRange True, otherwise make it false
|
||||||
if (-not $AutoNameRange) {
|
if (-not $AutoNameRange) {
|
||||||
$AutoNameRange = $true ; foreach ($h in $header) {if ($ws.names.name -notcontains $h) {$AutoNameRange = $false} }
|
$AutoNameRange = $true ; foreach ($h in $header) { if ($ws.names.name -notcontains $h) { $AutoNameRange = $false } }
|
||||||
}
|
}
|
||||||
#if we did not get a Rangename but there is a Range which covers the active part of the sheet, set Rangename to that.
|
#if we did not get a Rangename but there is a Range which covers the active part of the sheet, set Rangename to that.
|
||||||
if (-not $RangeName -and $ws.names.where({$_.name[0] -match '[a-z]'})) {
|
if (-not $RangeName -and $ws.names.where({ $_.name[0] -match '[a-z]' })) {
|
||||||
$theRange = $ws.names.where({
|
$theRange = $ws.names.where({
|
||||||
($_.Name[0] -match '[a-z]' ) -and
|
($_.Name[0] -match '[a-z]' ) -and
|
||||||
($_.Start.Row -eq $StartRow) -and
|
($_.Start.Row -eq $StartRow) -and
|
||||||
($_.Start.Column -eq $StartColumn) -and
|
($_.Start.Column -eq $StartColumn) -and
|
||||||
($_.End.Row -eq $ws.Dimension.End.Row) -and
|
($_.End.Row -eq $ws.Dimension.End.Row) -and
|
||||||
($_.End.Column -eq $ws.Dimension.End.column) } , 'First', 1)
|
($_.End.Column -eq $ws.Dimension.End.column) } , 'First', 1)
|
||||||
if ($theRange) {$rangename = $theRange.name}
|
if ($theRange) { $rangename = $theRange.name }
|
||||||
}
|
}
|
||||||
|
|
||||||
#if we did not get a table name but there is a table which covers the active part of the sheet, set table name to that, and don't do anything with autofilter
|
#if we did not get a table name but there is a table which covers the active part of the sheet, set table name to that, and don't do anything with autofilter
|
||||||
$existingTable = $ws.Tables.Where({$_.address.address -eq $ws.dimension.address},'First', 1)
|
$existingTable = $ws.Tables.Where({ $_.address.address -eq $ws.dimension.address }, 'First', 1)
|
||||||
if ($null -eq $TableName -and $existingTable) {
|
if ($null -eq $TableName -and $existingTable) {
|
||||||
$TableName = $existingTable.Name
|
$TableName = $existingTable.Name
|
||||||
$TableStyle = $existingTable.StyleName -replace "^TableStyle",""
|
$TableStyle = $existingTable.StyleName -replace "^TableStyle", ""
|
||||||
$AutoFilter = $false
|
$AutoFilter = $false
|
||||||
}
|
}
|
||||||
#if we did not get $autofilter but a filter range is set and it covers the right area, set autofilter to true
|
#if we did not get $autofilter but a filter range is set and it covers the right area, set autofilter to true
|
||||||
elseif (-not $AutoFilter -and $ws.Names['_xlnm._FilterDatabase']) {
|
elseif (-not $AutoFilter -and $ws.Names['_xlnm._FilterDatabase']) {
|
||||||
if ( ($ws.Names['_xlnm._FilterDatabase'].Start.Row -eq $StartRow) -and
|
if ( ($ws.Names['_xlnm._FilterDatabase'].Start.Row -eq $StartRow) -and
|
||||||
($ws.Names['_xlnm._FilterDatabase'].Start.Column -eq $StartColumn) -and
|
($ws.Names['_xlnm._FilterDatabase'].Start.Column -eq $StartColumn) -and
|
||||||
($ws.Names['_xlnm._FilterDatabase'].End.Row -eq $ws.Dimension.End.Row) -and
|
($ws.Names['_xlnm._FilterDatabase'].End.Row -eq $ws.Dimension.End.Row) -and
|
||||||
($ws.Names['_xlnm._FilterDatabase'].End.Column -eq $ws.Dimension.End.Column) ) {$AutoFilter = $true}
|
($ws.Names['_xlnm._FilterDatabase'].End.Column -eq $ws.Dimension.End.Column) ) { $AutoFilter = $true }
|
||||||
}
|
}
|
||||||
|
|
||||||
$row = $ws.Dimension.End.Row
|
$row = $ws.Dimension.End.Row
|
||||||
Write-Debug -Message ("Appending: headers are " + ($script:Header -join ", ") + " Start row is $row")
|
Write-Debug -Message ("Appending: headers are " + ($script:Header -join ", ") + " Start row is $row")
|
||||||
if ($Title) {Write-Warning -Message "-Title Parameter is ignored when appending."}
|
if ($Title) { Write-Warning -Message "-Title Parameter is ignored when appending." }
|
||||||
}
|
}
|
||||||
elseif ($Title) {
|
elseif ($Title) {
|
||||||
#Can only add a title if not appending!
|
#Can only add a title if not appending!
|
||||||
@@ -180,41 +180,41 @@
|
|||||||
$ws.Cells[$row, $StartColumn].Value = $Title
|
$ws.Cells[$row, $StartColumn].Value = $Title
|
||||||
$ws.Cells[$row, $StartColumn].Style.Font.Size = $TitleSize
|
$ws.Cells[$row, $StartColumn].Style.Font.Size = $TitleSize
|
||||||
|
|
||||||
if ($PSBoundParameters.ContainsKey("TitleBold")) {
|
if ($PSBoundParameters.ContainsKey("TitleBold")) {
|
||||||
#Set title to Bold face font if -TitleBold was specified.
|
#Set title to Bold face font if -TitleBold was specified.
|
||||||
#Otherwise the default will be unbolded.
|
#Otherwise the default will be unbolded.
|
||||||
$ws.Cells[$row, $StartColumn].Style.Font.Bold = [boolean]$TitleBold
|
$ws.Cells[$row, $StartColumn].Style.Font.Bold = [boolean]$TitleBold
|
||||||
}
|
}
|
||||||
if ($TitleBackgroundColor ) {
|
if ($TitleBackgroundColor ) {
|
||||||
if ($TitleBackgroundColor -is [string]) {$TitleBackgroundColor = [System.Drawing.Color]::$TitleBackgroundColor }
|
if ($TitleBackgroundColor -is [string]) { $TitleBackgroundColor = [System.Drawing.Color]::$TitleBackgroundColor }
|
||||||
$ws.Cells[$row, $StartColumn].Style.Fill.PatternType = $TitleFillPattern
|
$ws.Cells[$row, $StartColumn].Style.Fill.PatternType = $TitleFillPattern
|
||||||
$ws.Cells[$row, $StartColumn].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor)
|
$ws.Cells[$row, $StartColumn].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor)
|
||||||
}
|
}
|
||||||
$row ++ ; $startRow ++
|
$row ++ ; $startRow ++
|
||||||
}
|
}
|
||||||
else { $row = $StartRow }
|
else { $row = $StartRow }
|
||||||
$ColumnIndex = $StartColumn
|
$ColumnIndex = $StartColumn
|
||||||
$Numberformat = Expand-NumberFormat -NumberFormat $Numberformat
|
$Numberformat = Expand-NumberFormat -NumberFormat $Numberformat
|
||||||
if ((-not $ws.Dimension) -and ($Numberformat -ne $ws.Cells.Style.Numberformat.Format)) {
|
if ((-not $ws.Dimension) -and ($Numberformat -ne $ws.Cells.Style.Numberformat.Format)) {
|
||||||
$ws.Cells.Style.Numberformat.Format = $Numberformat
|
$ws.Cells.Style.Numberformat.Format = $Numberformat
|
||||||
$setNumformat = $false
|
$setNumformat = $false
|
||||||
}
|
}
|
||||||
else { $setNumformat = ($Numberformat -ne $ws.Cells.Style.Numberformat.Format) }
|
else { $setNumformat = ($Numberformat -ne $ws.Cells.Style.Numberformat.Format) }
|
||||||
}
|
}
|
||||||
catch {throw "Failed preparing to export to worksheet '$WorksheetName' to '$Path': $_"}
|
catch { throw "Failed preparing to export to worksheet '$WorksheetName' to '$Path': $_" }
|
||||||
#region Special case -inputobject passed a dataTable object
|
#region Special case -inputobject passed a dataTable object
|
||||||
<# If inputObject was passed via the pipeline it won't be visible until the process block, we will only see it here if it was passed as a parameter
|
<# If inputObject was passed via the pipeline it won't be visible until the process block, we will only see it here if it was passed as a parameter
|
||||||
if it is a data table don't do foreach on it (slow) - put the whole table in and set dates on date columns,
|
if it is a data table don't do foreach on it (slow) - put the whole table in and set dates on date columns,
|
||||||
set things up for the end block, and skip the process block #>
|
set things up for the end block, and skip the process block #>
|
||||||
if ($InputObject -is [System.Data.DataTable]) {
|
if ($InputObject -is [System.Data.DataTable]) {
|
||||||
if ($Append -and $ws.dimension) {
|
if ($Append -and $ws.dimension) {
|
||||||
$row ++
|
$row ++
|
||||||
$null = $ws.Cells[$row,$StartColumn].LoadFromDataTable($InputObject, $false )
|
$null = $ws.Cells[$row, $StartColumn].LoadFromDataTable($InputObject, $false )
|
||||||
if ($TableName -or $PSBoundParameters.ContainsKey('TableStyle')) {
|
if ($TableName -or $PSBoundParameters.ContainsKey('TableStyle')) {
|
||||||
Add-ExcelTable -Range $ws.Cells[$ws.Dimension] -TableName $TableName -TableStyle $TableStyle
|
Add-ExcelTable -Range $ws.Cells[$ws.Dimension] -TableName $TableName -TableStyle $TableStyle
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
#Change TableName if $TableName is non-empty; don't leave caller with a renamed table!
|
#Change TableName if $TableName is non-empty; don't leave caller with a renamed table!
|
||||||
$orginalTableName = $InputObject.TableName
|
$orginalTableName = $InputObject.TableName
|
||||||
if ($PSBoundParameters.ContainsKey("TableName")) {
|
if ($PSBoundParameters.ContainsKey("TableName")) {
|
||||||
@@ -226,157 +226,160 @@
|
|||||||
}
|
}
|
||||||
#Insert as a table, if Tablestyle didn't arrive as a default, or $TableName non-null - even if empty
|
#Insert as a table, if Tablestyle didn't arrive as a default, or $TableName non-null - even if empty
|
||||||
if ($null -ne $TableName -or $PSBoundParameters.ContainsKey("TableStyle")) {
|
if ($null -ne $TableName -or $PSBoundParameters.ContainsKey("TableStyle")) {
|
||||||
$null = $ws.Cells[$row,$StartColumn].LoadFromDataTable($InputObject, (-not $noHeader),$TableStyle )
|
$null = $ws.Cells[$row, $StartColumn].LoadFromDataTable($InputObject, (-not $noHeader), $TableStyle )
|
||||||
# Workaround for EPPlus not marking the empty row on an empty table as dummy row.
|
# Workaround for EPPlus not marking the empty row on an empty table as dummy row.
|
||||||
if ($InputObject.Rows.Count -eq 0) {
|
if ($InputObject.Rows.Count -eq 0) {
|
||||||
($ws.Tables | Select-Object -Last 1).TableXml.table.SetAttribute('insertRow', 1)
|
($ws.Tables | Select-Object -Last 1).TableXml.table.SetAttribute('insertRow', 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$null = $ws.Cells[$row,$StartColumn].LoadFromDataTable($InputObject, (-not $noHeader) )
|
$null = $ws.Cells[$row, $StartColumn].LoadFromDataTable($InputObject, (-not $noHeader) )
|
||||||
}
|
}
|
||||||
$InputObject.TableName = $orginalTableName
|
$InputObject.TableName = $orginalTableName
|
||||||
}
|
}
|
||||||
foreach ($c in $InputObject.Columns.where({$_.datatype -eq [datetime]})) {
|
foreach ($c in $InputObject.Columns.where({ $_.datatype -eq [datetime] })) {
|
||||||
Set-ExcelColumn -Worksheet $ws -Column ($c.Ordinal + $StartColumn) -NumberFormat 'Date-Time'
|
Set-ExcelColumn -Worksheet $ws -Column ($c.Ordinal + $StartColumn) -NumberFormat 'Date-Time'
|
||||||
}
|
}
|
||||||
foreach ($c in $InputObject.Columns.where({$_.datatype -eq [timespan]})) {
|
foreach ($c in $InputObject.Columns.where({ $_.datatype -eq [timespan] })) {
|
||||||
Set-ExcelColumn -Worksheet $ws -Column ($c.Ordinal + $StartColumn) -NumberFormat '[h]:mm:ss'
|
Set-ExcelColumn -Worksheet $ws -Column ($c.Ordinal + $StartColumn) -NumberFormat '[h]:mm:ss'
|
||||||
}
|
}
|
||||||
$ColumnIndex += $InputObject.Columns.Count - 1
|
$ColumnIndex += $InputObject.Columns.Count - 1
|
||||||
if ($noHeader) {$row += $InputObject.Rows.Count -1 }
|
if ($noHeader) { $row += $InputObject.Rows.Count - 1 }
|
||||||
else {$row += $InputObject.Rows.Count }
|
else { $row += $InputObject.Rows.Count }
|
||||||
$null = $PSBoundParameters.Remove('InputObject')
|
$null = $PSBoundParameters.Remove('InputObject')
|
||||||
$firstTimeThru = $false
|
$firstTimeThru = $false
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
else {$firstTimeThru = $true}
|
else { $firstTimeThru = $true }
|
||||||
}
|
}
|
||||||
|
|
||||||
process { if ($PSBoundParameters.ContainsKey("InputObject")) {
|
process {
|
||||||
try {
|
if ($PSBoundParameters.ContainsKey("InputObject")) {
|
||||||
if ($null -eq $InputObject) {$row += 1}
|
try {
|
||||||
foreach ($TargetData in $InputObject) {
|
if ($null -eq $InputObject) { $row += 1 }
|
||||||
if ($firstTimeThru) {
|
foreach ($TargetData in $InputObject) {
|
||||||
$firstTimeThru = $false
|
if ($firstTimeThru) {
|
||||||
$isDataTypeValueType = ($null -eq $TargetData) -or ($TargetData.GetType().name -match 'string|timespan|datetime|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ulong|ushort|URI|ExcelHyperLink')
|
$firstTimeThru = $false
|
||||||
if ($isDataTypeValueType ) {
|
$isDataTypeValueType = ($null -eq $TargetData) -or ($TargetData.GetType().name -match 'string|timespan|datetime|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ulong|ushort|URI|ExcelHyperLink')
|
||||||
$script:Header = @(".") # dummy value to make sure we go through the "for each name in $header"
|
if ($isDataTypeValueType ) {
|
||||||
if (-not $Append) {$row -= 1} # By default row will be 1, it is incremented before inserting values (so it ends pointing at final row.); si first data row is 2 - move back up 1 if there is no header .
|
$script:Header = @(".") # dummy value to make sure we go through the "for each name in $header"
|
||||||
|
if (-not $Append) { $row -= 1 } # By default row will be 1, it is incremented before inserting values (so it ends pointing at final row.); si first data row is 2 - move back up 1 if there is no header .
|
||||||
|
}
|
||||||
|
if ($null -ne $TargetData) { Write-Debug "DataTypeName is '$($TargetData.GetType().name)' isDataTypeValueType '$isDataTypeValueType'" }
|
||||||
}
|
}
|
||||||
if ($null -ne $TargetData) {Write-Debug "DataTypeName is '$($TargetData.GetType().name)' isDataTypeValueType '$isDataTypeValueType'" }
|
#region Add headers - if we are appending, or we have been through here once already we will have the headers
|
||||||
}
|
if (-not $script:Header) {
|
||||||
#region Add headers - if we are appending, or we have been through here once already we will have the headers
|
if ($DisplayPropertySet -and $TargetData.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames) {
|
||||||
if (-not $script:Header) {
|
$script:Header = $TargetData.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames.Where( { $_ -notin $ExcludeProperty })
|
||||||
if ($DisplayPropertySet -and $TargetData.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames) {
|
}
|
||||||
$script:Header = $TargetData.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames.Where( {$_ -notin $ExcludeProperty})
|
else {
|
||||||
}
|
if ($NoAliasOrScriptPropeties) { $propType = "Property" } else { $propType = "*" }
|
||||||
else {
|
$script:Header = $TargetData.PSObject.Properties.where( { $_.MemberType -like $propType }).Name
|
||||||
if ($NoAliasOrScriptPropeties) {$propType = "Property"} else {$propType = "*"}
|
}
|
||||||
$script:Header = $TargetData.PSObject.Properties.where( {$_.MemberType -like $propType}).Name
|
foreach ($exclusion in $ExcludeProperty) { $script:Header = $script:Header -notlike $exclusion }
|
||||||
}
|
if ($NoHeader) {
|
||||||
foreach ($exclusion in $ExcludeProperty) {$script:Header = $script:Header -notlike $exclusion}
|
# Don't push the headers to the spreadsheet
|
||||||
if ($NoHeader) {
|
$row -= 1
|
||||||
# Don't push the headers to the spreadsheet
|
}
|
||||||
$row -= 1
|
else {
|
||||||
}
|
$ColumnIndex = $StartColumn
|
||||||
else {
|
foreach ($Name in $script:Header) {
|
||||||
$ColumnIndex = $StartColumn
|
$ws.Cells[$row, $ColumnIndex].Value = $Name
|
||||||
foreach ($Name in $script:Header) {
|
Write-Verbose "Cell '$row`:$ColumnIndex' add header '$Name'"
|
||||||
$ws.Cells[$row, $ColumnIndex].Value = $Name
|
$ColumnIndex += 1
|
||||||
Write-Verbose "Cell '$row`:$ColumnIndex' add header '$Name'"
|
}
|
||||||
$ColumnIndex += 1
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
#endregion
|
||||||
#endregion
|
#region Add non header values
|
||||||
#region Add non header values
|
$row += 1
|
||||||
$row += 1
|
$ColumnIndex = $StartColumn
|
||||||
$ColumnIndex = $StartColumn
|
<#
|
||||||
<#
|
|
||||||
For each item in the header OR for the Data item if this is a simple Type or data table :
|
For each item in the header OR for the Data item if this is a simple Type or data table :
|
||||||
If it is a date insert with one of Excel's built in formats - recognized as "Date and time to be localized"
|
If it is a date insert with one of Excel's built in formats - recognized as "Date and time to be localized"
|
||||||
if it is a timespan insert with a built in format for elapsed hours, minutes and seconds
|
if it is a timespan insert with a built in format for elapsed hours, minutes and seconds
|
||||||
if its any other numeric insert as is , setting format if need be.
|
if its any other numeric insert as is , setting format if need be.
|
||||||
Preserve URI, Insert a data table, convert non string objects to string.
|
Preserve URI, Insert a data table, convert non string objects to string.
|
||||||
For strings, check for fomula, URI or Number, before inserting as a string (ignore nulls) #>
|
For strings, check for fomula, URI or Number, before inserting as a string (ignore nulls) #>
|
||||||
foreach ($Name in $script:Header) {
|
foreach ($Name in $script:Header) {
|
||||||
if ($isDataTypeValueType) {$v = $TargetData}
|
if ($isDataTypeValueType) { $v = $TargetData }
|
||||||
else {$v = $TargetData.$Name}
|
else { $v = $TargetData.$Name }
|
||||||
try {
|
try {
|
||||||
if ($v -is [DateTime]) {
|
if ($v -is [DateTime]) {
|
||||||
$ws.Cells[$row, $ColumnIndex].Value = $v
|
$ws.Cells[$row, $ColumnIndex].Value = $v
|
||||||
$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = 'm/d/yy h:mm' # This is not a custom format, but a preset recognized as date and localized.
|
$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = 'm/d/yy h:mm' # This is not a custom format, but a preset recognized as date and localized.
|
||||||
}
|
|
||||||
elseif ($v -is [TimeSpan]) {
|
|
||||||
$ws.Cells[$row, $ColumnIndex].Value = $v
|
|
||||||
$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = '[h]:mm:ss'
|
|
||||||
}
|
|
||||||
elseif ($v -is [System.ValueType]) {
|
|
||||||
$ws.Cells[$row, $ColumnIndex].Value = $v
|
|
||||||
if ($setNumformat) {$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
|
|
||||||
}
|
|
||||||
elseif ($v -is [uri] ) {
|
|
||||||
$ws.Cells[$row, $ColumnIndex].HyperLink = $v
|
|
||||||
$ws.Cells[$row, $ColumnIndex].Style.Font.Color.SetColor([System.Drawing.Color]::Blue)
|
|
||||||
$ws.Cells[$row, $ColumnIndex].Style.Font.UnderLine = $true
|
|
||||||
}
|
|
||||||
elseif ($v -isnot [String] ) { #Other objects or null.
|
|
||||||
if ($null -ne $v) { $ws.Cells[$row, $ColumnIndex].Value = $v.toString()}
|
|
||||||
}
|
|
||||||
elseif ($v[0] -eq '=') {
|
|
||||||
$ws.Cells[$row, $ColumnIndex].Formula = ($v -replace '^=','')
|
|
||||||
if ($setNumformat) {$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
|
|
||||||
}
|
|
||||||
elseif ( [System.Uri]::IsWellFormedUriString($v , [System.UriKind]::Absolute) ) {
|
|
||||||
if ($v -match "^xl://internal/") {
|
|
||||||
$referenceAddress = $v -replace "^xl://internal/" , ""
|
|
||||||
$display = $referenceAddress -replace "!A1$" , ""
|
|
||||||
$h = New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList $referenceAddress , $display
|
|
||||||
$ws.Cells[$row, $ColumnIndex].HyperLink = $h
|
|
||||||
}
|
}
|
||||||
else {$ws.Cells[$row, $ColumnIndex].HyperLink = $v } #$ws.Cells[$row, $ColumnIndex].Value = $v.AbsoluteUri
|
elseif ($v -is [TimeSpan]) {
|
||||||
$ws.Cells[$row, $ColumnIndex].Style.Font.Color.SetColor([System.Drawing.Color]::Blue)
|
$ws.Cells[$row, $ColumnIndex].Value = $v
|
||||||
$ws.Cells[$row, $ColumnIndex].Style.Font.UnderLine = $true
|
$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = '[h]:mm:ss'
|
||||||
}
|
}
|
||||||
else {
|
elseif ($v -is [System.ValueType]) {
|
||||||
$number = $null
|
$ws.Cells[$row, $ColumnIndex].Value = $v
|
||||||
if ( $numberRegex.IsMatch($v) -and # if it contains digit(s) - this syntax is quicker than -match for many items and cuts out slow checks for non numbers
|
if ($setNumformat) { $ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
|
||||||
$NoNumberConversion -ne '*' -and # and NoNumberConversion isn't specified
|
}
|
||||||
$NoNumberConversion -notcontains $Name -and
|
elseif ($v -is [uri] ) {
|
||||||
[Double]::TryParse($v, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number)
|
$ws.Cells[$row, $ColumnIndex].HyperLink = $v
|
||||||
) {
|
$ws.Cells[$row, $ColumnIndex].Style.Font.Color.SetColor([System.Drawing.Color]::Blue)
|
||||||
$ws.Cells[$row, $ColumnIndex].Value = $number
|
$ws.Cells[$row, $ColumnIndex].Style.Font.UnderLine = $true
|
||||||
if ($setNumformat) {$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
|
}
|
||||||
|
elseif ($v -isnot [String] ) {
|
||||||
|
#Other objects or null.
|
||||||
|
if ($null -ne $v) { $ws.Cells[$row, $ColumnIndex].Value = $v.toString() }
|
||||||
|
}
|
||||||
|
elseif ($v[0] -eq '=') {
|
||||||
|
$ws.Cells[$row, $ColumnIndex].Formula = ($v -replace '^=', '')
|
||||||
|
if ($setNumformat) { $ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
|
||||||
|
}
|
||||||
|
elseif ( [System.Uri]::IsWellFormedUriString($v , [System.UriKind]::Absolute) ) {
|
||||||
|
if ($v -match "^xl://internal/") {
|
||||||
|
$referenceAddress = $v -replace "^xl://internal/" , ""
|
||||||
|
$display = $referenceAddress -replace "!A1$" , ""
|
||||||
|
$h = New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList $referenceAddress , $display
|
||||||
|
$ws.Cells[$row, $ColumnIndex].HyperLink = $h
|
||||||
|
}
|
||||||
|
else { $ws.Cells[$row, $ColumnIndex].HyperLink = $v } #$ws.Cells[$row, $ColumnIndex].Value = $v.AbsoluteUri
|
||||||
|
$ws.Cells[$row, $ColumnIndex].Style.Font.Color.SetColor([System.Drawing.Color]::Blue)
|
||||||
|
$ws.Cells[$row, $ColumnIndex].Style.Font.UnderLine = $true
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$ws.Cells[$row, $ColumnIndex].Value = $v
|
$number = $null
|
||||||
|
if ( $numberRegex.IsMatch($v) -and # if it contains digit(s) - this syntax is quicker than -match for many items and cuts out slow checks for non numbers
|
||||||
|
$NoNumberConversion -ne '*' -and # and NoNumberConversion isn't specified
|
||||||
|
$NoNumberConversion -notcontains $Name -and
|
||||||
|
[Double]::TryParse($v, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number)
|
||||||
|
) {
|
||||||
|
$ws.Cells[$row, $ColumnIndex].Value = $number
|
||||||
|
if ($setNumformat) { $ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$ws.Cells[$row, $ColumnIndex].Value = $v
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
catch { Write-Warning -Message "Could not insert the '$Name' property at Row $row, Column $ColumnIndex" }
|
||||||
|
$ColumnIndex += 1
|
||||||
}
|
}
|
||||||
catch {Write-Warning -Message "Could not insert the '$Name' property at Row $row, Column $ColumnIndex"}
|
$ColumnIndex -= 1 # column index will be the last column whether isDataTypeValueType was true or false
|
||||||
$ColumnIndex += 1
|
#endregion
|
||||||
}
|
}
|
||||||
$ColumnIndex -= 1 # column index will be the last column whether isDataTypeValueType was true or false
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
|
catch { throw "Failed exporting data to worksheet '$WorksheetName' to '$Path': $_" }
|
||||||
}
|
}
|
||||||
catch {throw "Failed exporting data to worksheet '$WorksheetName' to '$Path': $_" }
|
}
|
||||||
}}
|
|
||||||
|
|
||||||
end {
|
end {
|
||||||
if ($firstTimeThru -and $ws.Dimension) {
|
if ($firstTimeThru -and $ws.Dimension) {
|
||||||
$LastRow = $ws.Dimension.End.Row
|
$LastRow = $ws.Dimension.End.Row
|
||||||
$LastCol = $ws.Dimension.End.Column
|
$LastCol = $ws.Dimension.End.Column
|
||||||
$endAddress = $ws.Dimension.End.Address
|
$endAddress = $ws.Dimension.End.Address
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$LastRow = $row
|
$LastRow = $row
|
||||||
$LastCol = $ColumnIndex
|
$LastCol = $ColumnIndex
|
||||||
$endAddress = [OfficeOpenXml.ExcelAddress]::GetAddress($LastRow , $LastCol)
|
$endAddress = [OfficeOpenXml.ExcelAddress]::GetAddress($LastRow , $LastCol)
|
||||||
}
|
}
|
||||||
$startAddress = [OfficeOpenXml.ExcelAddress]::GetAddress($StartRow, $StartColumn)
|
$startAddress = [OfficeOpenXml.ExcelAddress]::GetAddress($StartRow, $StartColumn)
|
||||||
$dataRange = "{0}:{1}" -f $startAddress, $endAddress
|
$dataRange = "{0}:{1}" -f $startAddress, $endAddress
|
||||||
|
|
||||||
Write-Debug "Data Range '$dataRange'"
|
Write-Debug "Data Range '$dataRange'"
|
||||||
if ($AutoNameRange) {
|
if ($AutoNameRange) {
|
||||||
@@ -385,13 +388,14 @@
|
|||||||
# if there aren't any headers, use the the first row of data to name the ranges: this is the last point that headers will be used.
|
# if there aren't any headers, use the the first row of data to name the ranges: this is the last point that headers will be used.
|
||||||
$headerRange = $ws.Dimension.Address -replace "\d+$", $StartRow
|
$headerRange = $ws.Dimension.Address -replace "\d+$", $StartRow
|
||||||
#using a slightly odd syntax otherwise header ends up as a 2D array
|
#using a slightly odd syntax otherwise header ends up as a 2D array
|
||||||
$ws.Cells[$headerRange].Value | ForEach-Object -Begin {$Script:header = @()} -Process {$Script:header += $_ }
|
$ws.Cells[$headerRange].Value | ForEach-Object -Begin { $Script:header = @() } -Process { $Script:header += $_ }
|
||||||
if ($PSBoundParameters.ContainsKey($TargetData)) { #if Export was called with data that writes no header start the range at $startRow ($startRow is data)
|
if ($PSBoundParameters.ContainsKey($TargetData)) {
|
||||||
$targetRow = $StartRow
|
#if Export was called with data that writes no header start the range at $startRow ($startRow is data)
|
||||||
|
$targetRow = $StartRow
|
||||||
}
|
}
|
||||||
else { $targetRow = $StartRow + 1 } #if Export was called without data to add names (assume $startRow is a header) or...
|
else { $targetRow = $StartRow + 1 } #if Export was called without data to add names (assume $startRow is a header) or...
|
||||||
} # ... called with data that writes a header, then start the range at $startRow + 1
|
} # ... called with data that writes a header, then start the range at $startRow + 1
|
||||||
else { $targetRow = $StartRow + 1 }
|
else { $targetRow = $StartRow + 1 }
|
||||||
|
|
||||||
#Dimension.start.row always seems to be one so we work out the target row
|
#Dimension.start.row always seems to be one so we work out the target row
|
||||||
#, but start.column is the first populated one and .Columns is the count of populated ones.
|
#, but start.column is the first populated one and .Columns is the count of populated ones.
|
||||||
@@ -400,7 +404,8 @@
|
|||||||
foreach ($c in 0..($LastCol - $StartColumn)) {
|
foreach ($c in 0..($LastCol - $StartColumn)) {
|
||||||
$targetRangeName = @($script:Header)[$c] #Let Add-ExcelName fix (and warn about) bad names
|
$targetRangeName = @($script:Header)[$c] #Let Add-ExcelName fix (and warn about) bad names
|
||||||
Add-ExcelName -RangeName $targetRangeName -Range $ws.Cells[$targetRow, ($StartColumn + $c ), $LastRow, ($StartColumn + $c )]
|
Add-ExcelName -RangeName $targetRangeName -Range $ws.Cells[$targetRow, ($StartColumn + $c ), $LastRow, ($StartColumn + $c )]
|
||||||
try {#this test can throw with some names, surpress any error
|
try {
|
||||||
|
#this test can throw with some names, surpress any error
|
||||||
if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress(($targetRangeName -replace '\W' , '_' ))) {
|
if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress(($targetRangeName -replace '\W' , '_' ))) {
|
||||||
Write-Warning -Message "AutoNameRange: Property name '$targetRangeName' is also a valid Excel address and may cause issues. Consider renaming the property."
|
Write-Warning -Message "AutoNameRange: Property name '$targetRangeName' is also a valid Excel address and may cause issues. Consider renaming the property."
|
||||||
}
|
}
|
||||||
@@ -410,13 +415,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {Write-Warning -Message "Failed adding named ranges to worksheet '$WorksheetName': $_" }
|
catch { Write-Warning -Message "Failed adding named ranges to worksheet '$WorksheetName': $_" }
|
||||||
}
|
}
|
||||||
#Empty string is not allowed as a name for ranges or tables.
|
#Empty string is not allowed as a name for ranges or tables.
|
||||||
if ($RangeName) { Add-ExcelName -Range $ws.Cells[$dataRange] -RangeName $RangeName}
|
if ($RangeName) { Add-ExcelName -Range $ws.Cells[$dataRange] -RangeName $RangeName }
|
||||||
|
|
||||||
#Allow table to be inserted by specifying Name, or Style or both; only process autoFilter if there is no table (they clash).
|
#Allow table to be inserted by specifying Name, or Style or both; only process autoFilter if there is no table (they clash).
|
||||||
if ($null -ne $TableName -or $PSBoundParameters.ContainsKey('TableStyle')) {
|
if ($null -ne $TableName -or $PSBoundParameters.ContainsKey('TableStyle')) {
|
||||||
#Already inserted Excel table if input was a DataTable
|
#Already inserted Excel table if input was a DataTable
|
||||||
if ($InputObject -isnot [System.Data.DataTable]) {
|
if ($InputObject -isnot [System.Data.DataTable]) {
|
||||||
Add-ExcelTable -Range $ws.Cells[$dataRange] -TableName $TableName -TableStyle $TableStyle
|
Add-ExcelTable -Range $ws.Cells[$dataRange] -TableName $TableName -TableStyle $TableStyle
|
||||||
@@ -427,19 +432,19 @@
|
|||||||
$ws.Cells[$dataRange].AutoFilter = $true
|
$ws.Cells[$dataRange].AutoFilter = $true
|
||||||
Write-Verbose -Message "Enabled autofilter. "
|
Write-Verbose -Message "Enabled autofilter. "
|
||||||
}
|
}
|
||||||
catch {Write-Warning -Message "Failed adding autofilter to worksheet '$WorksheetName': $_"}
|
catch { Write-Warning -Message "Failed adding autofilter to worksheet '$WorksheetName': $_" }
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($PivotTableDefinition) {
|
if ($PivotTableDefinition) {
|
||||||
foreach ($item in $PivotTableDefinition.GetEnumerator()) {
|
foreach ($item in $PivotTableDefinition.GetEnumerator()) {
|
||||||
$params = $item.value
|
$params = $item.value
|
||||||
if ($Activate) {$params.Activate = $true }
|
if ($Activate) { $params.Activate = $true }
|
||||||
if ($params.keys -notcontains 'SourceRange' -and
|
if ($params.keys -notcontains 'SourceRange' -and
|
||||||
($params.Keys -notcontains 'SourceWorksheet' -or $params.SourceWorksheet -eq $WorksheetName)) {$params.SourceRange = $dataRange}
|
($params.Keys -notcontains 'SourceWorksheet' -or $params.SourceWorksheet -eq $WorksheetName)) { $params.SourceRange = $dataRange }
|
||||||
if ($params.Keys -notcontains 'SourceWorksheet') {$params.SourceWorksheet = $ws }
|
if ($params.Keys -notcontains 'SourceWorksheet') { $params.SourceWorksheet = $ws }
|
||||||
if ($params.Keys -notcontains 'NoTotalsInPivot' -and $NoTotalsInPivot ) {$params.PivotTotals = 'None'}
|
if ($params.Keys -notcontains 'NoTotalsInPivot' -and $NoTotalsInPivot ) { $params.PivotTotals = 'None' }
|
||||||
if ($params.Keys -notcontains 'PivotTotals' -and $PivotTotals ) {$params.PivotTotals = $PivotTotals}
|
if ($params.Keys -notcontains 'PivotTotals' -and $PivotTotals ) { $params.PivotTotals = $PivotTotals }
|
||||||
if ($params.Keys -notcontains 'PivotDataToColumn' -and $PivotDataToColumn) {$params.PivotDataToColumn = $true}
|
if ($params.Keys -notcontains 'PivotDataToColumn' -and $PivotDataToColumn) { $params.PivotDataToColumn = $true }
|
||||||
|
|
||||||
Add-PivotTable -ExcelPackage $pkg -PivotTableName $item.key @Params
|
Add-PivotTable -ExcelPackage $pkg -PivotTableName $item.key @Params
|
||||||
}
|
}
|
||||||
@@ -453,23 +458,23 @@
|
|||||||
$PivotTableName += 'Pivot'
|
$PivotTableName += 'Pivot'
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($PivotTableName) {$params.PivotTableName = $PivotTableName}
|
if ($PivotTableName) { $params.PivotTableName = $PivotTableName }
|
||||||
else {$params.PivotTableName = $WorksheetName + 'PivotTable'}
|
else { $params.PivotTableName = $WorksheetName + 'PivotTable' }
|
||||||
if ($Activate) {$params.Activate = $true }
|
if ($Activate) { $params.Activate = $true }
|
||||||
if ($PivotFilter) {$params.PivotFilter = $PivotFilter}
|
if ($PivotFilter) { $params.PivotFilter = $PivotFilter }
|
||||||
if ($PivotRows) {$params.PivotRows = $PivotRows}
|
if ($PivotRows) { $params.PivotRows = $PivotRows }
|
||||||
if ($PivotColumns) {$Params.PivotColumns = $PivotColumns}
|
if ($PivotColumns) { $Params.PivotColumns = $PivotColumns }
|
||||||
if ($PivotData) {$Params.PivotData = $PivotData}
|
if ($PivotData) { $Params.PivotData = $PivotData }
|
||||||
if ($NoTotalsInPivot) {$params.PivotTotals = "None" }
|
if ($NoTotalsInPivot) { $params.PivotTotals = "None" }
|
||||||
Elseif ($PivotTotals) {$params.PivotTotals = $PivotTotals}
|
Elseif ($PivotTotals) { $params.PivotTotals = $PivotTotals }
|
||||||
if ($PivotDataToColumn) {$params.PivotDataToColumn = $true}
|
if ($PivotDataToColumn) { $params.PivotDataToColumn = $true }
|
||||||
if ($IncludePivotChart -or
|
if ($IncludePivotChart -or
|
||||||
$PSBoundParameters.ContainsKey('PivotChartType')) {
|
$PSBoundParameters.ContainsKey('PivotChartType')) {
|
||||||
$params.IncludePivotChart = $true
|
$params.IncludePivotChart = $true
|
||||||
$Params.ChartType = $PivotChartType
|
$Params.ChartType = $PivotChartType
|
||||||
if ($ShowCategory) {$params.ShowCategory = $true}
|
if ($ShowCategory) { $params.ShowCategory = $true }
|
||||||
if ($ShowPercent) {$params.ShowPercent = $true}
|
if ($ShowPercent) { $params.ShowPercent = $true }
|
||||||
if ($NoLegend) {$params.NoLegend = $true}
|
if ($NoLegend) { $params.NoLegend = $true }
|
||||||
}
|
}
|
||||||
Add-PivotTable -ExcelPackage $pkg -SourceWorksheet $ws @params
|
Add-PivotTable -ExcelPackage $pkg -SourceWorksheet $ws @params
|
||||||
}
|
}
|
||||||
@@ -513,9 +518,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {Write-Warning -Message "Failed adding Freezing the panes in worksheet '$WorksheetName': $_"}
|
catch { Write-Warning -Message "Failed adding Freezing the panes in worksheet '$WorksheetName': $_" }
|
||||||
|
|
||||||
if ($PSBoundParameters.ContainsKey("BoldTopRow")) { #it sets bold as far as there are populated cells: for whole row could do $ws.row($x).style.font.bold = $true
|
if ($PSBoundParameters.ContainsKey("BoldTopRow")) {
|
||||||
|
#it sets bold as far as there are populated cells: for whole row could do $ws.row($x).style.font.bold = $true
|
||||||
try {
|
try {
|
||||||
if ($Title) {
|
if ($Title) {
|
||||||
$range = $ws.Dimension.Address -replace '\d+', ($StartRow + 1)
|
$range = $ws.Dimension.Address -replace '\d+', ($StartRow + 1)
|
||||||
@@ -526,41 +532,41 @@
|
|||||||
$ws.Cells[$range].Style.Font.Bold = [boolean]$BoldTopRow
|
$ws.Cells[$range].Style.Font.Bold = [boolean]$BoldTopRow
|
||||||
Write-Verbose -Message "Set $range font style to bold."
|
Write-Verbose -Message "Set $range font style to bold."
|
||||||
}
|
}
|
||||||
catch {Write-Warning -Message "Failed setting the top row to bold in worksheet '$WorksheetName': $_"}
|
catch { Write-Warning -Message "Failed setting the top row to bold in worksheet '$WorksheetName': $_" }
|
||||||
}
|
}
|
||||||
if ($AutoSize -and -not $env:NoAutoSize) {
|
if ($AutoSize -and -not $env:NoAutoSize) {
|
||||||
try {
|
try {
|
||||||
#Don't fit the all the columns in the sheet; if we are adding cells beside things with hidden columns, that unhides them
|
#Don't fit the all the columns in the sheet; if we are adding cells beside things with hidden columns, that unhides them
|
||||||
if ($MaxAutoSizeRows -and $MaxAutoSizeRows -lt $LastRow ) {
|
if ($MaxAutoSizeRows -and $MaxAutoSizeRows -lt $LastRow ) {
|
||||||
$AutosizeRange = [OfficeOpenXml.ExcelAddress]::GetAddress($startRow,$StartColumn, $MaxAutoSizeRows , $LastCol)
|
$AutosizeRange = [OfficeOpenXml.ExcelAddress]::GetAddress($startRow, $StartColumn, $MaxAutoSizeRows , $LastCol)
|
||||||
$ws.Cells[$AutosizeRange].AutoFitColumns()
|
$ws.Cells[$AutosizeRange].AutoFitColumns()
|
||||||
}
|
}
|
||||||
else {$ws.Cells[$dataRange].AutoFitColumns() }
|
else { $ws.Cells[$dataRange].AutoFitColumns() }
|
||||||
Write-Verbose -Message "Auto-sized columns"
|
Write-Verbose -Message "Auto-sized columns"
|
||||||
}
|
}
|
||||||
catch { Write-Warning -Message "Failed autosizing columns of worksheet '$WorksheetName': $_"}
|
catch { Write-Warning -Message "Failed autosizing columns of worksheet '$WorksheetName': $_" }
|
||||||
}
|
}
|
||||||
elseif ($AutoSize) {Write-Warning -Message "Auto-fitting columns is not available with this OS configuration." }
|
elseif ($AutoSize) { Write-Warning -Message "Auto-fitting columns is not available with this OS configuration." }
|
||||||
|
|
||||||
foreach ($Sheet in $HideSheet) {
|
foreach ($Sheet in $HideSheet) {
|
||||||
try {
|
try {
|
||||||
$pkg.Workbook.Worksheets.Where({$_.Name -like $sheet}) | ForEach-Object {
|
$pkg.Workbook.Worksheets.Where({ $_.Name -like $sheet }) | ForEach-Object {
|
||||||
$_.Hidden = 'Hidden'
|
$_.Hidden = 'Hidden'
|
||||||
Write-verbose -Message "Sheet '$($_.Name)' Hidden."
|
Write-verbose -Message "Sheet '$($_.Name)' Hidden."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {Write-Warning -Message "Failed hiding worksheet '$sheet': $_"}
|
catch { Write-Warning -Message "Failed hiding worksheet '$sheet': $_" }
|
||||||
}
|
}
|
||||||
foreach ($Sheet in $UnHideSheet) {
|
foreach ($Sheet in $UnHideSheet) {
|
||||||
try {
|
try {
|
||||||
$pkg.Workbook.Worksheets.Where({$_.Name -like $sheet}) | ForEach-Object {
|
$pkg.Workbook.Worksheets.Where({ $_.Name -like $sheet }) | ForEach-Object {
|
||||||
$_.Hidden = 'Visible'
|
$_.Hidden = 'Visible'
|
||||||
Write-verbose -Message "Sheet '$($_.Name)' shown"
|
Write-verbose -Message "Sheet '$($_.Name)' shown"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {Write-Warning -Message "Failed showing worksheet '$sheet': $_"}
|
catch { Write-Warning -Message "Failed showing worksheet '$sheet': $_" }
|
||||||
}
|
}
|
||||||
if (-not $pkg.Workbook.Worksheets.Where({$_.Hidden -eq 'visible'})) {
|
if (-not $pkg.Workbook.Worksheets.Where({ $_.Hidden -eq 'visible' })) {
|
||||||
Write-Verbose -Message "No Sheets were left visible, making $WorksheetName visible"
|
Write-Verbose -Message "No Sheets were left visible, making $WorksheetName visible"
|
||||||
$ws.Hidden = 'Visible'
|
$ws.Hidden = 'Visible'
|
||||||
}
|
}
|
||||||
@@ -568,46 +574,46 @@
|
|||||||
foreach ($chartDef in $ExcelChartDefinition) {
|
foreach ($chartDef in $ExcelChartDefinition) {
|
||||||
if ($chartDef -is [System.Management.Automation.PSCustomObject]) {
|
if ($chartDef -is [System.Management.Automation.PSCustomObject]) {
|
||||||
$params = @{}
|
$params = @{}
|
||||||
$chartDef.PSObject.Properties | ForEach-Object {if ( $null -ne $_.value) {$params[$_.name] = $_.value}}
|
$chartDef.PSObject.Properties | ForEach-Object { if ( $null -ne $_.value) { $params[$_.name] = $_.value } }
|
||||||
Add-ExcelChart -Worksheet $ws @params
|
Add-ExcelChart -Worksheet $ws @params
|
||||||
}
|
}
|
||||||
elseif ($chartDef -is [hashtable] -or $chartDef -is[System.Collections.Specialized.OrderedDictionary]) {
|
elseif ($chartDef -is [hashtable] -or $chartDef -is [System.Collections.Specialized.OrderedDictionary]) {
|
||||||
Add-ExcelChart -Worksheet $ws @chartDef
|
Add-ExcelChart -Worksheet $ws @chartDef
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Calculate) {
|
if ($Calculate) {
|
||||||
try { [OfficeOpenXml.CalculationExtension]::Calculate($ws) }
|
try { [OfficeOpenXml.CalculationExtension]::Calculate($ws) }
|
||||||
catch { Write-Warning "One or more errors occured while calculating, save will continue, but there may be errors in the workbook. $_"}
|
catch { Write-Warning "One or more errors occured while calculating, save will continue, but there may be errors in the workbook. $_" }
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($Barchart -or $PieChart -or $LineChart -or $ColumnChart) {
|
if ($Barchart -or $PieChart -or $LineChart -or $ColumnChart) {
|
||||||
if ($NoHeader) {$FirstDataRow = $startRow}
|
if ($NoHeader) { $FirstDataRow = $startRow }
|
||||||
else {$FirstDataRow = $startRow + 1 }
|
else { $FirstDataRow = $startRow + 1 }
|
||||||
$range = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $startColumn, $FirstDataRow, $lastCol )
|
$range = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $startColumn, $FirstDataRow, $lastCol )
|
||||||
$xCol = $ws.cells[$range] | Where-Object {$_.value -is [string] } | ForEach-Object {$_.start.column} | Sort-Object | Select-Object -first 1
|
$xCol = $ws.cells[$range] | Where-Object { $_.value -is [string] } | ForEach-Object { $_.start.column } | Sort-Object | Select-Object -first 1
|
||||||
if (-not $xcol) {
|
if (-not $xcol) {
|
||||||
$xcol = $StartColumn
|
$xcol = $StartColumn
|
||||||
$range = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, ($startColumn +1), $FirstDataRow, $lastCol )
|
$range = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, ($startColumn + 1), $FirstDataRow, $lastCol )
|
||||||
}
|
}
|
||||||
$yCol = $ws.cells[$range] | Where-Object {$_.value -is [valueType] -or $_.Formula } | ForEach-Object {$_.start.column} | Sort-Object | Select-Object -first 1
|
$yCol = $ws.cells[$range] | Where-Object { $_.value -is [valueType] -or $_.Formula } | ForEach-Object { $_.start.column } | Sort-Object | Select-Object -first 1
|
||||||
if (-not ($xCol -and $ycol)) { Write-Warning -Message "Can't identify a string column and a number column to use as chart labels and data. "}
|
if (-not ($xCol -and $ycol)) { Write-Warning -Message "Can't identify a string column and a number column to use as chart labels and data. " }
|
||||||
else {
|
else {
|
||||||
$params = @{
|
$params = @{
|
||||||
XRange = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $xcol , $lastrow, $xcol)
|
XRange = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $xcol , $lastrow, $xcol)
|
||||||
YRange = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $ycol , $lastrow, $ycol)
|
YRange = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $ycol , $lastrow, $ycol)
|
||||||
Title = ''
|
Title = ''
|
||||||
Column = ($lastCol +1)
|
Column = ($lastCol + 1)
|
||||||
Width = 800
|
Width = 800
|
||||||
}
|
}
|
||||||
if ($ShowPercent) {$params["ShowPercent"] = $true}
|
if ($ShowPercent) { $params["ShowPercent"] = $true }
|
||||||
if ($ShowCategory) {$params["ShowCategory"] = $true}
|
if ($ShowCategory) { $params["ShowCategory"] = $true }
|
||||||
if ($NoLegend) {$params["NoLegend"] = $true}
|
if ($NoLegend) { $params["NoLegend"] = $true }
|
||||||
if (-not $NoHeader) {$params["SeriesHeader"] = $ws.Cells[$startRow, $YCol].Value}
|
if (-not $NoHeader) { $params["SeriesHeader"] = $ws.Cells[$startRow, $YCol].Value }
|
||||||
if ($ColumnChart) {$Params["chartType"] = "ColumnStacked" }
|
if ($ColumnChart) { $Params["chartType"] = "ColumnStacked" }
|
||||||
elseif ($Barchart) {$Params["chartType"] = "BarStacked" }
|
elseif ($Barchart) { $Params["chartType"] = "BarStacked" }
|
||||||
elseif ($PieChart) {$Params["chartType"] = "PieExploded3D" }
|
elseif ($PieChart) { $Params["chartType"] = "PieExploded3D" }
|
||||||
elseif ($LineChart) {$Params["chartType"] = "Line" }
|
elseif ($LineChart) { $Params["chartType"] = "Line" }
|
||||||
|
|
||||||
Add-ExcelChart -Worksheet $ws @params
|
Add-ExcelChart -Worksheet $ws @params
|
||||||
}
|
}
|
||||||
@@ -615,35 +621,36 @@
|
|||||||
|
|
||||||
# It now doesn't matter if the conditional formating rules are passed in $conditionalText or $conditional format.
|
# It now doesn't matter if the conditional formating rules are passed in $conditionalText or $conditional format.
|
||||||
# Just one with an alias for compatiblity it will break things for people who are using both at once
|
# Just one with an alias for compatiblity it will break things for people who are using both at once
|
||||||
foreach ($c in (@() + $ConditionalText + $ConditionalFormat) ) {
|
foreach ($c in (@() + $ConditionalText + $ConditionalFormat) ) {
|
||||||
try {
|
try {
|
||||||
#we can take an object with a .ConditionalType property made by New-ConditionalText or with a .Formatter Property made by New-ConditionalFormattingIconSet or a hash table
|
#we can take an object with a .ConditionalType property made by New-ConditionalText or with a .Formatter Property made by New-ConditionalFormattingIconSet or a hash table
|
||||||
if ($c.ConditionalType) {
|
if ($c.ConditionalType) {
|
||||||
$cfParams = @{RuleType = $c.ConditionalType; ConditionValue = $c.Text ;
|
$cfParams = @{RuleType = $c.ConditionalType; ConditionValue = $c.Text ;
|
||||||
BackgroundColor = $c.BackgroundColor; BackgroundPattern = $c.PatternType ;
|
BackgroundColor = $c.BackgroundColor; BackgroundPattern = $c.PatternType ;
|
||||||
ForeGroundColor = $c.ConditionalTextColor}
|
ForeGroundColor = $c.ConditionalTextColor
|
||||||
if ($c.Range) {$cfParams.Range = $c.Range}
|
}
|
||||||
else {$cfParams.Range = $ws.Dimension.Address }
|
if ($c.Range) { $cfParams.Range = $c.Range }
|
||||||
|
else { $cfParams.Range = $ws.Dimension.Address }
|
||||||
Add-ConditionalFormatting -Worksheet $ws @cfParams
|
Add-ConditionalFormatting -Worksheet $ws @cfParams
|
||||||
Write-Verbose -Message "Added conditional formatting to range $($c.range)"
|
Write-Verbose -Message "Added conditional formatting to range $($c.range)"
|
||||||
}
|
}
|
||||||
elseif ($c.formatter) {
|
elseif ($c.formatter) {
|
||||||
switch ($c.formatter) {
|
switch ($c.formatter) {
|
||||||
"ThreeIconSet" {Add-ConditionalFormatting -Worksheet $ws -ThreeIconsSet $c.IconType -range $c.range -reverse:$c.reverse }
|
"ThreeIconSet" { Add-ConditionalFormatting -Worksheet $ws -ThreeIconsSet $c.IconType -range $c.range -reverse:$c.reverse }
|
||||||
"FourIconSet" {Add-ConditionalFormatting -Worksheet $ws -FourIconsSet $c.IconType -range $c.range -reverse:$c.reverse }
|
"FourIconSet" { Add-ConditionalFormatting -Worksheet $ws -FourIconsSet $c.IconType -range $c.range -reverse:$c.reverse }
|
||||||
"FiveIconSet" {Add-ConditionalFormatting -Worksheet $ws -FiveIconsSet $c.IconType -range $c.range -reverse:$c.reverse }
|
"FiveIconSet" { Add-ConditionalFormatting -Worksheet $ws -FiveIconsSet $c.IconType -range $c.range -reverse:$c.reverse }
|
||||||
}
|
}
|
||||||
Write-Verbose -Message "Added conditional formatting to range $($c.range)"
|
Write-Verbose -Message "Added conditional formatting to range $($c.range)"
|
||||||
}
|
}
|
||||||
elseif ($c -is [hashtable] -or $c -is[System.Collections.Specialized.OrderedDictionary]) {
|
elseif ($c -is [hashtable] -or $c -is [System.Collections.Specialized.OrderedDictionary]) {
|
||||||
if (-not $c.Range -or $c.Address) {$c.Address = $ws.Dimension.Address }
|
if (-not $c.Range -or $c.Address) { $c.Address = $ws.Dimension.Address }
|
||||||
Add-ConditionalFormatting -Worksheet $ws @c
|
Add-ConditionalFormatting -Worksheet $ws @c
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {throw "Error applying conditional formatting to worksheet $_"}
|
catch { throw "Error applying conditional formatting to worksheet $_" }
|
||||||
}
|
}
|
||||||
foreach ($s in $Style) {
|
foreach ($s in $Style) {
|
||||||
if (-not $s.Range) {$s["Range"] = $ws.Dimension.Address }
|
if (-not $s.Range) { $s["Range"] = $ws.Dimension.Address }
|
||||||
Set-ExcelRange -Worksheet $ws @s
|
Set-ExcelRange -Worksheet $ws @s
|
||||||
}
|
}
|
||||||
if ($CellStyleSB) {
|
if ($CellStyleSB) {
|
||||||
@@ -652,7 +659,7 @@
|
|||||||
$LastColumn = $ws.Dimension.Address -replace "^.*:(\w*)\d+$" , '$1'
|
$LastColumn = $ws.Dimension.Address -replace "^.*:(\w*)\d+$" , '$1'
|
||||||
& $CellStyleSB $ws $TotalRows $LastColumn
|
& $CellStyleSB $ws $TotalRows $LastColumn
|
||||||
}
|
}
|
||||||
catch {Write-Warning -Message "Failed processing CellStyleSB in worksheet '$WorksheetName': $_"}
|
catch { Write-Warning -Message "Failed processing CellStyleSB in worksheet '$WorksheetName': $_" }
|
||||||
}
|
}
|
||||||
|
|
||||||
#Can only add password, may want to support -password $Null removing password.
|
#Can only add password, may want to support -password $Null removing password.
|
||||||
@@ -661,32 +668,18 @@
|
|||||||
$ws.Protection.SetPassword($Password)
|
$ws.Protection.SetPassword($Password)
|
||||||
Write-Verbose -Message 'Set password on workbook'
|
Write-Verbose -Message 'Set password on workbook'
|
||||||
}
|
}
|
||||||
catch {throw "Failed setting password for worksheet '$WorksheetName': $_"}
|
catch { throw "Failed setting password for worksheet '$WorksheetName': $_" }
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($PassThru) { $pkg }
|
if ($PassThru) { $pkg }
|
||||||
else {
|
else {
|
||||||
if ($ReturnRange) {$dataRange }
|
if ($ReturnRange) { $dataRange }
|
||||||
|
|
||||||
if ($Password) { $pkg.Save($Password) }
|
if ($Password) { $pkg.Save($Password) }
|
||||||
else { $pkg.Save() }
|
else { $pkg.Save() }
|
||||||
Write-Verbose -Message "Saved workbook $($pkg.File)"
|
Write-Verbose -Message "Saved workbook $($pkg.File)"
|
||||||
if ($ReZip) {
|
if ($ReZip) {
|
||||||
Write-Verbose -Message "Re-Zipping $($pkg.file) using .NET ZIP library"
|
Invoke-ExcelReZipFile -ExcelPackage $pkg
|
||||||
try {
|
|
||||||
Add-Type -AssemblyName 'System.IO.Compression.Filesystem' -ErrorAction stop
|
|
||||||
}
|
|
||||||
catch {
|
|
||||||
Write-Error "The -ReZip parameter requires .NET Framework 4.5 or later to be installed. Recommend to install Powershell v4+"
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
$TempZipPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath ([System.IO.Path]::GetRandomFileName())
|
|
||||||
$null = [io.compression.zipfile]::ExtractToDirectory($pkg.File, $TempZipPath)
|
|
||||||
Remove-Item $pkg.File -Force
|
|
||||||
$null = [io.compression.zipfile]::CreateFromDirectory($TempZipPath, $pkg.File)
|
|
||||||
}
|
|
||||||
catch {throw "Error resizipping $path : $_"}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$pkg.Dispose()
|
$pkg.Dispose()
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
# PowerShell + Excel = Better Together
|
# PowerShell + Excel = Better Together
|
||||||
|
|
||||||
|
|
||||||
Automate Excel via PowerShell without having Excel installed. Runs on Windows, Linux and MAC. Creating Tables, Pivot Tables, Charts and much more has just become a lot easier.
|
Automate Excel via PowerShell without having Excel installed. Runs on Windows, Linux and MAC. Creating Tables, Pivot Tables, Charts and much more has just become a lot easier.
|
||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
@@ -8,12 +9,6 @@ Automate Excel via PowerShell without having Excel installed. Runs on Windows, L
|
|||||||
|
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
Open `ImportExcel` as a remote repo in VS Code, without cloning it.
|
|
||||||
|
|
||||||
[](https://open.vscode.dev/dfinke/importexcel)
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
| CI System | Environment | Status |
|
| CI System | Environment | Status |
|
||||||
| :--- | :--- | :--- |
|
| :--- | :--- | :--- |
|
||||||
| Azure DevOps | Windows | [](https://dougfinke.visualstudio.com/ImportExcel/_build/latest?definitionId=21&branchName=master) |
|
| Azure DevOps | Windows | [](https://dougfinke.visualstudio.com/ImportExcel/_build/latest?definitionId=21&branchName=master) |
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
#Requires -Modules Pester
|
#Requires -Modules Pester
|
||||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments','',Justification='False Positives')]
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')]
|
||||||
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingCmdletAliases','',Justification='Testing for presence of alias')]
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingCmdletAliases', '', Justification = 'Testing for presence of alias')]
|
||||||
param()
|
param()
|
||||||
|
|
||||||
describe "Consistent passing of ranges." {
|
describe "Consistent passing of ranges." {
|
||||||
BeforeAll {
|
BeforeAll {
|
||||||
$path = "TestDrive:\test.xlsx"
|
$path = "TestDrive:\test.xlsx"
|
||||||
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 }
|
||||||
}
|
# }
|
||||||
}
|
}
|
||||||
Context "Conditional Formatting" {
|
Context "Conditional Formatting" {
|
||||||
it "accepts named ranges, cells['name'], worksheet + Name, worksheet + column " {
|
it "accepts named ranges, cells['name'], worksheet + Name, worksheet + column " {
|
||||||
Remove-Item -path $path -ErrorAction SilentlyContinue
|
Remove-Item -path $path -ErrorAction SilentlyContinue
|
||||||
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -AutoNameRange -Title "Services on $Env:COMPUTERNAME"
|
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -AutoNameRange -Title "Services on $Env:COMPUTERNAME"
|
||||||
{Add-ConditionalFormatting $excel.Services.Names["Status"] -StrikeThru -RuleType ContainsText -ConditionValue "Stopped" } | Should -Not -Throw
|
{ Add-ConditionalFormatting $excel.Services.Names["Status"] -StrikeThru -RuleType ContainsText -ConditionValue "Stopped" } | Should -Not -Throw
|
||||||
$excel.Services.ConditionalFormatting.Count | Should -Be 1
|
$excel.Services.ConditionalFormatting.Count | Should -Be 1
|
||||||
{Add-ConditionalFormatting $excel.Services.Cells["Name"] -Italic -RuleType ContainsText -ConditionValue "SVC" } | Should -Not -Throw
|
{ Add-ConditionalFormatting $excel.Services.Cells["Name"] -Italic -RuleType ContainsText -ConditionValue "SVC" } | Should -Not -Throw
|
||||||
$excel.Services.ConditionalFormatting.Count | Should -Be 2
|
$excel.Services.ConditionalFormatting.Count | Should -Be 2
|
||||||
$warnvar = $null
|
$warnvar = $null
|
||||||
Add-ConditionalFormatting $excel.Services.Column(3) `
|
Add-ConditionalFormatting $excel.Services.Column(3) `
|
||||||
@@ -25,25 +25,25 @@ describe "Consistent passing of ranges." {
|
|||||||
$excel.Services.ConditionalFormatting.Count | Should -Be 2
|
$excel.Services.ConditionalFormatting.Count | Should -Be 2
|
||||||
$warnvar = $null
|
$warnvar = $null
|
||||||
Add-ConditionalFormatting $excel.Services.Column(3) -Worksheet $excel.Services`
|
Add-ConditionalFormatting $excel.Services.Column(3) -Worksheet $excel.Services`
|
||||||
-underline -RuleType ContainsText -ConditionValue "Windows" -WarningVariable warnvar -WarningAction SilentlyContinue
|
-underline -RuleType ContainsText -ConditionValue "Windows" -WarningVariable warnvar -WarningAction SilentlyContinue
|
||||||
$warnvar | Should -BeNullOrEmpty
|
$warnvar | Should -BeNullOrEmpty
|
||||||
$excel.Services.ConditionalFormatting.Count | Should -Be 3
|
$excel.Services.ConditionalFormatting.Count | Should -Be 3
|
||||||
{Add-ConditionalFormatting "Status" -Worksheet $excel.Services `
|
{ Add-ConditionalFormatting "Status" -Worksheet $excel.Services `
|
||||||
-ForeGroundColor ([System.Drawing.Color]::Green) -RuleType ContainsText -ConditionValue "Running"} | Should -Not -Throw
|
-ForeGroundColor ([System.Drawing.Color]::Green) -RuleType ContainsText -ConditionValue "Running" } | Should -Not -Throw
|
||||||
$excel.Services.ConditionalFormatting.Count | Should -Be 4
|
$excel.Services.ConditionalFormatting.Count | Should -Be 4
|
||||||
Close-ExcelPackage -NoSave $excel
|
Close-ExcelPackage -NoSave $excel
|
||||||
}
|
}
|
||||||
|
|
||||||
it "accepts table, table.Address and worksheet + 'C:C' " {
|
it "accepts table, table.Address and worksheet + 'C:C' " {
|
||||||
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME"
|
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME"
|
||||||
{Add-ConditionalFormatting $excel.Services.Tables[0] `
|
{ Add-ConditionalFormatting $excel.Services.Tables[0] `
|
||||||
-Italic -RuleType ContainsText -ConditionValue "Svc" } | Should -Not -Throw
|
-Italic -RuleType ContainsText -ConditionValue "Svc" } | Should -Not -Throw
|
||||||
$excel.Services.ConditionalFormatting.Count | Should -Be 1
|
$excel.Services.ConditionalFormatting.Count | Should -Be 1
|
||||||
{Add-ConditionalFormatting $excel.Services.Tables["ServiceTable"].Address `
|
{ Add-ConditionalFormatting $excel.Services.Tables["ServiceTable"].Address `
|
||||||
-Bold -RuleType ContainsText -ConditionValue "windows" } | Should -Not -Throw
|
-Bold -RuleType ContainsText -ConditionValue "windows" } | Should -Not -Throw
|
||||||
$excel.Services.ConditionalFormatting.Count | Should -Be 2
|
$excel.Services.ConditionalFormatting.Count | Should -Be 2
|
||||||
{Add-ConditionalFormatting -Worksheet $excel.Services -Address "a:a" `
|
{ Add-ConditionalFormatting -Worksheet $excel.Services -Address "a:a" `
|
||||||
-RuleType ContainsText -ConditionValue "stopped" -ForeGroundColor ([System.Drawing.Color]::Red) } | Should -Not -Throw
|
-RuleType ContainsText -ConditionValue "stopped" -ForeGroundColor ([System.Drawing.Color]::Red) } | Should -Not -Throw
|
||||||
$excel.Services.ConditionalFormatting.Count | Should -Be 3
|
$excel.Services.ConditionalFormatting.Count | Should -Be 3
|
||||||
Close-ExcelPackage -NoSave $excel
|
Close-ExcelPackage -NoSave $excel
|
||||||
}
|
}
|
||||||
@@ -52,29 +52,29 @@ describe "Consistent passing of ranges." {
|
|||||||
Context "Formating (Set-ExcelRange or its alias Set-Format) " {
|
Context "Formating (Set-ExcelRange or its alias Set-Format) " {
|
||||||
it "accepts Named Range, cells['Name'], cells['A1:Z9'], row, Worksheet + 'A1:Z9'" {
|
it "accepts Named Range, cells['Name'], cells['A1:Z9'], row, Worksheet + 'A1:Z9'" {
|
||||||
$excel = Get-Service | Export-Excel -Path test2.xlsx -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -RangeName servicerange -Title "Services on $Env:COMPUTERNAME"
|
$excel = Get-Service | Export-Excel -Path test2.xlsx -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -RangeName servicerange -Title "Services on $Env:COMPUTERNAME"
|
||||||
{Set-format $excel.Services.Names["serviceRange"] -Bold } | Should -Not -Throw
|
{ Set-format $excel.Services.Names["serviceRange"] -Bold } | Should -Not -Throw
|
||||||
$excel.Services.cells["B2"].Style.Font.Bold | Should -Be $true
|
$excel.Services.cells["B2"].Style.Font.Bold | Should -Be $true
|
||||||
{Set-ExcelRange -Range $excel.Services.Cells["serviceRange"] -italic:$true } | Should -Not -Throw
|
{ Set-ExcelRange -Range $excel.Services.Cells["serviceRange"] -italic:$true } | Should -Not -Throw
|
||||||
$excel.Services.cells["C3"].Style.Font.Italic | Should -Be $true
|
$excel.Services.cells["C3"].Style.Font.Italic | Should -Be $true
|
||||||
{Set-format $excel.Services.Row(4) -underline -Bold:$false } | Should -Not -Throw
|
{ Set-format $excel.Services.Row(4) -underline -Bold:$false } | Should -Not -Throw
|
||||||
$excel.Services.cells["A4"].Style.Font.UnderLine | Should -Be $true
|
$excel.Services.cells["A4"].Style.Font.UnderLine | Should -Be $true
|
||||||
$excel.Services.cells["A4"].Style.Font.Bold | Should -Not -Be $true
|
$excel.Services.cells["A4"].Style.Font.Bold | Should -Not -Be $true
|
||||||
{Set-ExcelRange $excel.Services.Cells["A3:B3"] -StrikeThru } | Should -Not -Throw
|
{ Set-ExcelRange $excel.Services.Cells["A3:B3"] -StrikeThru } | Should -Not -Throw
|
||||||
$excel.Services.cells["B3"].Style.Font.Strike | Should -Be $true
|
$excel.Services.cells["B3"].Style.Font.Strike | Should -Be $true
|
||||||
{Set-ExcelRange -Worksheet $excel.Services -Range "A5:B6" -FontSize 8 } | Should -Not -Throw
|
{ Set-ExcelRange -Worksheet $excel.Services -Range "A5:B6" -FontSize 8 } | Should -Not -Throw
|
||||||
$excel.Services.cells["A5"].Style.Font.Size | Should -Be 8
|
$excel.Services.cells["A5"].Style.Font.Size | Should -Be 8
|
||||||
Close-ExcelPackage -NoSave $excel
|
Close-ExcelPackage -NoSave $excel
|
||||||
}
|
}
|
||||||
|
|
||||||
it "Accepts Table, Table.Address , worksheet + Name, Column," {
|
it "Accepts Table, Table.Address , worksheet + Name, Column," {
|
||||||
$excel = Get-Service | Export-Excel -Path test2.xlsx -WorksheetName Services -PassThru -AutoNameRange -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME"
|
$excel = Get-Service | Export-Excel -Path test2.xlsx -WorksheetName Services -PassThru -AutoNameRange -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME"
|
||||||
{Set-ExcelRange $excel.Services.Tables[0] -Italic } | Should -Not -Throw
|
{ Set-ExcelRange $excel.Services.Tables[0] -Italic } | Should -Not -Throw
|
||||||
$excel.Services.cells["C3"].Style.Font.Italic | Should -Be $true
|
$excel.Services.cells["C3"].Style.Font.Italic | Should -Be $true
|
||||||
{Set-format $excel.Services.Tables["ServiceTable"].Address -Underline } | Should -Not -Throw
|
{ Set-format $excel.Services.Tables["ServiceTable"].Address -Underline } | Should -Not -Throw
|
||||||
$excel.Services.cells["C3"].Style.Font.UnderLine | Should -Be $true
|
$excel.Services.cells["C3"].Style.Font.UnderLine | Should -Be $true
|
||||||
{Set-ExcelRange -Worksheet $excel.Services -Range "Name" -Bold } | Should -Not -Throw
|
{ Set-ExcelRange -Worksheet $excel.Services -Range "Name" -Bold } | Should -Not -Throw
|
||||||
$excel.Services.cells["B4"].Style.Font.Bold | Should -Be $true
|
$excel.Services.cells["B4"].Style.Font.Bold | Should -Be $true
|
||||||
{$excel.Services.Column(3) | Set-ExcelRange -FontColor ([System.Drawing.Color]::Red) } | Should -Not -Throw
|
{ $excel.Services.Column(3) | Set-ExcelRange -FontColor ([System.Drawing.Color]::Red) } | Should -Not -Throw
|
||||||
$excel.Services.cells["C4"].Style.Font.Color.Rgb | Should -Be "FFFF0000"
|
$excel.Services.cells["C4"].Style.Font.Color.Rgb | Should -Be "FFFF0000"
|
||||||
Close-ExcelPackage -NoSave $excel
|
Close-ExcelPackage -NoSave $excel
|
||||||
}
|
}
|
||||||
@@ -82,41 +82,41 @@ describe "Consistent passing of ranges." {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Context "PivotTables" {
|
Context "PivotTables" {
|
||||||
it "Accepts Named range, .Cells['Name'], name&Worksheet, cells['A1:Z9'], worksheet&'A1:Z9' "{
|
it "Accepts Named range, .Cells['Name'], name&Worksheet, cells['A1:Z9'], worksheet&'A1:Z9' " {
|
||||||
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -RangeName servicerange -Title "Services on $Env:COMPUTERNAME"
|
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -RangeName servicerange -Title "Services on $Env:COMPUTERNAME"
|
||||||
$ws = $excel.Workbook.Worksheets[1] #can get a worksheet by name or index - starting at 1
|
$ws = $excel.Workbook.Worksheets[1] #can get a worksheet by name or index - starting at 1
|
||||||
$end = $ws.Dimension.End.Address
|
$end = $ws.Dimension.End.Address
|
||||||
#can get a named ranged by name or index - starting at zero
|
#can get a named ranged by name or index - starting at zero
|
||||||
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt0 -SourceRange $ws.Names[0]`
|
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt0 -SourceRange $ws.Names[0]`
|
||||||
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
||||||
$excel.Workbook.Worksheets["pt0"] | Should -Not -BeNullOrEmpty
|
$excel.Workbook.Worksheets["pt0"] | Should -Not -BeNullOrEmpty
|
||||||
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt1 -SourceRange $ws.Names["servicerange"]`
|
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt1 -SourceRange $ws.Names["servicerange"]`
|
||||||
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
||||||
$excel.Workbook.Worksheets["pt1"] | Should -Not -BeNullOrEmpty
|
$excel.Workbook.Worksheets["pt1"] | Should -Not -BeNullOrEmpty
|
||||||
#Can specify the range for a pivot as NamedRange or Table or TableAddress or Worksheet + "A1:Z10" or worksheet + RangeName, or worksheet.cells["A1:Z10"] or worksheet.cells["RangeName"]
|
#Can specify the range for a pivot as NamedRange or Table or TableAddress or Worksheet + "A1:Z10" or worksheet + RangeName, or worksheet.cells["A1:Z10"] or worksheet.cells["RangeName"]
|
||||||
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt2 -SourceRange "servicerange" -SourceWorkSheet $ws `
|
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt2 -SourceRange "servicerange" -SourceWorkSheet $ws `
|
||||||
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
||||||
$excel.Workbook.Worksheets["pt2"] | Should -Not -BeNullOrEmpty
|
$excel.Workbook.Worksheets["pt2"] | Should -Not -BeNullOrEmpty
|
||||||
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt3 -SourceRange $ws.cells["servicerange"]`
|
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt3 -SourceRange $ws.cells["servicerange"]`
|
||||||
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
||||||
$excel.Workbook.Worksheets["pt3"] | Should -Not -BeNullOrEmpty
|
$excel.Workbook.Worksheets["pt3"] | Should -Not -BeNullOrEmpty
|
||||||
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt4 -SourceRange $ws.cells["A2:$end"]`
|
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt4 -SourceRange $ws.cells["A2:$end"]`
|
||||||
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
||||||
$excel.Workbook.Worksheets["pt4"] | Should -Not -BeNullOrEmpty
|
$excel.Workbook.Worksheets["pt4"] | Should -Not -BeNullOrEmpty
|
||||||
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt5 -SourceRange "A2:$end" -SourceWorkSheet $ws `
|
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt5 -SourceRange "A2:$end" -SourceWorkSheet $ws `
|
||||||
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
||||||
$excel.Workbook.Worksheets["pt5"] | Should -Not -BeNullOrEmpty
|
$excel.Workbook.Worksheets["pt5"] | Should -Not -BeNullOrEmpty
|
||||||
Close-ExcelPackage -NoSave $excel
|
Close-ExcelPackage -NoSave $excel
|
||||||
}
|
}
|
||||||
it "Accepts Table, Table.Addres " {
|
it "Accepts Table, Table.Addres " {
|
||||||
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME"
|
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME"
|
||||||
$ws = $excel.Workbook.Worksheets["Services"] #can get a worksheet by name or index - starting at 1
|
$ws = $excel.Workbook.Worksheets["Services"] #can get a worksheet by name or index - starting at 1
|
||||||
#Can get a table by name or -stating at zero. Can specify the range for a pivot as or Table or TableAddress
|
#Can get a table by name or -stating at zero. Can specify the range for a pivot as or Table or TableAddress
|
||||||
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt1 -SourceRange $ws.tables["servicetable"]`
|
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt1 -SourceRange $ws.tables["servicetable"]`
|
||||||
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
||||||
$excel.Workbook.Worksheets["pt1"] | Should -Not -BeNullOrEmpty
|
$excel.Workbook.Worksheets["pt1"] | Should -Not -BeNullOrEmpty
|
||||||
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt2 -SourceRange $ws.tables[0].Address `
|
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt2 -SourceRange $ws.tables[0].Address `
|
||||||
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
-PivotRows Status -PivotData Name } | Should -Not -Throw
|
||||||
$excel.Workbook.Worksheets["pt2"] | Should -Not -BeNullOrEmpty
|
$excel.Workbook.Worksheets["pt2"] | Should -Not -BeNullOrEmpty
|
||||||
Close-ExcelPackage -NoSave $excel
|
Close-ExcelPackage -NoSave $excel
|
||||||
}
|
}
|
||||||
|
|||||||
15
changelog.md
15
changelog.md
@@ -1,3 +1,18 @@
|
|||||||
|
# v7.4.2
|
||||||
|
|
||||||
|
- Thank you [James Mueller](https://github.com/jamesmmueller) Updated `ConvertFrom-ExcelToSQLInsert` to handle single quotes in the SQL statement.
|
||||||
|
|
||||||
|
- Thank you to Josh Hendricks
|
||||||
|
- Add images to spreadsheets. [Check it out](https://github.com/dfinke/ImportExcel/tree/master/Examples/AddImage)
|
||||||
|
- Catch up with him on [GitHub](https://github.com/joshooaj) and [Twitter](https://twitter.com/joshooaj) for the idea
|
||||||
|
|
||||||
|
# v7.4.1
|
||||||
|
|
||||||
|
- Implements: https://github.com/dfinke/ImportExcel/issues/1111
|
||||||
|
- Refactored ReZip into separate function
|
||||||
|
- Deletes temp folder after rezipping
|
||||||
|
- Added -ReZip to `Close-ExcelPackage`
|
||||||
|
|
||||||
# v7.4.0
|
# v7.4.0
|
||||||
|
|
||||||
- Thank you to [Max Goczall](https://github.com/muschebubusche) for this contribution!
|
- Thank you to [Max Goczall](https://github.com/muschebubusche) for this contribution!
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
# Examples
|
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Charts
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# Multiplecharts
|
|
||||||
|
|
||||||
## PowerShell
|
|
||||||
|
|
||||||
```text
|
|
||||||
$xlFile = "$env:TEMP\ImportExcelExample.xlsx"
|
|
||||||
Remove-Item $xlFile -ErrorAction Ignore
|
|
||||||
|
|
||||||
$data = ConvertFrom-Csv @"
|
|
||||||
ID,Product,Quantity,Price,Total
|
|
||||||
12001,Nails,37,3.99,147.63
|
|
||||||
12002,Hammer,5,12.10,60.5
|
|
||||||
12003,Saw,12,15.37,184.44
|
|
||||||
12010,Drill,20,8,160
|
|
||||||
12011,Crowbar,7,23.48,164.36
|
|
||||||
"@
|
|
||||||
|
|
||||||
$chart1 = New-ExcelChartDefinition -YRange "Price" -XRange "Product" -Title "Item price" -NoLegend -Height 225
|
|
||||||
$chart2 = New-ExcelChartDefinition -YRange "Total "-XRange "Product" -Title "Total sales" -NoLegend -Height 225 -Row 9 -Column 15
|
|
||||||
$chart3 = New-ExcelChartDefinition -YRange "Quantity"-XRange "Product" -Title "Sales volume" -NoLegend -Height 225 -Row 15
|
|
||||||
|
|
||||||
$data | Export-Excel -Path $xlFile -AutoFilter -AutoNameRange -AutoSize -Show -ExcelChartDefinition $chart1,$chart2,$chart3
|
|
||||||
```
|
|
||||||
|
|
||||||
## Result
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
# Untitled
|
|
||||||
|
|
||||||
BIN
images/FAQ_Images/DataStructureExcelPkg.png
Normal file
BIN
images/FAQ_Images/DataStructureExcelPkg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.8 KiB |
BIN
images/FAQ_Images/ExcelFileContents.png
Normal file
BIN
images/FAQ_Images/ExcelFileContents.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
BIN
images/FAQ_Images/ExcelFileContentsPostAdd.png
Normal file
BIN
images/FAQ_Images/ExcelFileContentsPostAdd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
BIN
images/FAQ_Images/ExcelFileDebugImg.jpg
Normal file
BIN
images/FAQ_Images/ExcelFileDebugImg.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
images/FAQ_Images/ValueAtIndexData.png
Normal file
BIN
images/FAQ_Images/ValueAtIndexData.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 KiB |
Reference in New Issue
Block a user