Compare commits

..

89 Commits

Author SHA1 Message Date
dfinke
d1976bf3a9 Prepped for 5.4.0 2018-11-03 11:33:15 -04:00
Doug Finke
ffcdd39ae9 Merge pull request #488 from jhoneill/master
Chart supports multiple X ranges and headers from cells
2018-11-03 15:03:45 +00:00
jhoneill
b4b5e75d28 Chart supports multiple X ranges and headers from cells 2018-11-03 13:20:30 +00:00
Doug Finke
4c3eb792d6 Merge pull request #482 from jhoneill/master
Parameter clean up, improvements to Merge-MultipleSheets
2018-11-01 22:07:41 +00:00
jhoneill
c4ef920bdf Fix stray $ in addConditionalFormatting. Updated readme 2018-11-01 21:56:37 +00:00
jhoneill
d81c2055e9 Found/Fixed more issues where zero or empty parameters should be allowed but where skipped. 2018-10-29 11:55:51 +00:00
jhoneill
4528f3b052 Merge remote-tracking branch 'upstream/master' 2018-10-29 07:34:12 +00:00
dfinke
5acec641fe updated 2018-10-25 18:32:44 -04:00
Doug Finke
04d06ff008 Merge pull request #474 from conradagramont/patch-1
Create AddMultiWorkSheet.ps1
2018-10-25 22:15:29 +00:00
jhoneill
1974beef2d Improved handling of Piped files in Merge-MultipleSheets 2018-10-25 15:11:21 +01:00
jhoneill
49f0c97635 Merge remote-tracking branch 'upstream/master' 2018-10-25 10:40:51 +01:00
jhoneill
0710724e2d Added code for -Passthru in Merge-MultipleSheets 2018-10-25 09:40:50 +01:00
Doug Finke
a6438d468a Update appveyor.yml
Save for another time. Looks like path separators are the first issue
2018-10-24 19:56:25 -04:00
Doug Finke
ce92461efc Update appveyor.yml
Enable Linux image for CI
2018-10-24 19:50:47 -04:00
Doug Finke
b3c4a334b5 Merge pull request #477 from jhoneill/master
Tests now handle V6 Process objects (more properties)
2018-10-24 23:47:08 +00:00
Conrad Agramont
6b2190bfff Updated AddMultiWorkSheet
Removed the extra code that wasn't required.
2018-10-24 16:37:10 -07:00
jhoneill
5822ef330e Merge remote-tracking branch 'upstream/master' 2018-10-24 23:32:58 +01:00
jhoneill
d78e3fff98 Tests now handle V6 Process objects (more properties) 2018-10-24 23:23:26 +01:00
Doug Finke
85bd85ee69 Merge pull request #475 from jhoneill/master
Colors for PS core and proof reading
2018-10-24 21:26:35 +00:00
jhoneill
04e8faaccc Re-instated trap for empty sheet in set row/col 2018-10-24 17:45:51 +01:00
jhoneill
2c062a4e5d Merge branch 'master' into master 2018-10-24 17:27:23 +01:00
jhoneill
80c1a945f0 Revert "Trap set row and column on empty shet"
This reverts commit 1d5ec26b04.
2018-10-24 17:18:59 +01:00
jhoneill
1d5ec26b04 Trap set row and column on empty shet 2018-10-24 17:14:33 +01:00
Conrad Agramont
860b2724f5 Create AddMultiWorkSheet.ps1
This example shows how to add multiple tabs within the same file.
2018-10-23 10:01:29 -07:00
jhoneill
c38648a654 Fix for color not casting strings in PS Core 2018-10-22 17:21:09 +01:00
jhoneill
dcd730a4d1 Fixed stray char in addConditional formatting 2018-10-21 22:33:59 +01:00
jhoneill
0fdaeb977b Help updates after more proof-reading 2018-10-19 11:12:46 +01:00
jhoneill
61173d5e40 Updates after proof reading help 2018-10-17 11:23:15 +01:00
jhoneill
d26f0c66dd More PS6 friendly tests. Help and pos param tweaks in Conditional Fmt 2018-10-15 13:14:14 +01:00
dfinke
fe4fcff444 Added synopsis 2018-10-10 14:12:23 -04:00
jhoneill
01c58faea8 Color constants are now [color] objects, not string for V6 compat. 2018-10-10 10:36:36 +01:00
dfinke
dce2f6d108 Set switch -DontCreateZip 2018-10-09 20:05:38 -04:00
dfinke
49afad6977 added pwsh to run tests in 2018-10-09 19:59:48 -04:00
jhoneill
b7add5f9e1 Changed color default parameters away from strings 2018-10-09 23:01:55 +01:00
Doug Finke
c07fc81dfe Merge pull request #458 from jhoneill/master
Fixed #457 & a couple more tweaks
2018-10-08 17:05:41 -04:00
jhoneill
3835ceeebb Better parameter sets for merge. Fixed bug with setting font name. 2018-10-08 21:35:19 +01:00
Doug Finke
6683bed799 Merge pull request #455 from SQLvariant/master
Added Example for SQL Server
2018-10-08 14:47:27 -04:00
dfinke
20aade4bdd Add Switch $DontCreateZip 2018-10-08 14:17:09 -04:00
dfinke
b6965e0724 azure devops did *not* skip 2018-10-06 16:26:15 -04:00
dfinke
9d85c6cb81 test for azure build pipeline to skip the build 2018-10-06 16:25:12 -04:00
dfinke
a17fc95415 adde azure devops yaml file 2018-10-06 16:21:54 -04:00
dfinke
ecb045274a remove line from readme 2018-10-06 16:13:40 -04:00
dfinke
e5c4a715d6 see if appveyor skips after checking in the readme 2018-10-06 16:12:16 -04:00
dfinke
e27e98a9eb Added skip_commits section 2018-10-06 16:10:02 -04:00
Doug Finke
9da8bf8bf7 Merge pull request #456 from dbaileyut/dbaileyut-patch-fixTypo
* Fix typo in Import-Excel help description
2018-10-05 17:59:32 -04:00
dbaileyut
50905c7989 * Fix typo in Import-Excel help description 2018-10-05 16:04:19 -05:00
jhoneill
91a7c17341 perf: removed verbose from loop in import. tests: better alias check 2018-10-04 21:31:47 +01:00
Aaron Nelson
3c18af50b9 Added Example for SQL Server to Import-Excel
Added an example for INSERTing rows into a SQL Server table from the Import-Excel function.
2018-10-04 15:36:42 -04:00
jhoneill
66f5d09ace Better param sets in Merge-WS & conditional formatting in Merge-Multi 2018-10-04 20:13:33 +01:00
Aaron Nelson
fa64299760 Added Example for SQL Server
Added an example for running a query from a SQL Server database using the Invoke-Sqlcmd cmdlet, and then exporting the results to Excel.
2018-10-04 14:29:33 -04:00
Doug Finke
c36e5fb582 Merge pull request #454 from dfinke/FixPivotStyleName
Renamed PivotTableSyle to PivotTableStyle - fixes #453
2018-10-04 10:00:18 -04:00
dfinke
5158addc36 Hotfix for misnamed parameter 2018-10-04 09:57:22 -04:00
dfinke
bf2e37ac9f bumped version to 5.3.4 2018-10-04 09:57:04 -04:00
dfinke
d22d40cdc2 Renamed PivotTableSyle to PivotTableStyle - fixes #453 2018-10-03 19:26:37 -04:00
dfinke
df49e04c6c tweak readme 2018-10-03 08:38:58 -04:00
dfinke
f60ca87358 bumped version 2018-10-03 08:34:45 -04:00
dfinke
cef95f9ebe Added to the readme 2018-10-03 08:34:31 -04:00
Doug Finke
288071035f Merge pull request #450 from jhoneill/master
Readme only
2018-10-03 08:25:31 -04:00
jhoneill
414d1ac72b Git Markup stuck in Readme 2018-10-03 12:05:01 +01:00
jhoneill
1c7241774f Three extra lines in readme.md 2018-10-03 10:55:54 +01:00
jhoneill
7c773ff915 Three extra lines in Readme.MD 2018-10-03 10:54:15 +01:00
jhoneill
46de6c5934 Two extra lines in Readme.MD 2018-10-03 10:47:04 +01:00
Doug Finke
955c737bb7 Merge pull request #449 from jhoneill/master
Fix for bug handling null and zero; date format applied in send-sql
2018-10-02 16:58:22 -04:00
jhoneill
74e5fee161 Fixed bugs relating to handling of null. zero and empty string as data. 2018-10-02 21:15:16 +01:00
Doug Finke
c3331e8f09 Merge pull request #446 from lazywinadmin/master
Expand a few aliases
2018-10-01 20:18:42 -04:00
François-Xavier Cat
1951a61699 Expand a few aliases 2018-10-01 17:01:15 -07:00
jhoneill
5b29ccd9c2 Send-SQLDataToExcel applies formatting to date fields. 2018-09-30 22:49:35 +01:00
Doug Finke
d8bd5a8cb6 Merge pull request #444 from jhoneill/master
Minor improvements
2018-09-28 17:42:45 -04:00
Doug Finke
820722b481 Merge branch 'master' into master 2018-09-28 17:40:58 -04:00
Doug Finke
08c82977f5 Merge pull request #442 from dfinke/RenameToLegendPosition
Renamed LegendPostion to LegendPosition
2018-09-28 17:33:40 -04:00
jhoneill
a2dd42fc80 Blitz on spelling mistakes in help. Still not 100% proof-read. 2018-09-28 12:07:22 +01:00
jhoneill
c1d778ef85 Readme update 2018-09-27 15:05:07 +01:00
jhoneill
7abb5dde89 Updates to help text (more proof reading still needed) 2018-09-27 14:55:21 +01:00
jhoneill
0f15f3e3e5 fixed incorrect range in chart test 2018-09-27 12:26:43 +01:00
jhoneill
3194bb0ee4 Merge branch 'master' of https://github.com/jhoneill/ImportExcel 2018-09-27 12:24:31 +01:00
jhoneill
b1f716f0d5 Better handling of autonamerange including piping columns to Set-Column to do multiple ranges. 2018-09-27 12:24:23 +01:00
jhoneill
a8f7a13248 Better handling of autonamerange including piping columns to Set-Column to do multiple ranges. 2018-09-27 12:00:01 +01:00
dfinke
d200a2929b Added Azure-DevOps build tag 2018-09-26 18:47:58 -04:00
dfinke
99e69bd6c0 Renamed LegendPostion to LegendPosition 2018-09-26 16:32:10 -04:00
dfinke
4f0c0d7c28 bumped, fix for aliases 2018-09-20 13:58:13 -04:00
Doug Finke
968d5a57b6 Merge pull request #438 from dfinke/TestFunctionAliases
Added ps1 to for testing aliases
2018-09-20 12:33:06 -04:00
dfinke
bdefb45095 Remove space from Alias attribute 2018-09-20 12:12:53 -04:00
dfinke
4297d2ef82 Confirms the errors 2018-09-20 12:09:19 -04:00
dfinke
a49bdb3abc Added ps1 to for testing aliases 2018-09-20 12:01:34 -04:00
dfinke
a983ecd765 Move to using Robocopy and the /mir flag 2018-09-20 11:44:53 -04:00
dfinke
5a7d84e624 Added comment for usage 2018-09-20 10:22:36 -04:00
dfinke
e0f5d9f789 Removed these files - look unused 2018-09-20 10:22:27 -04:00
dfinke
7d3bcb810c bumped build # 2018-09-20 09:25:14 -04:00
dfinke
8975aa2e95 Added PivotTable.ps1 2018-09-20 09:24:50 -04:00
53 changed files with 1694 additions and 1231 deletions

4
.gitignore vendored
View File

@@ -2,6 +2,8 @@
Thumbs.db Thumbs.db
ehthumbs.db ehthumbs.db
*.gitignore
# Folder config file # Folder config file
Desktop.ini Desktop.ini
@@ -14,6 +16,8 @@ $RECYCLE.BIN/
*.msm *.msm
*.msp *.msp
*.dll
# Windows shortcuts # Windows shortcuts
*.lnk *.lnk

View File

@@ -32,3 +32,6 @@ enums
Numberformat Numberformat
ChartDefiniton ChartDefiniton
hashtables hashtables
Agramont
AGramont
Jhoneill

View File

@@ -1,46 +1,97 @@
Function Add-ConditionalFormatting { Function Add-ConditionalFormatting {
<# <#
.Synopsis .Synopsis
Adds contitional formatting to worksheet. Adds conditional formatting to all or part of a worksheet.
.Description .Description
Conditional formatting allows excel to Conditional formatting allows Excel to:
* Mark cells with Icons depending on their value * Mark cells with icons depending on their value
* Show a databar whose length indicates the value or a 2 or 3 color scale where the color indicate the relative value * Show a databar whose length indicates the value or a two or three color scale where the color indicates the relative value
* Change the color, font, or number format of cells which meet given criteria * Change the color, font, or number format of cells which meet given criteria
Add-ConditionalFormatting allows these to be set; for fine tuning of the rules you can use the -PassThru switch, Add-ConditionalFormatting allows these parameters to be set; for fine tuning of
which will return the rule so that you can modify things which are specific to that type of rule, the rules, the -PassThru switch will return the rule so that you can modify
for example the values which correspond to each icon in an Icon set. things which are specific to that type of rule, example, the values which
correspond to each icon in an Icon-Set.
.Example .Example
> >
PS> $excel = $avdata | Export-Excel -Path (Join-path $FilePath "\Machines.XLSX" ) -WorksheetName "Server Anti-Virus" -AutoSize -FreezeTopRow -AutoFilter -PassThru $excel = $avdata | Export-Excel -Path (Join-path $FilePath "\Machines.XLSX" ) -WorksheetName "Server Anti-Virus" -AutoSize -FreezeTopRow -AutoFilter -PassThru
Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "b2:b1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "2003" Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "b2:b1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "2003"
Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "i2:i1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "Disabled" Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Address "i2:i1048576" -ForeGroundColor "RED" -RuleType ContainsText -ConditionValue "Disabled"
$excel.Workbook.Worksheets[1].Cells["D1:G1048576"].Style.Numberformat.Format = [cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern $excel.Workbook.Worksheets[1].Cells["D1:G1048576"].Style.Numberformat.Format = [cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern
$excel.Workbook.Worksheets[1].Row(1).style.font.bold = $true $excel.Workbook.Worksheets[1].Row(1).style.font.bold = $true
$excel.Save() ; $excel.Dispose() $excel.Save() ; $excel.Dispose()
Here Export-Excel is called with the -passThru parameter so the Excel Package object is stored in $Excel Here Export-Excel is called with the -PassThru parameter so the ExcelPackage object
The desired worksheet is selected and the then columns B and i are conditially formatted (excluding the top row) to show red text if representing Machines.XLSX is stored in $Excel.The desired worksheet is selected
the columns contain "2003" or "Disabled respectively. A fixed date format is then applied to columns D..G, and the top row is formatted. and then columns" B" and "I" are conditionally formatted (excluding the top row)
Finally the workbook is saved and the Excel object closed. to show red text if they contain "2003" or "Disabled" respectively.
A fixed date format is then applied to columns D to G, and the top row is formatted.
Finally the workbook is saved and the Excel package object is closed.
.Example .Example
> >
>PS $r = Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Range "B1:B100" -ThreeIconsSet Flags -Passthru $r = Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets[1] -Range "B1:B100" -ThreeIconsSet Flags -Passthru
$r.Reverse = $true ; $r.Icon1.Type = "Num"; $r.Icon2.Type = "Num" ; $r.Icon2.value = 100 ; $r.Icon3.type = "Num" ;$r.Icon3.value = 1000 $r.Reverse = $true ; $r.Icon1.Type = "Num"; $r.Icon2.Type = "Num" ; $r.Icon2.value = 100 ; $r.Icon3.type = "Num" ;$r.Icon3.value = 1000
Again Export-Excel has been called with -passthru leaving a package object in $Excel Again Export-Excel has been called with -PassThru leaving a package object
This time B1:B100 has been conditionally formatted with 3 icons, using the flags icon set. in $Excel. This time B1:B100 has been conditionally formatted with 3 icons,
Add-ConditionalFormatting does not provide access to every option in the formatting rule, so passthru has been used and the using the "Flags" Icon-Set. Add-ConditionalFormatting does not provide access
rule is to apply the flags in reverse order, and boundaries for the number which will set the split are set to 100 and 1000 to every option in the formatting rule, so -PassThru has been used and the
rule is modified to apply the flags in reverse order, and transitions
between flags are set to 100 and 1000.
.Example .Example
Add-ConditionalFormatting -WorkSheet $sheet -Range "D2:D1048576" -DataBarColor Red Add-ConditionalFormatting -WorkSheet $sheet -Range "D2:D1048576" -DataBarColor Red
This time $sheet holds an ExcelWorkseet object and databars are add to all of column D except for the tip row. This time $sheet holds an ExcelWorkshseet object and databars are added to
column D, excluding the top row.
.Example .Example
Add-ConditionalFormatting -Address $worksheet.cells["FinishPosition"] -RuleType Equal -ConditionValue 1 -ForeGroundColor Purple -Bold -Priority 1 -StopIfTrue Add-ConditionalFormatting -Address $worksheet.cells["FinishPosition"] -RuleType Equal -ConditionValue 1 -ForeGroundColor Purple -Bold -Priority 1 -StopIfTrue
In this example a named range is used to select the cells where the formula should apply. If a cell in the "FinishPosition" range is 1, then the text is turned to puple, boldface. In this example a named range is used to select the cells where the condition
This rule is move to first in the priority list, and where cells have a value of 1, no other rules will be processed. should apply, and instead of specifying a sheet and range within the sheet as
separate parameters, the cells where the format should apply are specified
directly. If a cell in the "FinishPosition" range is 1, then the text is
turned to Bold & Purple. This rule is moved to first in the priority list,
and where cells have a value of 1, no other rules will be processed.
.Example
>
$excel = Get-ChildItem | Select-Object -Property Name,Length,LastWriteTime,CreationTime | Export-Excel "$env:temp\test43.xlsx" -PassThru -AutoSize
$ws = $excel.Workbook.Worksheets["Sheet1"]
$ws.Cells["E1"].Value = "SavedAt"
$ws.Cells["F1"].Value = [datetime]::Now
$ws.Cells["F1"].Style.Numberformat.Format = (Expand-NumberFormat -NumberFormat 'Date-Time')
$lastRow = $ws.Dimension.End.Row
Add-ConditionalFormatting -WorkSheet $ws -address "A2:A$Lastrow" -RuleType LessThan -ConditionValue "A" -ForeGroundColor Gray
Add-ConditionalFormatting -WorkSheet $ws -address "B2:B$Lastrow" -RuleType GreaterThan -ConditionValue 1000000 -NumberFormat '#,###,,.00"M"'
Add-ConditionalFormatting -WorkSheet $ws -address "C2:C$Lastrow" -RuleType GreaterThan -ConditionValue "=INT($F$1-7)" -ForeGroundColor Green -StopIfTrue
Add-ConditionalFormatting -WorkSheet $ws -address "D2:D$Lastrow" -RuleType Equal -ConditionValue "=C2" -ForeGroundColor Blue -StopIfTrue
Close-ExcelPackage -Show $excel
The first few lines of code export a list of file and directory names, sizes
and dates to a spreadsheet. It puts the date of the export in cell F1.
The first Conditional format changes the color of files and folders that begin
with a ".", "_" or anything else which sorts before "A".
The second Conditional format changes the Number format of numbers bigger than
1 million, for example 1,234,567,890 will dispay as "1,234.57M"
The third highlights datestamps of files less than a week old when the export
was run; the = is necessary in the condition value otherwise the rule will
look for the the text INT($F$1-7), and the cell address for the date is fixed
using the standard Excel $ notation.
The final Conditional format looks for files which have not changed since they
were created. Here the condition value is "=C2". The = sign means C2 is treated
as a formula, not literal text. Unlike the file age, we want the cell used to
change for each cell where the conditional format applies. The first cell in
the conditional format range is D2, which is compared against C2, then D3 is
compared against C3 and so on. A common mistake is to include the title row in
the range and accidentally apply conditional formatting to it, or to begin the
range at row 2 but use row 1 as the starting point for comparisons.
.Example
Add-ConditionalFormatting $ws.Cells["B:B"] GreaterThan 10000000 -Fore Red -Stop -Pri 1
This version shows the shortest syntax - the Address, Ruletype, and
Conditionvalue can be identified from their position, and ForegroundColor,
StopIfTrue and Priority can all be shortend.
#> #>
Param ( Param (
#A block of cells to format - you can use a named range with -Address $ws.names[1] or $ws.cells["RangeName"] #A block of cells to format - you can use a named range with -Address $ws.names[1] or $ws.cells["RangeName"]
@@ -49,17 +100,17 @@
$Address , $Address ,
#The worksheet where the format is to be applied #The worksheet where the format is to be applied
[OfficeOpenXml.ExcelWorksheet]$WorkSheet , [OfficeOpenXml.ExcelWorksheet]$WorkSheet ,
#One of the standard named rules - Top / Bottom / Less than / Greater than / Contains etc. #A standard named-rule - Top / Bottom / Less than / Greater than / Contains etc.
[Parameter(Mandatory = $true, ParameterSetName = "NamedRule", Position = 1)] [Parameter(Mandatory = $true, ParameterSetName = "NamedRule", Position = 1)]
[OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType]$RuleType , [OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType]$RuleType ,
#Text colour for matching objects #Text color for matching objects
[Parameter(ParameterSetName = "NamedRule")] [Parameter(ParameterSetName = "NamedRule")]
[Alias("ForeGroundColour")] [Alias("ForegroundColour")]
[System.Drawing.Color]$ForeGroundColor, $ForegroundColor,
#colour for databar type charts #Color for databar type charts
[Parameter(Mandatory = $true, ParameterSetName = "DataBar")] [Parameter(Mandatory = $true, ParameterSetName = "DataBar")]
[Alias("DataBarColour")] [Alias("DataBarColour")]
[System.Drawing.Color]$DataBarColor, $DataBarColor,
#One of the three-icon set types (e.g. Traffic Lights) #One of the three-icon set types (e.g. Traffic Lights)
[Parameter(Mandatory = $true, ParameterSetName = "ThreeIconSet")] [Parameter(Mandatory = $true, ParameterSetName = "ThreeIconSet")]
[OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting3IconsSetType]$ThreeIconsSet, [OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting3IconsSetType]$ThreeIconsSet,
@@ -69,27 +120,27 @@
#A five-icon set name #A five-icon set name
[Parameter(Mandatory = $true, ParameterSetName = "FiveIconSet")] [Parameter(Mandatory = $true, ParameterSetName = "FiveIconSet")]
[OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting5IconsSetType]$FiveIconsSet, [OfficeOpenXml.ConditionalFormatting.eExcelconditionalFormatting5IconsSetType]$FiveIconsSet,
#Use the icon set in reverse order, or reverse the orders of Two- & Three-Color Scales #Use the Icon-Set in reverse order, or reverse the orders of Two- & Three-Color Scales
[Parameter(ParameterSetName = "NamedRule")] [Parameter(ParameterSetName = "NamedRule")]
[Parameter(ParameterSetName = "ThreeIconSet")] [Parameter(ParameterSetName = "ThreeIconSet")]
[Parameter(ParameterSetName = "FourIconSet")] [Parameter(ParameterSetName = "FourIconSet")]
[Parameter(ParameterSetName = "FiveIconSet")] [Parameter(ParameterSetName = "FiveIconSet")]
[switch]$Reverse, [switch]$Reverse,
#A value for the condition (e.g. 2000 if the test is 'lessthan 2000' ; Formulas should begin with "=" ) #A value for the condition (for example 2000 if the test is 'lessthan 2000'; Formulas should begin with "=" )
[Parameter(ParameterSetName = "NamedRule")] [Parameter(ParameterSetName = "NamedRule",Position = 2)]
$ConditionValue, $ConditionValue,
#A second value for the conditions like "between x and Y" #A second value for the conditions like "Between X and Y"
[Parameter(ParameterSetName = "NamedRule")] [Parameter(ParameterSetName = "NamedRule",Position = 3)]
$ConditionValue2, $ConditionValue2,
#Background colour for matching items #Background color for matching items
[Parameter(ParameterSetName = "NamedRule")] [Parameter(ParameterSetName = "NamedRule")]
[System.Drawing.Color]$BackgroundColor, $BackgroundColor,
#Background pattern for matching items #Background pattern for matching items
[Parameter(ParameterSetName = "NamedRule")] [Parameter(ParameterSetName = "NamedRule")]
[OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::None , [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::None ,
#Secondary colour when a background pattern requires it #Secondary color when a background pattern requires it
[Parameter(ParameterSetName = "NamedRule")] [Parameter(ParameterSetName = "NamedRule")]
[System.Drawing.Color]$PatternColor, $PatternColor,
#Sets the numeric format for matching items #Sets the numeric format for matching items
[Parameter(ParameterSetName = "NamedRule")] [Parameter(ParameterSetName = "NamedRule")]
$NumberFormat, $NumberFormat,
@@ -108,10 +159,10 @@
#Prevent the processing of subsequent rules #Prevent the processing of subsequent rules
[Parameter(ParameterSetName = "NamedRule")] [Parameter(ParameterSetName = "NamedRule")]
[switch]$StopIfTrue, [switch]$StopIfTrue,
#Set the sequence for rule processong #Set the sequence for rule processing
[int]$Priority, [int]$Priority,
#If specified pass the rule back to the caller to allow additional customization. #If specified pass the rule back to the caller to allow additional customization.
[switch]$Passthru [switch]$PassThru
) )
#Allow conditional formatting to work like Set-ExcelRange (with single ADDRESS parameter), split it to get worksheet and range of cells. #Allow conditional formatting to work like Set-ExcelRange (with single ADDRESS parameter), split it to get worksheet and range of cells.
@@ -141,11 +192,13 @@
#By this point we should have a worksheet object whose ConditionalFormatting collection we will add to. If not, bail. #By this point we should have a worksheet object whose ConditionalFormatting collection we will add to. If not, bail.
if (-not $worksheet -or $WorkSheet -isnot [OfficeOpenXml.ExcelWorksheet]) {write-warning "You need to provide a worksheet object." ; return} if (-not $worksheet -or $WorkSheet -isnot [OfficeOpenXml.ExcelWorksheet]) {write-warning "You need to provide a worksheet object." ; return}
#region create a rule of the right type #region create a rule of the right type
if ($RuleType -match 'IconSet$') {Write-warning -Message "You cannot configure a IconSet rule in this way; please use -$RuleType <SetName>." ; return} if ($RuleType -match 'IconSet$') {Write-warning -Message "You cannot configure a Icon-Set rule in this way; please use -$RuleType <SetName>." ; return}
if ($PSBoundParameters.ContainsKey("ThreeIconsSet" ) ) {$rule = $WorkSheet.ConditionalFormatting.AddThreeIconSet($Address , $ThreeIconsSet)} if ($PSBoundParameters.ContainsKey("DataBarColor" ) ) {if ($DataBarColor -is [string]) {$DataBarColor = [System.Drawing.Color]::$DataBarColor }
$rule = $WorkSheet.ConditionalFormatting.AddDatabar( $Address , $DataBarColor )
}
elseif ($PSBoundParameters.ContainsKey("ThreeIconsSet" ) ) {$rule = $WorkSheet.ConditionalFormatting.AddThreeIconSet($Address , $ThreeIconsSet)}
elseif ($PSBoundParameters.ContainsKey("FourIconsSet" ) ) {$rule = $WorkSheet.ConditionalFormatting.AddFourIconSet( $Address , $FourIconsSet )} elseif ($PSBoundParameters.ContainsKey("FourIconsSet" ) ) {$rule = $WorkSheet.ConditionalFormatting.AddFourIconSet( $Address , $FourIconsSet )}
elseif ($PSBoundParameters.ContainsKey("FiveIconsSet" ) ) {$rule = $WorkSheet.ConditionalFormatting.AddFiveIconSet( $Address , $FiveIconsSet )} elseif ($PSBoundParameters.ContainsKey("FiveIconsSet" ) ) {$rule = $WorkSheet.ConditionalFormatting.AddFiveIconSet( $Address , $FiveIconsSet )}
elseif ($PSBoundParameters.ContainsKey("DataBarColor" ) ) {$rule = $WorkSheet.ConditionalFormatting.AddDatabar( $Address , $DataBarColor )}
else {$rule = ($WorkSheet.ConditionalFormatting)."Add$RuleType"($Address ) } else {$rule = ($WorkSheet.ConditionalFormatting)."Add$RuleType"($Address ) }
if ($Reverse) { if ($Reverse) {
if ($rule.type -match 'IconSet$' ) {$rule.reverse = $true} if ($rule.type -match 'IconSet$' ) {$rule.reverse = $true}
@@ -156,7 +209,7 @@
#region set the rule conditions #region set the rule conditions
#for lessThan/GreaterThan/Equal/Between conditions make sure that strings are wrapped in quotes. Formulas should be passed with = which will be stripped. #for lessThan/GreaterThan/Equal/Between conditions make sure that strings are wrapped in quotes. Formulas should be passed with = which will be stripped.
if ($RuleType -match "Than|Equal|Between" ) { if ($RuleType -match "Than|Equal|Between" ) {
if ($ConditionValue) { if ($PSBoundParameters.ContainsKey("ConditionValue" )) {
$number = $Null $number = $Null
#if the condition type is not a value type, but parses as a number, make it the number #if the condition type is not a value type, but parses as a number, make it the number
if ($ConditionValue -isnot [System.ValueType] -and [Double]::TryParse($ConditionValue, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number) ) { if ($ConditionValue -isnot [System.ValueType] -and [Double]::TryParse($ConditionValue, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number) ) {
@@ -166,7 +219,7 @@
$ConditionValue = '"' + $ConditionValue +'"' $ConditionValue = '"' + $ConditionValue +'"'
} }
} }
if ($ConditionValue2) { if ($PSBoundParameters.ContainsKey("ConditionValue2")) {
$number = $Null $number = $Null
if ($ConditionValue -isnot [System.ValueType] -and [Double]::TryParse($ConditionValue2, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number) ) { if ($ConditionValue -isnot [System.ValueType] -and [Double]::TryParse($ConditionValue2, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number) ) {
$ConditionValue2 = $number $ConditionValue2 = $number
@@ -204,10 +257,13 @@
if ($PSBoundParameters.ContainsKey("Bold" ) ) {$rule.Style.Font.Bold = [boolean]$Bold } if ($PSBoundParameters.ContainsKey("Bold" ) ) {$rule.Style.Font.Bold = [boolean]$Bold }
if ($PSBoundParameters.ContainsKey("Italic" ) ) {$rule.Style.Font.Italic = [boolean]$Italic } if ($PSBoundParameters.ContainsKey("Italic" ) ) {$rule.Style.Font.Italic = [boolean]$Italic }
if ($PSBoundParameters.ContainsKey("StrikeThru" ) ) {$rule.Style.Font.Strike = [boolean]$StrikeThru } if ($PSBoundParameters.ContainsKey("StrikeThru" ) ) {$rule.Style.Font.Strike = [boolean]$StrikeThru }
if ($PSBoundParameters.ContainsKey("ForeGroundColor" ) ) {$rule.Style.Font.Color.color = $ForeGroundColor } if ($PSBoundParameters.ContainsKey("ForeGroundColor" ) ) {if ($ForeGroundColor -is [string]) {$ForeGroundColor = [System.Drawing.Color]::$ForeGroundColor }
if ($PSBoundParameters.ContainsKey("BackgroundColor" ) ) {$rule.Style.Fill.BackgroundColor.color = $BackgroundColor } $rule.Style.Font.Color.color = $ForeGroundColor }
if ($PSBoundParameters.ContainsKey("BackgroundColor" ) ) {if ($BackgroundColor -is [string]) {$BackgroundColor = [System.Drawing.Color]::$BackgroundColor }
$rule.Style.Fill.BackgroundColor.color = $BackgroundColor }
if ($PSBoundParameters.ContainsKey("BackgroundPattern") ) {$rule.Style.Fill.PatternType = $BackgroundPattern } if ($PSBoundParameters.ContainsKey("BackgroundPattern") ) {$rule.Style.Fill.PatternType = $BackgroundPattern }
if ($PSBoundParameters.ContainsKey("PatternColor" ) ) {$rule.Style.Fill.PatternColor.color = $PatternColor } if ($PSBoundParameters.ContainsKey("PatternColor" ) ) {if ($PatternColor -is [string]) {$PatternColor = [System.Drawing.Color]::$PatternColor }
$rule.Style.Fill.PatternColor.color = $PatternColor }
#endregion #endregion
#Allow further tweaking by returning the rule, if passthru specified #Allow further tweaking by returning the rule, if passthru specified
if ($Passthru) {$rule} if ($Passthru) {$rule}

View File

@@ -15,6 +15,7 @@ if (Get-Command -Name register-argumentCompleter -ErrorAction SilentlyContinue)
Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName FontColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName FontColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName TabColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Compare-Worksheet -ParameterName TabColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Join-Worksheet -ParameterName TitleBackgroundColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Merge-Worksheet -ParameterName AddBackgroundColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Merge-Worksheet -ParameterName AddBackgroundColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Merge-Worksheet -ParameterName ChangeBackgroundColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Merge-Worksheet -ParameterName ChangeBackgroundColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Merge-Worksheet ` -ParameterName DeleteBackgroundColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Merge-Worksheet ` -ParameterName DeleteBackgroundColor -ScriptBlock $Function:ColorCompletion
@@ -36,4 +37,5 @@ if (Get-Command -Name register-argumentCompleter -ErrorAction SilentlyContinue)
Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName BackgroundColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName FontColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName FontColor -ScriptBlock $Function:ColorCompletion
Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion Register-ArgumentCompleter -CommandName Set-ExcelRow -ParameterName PatternColor -ScriptBlock $Function:ColorCompletion
} }

View File

@@ -1,18 +1,21 @@
Function ConvertTo-ExcelXlsx { Function ConvertTo-ExcelXlsx {
[CmdletBinding()] <#
.SYNOPSIS
Converts an Excel xls to a xlsx using -ComObject
#>
[CmdletBinding()]
Param Param
( (
[parameter(Mandatory=$true, ValueFromPipeline)] [parameter(Mandatory = $true, ValueFromPipeline)]
[string]$Path, [string]$Path,
[parameter(Mandatory=$false)] [parameter(Mandatory = $false)]
[switch]$Force [switch]$Force
) )
Process Process {
{ if (-Not ($Path | Test-Path) ) {
if(-Not ($Path | Test-Path) ){
throw "File not found" throw "File not found"
} }
if(-Not ($Path | Test-Path -PathType Leaf) ){ if (-Not ($Path | Test-Path -PathType Leaf) ) {
throw "Folder paths are not allowed" throw "Folder paths are not allowed"
} }
@@ -20,26 +23,29 @@ Function ConvertTo-ExcelXlsx {
$xlsFile = Get-Item -Path $Path $xlsFile = Get-Item -Path $Path
$xlsxPath = "{0}x" -f $xlsFile.FullName $xlsxPath = "{0}x" -f $xlsFile.FullName
if($xlsFile.Extension -ne ".xls"){ if ($xlsFile.Extension -ne ".xls") {
throw "Expected .xls extension" throw "Expected .xls extension"
} }
if(Test-Path -Path $xlsxPath){ if (Test-Path -Path $xlsxPath) {
if($Force){ if ($Force) {
try { try {
Remove-Item $xlsxPath -Force Remove-Item $xlsxPath -Force
} catch { }
catch {
throw "{0} already exists and cannot be removed. The file may be locked by another application." -f $xlsxPath throw "{0} already exists and cannot be removed. The file may be locked by another application." -f $xlsxPath
} }
Write-Verbose $("Removed {0}" -f $xlsxPath) Write-Verbose $("Removed {0}" -f $xlsxPath)
} else { }
else {
throw "{0} already exists!" -f $xlsxPath throw "{0} already exists!" -f $xlsxPath
} }
} }
try{ try {
$Excel = New-Object -ComObject "Excel.Application" $Excel = New-Object -ComObject "Excel.Application"
} catch { }
catch {
throw "Could not create Excel.Application ComObject. Please verify that Excel is installed." throw "Could not create Excel.Application ComObject. Please verify that Excel is installed."
} }

View File

@@ -1,13 +1,23 @@
param(
[Switch]$DontCreateZip
)
##
# Used in Appveyor.yml
##
$PSVersionTable.PSVersion $PSVersionTable.PSVersion
## Create the zip before the tests run ## Create the zip before the tests run
## Otherwise the EPPlus.dll is in use after the Pester run ## Otherwise the EPPlus.dll is in use after the Pester run
$ModuleVersion = (Get-Content -Raw .\ImportExcel.psd1) | Invoke-Expression | ForEach-Object ModuleVersion $ModuleVersion = (Get-Content -Raw .\ImportExcel.psd1) | Invoke-Expression | ForEach-Object ModuleVersion
$dest = "ImportExcel-{0}-{1}.zip" -f $ModuleVersion, (Get-Date).ToString("yyyyMMddHHmmss") if (!$DontCreateZip) {
Compress-Archive -Path . -DestinationPath .\$dest $dest = "ImportExcel-{0}-{1}.zip" -f $ModuleVersion, (Get-Date).ToString("yyyyMMddHHmmss")
Compress-Archive -Path . -DestinationPath .\$dest
}
if ((Get-Module -ListAvailable pester) -eq $null) { if ($null -eq (Get-Module -ListAvailable pester)) {
Install-Module -Name Pester -Repository PSGallery -Force -Scope CurrentUser Install-Module -Name Pester -Repository PSGallery -Force -Scope CurrentUser
} }

View File

@@ -0,0 +1,15 @@
try {. $PSScriptRoot\..\..\LoadPSD1.ps1} catch {}
$xlSourcefile = "$env:TEMP\Source.xlsx"
write-host "Save location: $xlSourcefile"
Remove-Item $xlSourcefile -ErrorAction Ignore
#Put some simple data in a worksheet and Get an excel package object to represent the file
$TabData1 = 1..5 | Export-Excel $xlSourcefile -WorksheetName 'Tab 1' -AutoSize -AutoFilter
#Add another tab. Replace the $TabData2 with your data
$TabData2 = 1..10 | Export-Excel $xlSourcefile -WorksheetName 'Tab 2' -AutoSize -AutoFilter
#Add another tab. Replace the $TabData3 with your data
$TabData3 = 1..15 | Export-Excel $xlSourcefile -WorksheetName 'Tab 3' -AutoSize -AutoFilter -Show

View File

@@ -1,5 +1,5 @@
echo Last7Days LastMonth LastWeek NextMonth NextWeek ThisMonth ThisWeek Today Tomorrow Yesterday | echo Last7Days LastMonth LastWeek NextMonth NextWeek ThisMonth ThisWeek Today Tomorrow Yesterday |
% { Foreach-Object {
$text = @" $text = @"
`$f = ".\testExport.xlsx" `$f = ".\testExport.xlsx"

View File

@@ -8,7 +8,7 @@
$sign=@{sign=echo + -} $sign=@{sign=echo + -}
$location=@{location=echo Atlanta Newark Washington Chicago Philadelphia Houston Phoneix} $location=@{location=echo Atlanta Newark Washington Chicago Philadelphia Houston Phoneix}
$(1..6 | % { $(1..6 | Foreach-Object {
$from=$to="" $from=$to=""
while($from -eq $to) { while($from -eq $to) {

View File

@@ -1,15 +1,41 @@
Remove-item -path ~\documents\music.xlsx #requires -modules "Get-IndexedItem"
$excel = Get-IndexedItem "itemtype='.mp3'","AlbumArtist like '%'","RatingText <> '1 star'" -NoFiles -orderby AlbumArtist,AlbumTitle,TrackNumber -path c:\users -Recurse -Property AlbumArtist,Duration,title,EncodingBitrate,SampleRate,AlbumTitle,TrackNumber, Size | [cmdletbinding()]
Select-Object -Property AlbumArtist, AlbumTitle, TrackNumber, Title, Duration, SampleRate, EncodingBitRate, Size | Export-excel -path ~\documents\music.xlsx -WorksheetName Music -AutoNameRange -AutoSize -BoldTopRow -FreezeTopRow -PassThru Param()
$ws = $excel.Workbook.Worksheets[1] Remove-Item ~\documents\music.xlsx -ErrorAction SilentlyContinue
Set-ExcelColumn -Worksheet $ws -Column 6 -NumberFormat '0,"KHz"' [System.Diagnostics.Stopwatch]$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
Set-ExcelColumn -Worksheet $ws -Column 7 -NumberFormat '0,"Kbits/Sec"' -Width 18
Set-ExcelColumn -Worksheet $ws -Column 8 -NumberFormat '#.#,,"MB"' -Width 7
$pt = Add-PivotTable -PivotTableName SpaceUsedByMusic -ExcelPackage $excel -SourceWorkSheet $ws -PivotRows ALBUMARTIST -PivotData @{"Size"="Sum"} -PivotNumberFormat '#.#,,"MB"' -Activate -PassThru
$pt.RowFields[0].Sort = [OfficeOpenXml.Table.PivotTable.eSortType]::Ascending
$a = $ws.Dimension.address #Query system index for .MP3 files in C:\Users, where album artist is non-blank. Leave sorted table with columns of interest in $Music.
Add-ExcelTable -Range $ws.cells[$a] -TableStyle Light1 -TableName Musictable -ShowFilter:$false -ShowTotal -ShowFirstColumn
Add-ConditionalFormatting -Address $ws.Names[1] -RuleType ContainsText -ConditionValue "Hits" -ForeGroundColor Blue Get-IndexedItem "itemtype='.mp3'","AlbumArtist like '%'" -Recurse C:\Users -OutputVariable Music `
Add-ConditionalFormatting -Address $ws.Cells["Albumartist"] -RuleType ContainsText -ConditionValue "Numan" -ForeGroundColor red -OrderBy AlbumArtist, AlbumTitle, TrackNumber, Title -NoFiles `
-Property AlbumArtist, AlbumTitle, TrackNumber, Title, Duration, Size, SampleRate
Write-Verbose -Message ("Fetched " + $music.Rows.Count + " rows from index: " + $stopwatch.Elapsed.TotalSeconds)
#Send Table in $Music to Excel, format as a table, point $ws to the Worksheet
$excel = Send-SQLDataToExcel -Path ~\documents\music.xlsx -DataTable $music -WorkSheetname Music -TableName Music -Passthru
Write-Verbose -Message ("Inserted into Excel: " + $stopwatch.Elapsed.TotalSeconds)
$ws = $excel.Music
#Strip "SYSTEM.", "SYSTEM.AUDIO", "SYSTEM.MEDIA", "SYSTEM.MUSIC" from the column headings
#Convert Duration (column 5) from 100ns ticks to days and format as minutes, seconds, decimal
#Format filesize and sample rate nicely
#Autofit the columns.
Set-ExcelRow -Worksheet $ws -Row 1 -Value {($worksheet.cells[$row,$column].value -replace '^SYSTEM\.','') -replace '^MEDIA\.|^AUDIO\.|^MUSIC\.','' }
Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'mm:ss.0' -StartRow 2 -Value {$worksheet.cells[$row,$column].value / 864000000000 }
Write-Verbose -Message ("Cells Reset: " + $stopwatch.Elapsed.TotalSeconds)
Set-Column -Worksheet $ws -Column 6 -NumberFormat '#.#,,"MB"'
Set-ExcelColumn -Worksheet $ws -Column 7 -NumberFormat '0.0,"KHz"'
$ws.Cells[$ws.Dimension].AutoFitColumns()
#Make a Pivot table for sum of space and count of tracks by artist. Sort by artist, apply formatting to space, give it nice titles.
$pt = Add-PivotTable -PassThru -PivotTableName SpaceUsedByMusic -ExcelPackage $excel -SourceWorkSheet $ws `
-PivotRows ALBUMARTIST -PivotData ([ordered]@{"Size"="Sum"; "Duration"="Count"}) -PivotDataToColumn
$pt.RowFields[0].Sort = [OfficeOpenXml.Table.PivotTable.eSortType]::Ascending
$pt.DataFields[0].Format = '#.0,,"MB"'
$pt.DataFields[0].Name = 'Space Used'
$pt.DataFields[1].Name = 'Tracks'
#Save the file, and load it into Excel
$stopwatch.Stop()
Write-Verbose -Message ("Pivot Done: " + $stopwatch.Elapsed.TotalSeconds)
Close-ExcelPackage -show $excel Close-ExcelPackage -show $excel

View File

@@ -15,12 +15,12 @@ Apple, New York, 1200,700
#Add a pivot table, specify its address to put it on the same sheet, use the data that was just exported set the table style and number format. #Add a pivot table, specify its address to put it on the same sheet, use the data that was just exported set the table style and number format.
#Use the "City" for the row names, and "Product" for the columnnames, and sum both the gross and net values for each City/Product combination; add grand totals to rows and columns. #Use the "City" for the row names, and "Product" for the columnnames, and sum both the gross and net values for each City/Product combination; add grand totals to rows and columns.
# activate the sheet and add a pivot chart (defined in a hash table) # activate the sheet and add a pivot chart (defined in a hash table)
Add-PivotTable -Address $excel.Sheet1.Cells["F1"] -SourceWorkSheet $Excel.Sheet1 -SourceRange $Excel.Sheet1.Dimension.Address -PivotTableName "Sales" -PivotTableSyle "Medium12" -PivotNumberFormat "$#,##0.00" ` Add-PivotTable -Address $excel.Sheet1.Cells["F1"] -SourceWorkSheet $Excel.Sheet1 -SourceRange $Excel.Sheet1.Dimension.Address -PivotTableName "Sales" -PivotTableStyle "Medium12" -PivotNumberFormat "$#,##0.00" `
-PivotRows "City" -PivotColumns "Product" -PivotData @{Gross="Sum";Net="Sum"}-PivotTotals "Both" -Activate -PivotChartDefinition @{ -PivotRows "City" -PivotColumns "Product" -PivotData @{Gross="Sum";Net="Sum"}-PivotTotals "Both" -Activate -PivotChartDefinition @{
Title="Gross and net by city and product"; Title="Gross and net by city and product";
ChartType="ColumnClustered"; ChartType="ColumnClustered";
Column=11; Width=500; Height=360; Column=11; Width=500; Height=360;
YMajorUnit=500; YMinorUnit=100; YAxisNumberformat="$#,##0" YMajorUnit=500; YMinorUnit=100; YAxisNumberformat="$#,##0"
LegendPostion="Bottom"} LegendPosition="Bottom"}
#Save and open in excel #Save and open in excel
Close-ExcelPackage $excel -Show Close-ExcelPackage $excel -Show

View File

@@ -1,6 +1,6 @@
try {. $PSScriptRoot\..\..\LoadPSD1.ps1} catch {} try {. $PSScriptRoot\..\..\LoadPSD1.ps1} catch {}
$plt = New-Plot $plt = New-Plot
$plt.Plot((Get-Range 0 5 .02|%{[math]::Cos(2*[math]::pi*$_)})) $plt.Plot((Get-Range 0 5 .02|Foreach-Object {[math]::Cos(2*[math]::pi*$_)}))
$plt.SetChartSize(800,300) $plt.SetChartSize(800,300)
$plt.Show() $plt.Show()

View File

@@ -1,5 +1,7 @@
try {. $PSScriptRoot\..\..\LoadPSD1.ps1} catch {} #requires -modules "getSql"
try {. $PSScriptRoot\..\..\LoadPSD1.ps1} catch {}
#download f1Results from https://1drv.ms/f/s!AhfYu7-CJv4egbt5FD7Cdxi8jSz3aQ and update the path below
Get-SQL -Session f1 -Excel -Connection C:\Users\mcp\OneDrive\Public\F1\f1Results.xlsx -showtables -Verbose Get-SQL -Session f1 -Excel -Connection C:\Users\mcp\OneDrive\Public\F1\f1Results.xlsx -showtables -Verbose
Remove-Item .\demo3.xlsx Remove-Item .\demo3.xlsx

View File

@@ -2,6 +2,6 @@ try {. $PSScriptRoot\..\..\LoadPSD1.ps1} catch {}
. $PSScriptRoot\TestAPIReadXls.ps1 . $PSScriptRoot\TestAPIReadXls.ps1
Test-APIReadXls $PSScriptRoot\testlist.xlsx | % { Test-APIReadXls $PSScriptRoot\testlist.xlsx | Foreach-Object {
Invoke-Pester -Script $_.fullname -PassThru -Show None Invoke-Pester -Script $_.fullname -PassThru -Show None
} }

View File

@@ -1,21 +1,25 @@
function Export-Excel { function Export-Excel {
<# <#
.SYNOPSIS .SYNOPSIS
Export data to an Excel worksheet. Exports data to an Excel worksheet.
.DESCRIPTION .DESCRIPTION
Export data to an Excel file and where possible try to convert numbers so Excel recognizes them as numbers instead of text. After all. Excel is a spreadsheet program used for number manipulation and calculations. In case the number conversion is not desired, use the parameter '-NoNumberConversion *'. Exports data to an Excel file and where possible tries to convert numbers
in text fields so Excel recognizes them as numbers instead of text.
After all: Excel is a spreadsheet program used for number manipulation
and calculations. If number conversion is not desired, use the
parameter -NoNumberConversion *.
.PARAMETER Path .PARAMETER Path
Path to a new or existing .XLSX file. Path to a new or existing .XLSX file.
.PARAMETER ExcelPackage .PARAMETER ExcelPackage
An object representing an Excel Package - usually this is returned by specifying -Passthru allowing multiple commands to work on the same Workbook without saving and reloading each time. An object representing an Excel Package - usually this is returned by specifying -PassThru allowing multiple commands to work on the same workbook without saving and reloading each time.
.PARAMETER WorksheetName .PARAMETER WorksheetName
The name of a sheet within the workbook - "Sheet1" by default. The name of a sheet within the workbook - "Sheet1" by default.
.PARAMETER ClearSheet .PARAMETER ClearSheet
If specified Export-Excel will remove any existing worksheet with the selected name. The Default behaviour is to overwrite cells in this sheet as needed (but leaving non-overwritten ones in place). If specified Export-Excel will remove any existing worksheet with the selected name. The Default behaviour is to overwrite cells in this sheet as needed (but leaving non-overwritten ones in place).
.PARAMETER Append .PARAMETER Append
If specified data will be added to the end of an existing sheet, using the same column headings. If specified dat,a will be added to the end of an existing sheet, using the same column headings.
.PARAMETER TargetData .PARAMETER TargetData
Data to insert onto the worksheet - this is often provided from the pipeline. Data to insert onto the worksheet - this is usually provided from the pipeline.
.PARAMETER DisplayPropertySet .PARAMETER DisplayPropertySet
Many (but not all) objects have a hidden property named psStandardmembers with a child property DefaultDisplayPropertySet ; this parameter reduces the properties exported to those in this set. Many (but not all) objects have a hidden property named psStandardmembers with a child property DefaultDisplayPropertySet ; this parameter reduces the properties exported to those in this set.
.PARAMETER NoAliasOrScriptPropeties .PARAMETER NoAliasOrScriptPropeties
@@ -37,34 +41,36 @@
.PARAMETER Password .PARAMETER Password
Sets password protection on the workbook. Sets password protection on the workbook.
.PARAMETER IncludePivotTable .PARAMETER IncludePivotTable
Adds a Pivot table using the data in the worksheet. Adds a PivotTable using the data in the worksheet.
.PARAMETER PivotTableName .PARAMETER PivotTableName
If a Pivot table is created from command line parameters, specificies the name of the new sheet holding the pivot. If Omitted this will be "WorksheetName-PivotTable" If a PivotTable is created from command line parameters, specifies the name of the new sheet holding the pivot. Defaults to "WorksheetName-PivotTable".
.PARAMETER PivotRows .PARAMETER PivotRows
Name(s) columns from the spreadhseet which will provide the Row name(s) in a pivot table created from command line parameters. Name(s) of column(s) from the spreadsheet which will provide the Row name(s) in a PivotTable created from command line parameters.
.PARAMETER PivotColumns .PARAMETER PivotColumns
Name(s) columns from the spreadhseet which will provide the Column name(s) in a pivot table created from command line parameters. Name(s) of columns from the spreadsheet which will provide the Column name(s) in a PivotTable created from command line parameters.
.PARAMETER PivotFilter .PARAMETER PivotFilter
Name(s) columns from the spreadhseet which will provide the Filter name(s) in a pivot table created from command line parameters. Name(s) columns from the spreadsheet which will provide the Filter name(s) in a PivotTable created from command line parameters.
.PARAMETER PivotData .PARAMETER PivotData
In a pivot table created from command line parameters, the fields to use in the table body are given as a Hash table in the form ColumnName = Average|Count|CountNums|Max|Min|Product|None|StdDev|StdDevP|Sum|Var|VarP . In a PivotTable created from command line parameters, the fields to use in the table body are given as a Hash table in the form ColumnName = Average|Count|CountNums|Max|Min|Product|None|StdDev|StdDevP|Sum|Var|VarP.
.PARAMETER PivotDataToColumn .PARAMETER PivotDataToColumn
If there are multiple datasets in a PivotTable, by default they are shown seperatate rows under the given row heading; this switch makes them seperate columns. If there are multiple datasets in a PivotTable, by default they are shown as separate rows under the given row heading; this switch makes them separate columns.
.PARAMETER NoTotalsInPivot .PARAMETER NoTotalsInPivot
In a pivot table created from command line parameters, prevents the addition of totals to rows and columns. In a PivotTable created from command line parameters, prevents the addition of totals to rows and columns.
.PARAMETER PivotTotals
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.
.PARAMETER PivotTableDefinition .PARAMETER PivotTableDefinition
Instead of describing a single pivot table with mutliple commandline paramters; you can use a HashTable in the form PivotTableName = Definition; Instead of describing a single PivotTable with multiple command-line parameters; you can use a HashTable in the form PivotTableName = Definition;
Definition is itself a hashtable with Sheet PivotTows, PivotColumns, PivotData, IncludePivotChart and ChartType values. Definition is itself a Hashtable with Sheet, PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values.
.PARAMETER IncludePivotChart .PARAMETER IncludePivotChart
Include a chart with the Pivot table - implies -IncludePivotTable. Include a chart with the PivotTable - implies -IncludePivotTable.
.PARAMETER ChartType .PARAMETER ChartType
The type for Pivot chart (one of Excel's defined chart types) The type for PivotChart (one of Excel's defined chart types).
.PARAMETER NoLegend .PARAMETER NoLegend
Exclude the legend from the pivot chart. Exclude the legend from the PivotChart.
.PARAMETER ShowCategory .PARAMETER ShowCategory
Add category labels to the pivot chart. Add category labels to the PivotChart.
.PARAMETER ShowPercent .PARAMETER ShowPercent
Add Percentage labels to the pivot chart. Add percentage labels to the PivotChart.
.PARAMETER ConditionalFormat .PARAMETER ConditionalFormat
One or more conditional formatting rules defined with New-ConditionalFormattingIconSet. One or more conditional formatting rules defined with New-ConditionalFormattingIconSet.
.PARAMETER ConditionalText .PARAMETER ConditionalText
@@ -72,13 +78,13 @@
.PARAMETER NoNumberConversion .PARAMETER NoNumberConversion
By default we convert all values to numbers if possible, but this isn't always desirable. NoNumberConversion allows you to add exceptions for the conversion. Wildcards (like '*') are allowed. By default we convert all values to numbers if possible, but this isn't always desirable. NoNumberConversion allows you to add exceptions for the conversion. Wildcards (like '*') are allowed.
.PARAMETER BoldTopRow .PARAMETER BoldTopRow
Makes the top Row boldface. Makes the top row boldface.
.PARAMETER NoHeader .PARAMETER NoHeader
Does not put field names at the top of columns. Does not put field names at the top of columns.
.PARAMETER RangeName .PARAMETER RangeName
Makes the data in the worksheet a named range. Makes the data in the worksheet a named range.
.PARAMETER TableName .PARAMETER TableName
Makes the data in the worksheet a table with a name applies a style to it. Name must not contain spaces. Makes the data in the worksheet a table with a name, and applies a style to it. Name must not contain spaces.
.PARAMETER TableStyle .PARAMETER TableStyle
Selects the style for the named table - defaults to 'Medium6'. Selects the style for the named table - defaults to 'Medium6'.
.PARAMETER BarChart .PARAMETER BarChart
@@ -90,22 +96,22 @@
.PARAMETER PieChart .PARAMETER PieChart
Creates a "quick" pie chart using the first text column as labels and the first numeric column as values Creates a "quick" pie chart using the first text column as labels and the first numeric column as values
.PARAMETER ExcelChartDefinition .PARAMETER ExcelChartDefinition
A hash table containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-pivot] charts. A hash table containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-Pivot] charts.
.PARAMETER HideSheet .PARAMETER HideSheet
Name(s) of Sheet(s) to hide in the workbook, supports wildcards. If all sheets would be hidden, the sheet being worked on will be revealed . Name(s) of Sheet(s) to hide in the workbook, supports wildcards. If the selection would cause all sheets to be hidden, the sheet being worked on will be revealed.
.PARAMETER UnHideSheet .PARAMETER UnHideSheet
Name(s) of Sheet(s) to Reveal in the workbook, supports wildcards. Name(s) of Sheet(s) to reveal in the workbook, supports wildcards.
.PARAMETER MoveToStart .PARAMETER MoveToStart
If specified, the worksheet will be moved to the start of the workbook. If specified, the worksheet will be moved to the start of the workbook.
MoveToStart takes precedence over MoveToEnd, Movebefore and MoveAfter if more than one is specified. -MoveToStart takes precedence over -MoveToEnd, -Movebefore and -MoveAfter if more than one is specified.
.PARAMETER MoveToEnd .PARAMETER MoveToEnd
If specified, the worksheet will be moved to the end of the workbook. If specified, the worksheet will be moved to the end of the workbook.
(This is the default position for newly created sheets, but this can be used to move existing sheets.) (This is the default position for newly created sheets, but this can be used to move existing sheets.)
.PARAMETER MoveBefore .PARAMETER MoveBefore
If specified, the worksheet will be moved before the nominated one (which can be a postion starting from 1, or a name). If specified, the worksheet will be moved before the nominated one (which can be a position starting from 1, or a name).
MoveBefore takes precedence over MoveAfter if both are specified. -MoveBefore takes precedence over -MoveAfter if both are specified.
.PARAMETER MoveAfter .PARAMETER MoveAfter
If specified, the worksheet will be moved after the nominated one (which can be a postion starting from 1, or a name or *). If specified, the worksheet will be moved after the nominated one (which can be a position starting from 1, or a name or *).
If * is used, the worksheet names will be examined starting with the first one, and the sheet placed after the last sheet which comes before it alphabetically. If * is used, the worksheet names will be examined starting with the first one, and the sheet placed after the last sheet which comes before it alphabetically.
.PARAMETER KillExcel .PARAMETER KillExcel
Closes Excel - prevents errors writing to the file because Excel has it open. Closes Excel - prevents errors writing to the file because Excel has it open.
@@ -122,15 +128,15 @@
.PARAMETER FreezeTopRowFirstColumn .PARAMETER FreezeTopRowFirstColumn
Freezes top row and left column (equivalent to Freeze pane 2,2 ). Freezes top row and left column (equivalent to Freeze pane 2,2 ).
.PARAMETER FreezePane .PARAMETER FreezePane
Freezes panes at specified coordinates (in the form RowNumber , ColumnNumber). Freezes panes at specified coordinates (in the form RowNumber, ColumnNumber).
.PARAMETER AutoFilter .PARAMETER AutoFilter
Enables the 'Filter' in Excel on the complete header row. So users can easily sort, filter and/or search the data in the selected column from within Excel. Enables the Excel filter on the complete header row, so users can easily sort, filter and/or search the data in the selected column.
.PARAMETER AutoSize .PARAMETER AutoSize
Sizes the width of the Excel column to the maximum width needed to display all the containing data in that cell. Sizes the width of the Excel column to the maximum width needed to display all the containing data in that cell.
.PARAMETER Activate .PARAMETER Activate
If there is already content in the workbook, a new sheet will not be active UNLESS Activate is specified; if a Pivot table is included it will be the active sheet If there is already content in the workbook, a new sheet will not be active UNLESS Activate is specified; if a PivotTable is included it will be the active sheet
.PARAMETER Now .PARAMETER Now
The 'Now' switch is a shortcut that creates automatically a temporary file, enables 'AutoSize', 'AutoFiler' and 'Show', and opens the file immediately. The -Now switch is a shortcut that automatically creates a temporary file, enables "AutoSize", "AutoFiler" and "Show", and opens the file immediately.
.PARAMETER NumberFormat .PARAMETER NumberFormat
Formats all values that can be converted to a number to the format specified. Formats all values that can be converted to a number to the format specified.
@@ -147,10 +153,10 @@
# number with 2 decimal places. # number with 2 decimal places.
'0.00' '0.00'
# number with 2 decimal places and thousand separator. # number with 2 decimal places and thousand-separator.
'#,##0.00' '#,##0.00'
# number with 2 decimal places and thousand separator and money symbol. # number with 2 decimal places and thousand-separator and money-symbol.
'€#,##0.00' '€#,##0.00'
# percentage (1 = 100%, 0.01 = 1%) # percentage (1 = 100%, 0.01 = 1%)
@@ -160,7 +166,7 @@
'[Blue]$#,##0.00;[Red]-$#,##0.00' '[Blue]$#,##0.00;[Red]-$#,##0.00'
.PARAMETER ReZip .PARAMETER ReZip
If specified, Export-Excel will expand the contents of the .XLSX file (which is multiple files in a zip archive) and rebuilt it. If specified, Export-Excel will expand the contents of the .XLSX file (which is multiple files in a zip archive) and rebuild it.
.PARAMETER NoClobber .PARAMETER NoClobber
Not used. Left in to avoid problems with older scripts, it may be removed in future versions. Not used. Left in to avoid problems with older scripts, it may be removed in future versions.
.PARAMETER CellStyleSB .PARAMETER CellStyleSB
@@ -169,10 +175,10 @@
.PARAMETER Show .PARAMETER Show
Opens the Excel file immediately after creation. Convenient for viewing the results instantly without having to search for the file first. Opens the Excel file immediately after creation. Convenient for viewing the results instantly without having to search for the file first.
.PARAMETER ReturnRange .PARAMETER ReturnRange
If specified, Export-Excel returns the range of added cells in the format "A1:Z100" If specified, Export-Excel returns the range of added cells in the format "A1:Z100".
.PARAMETER PassThru .PARAMETER PassThru
If specified, Export-Excel returns an object representing the Excel package without saving the package first. To save it you need to call the save or Saveas method or send it back to Export-Excel. If specified, Export-Excel returns an object representing the Excel package without saving the package first.
To save, you need to call Close-ExcelPackage or send the object back to Export-Excel, or use its .Save() or SaveAs() method.
.EXAMPLE .EXAMPLE
Get-Process | Export-Excel .\Test.xlsx -show Get-Process | Export-Excel .\Test.xlsx -show
Export all the processes to the Excel file 'Test.xlsx' and open the file immediately. Export all the processes to the Excel file 'Test.xlsx' and open the file immediately.
@@ -188,7 +194,9 @@
Write-Output -1 668 34 777 860 -0.5 119 -0.1 234 788 | Write-Output -1 668 34 777 860 -0.5 119 -0.1 234 788 |
Export-Excel @ExcelParams -NumberFormat '[Blue]$#,##0.00;[Red]-$#,##0.00' Export-Excel @ExcelParams -NumberFormat '[Blue]$#,##0.00;[Red]-$#,##0.00'
Exports all data to the Excel file 'Excel.xslx' and colors the negative values in 'Red' and the positive values in 'Blue'. It will also add a dollar sign '$' in front of the rounded numbers to two decimal characters behind the comma. Exports all data to the Excel file 'Excel.xslx' and colors the negative values
in Red and the positive values in Blue. It will also add a dollar sign in front
of the numbers which use a thousand seperator and display to two decimal places.
.EXAMPLE .EXAMPLE
> >
@@ -214,7 +222,9 @@
PhoneNr3 = '+3244444444' PhoneNr3 = '+3244444444'
} | Export-Excel @ExcelParams -NoNumberConversion IPAddress, Number1 } | Export-Excel @ExcelParams -NoNumberConversion IPAddress, Number1
Exports all data to the Excel file 'Excel.xslx' and tries to convert all values to numbers where possible except for 'IPAddress' and 'Number1'. These are stored in the sheet 'as is', without being converted to a number. Exports all data to the Excel file "Excel.xlsx" and tries to convert all values
to numbers where possible except for "IPAddress" and "Number1", which are
stored in the sheet 'as is', without being converted to a number.
.EXAMPLE .EXAMPLE
> >
@@ -240,7 +250,9 @@
PhoneNr3 = '+3244444444' PhoneNr3 = '+3244444444'
} | Export-Excel @ExcelParams -NoNumberConversion * } | Export-Excel @ExcelParams -NoNumberConversion *
Exports all data to the Excel file 'Excel.xslx' as is, no number conversion will take place. This means that Excel will show the exact same data that you handed over to the 'Export-Excel' function. Exports all data to the Excel file 'Excel.xslx' as is, no number conversion
will take place. This means that Excel will show the exact same data that
you handed over to the 'Export-Excel' function.
.EXAMPLE .EXAMPLE
> >
@@ -255,7 +267,11 @@
New-ConditionalText -ConditionalType GreaterThan 525 -ConditionalTextColor DarkRed -BackgroundColor LightPink New-ConditionalText -ConditionalType GreaterThan 525 -ConditionalTextColor DarkRed -BackgroundColor LightPink
) )
Exports data that will have a 'Conditional formatting rule' in Excel on these cells that will show the background fill color in 'LightPink' and the text color in 'DarkRed' when the value is greater then '525'. In case this condition is not met the color will be the default, black text on a white background. Exports data that will have a Conditional Formatting rule in Excel
that will show cells with a value is greater than 525, whith a
background fill color of "LightPink" and the text in "DarkRed".
Where condition is not met the color willbe the default, black
text on a white background.
.EXAMPLE .EXAMPLE
> >
@@ -265,13 +281,18 @@
Verbose = $true Verbose = $true
} }
Remove-Item -Path $ExcelParams.Path -Force -EA Ignore Remove-Item -Path $ExcelParams.Path -Force -EA Ignore
Get-Service | Select Name, Status, DisplayName, ServiceName | Get-Service | Select-Object -Property Name, Status, DisplayName, ServiceName |
Export-Excel @ExcelParams -ConditionalText $( Export-Excel @ExcelParams -ConditionalText $(
New-ConditionalText Stop DarkRed LightPink New-ConditionalText Stop DarkRed LightPink
New-ConditionalText Running Blue Cyan New-ConditionalText Running Blue Cyan
) )
Export all services to an Excel sheet where all cells have a 'Conditional formatting rule' in Excel that will show the background fill color in 'LightPink' and the text color in 'DarkRed' when the value contains the word 'Stop'. If the value contains the word 'Running' it will have a background fill color in 'Cyan' and a text color 'Blue'. In case none of these conditions are met the color will be the default, black text on a white background. Exports all services to an Excel sheet, setting a Conditional formatting rule
that will set the background fill color to "LightPink" and the text color
to "DarkRed" when the value contains the word "Stop".
If the value contains the word "Running" it will have a background fill
color of "Cyan" and text colored 'Blue'. If neither condition is met, the
color will be the default, black text on a white background.
.EXAMPLE .EXAMPLE
> >
@@ -306,7 +327,8 @@
$Array | Out-GridView -Title 'Not showing Member3 and Member4' $Array | Out-GridView -Title 'Not showing Member3 and Member4'
$Array | Update-FirstObjectProperties | Export-Excel @ExcelParams -WorksheetName Numbers $Array | Update-FirstObjectProperties | Export-Excel @ExcelParams -WorksheetName Numbers
Updates the first object of the array by adding property 'Member3' and 'Member4'. Afterwards. all objects are exported to an Excel file and all column headers are visible. Updates the first object of the array by adding property 'Member3' and 'Member4'.
Afterwards. all objects are exported to an Excel file and all column headers are visible.
.EXAMPLE .EXAMPLE
Get-Process | Export-Excel .\test.xlsx -WorksheetName Processes -IncludePivotTable -Show -PivotRows Company -PivotData PM Get-Process | Export-Excel .\test.xlsx -WorksheetName Processes -IncludePivotTable -Show -PivotRows Company -PivotData PM
@@ -337,10 +359,10 @@
Get-Process | Select-Object -Property Name,Company,Handles,CPU,VM | Export-Excel -Path .\test.xlsx -AutoSize -WorksheetName 'sheet2' Get-Process | Select-Object -Property Name,Company,Handles,CPU,VM | Export-Excel -Path .\test.xlsx -AutoSize -WorksheetName 'sheet2'
Export-Excel -Path .\test.xlsx -PivotTableDefinition $pt -Show Export-Excel -Path .\test.xlsx -PivotTableDefinition $pt -Show
This example defines two pivot tables. Then it puts Service data on Sheet1 with one call to Export-Excel and Process Data on sheet2 with a second call to Export-Excel. This example defines two PivotTables. Then it puts Service data on Sheet1
The thrid and final call adds the two pivot tables and opens the spreadsheet in Excel. with one call to Export-Excel and Process Data on sheet2 with a second
call to Export-Excel. The third and final call adds the two PivotTables
and opens the spreadsheet in Excel.
.EXAMPLE .EXAMPLE
> >
PS> Remove-Item -Path .\test.xlsx PS> Remove-Item -Path .\test.xlsx
@@ -352,13 +374,15 @@
$excel.Dispose() $excel.Dispose()
Start-Process .\test.xlsx Start-Process .\test.xlsx
This example uses -passthrough - put service information into sheet1 of the work book and saves the excelPackageObject in $Excel. This example uses -PassThru. It puts service information into sheet1 of the
It then uses the package object to apply formatting, and then saves the workbook and disposes of the object before loading the document in Excel. workbook and saves the ExcelPackage object in $Excel. It then uses the package
object to apply formatting, and then saves the workbook and disposes of the object
before loading the document in Excel. Other commands in the module remove the need
to work directly with the package object in this way.
.EXAMPLE .EXAMPLE
> >
PS> Remove-Item -Path .\test.xlsx -ErrorAction Ignore PS> Remove-Item -Path .\test.xlsx -ErrorAction Ignore
$excel = Get-Process | Select-Object -Property Name,Company,Handles,CPU,PM,NPM,WS | Export-Excel -Path .\test.xlsx -ClearSheet -WorksheetName "Processes" -PassThru $excel = Get-Process | Select-Object -Property Name,Company,Handles,CPU,PM,NPM,WS | Export-Excel -Path .\test.xlsx -ClearSheet -WorksheetName "Processes" -PassThru
$sheet = $excel.Workbook.Worksheets["Processes"] $sheet = $excel.Workbook.Worksheets["Processes"]
$sheet.Column(1) | Set-ExcelRange -Bold -AutoFit $sheet.Column(1) | Set-ExcelRange -Bold -AutoFit
@@ -372,12 +396,23 @@
foreach ($c in 5..9) {Set-ExcelRange -Address $sheet.Column($c) -AutoFit } foreach ($c in 5..9) {Set-ExcelRange -Address $sheet.Column($c) -AutoFit }
Export-Excel -ExcelPackage $excel -WorksheetName "Processes" -IncludePivotChart -ChartType ColumnClustered -NoLegend -PivotRows company -PivotData @{'Name'='Count'} -Show Export-Excel -ExcelPackage $excel -WorksheetName "Processes" -IncludePivotChart -ChartType ColumnClustered -NoLegend -PivotRows company -PivotData @{'Name'='Count'} -Show
This a more sophisticated version of the previous example showing different ways of using Set-ExcelRange, and also adding conditional formatting. This a more sophisticated version of the previous example showing different
In the final command a Pivot chart is added and the workbook is opened in Excel. ways of using Set-ExcelRange, and also adding conditional formatting.
In the final command a PivotChart is added and the workbook is opened in Excel.
.EXAMPLE .EXAMPLE
0..360 | ForEach-Object {[pscustomobject][ordered]@{X=$_; Sinx="=Sin(Radians(x)) "} } | Export-Excel -now -LineChart -AutoNameRange 0..360 | ForEach-Object {[pscustomobject][ordered]@{X=$_; Sinx="=Sin(Radians(x)) "} } | Export-Excel -now -LineChart -AutoNameRange
Creates a line chart showing the value of Sine(x) for values of X between 0 and 360 degrees. Creates a line chart showing the value of Sine(x) for values of X between 0 and 360 degrees.
.EXAMPLE
>
PS> Invoke-Sqlcmd -ServerInstance localhost\DEFAULT -Database AdventureWorks2014 -Query "select * from sys.tables" -OutputAs DataRows |
Export-Excel -Path .\SysTables_AdventureWorks2014.xlsx -WorksheetName Tables
Runs a query against a SQL Server database and outputs the resulting rows DataRows using the -OutputAs parameter.
The results are then piped to the Export-Excel function.
NOTE: You need to install the SqlServer module from the PowerShell Gallery in oder to get the -OutputAs parameter for the Invoke-Sqlcmd cmdlet.
.LINK .LINK
https://github.com/dfinke/ImportExcel https://github.com/dfinke/ImportExcel
#> #>
@@ -403,7 +438,7 @@
[OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'Solid', [OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'Solid',
[Switch]$TitleBold, [Switch]$TitleBold,
[Int]$TitleSize = 22, [Int]$TitleSize = 22,
[System.Drawing.Color]$TitleBackgroundColor, $TitleBackgroundColor,
[Switch]$IncludePivotTable, [Switch]$IncludePivotTable,
[String]$PivotTableName, [String]$PivotTableName,
[String[]]$PivotRows, [String[]]$PivotRows,
@@ -469,12 +504,12 @@
[Object[]]$ConditionalFormat, [Object[]]$ConditionalFormat,
[Object[]]$ConditionalText, [Object[]]$ConditionalText,
[ScriptBlock]$CellStyleSB, [ScriptBlock]$CellStyleSB,
#If there is already content in the workbook the sheet with the Pivot table will not be active UNLESS Activate is specified #If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified
[switch]$Activate, [switch]$Activate,
[Parameter(ParameterSetName = 'Now')] [Parameter(ParameterSetName = 'Now')]
[Switch]$Now, [Switch]$Now,
[Switch]$ReturnRange, [Switch]$ReturnRange,
#By default Pivot tables 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"
@@ -646,12 +681,13 @@
$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 ($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 = $True $ws.Cells[$Row, $StartColumn].Style.Font.Bold = [boolean]$TitleBold
} }
if ($TitleBackgroundColor ) { if ($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)
} }
@@ -681,15 +717,14 @@
} }
Process { Process {
if ($TargetData) { if ($PSBoundParameters.ContainsKey("TargetData")) {
try { try {
if ($firstTimeThru) { if ($firstTimeThru) {
$firstTimeThru = $false $firstTimeThru = $false
$isDataTypeValueType = $TargetData.GetType().name -match 'string|timespan|datetime|bool|byte|char|decimal|double|float|int|long|sbyte|short|uint|ulong|ushort|URI|ExcelHyperLink' $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')
if ($isDataTypeValueType -and -not $Append) {$row -= 1} #row incremented before adding values, so it is set to the number of rows inserted at the end if ($isDataTypeValueType -and -not $Append) {$row -= 1} #row incremented before adding values, so it is set to the number of rows inserted at the end
Write-Debug "DataTypeName is '$($TargetData.GetType().name)' isDataTypeValueType '$isDataTypeValueType'" if ($null -ne $TargetData) {Write-Debug "DataTypeName is '$($TargetData.GetType().name)' isDataTypeValueType '$isDataTypeValueType'" }
} }
if ($isDataTypeValueType) { if ($isDataTypeValueType) {
$ColumnIndex = $StartColumn $ColumnIndex = $StartColumn
$Row += 1 $Row += 1
@@ -727,7 +762,7 @@
foreach ($Name in $script:Header) { foreach ($Name in $script:Header) {
try {Add-CellValue -TargetCell $ws.Cells[$Row, $ColumnIndex] -CellValue $TargetData.$Name} try {Add-CellValue -TargetCell $ws.Cells[$Row, $ColumnIndex] -CellValue $TargetData.$Name}
catch {Write-Warning -Message "Could not insert the $Name property at Row $Row, Column $Column"} catch {Write-Warning -Message "Could not insert the '$Name' property at Row $Row, Column $ColumnIndex"}
$ColumnIndex += 1 $ColumnIndex += 1
} }
$ColumnIndex -= 1 # column index will be the last column whether isDataTypeValueType was true or false $ColumnIndex -= 1 # column index will be the last column whether isDataTypeValueType was true or false
@@ -741,7 +776,7 @@
} }
End { End {
if ($firstTimeThru) { 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
@@ -762,29 +797,30 @@
$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 there is no header start the range at $startRow if ($PSBoundParameters.ContainsKey($TargetData)) { #if Export was called with data that writes no header start the range at $startRow ($startRow is data)
$targetRow = $StartRow $targetRow = $StartRow
} }
else { else { $targetRow = $StartRow + 1 } #if Export was called without data to add names (assume $startRow is a header) or...
#if there is a header, start the range and the next row down. } # ... called with data that writes a header, then start the range at $startRow + 1
$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.
# if we have 5 columns from 3 to 8, headers are numbered 0..4, so that is in the for loop and used for getting the name... # if we have 5 columns from 3 to 8, headers are numbered 0..4, so that is in the for loop and used for getting the name...
# but we have to add the start column on when referencing positions # but we have to add the start column on when referencing positions
foreach ($c in 0..($LastCol - $StartColumn)) { foreach ($c in 0..($LastCol - $StartColumn)) {
$targetRangeName = $script:Header[$c] -replace '\W' , '_' $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 )]
if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress($targetRangeName)) { try {#this test can throw with some names, surpress any error
if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress(($targetRangeName -replace '\W' , '_' ))) {
Write-Warning "AutoNameRange: Property name '$targetRangeName' is also a valid Excel address and may cause issues. Consider renaming the property name." Write-Warning "AutoNameRange: Property name '$targetRangeName' is also a valid Excel address and may cause issues. Consider renaming the property name."
} }
} Catch {}
} }
} }
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.
if ($RangeName) { Add-ExcelName -Range $ws.Cells[$dataRange] -RangeName $RangeName} if ($RangeName) { Add-ExcelName -Range $ws.Cells[$dataRange] -RangeName $RangeName}
if ($TableName) { if ($TableName) {
@@ -821,7 +857,7 @@
'SourceRange' = $dataRange 'SourceRange' = $dataRange
} }
if ($PivotTableName -and ($pkg.workbook.worksheets.tables.name -contains $PivotTableName)) { if ($PivotTableName -and ($pkg.workbook.worksheets.tables.name -contains $PivotTableName)) {
Write-Warning -Message "The selected Pivot table name '$PivotTableName' is already used as a table name. Adding a suffix of 'Pivot'." Write-Warning -Message "The selected PivotTable name '$PivotTableName' is already used as a table name. Adding a suffix of 'Pivot'."
$PivotTableName += 'Pivot' $PivotTableName += 'Pivot'
} }
@@ -859,22 +895,22 @@
$ws.View.FreezePanes(1, 2) $ws.View.FreezePanes(1, 2)
Write-Verbose -Message "Froze first column" Write-Verbose -Message "Froze first column"
} }
#Must be 1..maxrows or and array of 1..maxRows,1..MaxCols
if ($FreezePane) { if ($FreezePane) {
$freezeRow, $freezeColumn = $FreezePane $freezeRow, $freezeColumn = $FreezePane
if (-not $freezeColumn -or $freezeColumn -eq 0) { if (-not $freezeColumn -or $freezeColumn -eq 0) {
$freezeColumn = 1 $freezeColumn = 1
} }
if ($freezeRow -gt 1) { if ($freezeRow -ge 1) {
$ws.View.FreezePanes($freezeRow, $freezeColumn) $ws.View.FreezePanes($freezeRow, $freezeColumn)
Write-Verbose -Message "Froze pandes at row $freezeRow and column $FreezeColumn" Write-Verbose -Message "Froze panes at row $freezeRow and column $FreezeColumn"
} }
} }
} }
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 ($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)
@@ -882,7 +918,7 @@
else { else {
$range = $ws.Dimension.Address -replace '\d+', $StartRow $range = $ws.Dimension.Address -replace '\d+', $StartRow
} }
$ws.Cells[$range].Style.Font.Bold = $true $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': $_"}
@@ -989,7 +1025,7 @@
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) {$c.Range = $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
} }
} }
@@ -1005,6 +1041,7 @@
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.
if ($Password) { if ($Password) {
try { try {
$ws.Protection.SetPassword($Password) $ws.Protection.SetPassword($Password)
@@ -1077,10 +1114,10 @@ function Add-WorkSheet {
#An object representing an Excel Package. #An object representing an Excel Package.
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = "Package", Position = 0)] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = "Package", Position = 0)]
[OfficeOpenXml.ExcelPackage]$ExcelPackage, [OfficeOpenXml.ExcelPackage]$ExcelPackage,
#An Excel workbook to which the Worksheet will be added - a package contains one workbook so you can use whichever fits at the time. #An Excel Workbook to which the Worksheet will be added - a Package contains one Workbook, so you can use whichever fits at the time.
[Parameter(Mandatory = $true, ParameterSetName = "WorkBook")] [Parameter(Mandatory = $true, ParameterSetName = "WorkBook")]
[OfficeOpenXml.ExcelWorkbook]$ExcelWorkbook, [OfficeOpenXml.ExcelWorkbook]$ExcelWorkbook,
#The name of the worksheet 'Sheet1' by default. #The name of the worksheet, 'Sheet1' by default.
[string]$WorksheetName , [string]$WorksheetName ,
#If the worksheet already exists, by default it will returned, unless -ClearSheet is specified in which case it will be deleted and re-created. #If the worksheet already exists, by default it will returned, unless -ClearSheet is specified in which case it will be deleted and re-created.
[switch]$ClearSheet, [switch]$ClearSheet,
@@ -1090,13 +1127,13 @@ function Add-WorkSheet {
#If specified, the worksheet will be moved to the end of the workbook. #If specified, the worksheet will be moved to the end of the workbook.
#(This is the default position for newly created sheets, but this can be used to move existing sheets.) #(This is the default position for newly created sheets, but this can be used to move existing sheets.)
[Switch]$MoveToEnd, [Switch]$MoveToEnd,
#If specified, the worksheet will be moved before the nominated one (which can be a postion starting from 1, or a name). #If specified, the worksheet will be moved before the nominated one (which can be an index starting from 1, or a name).
#MoveBefore takes precedence over MoveAfter if both are specified. #MoveBefore takes precedence over MoveAfter if both are specified.
$MoveBefore , $MoveBefore ,
# If specified, the worksheet will be moved after the nominated one (which can be a postion starting from 1, or a name or *). # If specified, the worksheet will be moved after the nominated one (which can be an index starting from 1, or a name or *).
# If * is used, the worksheet names will be examined starting with the first one, and the sheet placed after the last sheet which comes before it alphabetically. # If * is used, the worksheet names will be examined starting with the first one, and the sheet placed after the last sheet which comes before it alphabetically.
$MoveAfter , $MoveAfter ,
#If there is already content in the workbook the new sheet will not be active UNLESS Activate is specified #If there is already content in the workbook the new sheet will not be active UNLESS Activate is specified.
[switch]$Activate, [switch]$Activate,
#If worksheet is provided as a copy source the new worksheet will be a copy of it. The source can be in the same workbook, or in a different file. #If worksheet is provided as a copy source the new worksheet will be a copy of it. The source can be in the same workbook, or in a different file.
[OfficeOpenXml.ExcelWorksheet]$CopySource, [OfficeOpenXml.ExcelWorksheet]$CopySource,
@@ -1168,34 +1205,35 @@ function Add-WorkSheet {
function Select-Worksheet { function Select-Worksheet {
<# <#
.SYNOPSIS .SYNOPSIS
Sets the selected tab in an Excel workbook to be the chosen sheet, and unselects all the others. Sets the selected tab in an Excel workbook to be the chosen sheet and unselects all the others.
.DESCRIPTION .DESCRIPTION
Sometimes when a sheet is added we want it to be the active sheet, sometimes we want the active sheet to be left as it was. Sometimes when a sheet is added we want it to be the active sheet, sometimes we want the active sheet to be left as it was.
Select-Worksheet exists to change the which sheet is the selected tab when Excel opens the file. Select-Worksheet exists to change which sheet is the selected tab when Excel opens the file.
.EXAMPLE .EXAMPLE
Select-Worksheet -ExcelWorkbook $ExcelWorkbook -WorksheetName "NewSheet" Select-Worksheet -ExcelWorkbook $ExcelWorkbook -WorksheetName "NewSheet"
$ExcelWorkbook holds the a workbook object containing a sheet named "NewSheet"; $ExcelWorkbook holds a workbook object containing a sheet named "NewSheet";
This sheet will become the [only] active sheet in the workbook This sheet will become the [only] active sheet in the workbook
.EXAMPLE .EXAMPLE
Select-Worksheet -ExcelPackage $Pkg -WorksheetName "NewSheet2" Select-Worksheet -ExcelPackage $Pkg -WorksheetName "NewSheet2"
$pkg holds an Excel Package, whose workbook contains a sheet named "NewSheet2" $pkg holds an Excel Package, whose workbook contains a sheet named "NewSheet2"
This sheet will become the [only] active sheet in the workbook This sheet will become the [only] active sheet in the workbook.
.EXAMPLE .EXAMPLE
Select-Worksheet -ExcelWorksheet $ws Select-Worksheet -ExcelWorksheet $ws
$ws holds an Excel worksheet which will become the [only] active sheet in the workbook $ws holds an Excel worksheet which will become the [only] active sheet
in its workbook.
#> #>
param ( param (
#An object representing an Excel Package. #An object representing an ExcelPackage.
[Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'Package', Position = 0)] [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = 'Package', Position = 0)]
[OfficeOpenXml.ExcelPackage]$ExcelPackage, [OfficeOpenXml.ExcelPackage]$ExcelPackage,
#An Excel workbook to which the Worksheet will be added - a package contains one workbook so you can use workbook or package as it suits #An Excel workbook to which the Worksheet will be added - a package contains one Workbook so you can use workbook or package as it suits.
[Parameter(Mandatory = $true, ParameterSetName = 'WorkBook')] [Parameter(Mandatory = $true, ParameterSetName = 'WorkBook')]
[OfficeOpenXml.ExcelWorkbook]$ExcelWorkbook, [OfficeOpenXml.ExcelWorkbook]$ExcelWorkbook,
[Parameter(ParameterSetName='Package')] [Parameter(ParameterSetName='Package')]
[Parameter(ParameterSetName='Workbook')] [Parameter(ParameterSetName='Workbook')]
#The name of the worksheet 'Sheet1' by default. #The name of the worksheet "Sheet1" by default.
[string]$WorksheetName, [string]$WorksheetName,
#An object representing an Excel worksheet #An object representing an Excel worksheet.
[Parameter(ParameterSetName='Sheet',Mandatory=$true)] [Parameter(ParameterSetName='Sheet',Mandatory=$true)]
[OfficeOpenXml.ExcelWorksheet]$ExcelWorksheet [OfficeOpenXml.ExcelWorksheet]$ExcelWorksheet
) )
@@ -1215,7 +1253,7 @@ function Select-Worksheet {
Function Add-ExcelName { Function Add-ExcelName {
<# <#
.SYNOPSIS .SYNOPSIS
Adds a named range to an existing Excel worksheet Adds a named-range to an existing Excel worksheet.
.DESCRIPTION .DESCRIPTION
It is often helpful to be able to refer to sets of cells with a name rather than using their co-ordinates; Add-ExcelName sets up these names. It is often helpful to be able to refer to sets of cells with a name rather than using their co-ordinates; Add-ExcelName sets up these names.
.EXAMPLE .EXAMPLE
@@ -1228,7 +1266,7 @@ Function Add-ExcelName {
#The range of cells to assign as a name. #The range of cells to assign as a name.
[Parameter(Mandatory=$true)] [Parameter(Mandatory=$true)]
[OfficeOpenXml.ExcelRange]$Range, [OfficeOpenXml.ExcelRange]$Range,
#The name to assign to the range. If the name exists it will be updated to the new range. If no name is specified the first cell in the range will be used as the name #The name to assign to the range. If the name exists it will be updated to the new range. If no name is specified, the first cell in the range will be used as the name.
[String]$RangeName [String]$RangeName
) )
try { try {
@@ -1268,36 +1306,36 @@ function Add-ExcelTable {
.EXAMPLE .EXAMPLE
Add-ExcelTable -Range $ws.cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName Musictable -ShowFilter:$false -ShowTotal -ShowFirstColumn Add-ExcelTable -Range $ws.cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName Musictable -ShowFilter:$false -ShowTotal -ShowFirstColumn
Again $ws is a worksheet, range here is the whole of the active part of the worksheet. The table style and name are set, Again $ws is a worksheet, range here is the whole of the active part of the worksheet. The table style and name are set,
the filter is turned off, a totals row added and first column set in bold. the filter is turned off, and a "Totals" row added, and first column is set in bold.
#> #>
[CmdletBinding()] [CmdletBinding()]
[OutputType([OfficeOpenXml.Table.ExcelTable])] [OutputType([OfficeOpenXml.Table.ExcelTable])]
param ( param (
#The range of cells to assign to a table #The range of cells to assign to a table.
[Parameter(Mandatory=$true)] [Parameter(Mandatory=$true)]
[OfficeOpenXml.ExcelRange]$Range, [OfficeOpenXml.ExcelRange]$Range,
#The name for the table #The name for the Table - this should be unqiue in the Workbook.
[Parameter(Mandatory=$true)] [Parameter(Mandatory=$true)]
[String]$TableName, [String]$TableName,
#The Style for the table, by default Medium 6 #The Style for the table, by default "Medium6" is used
[OfficeOpenXml.Table.TableStyles]$TableStyle = 'Medium6', [OfficeOpenXml.Table.TableStyles]$TableStyle = 'Medium6',
#By default the header row is shown - it can be turned off with -ShowHeader:$false #By default the header row is shown - it can be turned off with -ShowHeader:$false.
[Switch]$ShowHeader , [Switch]$ShowHeader ,
#By default the filter is enabled - it can be turned off with -ShowFilter:$false #By default the filter is enabled - it can be turned off with -ShowFilter:$false.
[Switch]$ShowFilter, [Switch]$ShowFilter,
#Show total adds a totals row. This does not automatically sum the columns but provides a drop-down in each to select sum, average etc #Show total adds a totals row. This does not automatically sum the columns but provides a drop-down in each to select sum, average etc
[Switch]$ShowTotal, [Switch]$ShowTotal,
#Hashtable in the form ColumnName = "Average"|"Count"|"CountNums"|"Max"|"Min"|"None"|"StdDev"|"Sum"|"Var" - if specified ShowTotal is not needed. #A HashTable in the form ColumnName = "Average"|"Count"|"CountNums"|"Max"|"Min"|"None"|"StdDev"|"Sum"|"Var" - if specified, -ShowTotal is not needed.
[hashtable]$TotalSettings, [hashtable]$TotalSettings,
#Highlights the first column in bold #Highlights the first column in bold.
[Switch]$ShowFirstColumn, [Switch]$ShowFirstColumn,
#Highlights the last column in bold #Highlights the last column in bold.
[Switch]$ShowLastColumn, [Switch]$ShowLastColumn,
#By default the table formats show striped rows, the can be turned off with -ShowRowStripes:$false #By default the table formats show striped rows, the can be turned off with -ShowRowStripes:$false
[Switch]$ShowRowStripes, [Switch]$ShowRowStripes,
#Turns on column stripes. #Turns on column stripes.
[Switch]$ShowColumnStripes, [Switch]$ShowColumnStripes,
#If -PassThru is specified the table object will be returned to allow additional #If -PassThru is specified, the table object will be returned to allow additional changes to be made.
[Switch]$PassThru [Switch]$PassThru
) )
try { try {

View File

@@ -21,9 +21,9 @@ function Get-HtmlTable {
if(!$propertyNames) { if(!$propertyNames) {
if($cells[0].tagName -eq 'th') { if($cells[0].tagName -eq 'th') {
$propertyNames = @($cells | foreach {$_.innertext -replace ' ',''}) $propertyNames = @($cells | ForEach-Object {$_.innertext -replace ' ',''})
} else { } else {
$propertyNames = @(1..($cells.Count + 2) | % { "P$_" }) $propertyNames = @(1..($cells.Count + 2) | Foreach-Object { "P$_" })
} }
continue continue
} }

View File

@@ -1,7 +1,7 @@
function Get-XYRange { function Get-XYRange {
param($targetData) param($targetData)
$record = $targetData| select -First 1 $record = $targetData | Select-Object -First 1
$p=$record.psobject.Properties.name $p=$record.psobject.Properties.name
$infer = for ($idx = 0; $idx -lt $p.Count; $idx++) { $infer = for ($idx = 0; $idx -lt $p.Count; $idx++) {
@@ -20,7 +20,7 @@ function Get-XYRange {
} }
[PSCustomObject]@{ [PSCustomObject]@{
XRange = $infer | ? {$_.datatype -match 'string'} | select -First 1 excelcolumn, name XRange = $infer | Where-Object -FilterScript {$_.datatype -match 'string'} | Select-Object -First 1 -Property excelcolumn, name
YRange = $infer | ? {$_.datatype -match 'int|double'} |select -First 1 excelcolumn, name YRange = $infer | Where-Object -FilterScript {$_.datatype -match 'int|double'} | Select-Object -First 1 -Property excelcolumn, name
} }
} }

View File

@@ -89,7 +89,7 @@ function ConvertFrom-ExcelColumnName {
$sum=0 $sum=0
$columnName.ToCharArray() | $columnName.ToCharArray() |
ForEach { ForEach-Object {
$sum*=26 $sum*=26
$sum+=[char]$_.tostring().toupper()-[char]'A'+1 $sum+=[char]$_.tostring().toupper()-[char]'A'+1
} }

View File

@@ -1,85 +1,85 @@
@{ @{
# Script module or binary module file associated with this manifest. # Script module or binary module file associated with this manifest.
RootModule = 'ImportExcel.psm1' RootModule = 'ImportExcel.psm1'
# Version number of this module. # Version number of this module.
ModuleVersion = '5.3.0' ModuleVersion = '5.4.0'
# ID used to uniquely identify this module # ID used to uniquely identify this module
GUID = '60dd4136-feff-401a-ba27-a84458c57ede' GUID = '60dd4136-feff-401a-ba27-a84458c57ede'
# Author of this module # Author of this module
Author = 'Douglas Finke' Author = 'Douglas Finke'
# Company or vendor of this module # Company or vendor of this module
CompanyName = 'Doug Finke' CompanyName = 'Doug Finke'
# Copyright statement for this module # Copyright statement for this module
Copyright = 'c 2015 All rights reserved.' Copyright = 'c 2015 All rights reserved.'
# Description of the functionality provided by this module # Description of the functionality provided by this module
Description = @' Description = @'
PowerShell module to import/export Excel spreadsheets, without Excel. PowerShell module to import/export Excel spreadsheets, without Excel.
Check out the How To Videos https://www.youtube.com/watch?v=U3Ne_yX4tYo&list=PL5uoqS92stXioZw-u-ze_NtvSo0k0K0kq Check out the How To Videos https://www.youtube.com/watch?v=U3Ne_yX4tYo&list=PL5uoqS92stXioZw-u-ze_NtvSo0k0K0kq
'@ '@
# Minimum version of the Windows PowerShell engine required by this module # Minimum version of the Windows PowerShell engine required by this module
# PowerShellVersion = '' # PowerShellVersion = ''
# Name of the Windows PowerShell host required by this module # Name of the Windows PowerShell host required by this module
# PowerShellHostName = '' # PowerShellHostName = ''
# Minimum version of the Windows PowerShell host required by this module # Minimum version of the Windows PowerShell host required by this module
# PowerShellHostVersion = '' # PowerShellHostVersion = ''
# Minimum version of Microsoft .NET Framework required by this module # Minimum version of Microsoft .NET Framework required by this module
# DotNetFrameworkVersion = '' # DotNetFrameworkVersion = ''
# Minimum version of the common language runtime (CLR) required by this module # Minimum version of the common language runtime (CLR) required by this module
# CLRVersion = '' # CLRVersion = ''
# Processor architecture (None, X86, Amd64) required by this module # Processor architecture (None, X86, Amd64) required by this module
# ProcessorArchitecture = '' # ProcessorArchitecture = ''
# Modules that must be imported into the global environment prior to importing this module # Modules that must be imported into the global environment prior to importing this module
# RequiredModules = @() # RequiredModules = @()
# Assemblies that must be loaded prior to importing this module # Assemblies that must be loaded prior to importing this module
# RequiredAssemblies = @() # RequiredAssemblies = @()
# Script files (.ps1) that are run in the caller's environment prior to importing this module. # Script files (.ps1) that are run in the caller's environment prior to importing this module.
# ScriptsToProcess = @() # ScriptsToProcess = @()
# Type files (.ps1xml) to be loaded when importing this module # Type files (.ps1xml) to be loaded when importing this module
# TypesToProcess = @() # TypesToProcess = @()
# Format files (.ps1xml) to be loaded when importing this module # Format files (.ps1xml) to be loaded when importing this module
# FormatsToProcess = @() # FormatsToProcess = @()
# Modules to import as nested modules of the module specified in RootModule/ModuleToProcess # Modules to import as nested modules of the module specified in RootModule/ModuleToProcess
# NestedModules = @() # NestedModules = @()
# Functions to export from this module # Functions to export from this module
FunctionsToExport = '*' FunctionsToExport = '*'
# Cmdlets to export from this module # Cmdlets to export from this module
CmdletsToExport = '*' CmdletsToExport = '*'
# Variables to export from this module # Variables to export from this module
VariablesToExport = '*' VariablesToExport = '*'
# Aliases to export from this module # Aliases to export from this module
AliasesToExport = '*' AliasesToExport = '*'
# List of all modules packaged with this module # List of all modules packaged with this module
# ModuleList = @() # ModuleList = @()
# List of all files packaged with this module # List of all files packaged with this module
# FileList = @() # FileList = @()
# Private data to pass to the module specified in RootModule/ModuleToProcess # Private data to pass to the module specified in RootModule/ModuleToProcess
PrivateData = @{ PrivateData = @{
# PSData is module packaging and gallery metadata embedded in PrivateData # PSData is module packaging and gallery metadata embedded in PrivateData
# It's for rebuilding PowerShellGet (and PoshCode) NuGet-style packages # It's for rebuilding PowerShellGet (and PoshCode) NuGet-style packages
# We had to do this because it's the only place we're allowed to extend the manifest # We had to do this because it's the only place we're allowed to extend the manifest
@@ -89,7 +89,7 @@ PrivateData = @{
Category = "Scripting Excel" Category = "Scripting Excel"
# Keyword tags to help users find this module via navigations and search. # Keyword tags to help users find this module via navigations and search.
Tags = @("Excel","EPPlus","Export","Import") Tags = @("Excel", "EPPlus", "Export", "Import")
# The web address of an icon which can be used in galleries to represent this module # The web address of an icon which can be used in galleries to represent this module
#IconUri = "http://pesterbdd.com/images/Pester.png" #IconUri = "http://pesterbdd.com/images/Pester.png"
@@ -109,12 +109,12 @@ PrivateData = @{
# Indicates this is a pre-release/testing version of the module. # Indicates this is a pre-release/testing version of the module.
IsPrerelease = 'False' IsPrerelease = 'False'
} }
} }
# HelpInfo URI of this module # HelpInfo URI of this module
# HelpInfoURI = '' # HelpInfoURI = ''
# Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix. # Default prefix for commands exported from this module. Override the default prefix using Import-Module -Prefix.
# DefaultCommandPrefix = '' # DefaultCommandPrefix = ''
} }

View File

@@ -63,7 +63,7 @@ function Import-Excel {
.DESCRIPTION .DESCRIPTION
The Import-Excel cmdlet creates custom objects from the rows in an Excel worksheet. Each row represents one object. All of this is possible without installing Microsoft Excel and by using the .NET library EPPLus.dll. The Import-Excel cmdlet creates custom objects from the rows in an Excel worksheet. Each row represents one object. All of this is possible without installing Microsoft Excel and by using the .NET library EPPLus.dll.
By default, the property names of the objects are retrieved from the column headers. Because an object cannot have a blanc property name, only columns with column headers will be imported. By default, the property names of the objects are retrieved from the column headers. Because an object cannot have a blank property name, only columns with column headers will be imported.
If the default behavior is not desired and you want to import the complete worksheet as is, the parameter -NoHeader can be used. In case you want to provide your own property names, you can use the parameter -HeaderName. If the default behavior is not desired and you want to import the complete worksheet as is, the parameter -NoHeader can be used. In case you want to provide your own property names, you can use the parameter -HeaderName.
@@ -221,7 +221,7 @@ function Import-Excel {
Notice that empty rows and empty columns are not imported. Notice that empty rows and empty columns are not imported.
.EXAMPLE .EXAMPLE
Import data from an Excel worksheet. One object is created for each row. The property names are provided with the -HeaderName parameter. The import will start from row 2 and empty columns and rows are not imported. Import data from an Excel worksheet. One object is created for each row. The property names are provided with the -HeaderName parameter. The import will start from row 2 and empty columns and rows are not imported.
---------------------------------------------------------- ----------------------------------------------------------
@@ -241,6 +241,16 @@ function Import-Excel {
Notice that only 1 object is imported with only 3 properties. Column B and row 2 are empty and have been disregarded by using the switch '-DataOnly'. The property names have been named with the values provided with the parameter '-HeaderName'. Row number 1 with Chuck Norris has not been imported, because we started the import from row 2 with the parameter -StartRow 2. Notice that only 1 object is imported with only 3 properties. Column B and row 2 are empty and have been disregarded by using the switch '-DataOnly'. The property names have been named with the values provided with the parameter '-HeaderName'. Row number 1 with Chuck Norris has not been imported, because we started the import from row 2 with the parameter -StartRow 2.
.EXAMPLE
>
PS> ,(Import-Excel -Path .\SysTables_AdventureWorks2014.xlsx) |
Write-SqlTableData -ServerInstance localhost\DEFAULT -Database BlankDB -SchemaName dbo -TableName MyNewTable_fromExcel -Force
Imports data from an Excel file and pipe the data to the Write-SqlTableData to be INSERTed into a table in a SQL Server database.
The ",( ... )" around the Import-Excel command allows all rows to be imported from the Excel file, prior to pipelining to the Write-SqlTableData cmdlet. This helps prevent a RBAR scenario and is important when trying to import thousands of rows.
The -Force parameter will be ignored if the table already exists. However, if a table is not found that matches the values provided by -SchemaName and -TableName parameters, it will create a new table in SQL Server database. The Write-SqlTableData cmdlet will inherit the column names & datatypes for the new table from the object being piped in.
NOTE: You need to install the SqlServer module from the PowerShell Gallery in oder to get the Write-SqlTableData cmdlet.
.LINK .LINK
https://github.com/dfinke/ImportExcel https://github.com/dfinke/ImportExcel
@@ -394,12 +404,13 @@ function Import-Excel {
else { else {
#region Create one object per row #region Create one object per row
foreach ($R in $Rows) { foreach ($R in $Rows) {
Write-Verbose "Import row '$R'" #Disabled write-verbose for speed
# Write-Verbose "Import row '$R'"
$NewRow = [Ordered]@{} $NewRow = [Ordered]@{}
foreach ($P in $PropertyNames) { foreach ($P in $PropertyNames) {
$NewRow[$P.Value] = $Worksheet.Cells[$R, $P.Column].Value $NewRow[$P.Value] = $Worksheet.Cells[$R, $P.Column].Value
Write-Verbose "Import cell '$($Worksheet.Cells[$R, $P.Column].Address)' with property name '$($p.Value)' and value '$($Worksheet.Cells[$R, $P.Column].Value)'." # Write-Verbose "Import cell '$($Worksheet.Cells[$R, $P.Column].Address)' with property name '$($p.Value)' and value '$($Worksheet.Cells[$R, $P.Column].Value)'."
} }
[PSCustomObject]$NewRow [PSCustomObject]$NewRow

View File

@@ -68,7 +68,7 @@ function Invoke-AllTests {
) )
$resultCount=0 $resultCount=0
$tests.GetEnumerator() | ForEach { $tests.GetEnumerator() | ForEach-Object {
$result=& $_.Value $target $result=& $_.Value $target

View File

@@ -1,47 +1,3 @@
<# $fullPath = 'C:\Program Files\WindowsPowerShell\Modules\ImportExcel'
.SYNOPSIS
Install the module in the PowerShell module folder.
.DESCRIPTION Robocopy . $fullPath /mir /XD .vscode .git examples testimonials images spikes /XF appveyor.yml .gitattributes .gitignore
Install the module in the PowerShell module folder by copying all the files.
#>
[CmdLetBinding()]
Param (
[ValidateNotNullOrEmpty()]
[String]$ModuleName = 'ImportExcel',
[ValidateScript({Test-Path -Path $_ -Type Container})]
[String]$ModulePath = 'C:\Program Files\WindowsPowerShell\Modules'
)
Begin {
Try {
Write-Verbose "$ModuleName module installation started"
$Files = Get-Content $PSScriptRoot\filelist.txt
}
Catch {
throw "Failed installing the module '$ModuleName': $_"
}
}
Process {
Try {
$TargetPath = Join-Path -Path $ModulePath -ChildPath $ModuleName
if (-not (Test-Path $TargetPath)) {
New-Item -Path $TargetPath -ItemType Directory -EA Stop | Out-Null
Write-Verbose "$ModuleName created module folder '$TargetPath'"
}
Get-ChildItem $Files | ForEach-Object {
Copy-Item -Path $_.FullName -Destination "$($TargetPath)\$($_.Name)"
Write-Verbose "$ModuleName installed module file '$($_.Name)'"
}
Write-Verbose "$ModuleName module installation successful"
}
Catch {
throw "Failed installing the module '$ModuleName': $_"
}
}

View File

@@ -3,39 +3,48 @@
.SYNOPSIS .SYNOPSIS
Combines data on all the sheets in an Excel worksheet onto a single sheet. Combines data on all the sheets in an Excel worksheet onto a single sheet.
.DESCRIPTION .DESCRIPTION
Join worksheet can work in two main ways: Join-Worksheet can work in two main ways, either
Either Combining data which has the same layout from many pages into one, or combining pages which have nothing in common. Combining data which has the same layout from many pages into one, or
In the former case the header row is copied from the first sheet and, by default, each row of data is labelled with the name of the sheet it came from. combining pages which have nothing in common.
In the latter case -NoHeader is specified, and each copied block can have the sheet it came from placed above it as a title. In the former case the header row is copied from the first sheet and,
.EXAMPLE by default, each row of data is labelled with the name of the sheet it came from.
In the latter case -NoHeader is specified, and each copied block can have the
sheet it came from placed above it as a title.
.EXAMPLE .EXAMPLE
> >
PS> foreach ($computerName in @('Server1', 'Server2', 'Server3', 'Server4')) { PS> foreach ($computerName in @('Server1', 'Server2', 'Server3', 'Server4')) {
Get-Service -ComputerName $computerName | Select-Object -Property Status, Name, DisplayName, StartType | Get-Service -ComputerName $computerName | Select-Object -Property Status, Name, DisplayName, StartType |
Export-Excel -Path .\test.xlsx -WorkSheetname $computerName -AutoSize Export-Excel -Path .\test.xlsx -WorkSheetname $computerName -AutoSize
} }
$ptDef =New-PivotTableDefinition -PivotTableName "Pivot1" -SourceWorkSheet "Combined" -PivotRows "Status" -PivotFilter "MachineName" -PivotData @{Status='Count'} -IncludePivotChart -ChartType BarClustered3D PS> $ptDef =New-PivotTableDefinition -PivotTableName "Pivot1" -SourceWorkSheet "Combined" -PivotRows "Status" -PivotFilter "MachineName" -PivotData @{Status='Count'} -IncludePivotChart -ChartType BarClustered3D
Join-Worksheet -Path .\test.xlsx -WorkSheetName combined -FromLabel "MachineName" -HideSource -AutoSize -FreezeTopRow -BoldTopRow -PivotTableDefinition $pt -Show PS> Join-Worksheet -Path .\test.xlsx -WorkSheetName combined -FromLabel "MachineName" -HideSource -AutoSize -FreezeTopRow -BoldTopRow -PivotTableDefinition $pt -Show
The foreach command gets the services running on four servers and exports each to its own page in Test.xlsx. The foreach command gets the services running on four servers and exports each
$PtDef= creates a defintion for a single Pivot table. to its own page in Test.xlsx.
The Join-Worksheet command uses the same file and merges the results onto a sheet named "Combined". It sets a column header of "Machinename", $PtDef= creates a definition for a PivotTable.
this column will contain the name of the sheet the data was copied from; after copying the data to the sheet "combined", the other sheets will be hidden. The Join-Worksheet command uses the same file and merges the results into a sheet
Join-Worksheet finishes by calling export-Excel to AutoSize cells, freeze the top row and make it bold and add the Pivot table. named "Combined". It sets a column header of "Machinename", this column will
contain the name of the sheet the data was copied from; after copying the data
to the sheet "Combined", the other sheets will be hidden.
Join-Worksheet finishes by calling Export-Excel to AutoSize cells, freeze the
top row and make it bold and add thePivotTable.
.EXAMPLE .EXAMPLE
> >
PS> Get-WmiObject -Class win32_logicaldisk | select -Property DeviceId,VolumeName, Size,Freespace | PS> Get-WmiObject -Class win32_logicaldisk | Select-Object -Property DeviceId,VolumeName, Size,Freespace |
Export-Excel -Path "$env:computerName.xlsx" -WorkSheetname Volumes -NumberFormat "0,000" Export-Excel -Path "$env:computerName.xlsx" -WorkSheetname Volumes -NumberFormat "0,000"
Get-NetAdapter | Select-Object Name,InterfaceDescription,MacAddress,LinkSpeed | PS> Get-NetAdapter | Select-Object Name,InterfaceDescription,MacAddress,LinkSpeed |
Export-Excel -Path "$env:COMPUTERNAME.xlsx" -WorkSheetname NetAdapter Export-Excel -Path "$env:COMPUTERNAME.xlsx" -WorkSheetname NetAdapter
Join-Worksheet -Path "$env:COMPUTERNAME.xlsx" -WorkSheetName Summary -Title "Summary" -TitleBold -TitleSize 22 -NoHeader -LabelBlocks -AutoSize -HideSource -show PS> Join-Worksheet -Path "$env:COMPUTERNAME.xlsx" -WorkSheetName Summary -Title "Summary" -TitleBold -TitleSize 22 -NoHeader -LabelBlocks -AutoSize -HideSource -show
The first two commands get logical disk and network card information; each type is exported to its own sheet in a workbook. The first two commands get logical-disk and network-card information; each type
The Join-worksheet command copies both onto a page named "Summary". Because the data is disimilar -NoHeader is specified, ensuring the whole of each page is copied. is exported to its own sheet in a workbook.
Specifying -LabelBlocks causes each sheet's name to become a title on the summary page above the copied data. The Join-Worksheet command copies both onto a page named "Summary". Because
The source data is hidden, a title is added in 22 point boldface and the columns are sized to fit the data. the data is dissimilar, -NoHeader is specified, ensuring the whole of each
page is copied. Specifying -LabelBlocks causes each sheet's name to become
a title on the summary page above the copied data. The source data is
hidden, a title is added in 22 point boldface and the columns are sized
to fit the data.
#> #>
[CmdletBinding(DefaultParameterSetName = 'Default')] [CmdletBinding(DefaultParameterSetName = 'Default')]
param ( param (
@@ -43,21 +52,21 @@
[Parameter(ParameterSetName = "Default", Position = 0)] [Parameter(ParameterSetName = "Default", Position = 0)]
[Parameter(ParameterSetName = "Table" , Position = 0)] [Parameter(ParameterSetName = "Table" , Position = 0)]
[String]$Path , [String]$Path ,
# An object representing an Excel Package - usually this is returned by specifying -Passthru allowing multiple commands to work on the same Workbook without saving and reloading each time. # An object representing an Excel Package - either from Open-Excel Package or specifying -PassThru to Export-Excel.
[Parameter(Mandatory = $true, ParameterSetName = "PackageDefault")] [Parameter(Mandatory = $true, ParameterSetName = "PackageDefault")]
[Parameter(Mandatory = $true, ParameterSetName = "PackageTable")] [Parameter(Mandatory = $true, ParameterSetName = "PackageTable")]
[OfficeOpenXml.ExcelPackage]$ExcelPackage, [OfficeOpenXml.ExcelPackage]$ExcelPackage,
# The name of a sheet within the workbook where the other sheets will be joined together - "Combined" by default. # The name of a sheet within the workbook where the other sheets will be joined together - "Combined" by default.
$WorkSheetName = 'Combined', $WorkSheetName = 'Combined',
# If specified any pre-existing target for the joined data will be deleted and re-created; otherwise data will be appended on this sheet. # If specified ,any pre-existing target for the joined data will be deleted and re-created; otherwise data will be appended on this sheet.
[switch]$Clearsheet, [switch]$Clearsheet,
#Join-Worksheet assumes each sheet has identical headers and the headers should be copied to the target sheet, unless -NoHeader is specified. #Join-Worksheet assumes each sheet has identical headers and the headers should be copied to the target sheet, unless -NoHeader is specified.
[switch]$NoHeader, [switch]$NoHeader,
#If -NoHeader is NOT specified, then rows of data will be labeled with the name of the sheet they came, FromLabel is the header for this column. If it is null or empty, the labels will be omitted. #If -NoHeader is NOT specified, then rows of data will be labeled with the name of the sheet they came from. FromLabel is the header for this column. If it is null or empty, the labels will be omitted.
$FromLabel = "From" , [string]$FromLabel = "From" ,
#If specified, the copied blocks of data will have the name of the sheet they were copied from inserted above them as a title. #If specified, the copied blocks of data will have the name of the sheet they were copied from inserted above them as a title.
[switch]$LabelBlocks, [switch]$LabelBlocks,
#Sizes the width of the Excel column to the maximum width needed to display all the containing data in that cell. #Sets the width of the Excel columns to display all the data in their cells.
[Switch]$AutoSize, [Switch]$AutoSize,
#Freezes headers etc. in the top row. #Freezes headers etc. in the top row.
[Switch]$FreezeTopRow, [Switch]$FreezeTopRow,
@@ -67,25 +76,25 @@
[Switch]$FreezeTopRowFirstColumn, [Switch]$FreezeTopRowFirstColumn,
# Freezes panes at specified coordinates (in the form RowNumber , ColumnNumber). # Freezes panes at specified coordinates (in the form RowNumber , ColumnNumber).
[Int[]]$FreezePane, [Int[]]$FreezePane,
#Enables the 'Filter' in Excel on the complete header row. So users can easily sort, filter and/or search the data in the select column from within Excel. #Enables the Excel filter on the headers of the combined sheet.
[Parameter(ParameterSetName = 'Default')] [Parameter(ParameterSetName = 'Default')]
[Parameter(ParameterSetName = 'PackageDefault')] [Parameter(ParameterSetName = 'PackageDefault')]
[Switch]$AutoFilter, [Switch]$AutoFilter,
#Makes the top Row boldface. #Makes the top row boldface.
[Switch]$BoldTopRow, [Switch]$BoldTopRow,
#If Specified hides the sheets that the data is copied from. #If specified, hides the sheets that the data is copied from.
[switch]$HideSource, [switch]$HideSource,
#Text of a title to be placed in Cell A1. #Text of a title to be placed in Cell A1.
[String]$Title, [String]$Title,
#Sets the fill pattern for the title cell. #Sets the fill pattern for the title cell.
[OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'None', [OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'Solid',
#Sets the cell background color for the title cell. #Sets the cell background color for the title cell.
[System.Drawing.Color]$TitleBackgroundColor, $TitleBackgroundColor,
#Sets the title in boldface type. #Sets the title in boldface type.
[Switch]$TitleBold, [Switch]$TitleBold,
#Sets the point size for the title. #Sets the point size for the title.
[Int]$TitleSize = 22, [Int]$TitleSize = 22,
#Hashtable(s) with Sheet PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values to specify a definition for one or more pivot table(s). #Hashtable(s) with Sheet PivotRows, PivotColumns, PivotData, IncludePivotChart and ChartType values to specify a definition for one or morePivotTable(s).
[Hashtable]$PivotTableDefinition, [Hashtable]$PivotTableDefinition,
#A hashtable containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-pivot] charts. #A hashtable containing ChartType, Title, NoLegend, ShowCategory, ShowPercent, Yrange, Xrange and SeriesHeader for one or more [non-pivot] charts.
[Object[]]$ExcelChartDefinition, [Object[]]$ExcelChartDefinition,
@@ -109,13 +118,13 @@
})] })]
[Parameter(ParameterSetName = 'Table' , Mandatory = $true)] [Parameter(ParameterSetName = 'Table' , Mandatory = $true)]
[Parameter(ParameterSetName = 'PackageTable' , Mandatory = $true)] [Parameter(ParameterSetName = 'PackageTable' , Mandatory = $true)]
# Makes the data in the worksheet a table with a name applies a style to it. Name must not contain spaces. # Makes the data in the worksheet a table with a name and applies a style to it. Name must not contain spaces.
[String]$TableName, [String]$TableName,
[Parameter(ParameterSetName = 'Table')] [Parameter(ParameterSetName = 'Table')]
[Parameter(ParameterSetName = 'PackageTable')] [Parameter(ParameterSetName = 'PackageTable')]
#Selects the style for the named table - defaults to 'Medium6'. #Selects the style for the named table - defaults to "Medium6".
[OfficeOpenXml.Table.TableStyles]$TableStyle = 'Medium6', [OfficeOpenXml.Table.TableStyles]$TableStyle = 'Medium6',
#Selects the style for the named table - defaults to 'Medium6'. #If specified, returns the range of cells in the combined sheet, in the format "A1:Z100".
[switch]$ReturnRange, [switch]$ReturnRange,
#Opens the Excel file immediately after creation. Convenient for viewing the results instantly without having to search for the file first. #Opens the Excel file immediately after creation. Convenient for viewing the results instantly without having to search for the file first.
[switch]$Show, [switch]$Show,
@@ -140,6 +149,7 @@
if ($TitleBold) {$destinationSheet.Cells[1, 1].Style.Font.Bold = $True } if ($TitleBold) {$destinationSheet.Cells[1, 1].Style.Font.Bold = $True }
#Can only set TitleBackgroundColor if TitleFillPattern is something other than None. #Can only set TitleBackgroundColor if TitleFillPattern is something other than None.
if ($TitleBackgroundColor -AND ($TitleFillPattern -ne 'None')) { if ($TitleBackgroundColor -AND ($TitleFillPattern -ne 'None')) {
if ($TitleBackgroundColor -is [string]) {$TitleBackgroundColor = [System.Drawing.Color]::$TitleBackgroundColor }
$destinationSheet.Cells[1, 1].Style.Fill.PatternType = $TitleFillPattern $destinationSheet.Cells[1, 1].Style.Fill.PatternType = $TitleFillPattern
$destinationSheet.Cells[1, 1].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor) $destinationSheet.Cells[1, 1].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor)
} }
@@ -151,6 +161,7 @@
#Assume every row has titles in row 1, copy row 1 from first sheet to new sheet. #Assume every row has titles in row 1, copy row 1 from first sheet to new sheet.
$destinationSheet.Select("A$row") $destinationSheet.Select("A$row")
$ExcelPackage.Workbook.Worksheets[1].cells["1:1"].Copy($destinationSheet.SelectedRange) $ExcelPackage.Workbook.Worksheets[1].cells["1:1"].Copy($destinationSheet.SelectedRange)
#fromlabel can't be an empty string
if ($FromLabel ) { if ($FromLabel ) {
#Add a column which says where the data comes from. #Add a column which says where the data comes from.
$fromColumn = ($destinationSheet.Dimension.Columns + 1) $fromColumn = ($destinationSheet.Dimension.Columns + 1)

View File

@@ -1,84 +1,103 @@
Function Merge-Worksheet { Function Merge-Worksheet {
<# <#
.Synopsis .Synopsis
Merges two worksheets (or other objects) into a single worksheet with differences marked up. Merges two Worksheets (or other objects) into a single Worksheet with differences marked up.
.Description .Description
The Compare-Worksheet command takes two worksheets and marks differences in the source document, and optionally outputs a grid showing the changes. The Compare-Worksheet command takes two Worksheets and marks differences in the source document, and optionally outputs a grid showing the changes.
By contrast the Merge-Worksheet command takes the worksheets and combines them into a single sheet showing the old and new data side by side . By contrast the Merge-Worksheet command takes the Worksheets and combines them into a single sheet showing the old and new data side by side.
Although it is designed to work with Excel data it can work with arrays of any kind of object; so it can be a merge *of* worksheets, or a merge *to* worksheet. Although it is designed to work with Excel data it can work with arrays of any kind of object; so it can be a merge *of* Worksheets, or a merge *to* a Worksheet.
.Example .Example
merge-worksheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -show Merge-Worksheet "Server54.xlsx" "Server55.xlsx" -WorksheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -show
The workbooks contain audit information for two servers, one page contains a list of services. This command creates a worksheet named 54-55 The workbooks contain audit information for two servers, one sheet contains
in a workbook named services which shows all the services and their differences, and opens it in Excel. a list of services. This command creates a worksheet named "54-55" in a
workbook named "services.xlsx" which shows all the services and their
differences, and opens the new workbook in Excel.
.Example .Example
merge-worksheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -HideEqual -AddBackgroundColor LightBlue -show Merge-Worksheet "Server54.xlsx" "Server55.xlsx" -WorksheetName services -OutputFile Services.xlsx -OutputSheetName 54-55 -HideEqual -AddBackgroundColor LightBlue -show
This modifies the previous command to hide the equal rows in the output sheet and changes the color used to mark rows added to the second file. This modifies the previous command to hide the equal rows in the output
sheet and changes the color used to mark rows added to the second file.
.Example .Example
merge-worksheet -OutputFile .\j1.xlsx -OutputSheetName test11 -ReferenceObject (dir .\ImportExcel\4.0.7) -DifferenceObject (dir .\ImportExcel\4.0.8) -Property Length -Show Merge-Worksheet -OutputFile .\j1.xlsx -OutputSheetName test11 -ReferenceObject (dir .\ImportExcel\4.0.7) -DifferenceObject (dir .\ImportExcel\4.0.8) -Property Length -Show
This version compares two directories, and marks what has changed. This version compares two directories, and marks what has changed.
Because no "Key" property is given, "Name" is assumed to be the key and the only other property examined is length. Because no "Key" property is given, "Name" is assumed to be the key
Files which are added or deleted or have changed size will be highlighed in the output sheet. Changes to dates or other attributes will be ignored. and the only other property examined is length. Files which are added
or deleted or have changed size will be highlighed in the output sheet.
Changes to dates or other attributes will be ignored.
.Example .Example
merge-worksheet -RefO (dir .\ImportExcel\4.0.7) -DiffO (dir .\ImportExcel\4.0.8) -Pr Length | Out-GridView Merge-Worksheet -RefO (dir .\ImportExcel\4.0.7) -DiffO (dir .\ImportExcel\4.0.8) -Pr Length | Out-GridView
This time no file is written and the results -which include all properties, not just length, are output and sent to Out-Gridview. This time no file is written and the results - which include all properties,
This version uses aliases to shorten the parameters, not just length, are output and sent to Out-Gridview. This version uses
(OutputFileName can be "outFile" and the sheet "OutSheet" : DifferenceObject & ReferenceObject can be DiffObject & RefObject). aliases to shorten the parameters, (OutputFileName can be "outFile" and
the Sheet can be"OutSheet"; DifferenceObject & ReferenceObject can be
DiffObject & RefObject respectively).
#> #>
[cmdletbinding(SupportsShouldProcess=$true)] [cmdletbinding(SupportsShouldProcess=$true)]
Param( Param(
#First Excel file to compare. You can compare two Excel files or two other objects but not one of each. #First Excel file to compare. You can compare two Excel files or two other objects or a reference obhct against a difference file, but not a reference file against an object.
[parameter(ParameterSetName='A',Mandatory=$true,Position=0)] [parameter(ParameterSetName='A',Mandatory=$true,Position=0)] #A = Compare two files default headers
[parameter(ParameterSetName='B',Mandatory=$true,Position=0)] [parameter(ParameterSetName='B',Mandatory=$true,Position=0)] #B = Compare two files user supplied headers
[parameter(ParameterSetName='C',Mandatory=$true,Position=0)] [parameter(ParameterSetName='C',Mandatory=$true,Position=0)] #C = Compare two files headers P1, P2, P3 etc
$Referencefile , $Referencefile ,
#Second Excel file to compare. #Second Excel file to compare.
[parameter(ParameterSetName='A',Mandatory=$true,Position=1)] [parameter(ParameterSetName='A',Mandatory=$true,Position=1)]
[parameter(ParameterSetName='B',Mandatory=$true,Position=1)] [parameter(ParameterSetName='B',Mandatory=$true,Position=1)]
[parameter(ParameterSetName='C',Mandatory=$true,Position=1)] [parameter(ParameterSetName='C',Mandatory=$true,Position=1)]
[parameter(ParameterSetName='E',Mandatory=$true,Position=1)] [parameter(ParameterSetName='E',Mandatory=$true,Position=1)] #D Compare two objects; E = Compare one object one file that uses default headers
[parameter(ParameterSetName='F',Mandatory=$true,Position=1)] #F = Compare one object one file that uses user supplied headers
[parameter(ParameterSetName='G',Mandatory=$true,Position=1)] #G Compare one object one file that uses headers P1, P2, P3 etc
$Differencefile , $Differencefile ,
#Name(s) of worksheets to compare, #Name(s) of Worksheets to compare.
[parameter(ParameterSetName='A',Position=2)] [parameter(ParameterSetName='A',Position=2)] #Applies to all sets EXCEPT D which is two objects (no sheets)
[parameter(ParameterSetName='B',Position=2)] [parameter(ParameterSetName='B',Position=2)]
[parameter(ParameterSetName='C',Position=2)] [parameter(ParameterSetName='C',Position=2)]
[parameter(ParameterSetName='E',Position=2)] [parameter(ParameterSetName='E',Position=2)]
$WorkSheetName = "Sheet1", [parameter(ParameterSetName='F',Position=2)]
[parameter(ParameterSetName='G',Position=2)]
$WorksheetName = "Sheet1",
#The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. #The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row.
[parameter(ParameterSetName='A')] [parameter(ParameterSetName='A')] #Applies to all sets EXCEPT D which is two objects (no sheets, so no start row )
[parameter(ParameterSetName='B')] [parameter(ParameterSetName='B')]
[parameter(ParameterSetName='C')] [parameter(ParameterSetName='C')]
[parameter(ParameterSetName='E')] [parameter(ParameterSetName='E')]
[parameter(ParameterSetName='F')]
[parameter(ParameterSetName='G')]
[int]$Startrow = 1, [int]$Startrow = 1,
#Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. #Specifies custom property names to use, instead of the values defined in the column headers of the Start ROw.
[Parameter(ParameterSetName='B',Mandatory=$true)] [Parameter(ParameterSetName='B',Mandatory=$true)] #Compare object + sheet or 2 sheets with user supplied headers
[Parameter(ParameterSetName='F',Mandatory=$true)]
[String[]]$Headername, [String[]]$Headername,
#Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet. #Automatically generate property names (P1, P2, P3, ..) instead of using the values the top row of the sheet.
[Parameter(ParameterSetName='C',Mandatory=$true)] [Parameter(ParameterSetName='C',Mandatory=$true)] #Compare object + sheet or 2 sheets with headers of P1, P2, P3 ...
[Parameter(ParameterSetName='G',Mandatory=$true)]
[switch]$NoHeader, [switch]$NoHeader,
#Object to compare if a worksheet is NOT being used. #Reference object to compare if a Worksheet is NOT being used. Reference object can combine with a difference sheet or difference object
[parameter(ParameterSetName='D',Mandatory=$true)] [parameter(ParameterSetName='D',Mandatory=$true)]
[parameter(ParameterSetName='E',Mandatory=$true)] [parameter(ParameterSetName='E',Mandatory=$true)]
[parameter(ParameterSetName='F',Mandatory=$true)]
[parameter(ParameterSetName='G',Mandatory=$true)]
[Alias('RefObject')] [Alias('RefObject')]
$ReferenceObject , $ReferenceObject ,
#Object to compare if a worksheet is NOT being used. #Difference object to compare if a Worksheet is NOT being used for either half. Can't have a reference sheet and difference object.
[parameter(ParameterSetName='D',Mandatory=$true,Position=1)] [parameter(ParameterSetName='D',Mandatory=$true,Position=1)]
[Alias('DiffObject')] [Alias('DiffObject')]
$DifferenceObject , $DifferenceObject ,
[parameter(ParameterSetName='D',Position=2)] [parameter(ParameterSetName='D',Position=2)]
[parameter(ParameterSetName='E',Position=3)] [parameter(ParameterSetName='E',Position=2)]
[parameter(ParameterSetName='F',Position=2)]
[parameter(ParameterSetName='G',Position=2)]
#If there isn't a filename to use to label data from the "Difference" side, DiffPrefix is used, it defaults to "=>" #If there isn't a filename to use to label data from the "Difference" side, DiffPrefix is used, it defaults to "=>"
$DiffPrefix = "=>" , $DiffPrefix = "=>" ,
#File to hold merged data. #File to hold merged data.
[parameter(Position=3)] [parameter(Position=3)]
[Alias('OutFile')] [Alias('OutFile')]
$OutputFile , $OutputFile ,
#Name of worksheet to output - if none specified will use the reference worksheet name. #Name of Worksheet to output - if none specified will use the reference Worksheet name.
[parameter(Position=4)] [parameter(Position=4)]
[Alias('OutSheet')] [Alias('OutSheet')]
$OutputSheetName = "Sheet1", $OutputSheetName = "Sheet1",
@@ -89,51 +108,54 @@
#Name of a column which is unique used to pair up rows from the refence and difference side, default is "Name". #Name of a column which is unique used to pair up rows from the refence and difference side, default is "Name".
$Key = "Name" , $Key = "Name" ,
#Sets the font color for the "key" field; this means you can filter by color to get only changed rows. #Sets the font color for the "key" field; this means you can filter by color to get only changed rows.
[System.Drawing.Color]$KeyFontColor = "DarkRed", $KeyFontColor = [System.Drawing.Color]::DarkRed ,
#Sets the background color for changed rows. #Sets the background color for changed rows.
[System.Drawing.Color]$ChangeBackgroundColor = "Orange", $ChangeBackgroundColor = [System.Drawing.Color]::Orange,
#Sets the background color for rows in the reference but deleted from the difference sheet. #Sets the background color for rows in the reference but deleted from the difference sheet.
[System.Drawing.Color]$DeleteBackgroundColor = "LightPink", $DeleteBackgroundColor = [System.Drawing.Color]::LightPink,
#Sets the background color for rows not in the reference but added to the difference sheet. #Sets the background color for rows not in the reference but added to the difference sheet.
[System.Drawing.Color]$AddBackgroundColor = "PaleGreen", $AddBackgroundColor = [System.Drawing.Color]::PaleGreen,
#if Specified hides the rows in the spreadsheet that are equal and only shows changes, added or deleted rows. #if specified, hides the rows in the spreadsheet that are equal and only shows changes, added or deleted rows.
[switch]$HideEqual , [switch]$HideEqual ,
#If specified outputs the data to the pipeline (you can add -whatif so it the command only outputs to the pipeline). #If specified, outputs the data to the pipeline (you can add -WhatIf so the command only outputs to the pipeline).
[switch]$Passthru , [switch]$Passthru ,
#If specified, opens the output workbook. #If specified, opens the output workbook.
[Switch]$Show [Switch]$Show
) )
#region Read Excel data #region Read Excel data
if ($Differencefile -is [System.IO.FileInfo]) {$Differencefile = $Differencefile.FullName}
if ($Referencefile -is [System.IO.FileInfo]) {$Referencefile = $Referencefile.FullName}
if ($Referencefile -and $Differencefile) { if ($Referencefile -and $Differencefile) {
#if the filenames don't resolve, give up now. #if the filenames don't resolve, give up now.
try { $oneFile = ((Resolve-Path -Path $Referencefile -ErrorAction Stop).path -eq (Resolve-Path -Path $Differencefile -ErrorAction Stop).path)} try { $oneFile = ((Resolve-Path -Path $Referencefile -ErrorAction Stop).path -eq (Resolve-Path -Path $Differencefile -ErrorAction Stop).path)}
Catch { Write-Warning -Message "Could not Resolve the filenames." ; return } Catch { Write-Warning -Message "Could not Resolve the filenames." ; return }
#If we have one file , we must have two different worksheet names. If we have two files $worksheetName can be a single string or two strings. #If we have one file , we must have two different Worksheet names. If we have two files $WorksheetName can be a single string or two strings.
if ($onefile -and ( ($WorkSheetName.count -ne 2) -or $WorkSheetName[0] -eq $WorkSheetName[1] ) ) { if ($onefile -and ( ($WorksheetName.count -ne 2) -or $WorksheetName[0] -eq $WorksheetName[1] ) ) {
Write-Warning -Message "If both the Reference and difference file are the same then worksheet name must provide 2 different names" Write-Warning -Message "If both the Reference and difference file are the same then Worksheet name must provide 2 different names"
return return
} }
if ($WorkSheetName.count -eq 2) {$workSheet2 = $DiffPrefix = $WorkSheetName[1] ; $worksheet1 = $WorkSheetName[0] ; } if ($WorksheetName.count -eq 2) {$Worksheet2 = $DiffPrefix = $WorksheetName[1] ; $Worksheet1 = $WorksheetName[0] ; }
elseif ($WorkSheetName -is [string]) {$worksheet2 = $workSheet1 = $WorkSheetName ; elseif ($WorksheetName -is [string]) {$Worksheet2 = $Worksheet1 = $WorksheetName ;
$DiffPrefix = (Split-Path -Path $Differencefile -Leaf) -replace "\.xlsx$","" } $DiffPrefix = (Split-Path -Path $Differencefile -Leaf) -replace "\.xlsx$","" }
else {Write-Warning -Message "You must provide either a single worksheet name or two names." ; return } else {Write-Warning -Message "You must provide either a single Worksheet name or two names." ; return }
$params= @{ ErrorAction = [System.Management.Automation.ActionPreference]::Stop } $params= @{ ErrorAction = [System.Management.Automation.ActionPreference]::Stop }
foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}} foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}}
try { try {
$ReferenceObject = Import-Excel -Path $Referencefile -WorksheetName $WorkSheet1 @params $ReferenceObject = Import-Excel -Path $Referencefile -WorksheetName $Worksheet1 @params
$DifferenceObject = Import-Excel -Path $Differencefile -WorksheetName $WorkSheet2 @Params $DifferenceObject = Import-Excel -Path $Differencefile -WorksheetName $Worksheet2 @Params
} }
Catch {Write-Warning -Message "Could not read the worksheet from $Referencefile::$worksheet1 and/or $Differencefile::$worksheet2." ; return } Catch {Write-Warning -Message "Could not read the Worksheet from $Referencefile::$Worksheet1 and/or $Differencefile::$Worksheet2." ; return }
if ($NoHeader) {$firstDataRow = $Startrow } else {$firstDataRow = $Startrow + 1} if ($NoHeader) {$firstDataRow = $Startrow } else {$firstDataRow = $Startrow + 1}
} }
elseif ( $Differencefile) { elseif ( $Differencefile) {
if ($WorkSheetName -isnot [string]) {Write-Warning -Message "You must provide a single worksheet name." ; return } if ($WorksheetName -isnot [string]) {Write-Warning -Message "You must provide a single Worksheet name." ; return }
$params = @{WorkSheetName=$WorkSheetName; Path=$Differencefile; ErrorAction = [System.Management.Automation.ActionPreference]::Stop ;} $params = @{WorksheetName=$WorksheetName; Path=$Differencefile; ErrorAction=[System.Management.Automation.ActionPreference]::Stop }
foreach ($p in @("HeaderName","NoHeader","StartRow")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}}
try {$DifferenceObject = Import-Excel @Params } try {$DifferenceObject = Import-Excel @Params }
Catch {Write-Warning -Message "Could not read the worksheet '$WorkSheetName' from $Differencefile::$WorkSheetName." ; return } Catch {Write-Warning -Message "Could not read the Worksheet '$WorksheetName' from $Differencefile::$WorksheetName." ; return }
if ($DiffPrefix -eq "=>" ) { if ($DiffPrefix -eq "=>" ) {
$DiffPrefix = (Split-Path -Path $Differencefile -Leaf) -replace "\.xlsx$","" $DiffPrefix = (Split-Path -Path $Differencefile -Leaf) -replace "\.xlsx$",""
} }
@@ -149,7 +171,7 @@
$headings = $DifferenceObject[0].psobject.Properties.Name # This preserves the sequence - using get-member would sort them alphabetically! There may be extra properties in $headings = $DifferenceObject[0].psobject.Properties.Name # This preserves the sequence - using get-member would sort them alphabetically! There may be extra properties in
if ($NoHeader -and "Name" -eq $Key) {$Key = "p1"} if ($NoHeader -and "Name" -eq $Key) {$Key = "p1"}
if ($headings -notcontains $Key -and if ($headings -notcontains $Key -and
('*' -ne $Key)) {Write-Warning -Message "You need to specify one of the headings in the sheet '$worksheet1' as a key." ; return } ('*' -ne $Key)) {Write-Warning -Message "You need to specify one of the headings in the sheet '$Worksheet1' as a key." ; return }
foreach ($p in $Property) { $propList += ($headings.where({$_ -like $p}) )} foreach ($p in $Property) { $propList += ($headings.where({$_ -like $p}) )}
foreach ($p in $ExcludeProperty) { $propList = $propList.where({$_ -notlike $p}) } foreach ($p in $ExcludeProperty) { $propList = $propList.where({$_ -notlike $p}) }
if (($propList -notcontains $Key) -and if (($propList -notcontains $Key) -and
@@ -199,19 +221,29 @@
else {$Rowhash[$row.$key] = $rowNo } else {$Rowhash[$row.$key] = $rowNo }
$rowNo ++ $rowNo ++
} }
if ($DifferenceObject.count -gt $Rowhash.Keys.Count) {
Write-Warning -Message "Difference object has $($DifferenceObject.Count) rows; but only $($Rowhash.keys.count) unique keys"
}
if ($Key -eq '*') {$key = "_ALL"} if ($Key -eq '*') {$key = "_ALL"}
#endregion #endregion
#We need to know all the properties we've met on the objects we've diffed
$eDiffProps = [ordered]@{}
#When we do a compare object changes will result in two rows so we group them and join them together.
$expandedDiff = Compare-Object -ReferenceObject $ReferenceObject -DifferenceObject $DifferenceObject -Property $propList -PassThru -IncludeEqual | $expandedDiff = Compare-Object -ReferenceObject $ReferenceObject -DifferenceObject $DifferenceObject -Property $propList -PassThru -IncludeEqual |
Group-Object -Property $key | ForEach-Object { Group-Object -Property $key | ForEach-Object {
#The value of the key column is the name of the group. #The value of the key column is the name of the Group.
$keyval = $_.name $keyval = $_.name
#we're going to create a custom object from a hash table. ??Might no longer need to preserve the field order #we're going to create a custom object from a hash table.
$hash = [ordered]@{} $hash = [ordered]@{}
foreach ($result in $_.Group) { foreach ($result in $_.Group) {
if ($result.SideIndicator -ne "=>") {$hash["_Row"] = $result._Row } if ($result.SideIndicator -ne "=>") {$hash["_Row"] = $result._Row }
elseif (-not $hash["$DiffPrefix Row"]) {$hash["_Row"] = "" } elseif (-not $hash["$DiffPrefix Row"]) {$hash["_Row"] = "" }
#if we have already set the side, be this must the second record, so set side to indicate "changed" #if we have already set the side, this must be the second record, so set side to indicate "changed"; if we got two "Same" indicators we may have a classh of keys
if ($hash.Side) {$hash.Side = "<>"} else {$hash["Side"] = $result.SideIndicator} if ($hash.Side) {
if ($hash.Side -eq $result.SideIndicator) {Write-Warning -Message "'$keyval' may be a duplicate."}
$hash.Side = "<>"
}
else {$hash["Side"] = $result.SideIndicator}
switch ($hash.side) { switch ($hash.side) {
'==' { $hash["$DiffPrefix is"] = 'Same' } '==' { $hash["$DiffPrefix is"] = 'Same' }
'=>' { $hash["$DiffPrefix is"] = 'Added' } '=>' { $hash["$DiffPrefix is"] = 'Added' }
@@ -224,7 +256,7 @@
} }
'<=' { $hash["$DiffPrefix is"] = 'Removed'} '<=' { $hash["$DiffPrefix is"] = 'Removed'}
} }
#find the number of the row in the the "difference" object which has this key. If it is the object is only the reference this will be blank. #find the number of the row in the the "difference" object which has this key. If it is the object is only in the reference this will be blank.
$hash["$DiffPrefix Row"] = $Rowhash[$keyval] $hash["$DiffPrefix Row"] = $Rowhash[$keyval]
$hash[$key] = $keyval $hash[$key] = $keyval
#Create FieldName and/or =>FieldName columns #Create FieldName and/or =>FieldName columns
@@ -236,6 +268,8 @@
elseif ($result.SideIndicator -eq "=>") { $hash[("$DiffPrefix $p")] = $result.$P} elseif ($result.SideIndicator -eq "=>") { $hash[("$DiffPrefix $p")] = $result.$P}
} }
} }
foreach ($k in $hash.keys) {$eDiffProps[$k] = $true}
[Pscustomobject]$hash [Pscustomobject]$hash
} | Sort-Object -Property "_row" } | Sort-Object -Property "_row"
@@ -246,35 +280,35 @@
$expandedDiff = $expandedDiff | Sort-Object -Property "$DiffPrefix Row" $expandedDiff = $expandedDiff | Sort-Object -Property "$DiffPrefix Row"
for ($i = 1; $i -lt $expandedDiff.Count; $i++) {if (-not $expandedDiff[$i]."_Row") {$expandedDiff[$i]."_Row" = $expandedDiff[$i-1]."_Row" } } for ($i = 1; $i -lt $expandedDiff.Count; $i++) {if (-not $expandedDiff[$i]."_Row") {$expandedDiff[$i]."_Row" = $expandedDiff[$i-1]."_Row" } }
$AllProps = @("_Row") + $OutputProps + $expandedDiff[0].psobject.properties.name.where({$_ -notin ($outputProps + @("_row","side","SideIndicator","_ALL" ))}) $AllProps = @("_Row") + $OutputProps + $eDiffProps.keys.where({$_ -notin ($outputProps + @("_row","side","SideIndicator","_ALL" ))})
if ($PassThru -or -not $OutputFile) {return ($expandedDiff | Select-Object -Property $allprops | Sort-Object -Property "_row", "$DiffPrefix Row" | Update-FirstObjectProperties ) } if ($PassThru -or -not $OutputFile) {return ($expandedDiff | Select-Object -Property $allprops | Sort-Object -Property "_row", "$DiffPrefix Row" ) }
elseif ($PSCmdlet.ShouldProcess($OutputFile,"Write Output to Excel file")) { elseif ($PSCmdlet.ShouldProcess($OutputFile,"Write Output to Excel file")) {
$expandedDiff = $expandedDiff | Sort-Object -Property "_row", "$DiffPrefix Row" $expandedDiff = $expandedDiff | Sort-Object -Property "_row", "$DiffPrefix Row"
$xl = $expandedDiff | Select-Object -Property $OutputProps | Update-FirstObjectProperties | $xl = $expandedDiff | Select-Object -Property $OutputProps | Update-FirstObjectProperties |
Export-Excel -Path $OutputFile -WorkSheetname $OutputSheetName -FreezeTopRow -BoldTopRow -AutoSize -AutoFilter -PassThru Export-Excel -Path $OutputFile -Worksheetname $OutputSheetName -FreezeTopRow -BoldTopRow -AutoSize -AutoFilter -PassThru
$ws = $xl.Workbook.Worksheets[$OutputSheetName] $ws = $xl.Workbook.Worksheets[$OutputSheetName]
for ($i = 0; $i -lt $expandedDiff.Count; $i++ ) { for ($i = 0; $i -lt $expandedDiff.Count; $i++ ) {
if ( $expandedDiff[$i].side -ne "==" ) { if ( $expandedDiff[$i].side -ne "==" ) {
Set-ExcelRange -WorkSheet $ws -Range ("A" + ($i + 2 )) -FontColor $KeyFontColor Set-ExcelRange -Worksheet $ws -Range ("A" + ($i + 2 )) -FontColor $KeyFontColor
} }
elseif ( $HideEqual ) {$ws.row($i+2).hidden = $true } elseif ( $HideEqual ) {$ws.row($i+2).hidden = $true }
if ( $expandedDiff[$i].side -eq "<>" ) { if ( $expandedDiff[$i].side -eq "<>" ) {
$range = $ws.Dimension -replace "\d+", ($i + 2 ) $range = $ws.Dimension -replace "\d+", ($i + 2 )
Set-ExcelRange -WorkSheet $ws -Range $range -BackgroundColor $ChangeBackgroundColor Set-ExcelRange -Worksheet $ws -Range $range -BackgroundColor $ChangeBackgroundColor
} }
elseif ( $expandedDiff[$i].side -eq "<=" ) { elseif ( $expandedDiff[$i].side -eq "<=" ) {
$rangeR1C1 = "R[{0}]C[1]:R[{0}]C[{1}]" -f ($i + 2 ) , $lastRefColNo $rangeR1C1 = "R[{0}]C[1]:R[{0}]C[{1}]" -f ($i + 2 ) , $lastRefColNo
$range = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1($rangeR1C1,0,0) $range = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1($rangeR1C1,0,0)
Set-ExcelRange -WorkSheet $ws -Range $range -BackgroundColor $DeleteBackgroundColor Set-ExcelRange -Worksheet $ws -Range $range -BackgroundColor $DeleteBackgroundColor
} }
elseif ( $expandedDiff[$i].side -eq "=>" ) { elseif ( $expandedDiff[$i].side -eq "=>" ) {
if ($propList.count -gt 1) { if ($propList.count -gt 1) {
$rangeR1C1 = "R[{0}]C[{1}]:R[{0}]C[{2}]" -f ($i + 2 ) , $FirstDiffColNo , $lastDiffColNo $rangeR1C1 = "R[{0}]C[{1}]:R[{0}]C[{2}]" -f ($i + 2 ) , $FirstDiffColNo , $lastDiffColNo
$range = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1($rangeR1C1,0,0) $range = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1($rangeR1C1,0,0)
Set-ExcelRange -WorkSheet $ws -Range $range -BackgroundColor $AddBackgroundColor Set-ExcelRange -Worksheet $ws -Range $range -BackgroundColor $AddBackgroundColor
} }
Set-ExcelRange -WorkSheet $ws -Range ("A" + ($i + 2 )) -BackgroundColor $AddBackgroundColor Set-ExcelRange -Worksheet $ws -Range ("A" + ($i + 2 )) -BackgroundColor $AddBackgroundColor
} }
} }
Close-ExcelPackage -ExcelPackage $xl -Show:$Show Close-ExcelPackage -ExcelPackage $xl -Show:$Show
@@ -284,82 +318,102 @@
Function Merge-MultipleSheets { Function Merge-MultipleSheets {
<# <#
.Synopsis .Synopsis
Merges worksheets into a single worksheet with differences marked up. Merges Worksheets into a single Worksheet with differences marked up.
.Description .Description
The Merge worksheet command combines 2 sheets. Merge-MultipleSheets is designed to merge more than 2. The Merge Worksheet command combines two sheets. Merge-MultipleSheets is
So if asked to merge sheets A,B,C which contain Services, with a Name, Displayname and Start mode, where "name" is treated as the key designed to merge more than two. So if asked to merge sheets A,B,C which
Merge-MultipleSheets calls Merge-Worksheet to merge Name, Displayname and Start mode, from sheets A and C contain Services, with a Name, Displayname and Start mode, where "Name" is
the result has column headings -Row, Name, DisplayName, Startmode, C-DisplayName, C-StartMode C-Is, C-Row treated as the key, Merge-MultipleSheets calls Merge-Worksheet to merge
Merge-MultipleSheets then calls Merge-Worsheet with this result and sheet B, comparing 'Name', 'Displayname' and 'Start mode' columns on each side "Name", "Displayname" and "Startmode" from sheets A and C; the result has
which outputs _Row, Name, DisplayName, Startmode, B-DisplayName, B-StartMode B-Is, B-Row, C-DisplayName, C-StartMode C-Is, C-Row column headings "_Row", "Name", "DisplayName", "Startmode", "C-DisplayName",
Any columns in the "reference" side which are not used in the comparison are appended on the right, which is we compare the sheets in reverse order. "C-StartMode", "C-Is" and "C-Row".
Merge-MultipleSheets then calls Merge-Worksheet again passing it the
intermediate result and sheet B, comparing "Name", "Displayname" and
"Start mode" columns on each side, and gets a result with columns "_Row",
"Name", "DisplayName", "Startmode", "B-DisplayName", "B-StartMode", "B-Is",
"B-Row", "C-DisplayName", "C-StartMode", "C-Is" and "C-Row". Any columns on
the "reference" side which are not used in the comparison are added on the
right, which is why we compare the sheets in reverse order.
The "Is" column holds "Same", "Added", "Removed" or "Changed" and is used for conditional formatting in the output sheet (this is hidden by default), The "Is" columns hold "Same", "Added", "Removed" or "Changed" and is used for
and when the data is written to Excel the "reference" columns, in this case "DisplayName" and "Start" are renamed to reflect their source, conditional formatting in the output sheet (these columns are hidden by default),
so become "A-DisplayName" and "A-Start". and when the data is written to Excel the "reference" columns, in this case
"DisplayName" and "Start" are renamed to reflect their source, so become
"A-DisplayName" and "A-Start".
Conditional formatting is also applied to the "key" column (name in this case) so the view can be filtered to rows with changes by filtering this column on color. Conditional formatting is also applied to the Key column ("Name" in this
case) so the view can be filtered to rows with changes by filtering this
column on color.
Note: the processing order can affect what is seen as a change. For example if there is an extra item in sheet B in the example above, Note: the processing order can affect what is seen as a change. For example
Sheet C will be processed and that row and will not be seen to be missing. When sheet B is processed it is marked as an addition, and the conditional formatting marks if there is an extra item in sheet B in the example above, Sheet C will be
the entries from sheet A to show that a values were added in at least one sheet. processed and that row and will not be seen to be missing. When sheet B is
However if Sheet B is the reference sheet, A and C will be seen to have an item removed; processed it is marked as an addition, and the conditional formatting marks
and if B is processed before C, the extra item is known when C is processed and so C is considered to be missing that item. the entries from sheet A to show that a values were added in at least one
sheet. However if Sheet B is the reference sheet, A and C will be seen to
have an item removed; and if B is processed before C, the extra item is
known when C is processed and so C is considered to be missing that item.
.Example .Example
dir Server*.xlsx | Merge-MulipleSheets -WorkSheetName Services -OutputFile Test2.xlsx -OutputSheetName Services -Show dir Server*.xlsx | Merge-MulipleSheets -WorksheetName Services -OutputFile Test2.xlsx -OutputSheetName Services -Show
We are auditing servers and each one has a workbook in the current directory which contains a "Services" worksheet (the result of Here we are auditing servers and each one has a workbook in the current
Get-WmiObject -Class win32_service | Select-Object -Property Name, Displayname, Startmode directory which contains a "Services" Worksheet (the result of
No key is specified so the key is assumed to be the "Name" column. The files are merged and the result is opened on completion. Get-WmiObject -Class win32_service | Select-Object -Property Name, Displayname, Startmode)
No key is specified so the key is assumed to be the "Name" column.
The files are merged and the result is opened on completion.
.Example .Example
dir Serv*.xlsx | Merge-MulipleSheets -WorkSheetName Software -Key "*" -ExcludeProperty Install* -OutputFile Test2.xlsx -OutputSheetName Software -Show dir Serv*.xlsx | Merge-MulipleSheets -WorksheetName Software -Key "*" -ExcludeProperty Install* -OutputFile Test2.xlsx -OutputSheetName Software -Show
The server audit files in the previous example also have "Software" worksheet, but no single field on that sheet works as a key. The server audit files in the previous example also have "Software" worksheet,
Specifying "*" for the key produces a compound key using all non-excluded fields (and the installation date and file location are excluded). but no single field on that sheet works as a key. Specifying "*" for the key
produces a compound key using all non-excluded fields (and the installation
date and file location are excluded).
.Example .Example
Merge-MulipleSheets -Path hotfixes.xlsx -WorkSheetName Serv* -Key hotfixid -OutputFile test2.xlsx -OutputSheetName hotfixes -HideRowNumbers -Show Merge-MulipleSheets -Path hotfixes.xlsx -WorksheetName Serv* -Key hotfixid -OutputFile test2.xlsx -OutputSheetName hotfixes -HideRowNumbers -Show
This time all the servers have written their hofix information to their own worksheets in a shared Excel workbook named "Hotfixes" This time all the servers have written their hotfix information to their own
(the information was obtained by running Get-Hotfix | Sort-Object -Property description,hotfixid | Select-Object -Property Description,HotfixID) worksheets in a shared Excel workbook named "Hotfixes.xlsx" (the information was
This ignores any sheets which are not named "Serv*", and uses the HotfixID as the key ; in this version the row numbers are hidden. obtained by running Get-Hotfix | Sort-Object -Property description,hotfixid | Select-Object -Property Description,HotfixID)
This ignores any sheets which are not named "Serv*", and uses the HotfixID as
the key; in this version the row numbers are hidden.
#> #>
[cmdletbinding()] [cmdletbinding()]
[Alias("Merge-MulipleSheets")] #[Alias("Merge-MulipleSheets")] #There was a spelling error in the first release. This was there to ensure things didn't break but intelisense gave the alias first.
param ( param (
#Paths to the files to be merged. #Paths to the files to be merged. Files are also accepted
[Parameter(Mandatory=$true,ValueFromPipeline=$true)] [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
[string[]]$Path , $Path ,
#The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. #The row from where we start to import data, all rows above the Start row are disregarded. By default this is the first row.
[int]$Startrow = 1, [int]$Startrow = 1,
#Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. #Specifies custom property names to use, instead of the values defined in the column headers of the Start row.
[String[]]$Headername, [String[]]$Headername,
#Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet. #If specified, property names will be automatically generated (P1, P2, P3, ..) instead of using the values from the start row.
[switch]$NoHeader, [switch]$NoHeader,
#Name(s) of worksheets to compare, #Name(s) of Worksheets to compare.
$WorkSheetName = "Sheet1", $WorksheetName = "Sheet1",
#File to write output to #File to write output to.
[Alias('OutFile')] [Alias('OutFile')]
$OutputFile = ".\temp.xlsx", $OutputFile = ".\temp.xlsx",
#Name of worksheet to output - if none specified will use the reference worksheet name. #Name of Worksheet to output - if none specified will use the reference Worksheet name.
[Alias('OutSheet')] [Alias('OutSheet')]
$OutputSheetName = "Sheet1", $OutputSheetName = "Sheet1",
#Properties to include in the DIFF - supports wildcards, default is "*". #Properties to include in the comparison - supports wildcards, default is "*".
$Property = "*" , $Property = "*" ,
#Properties to exclude from the the search - supports wildcards. #Properties to exclude from the the comparison - supports wildcards.
$ExcludeProperty , $ExcludeProperty ,
#Name of a column which is unique used to pair up rows from the refence and difference side, default is "Name". #Name of a column which is unique used to pair up rows from the reference and difference sides, default is "Name".
$Key = "Name" , $Key = "Name" ,
#Sets the font color for the "key" field; this means you can filter by color to get only changed rows. #Sets the font color for the Key field; this means you can filter by color to get only changed rows.
[System.Drawing.Color]$KeyFontColor = "Red", $KeyFontColor = [System.Drawing.Color]::Red,
#Sets the background color for changed rows. #Sets the background color for changed rows.
[System.Drawing.Color]$ChangeBackgroundColor = "Orange", $ChangeBackgroundColor = [System.Drawing.Color]::Orange,
#Sets the background color for rows in the reference but deleted from the difference sheet. #Sets the background color for rows in the reference but deleted from the difference sheet.
[System.Drawing.Color]$DeleteBackgroundColor = "LightPink", $DeleteBackgroundColor = [System.Drawing.Color]::LightPink,
#Sets the background color for rows not in the reference but added to the difference sheet. #Sets the background color for rows not in the reference but added to the difference sheet.
[System.Drawing.Color]$AddBackgroundColor = "Orange", $AddBackgroundColor = [System.Drawing.Color]::Orange,
#if Specified hides the columns in the spreadsheet that contain the row numbers #If specified, hides the columns in the spreadsheet that contain the row numbers.
[switch]$HideRowNumbers , [switch]$HideRowNumbers ,
#If specified outputs the data to the pipeline (you can add -whatif so it the command only outputs to the command) #If specified, outputs the data to the pipeline (you can add -whatif so it the command only outputs to the pipeline).
[switch]$Passthru , [switch]$Passthru ,
#If specified, opens the output workbook. #If specified, opens the output workbook.
[Switch]$Show [Switch]$Show
@@ -367,50 +421,51 @@ Function Merge-MultipleSheets {
begin { $filestoProcess = @() } begin { $filestoProcess = @() }
process { $filestoProcess += $Path} process { $filestoProcess += $Path}
end { end {
if ($filestoProcess.Count -eq 1 -and $WorkSheetName -match '\*') { if ($filestoProcess.Count -eq 1 -and $WorksheetName -match '\*') {
Write-Progress -Activity "Merging sheets" -CurrentOperation "Expanding * to names of sheets in $($filestoProcess[0]). " Write-Progress -Activity "Merging sheets" -CurrentOperation "Expanding * to names of sheets in $($filestoProcess[0]). "
$excel = Open-ExcelPackage -Path $filestoProcess $excel = Open-ExcelPackage -Path $filestoProcess
$WorksheetName = $excel.Workbook.Worksheets.Name.where({$_ -like $WorkSheetName}) $WorksheetName = $excel.Workbook.Worksheets.Name.where({$_ -like $WorksheetName})
Close-ExcelPackage -NoSave -ExcelPackage $excel Close-ExcelPackage -NoSave -ExcelPackage $excel
} }
#Merge indentically named sheets in different work books; #Merge identically named sheets in different work books;
if ($filestoProcess.Count -ge 2 -and $WorkSheetName -is "string" ) { if ($filestoProcess.Count -ge 2 -and $WorksheetName -is "string" ) {
Get-Variable -Name 'HeaderName','NoHeader','StartRow','Key','Property','ExcludeProperty','WorkSheetName' -ErrorAction SilentlyContinue | Get-Variable -Name 'HeaderName','NoHeader','StartRow','Key','Property','ExcludeProperty','WorksheetName' -ErrorAction SilentlyContinue |
Where-Object {$_.Value} | ForEach-Object -Begin {$params= @{} } -Process {$params[$_.Name] = $_.Value} Where-Object {$_.Value} | ForEach-Object -Begin {$params= @{} } -Process {$params[$_.Name] = $_.Value}
Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($filestoProcess[-1]) against $($filestoProcess[0]). " Write-Progress -Activity "Merging sheets" -CurrentOperation "comparing '$WorksheetName' in $($filestoProcess[-1]) against $($filestoProcess[0]). "
$merged = Merge-Worksheet @params -Referencefile $filestoProcess[0] -Differencefile $filestoProcess[-1] $merged = Merge-Worksheet @params -Referencefile $filestoProcess[0] -Differencefile $filestoProcess[-1]
$nextFileNo = 2 $nextFileNo = 2
while ($nextFileNo -lt $filestoProcess.count -and $merged) { while ($nextFileNo -lt $filestoProcess.count -and $merged) {
Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($filestoProcess[-$nextFileNo]) against $($filestoProcess[0]). " Write-Progress -Activity "Merging sheets" -CurrentOperation "comparing '$WorksheetName' in $($filestoProcess[-$nextFileNo]) against $($filestoProcess[0]). "
$merged = Merge-Worksheet @params -ReferenceObject $merged -Differencefile $filestoProcess[-$nextFileNo] $merged = Merge-Worksheet @params -ReferenceObject $merged -Differencefile $filestoProcess[-$nextFileNo]
$nextFileNo ++ $nextFileNo ++
} }
} }
#Merge different sheets from one workbook #Merge different sheets from one workbook
elseif ($filestoProcess.Count -eq 1 -and $WorkSheetName.Count -ge 2 ) { elseif ($filestoProcess.Count -eq 1 -and $WorksheetName.Count -ge 2 ) {
Get-Variable -Name 'HeaderName','NoHeader','StartRow','Key','Property','ExcludeProperty' -ErrorAction SilentlyContinue | Get-Variable -Name 'HeaderName','NoHeader','StartRow','Key','Property','ExcludeProperty' -ErrorAction SilentlyContinue |
Where-Object {$_.Value} | ForEach-Object -Begin {$params= @{} } -Process {$params[$_.Name] = $_.Value} Where-Object {$_.Value} | ForEach-Object -Begin {$params= @{} } -Process {$params[$_.Name] = $_.Value}
Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($WorkSheetName[-1]) against $($WorkSheetName[0]). " Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($WorksheetName[-1]) against $($WorksheetName[0]). "
$merged = Merge-Worksheet @params -Referencefile $filestoProcess[0] -Differencefile $filestoProcess[0] -WorkSheetName $WorkSheetName[0,-1] $merged = Merge-Worksheet @params -Referencefile $filestoProcess[0] -Differencefile $filestoProcess[0] -WorksheetName $WorksheetName[0,-1]
$nextSheetNo = 2 $nextSheetNo = 2
while ($nextSheetNo -lt $WorkSheetName.count -and $merged) { while ($nextSheetNo -lt $WorksheetName.count -and $merged) {
Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($WorkSheetName[-$nextSheetNo]) against $($WorkSheetName[0]). " Write-Progress -Activity "Merging sheets" -CurrentOperation "Comparing $($WorksheetName[-$nextSheetNo]) against $($WorksheetName[0]). "
$merged = Merge-Worksheet @params -ReferenceObject $merged -Differencefile $filestoProcess[0] -WorkSheetName $WorkSheetName[-$nextSheetNo] -DiffPrefix $WorkSheetName[-$nextSheetNo] $merged = Merge-Worksheet @params -ReferenceObject $merged -Differencefile $filestoProcess[0] -WorksheetName $WorksheetName[-$nextSheetNo] -DiffPrefix $WorksheetName[-$nextSheetNo]
$nextSheetNo ++ $nextSheetNo ++
} }
} }
#We either need one worksheet name and many files or one file and many sheets. #We either need one Worksheet name and many files or one file and many sheets.
else { Write-Warning -Message "Need at least two files to process" ; return } else { Write-Warning -Message "Need at least two files to process" ; return }
#if the process didn't return data then abandon now. #if the process didn't return data then abandon now.
if (-not $merged) {Write-Warning -Message "The merge operation did not return any data."; return } if (-not $merged) {Write-Warning -Message "The merge operation did not return any data."; return }
$orderByProperties = $merged[0].psobject.properties.where({$_.name -match "row$"}).name $orderByProperties = $merged[0].psobject.properties.where({$_.name -match "row$"}).name
Write-Progress -Activity "Merging sheets" -CurrentOperation "Creating output sheet '$OutputSheetName' in $OutputFile" Write-Progress -Activity "Merging sheets" -CurrentOperation "creating output sheet '$OutputSheetName' in $OutputFile"
$excel = $merged | Sort-Object -Property $orderByProperties | Update-FirstObjectProperties | $excel = $merged | Sort-Object -Property $orderByProperties |
Export-Excel -Path $OutputFile -WorkSheetname $OutputSheetName -ClearSheet -BoldTopRow -AutoFilter -PassThru Export-Excel -Path $OutputFile -Worksheetname $OutputSheetName -ClearSheet -BoldTopRow -AutoFilter -PassThru
$sheet = $excel.Workbook.Worksheets[$OutputSheetName] $sheet = $excel.Workbook.Worksheets[$OutputSheetName]
#We will put in a conditional format for "if all the others are not flagged as 'same'" to mark rows where something is added, removed or changed #We will put in a conditional format for "if all the others are not flagged as 'same'" to mark rows where something is added, removed or changed
@@ -424,8 +479,8 @@ Function Merge-MultipleSheets {
if ($filesToProcess.Count -ge 2) { if ($filesToProcess.Count -ge 2) {
$refPrefix = (Split-Path -Path $filestoProcess[0] -Leaf) -replace "\.xlsx$"," " $refPrefix = (Split-Path -Path $filestoProcess[0] -Leaf) -replace "\.xlsx$"," "
} }
else {$refPrefix = $WorkSheetName[0] } else {$refPrefix = $WorksheetName[0] }
Write-Progress -Activity "Merging sheets" -CurrentOperation "Applying formatting to sheet '$OutputSheetName' in $OutputFile" Write-Progress -Activity "Merging sheets" -CurrentOperation "applying formatting to sheet '$OutputSheetName' in $OutputFile"
#Find the column headings which are in the form "diffFile is"; which will hold 'Same', 'Added' or 'Changed' #Find the column headings which are in the form "diffFile is"; which will hold 'Same', 'Added' or 'Changed'
foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -match "\sIS$"}) ) { foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -match "\sIS$"}) ) {
#Work leftwards across the headings applying conditional formatting which says #Work leftwards across the headings applying conditional formatting which says
@@ -434,7 +489,7 @@ Function Merge-MultipleSheets {
$columnNo = $cell.start.Column -1 $columnNo = $cell.start.Column -1
$cellAddr = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R1C$columnNo",1,$columnNo) $cellAddr = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R1C$columnNo",1,$columnNo)
while ($sheet.cells[$cellAddr].value -match $prefix) { while ($sheet.cells[$cellAddr].value -match $prefix) {
$condFormattingParams = @{RuleType='Expression'; BackgroundPattern='Solid'; WorkSheet=$sheet; Range=$([OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[1]C[$columnNo]:R[1048576]C[$columnNo]",0,0)) } $condFormattingParams = @{RuleType='Expression'; BackgroundPattern='Solid'; Worksheet=$sheet; StopIfTrue=$true; Range=$([OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[1]C[$columnNo]:R[1048576]C[$columnNo]",0,0)) }
Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Added"' ) -BackgroundColor $AddBackgroundColor Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Added"' ) -BackgroundColor $AddBackgroundColor
Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Changed"') -BackgroundColor $ChangeBackgroundColor Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Changed"') -BackgroundColor $ChangeBackgroundColor
Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Removed"') -BackgroundColor $DeleteBackgroundColor Add-ConditionalFormatting @condFormattingParams -ConditionValue ($cell.Address + '="Removed"') -BackgroundColor $DeleteBackgroundColor
@@ -450,15 +505,16 @@ Function Merge-MultipleSheets {
$nameRegex = $colNames -Join '|' $nameRegex = $colNames -Join '|'
foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -Notmatch $nameRegex}) ) { foreach ($cell in $sheet.Cells[($sheet.Dimension.Address -replace "\d+$","1")].Where({$_.value -Notmatch $nameRegex}) ) {
$cell.Value = $refPrefix + $cell.Value $cell.Value = $refPrefix + $cell.Value
$condFormattingParams = @{RuleType='Expression'; BackgroundPattern='None'; WorkSheet=$sheet; Range=[OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[2]C[$($cell.start.column)]:R[1048576]C[$($cell.start.column)]",0,0)} $condFormattingParams = @{RuleType='Expression'; BackgroundPattern='Solid'; Worksheet=$sheet; StopIfTrue=$true; Range=[OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[2]C[$($cell.start.column)]:R[1048576]C[$($cell.start.column)]",0,0)}
Add-ConditionalFormatting @condFormattingParams -ConditionValue ("OR(" +(($sameChecks -join ",") -replace '<>"Same"','="Added"') +")" ) -BackgroundColor $DeleteBackgroundColor Add-ConditionalFormatting @condFormattingParams -ConditionValue ("OR(" +(($sameChecks -join ",") -replace '<>"Same"','="Added"' ) +")" ) -BackgroundColor $DeleteBackgroundColor
Add-ConditionalFormatting @condFormattingParams -ConditionValue ("AND(" +(($sameChecks -join ",") -replace '<>"Same"','="Changed"') +")" ) -BackgroundColor $ChangeBackgroundColor
} }
#We've made a bunch of things wider so now is the time to autofit columns. Any hiding has to come AFTER this, because it unhides things #We've made a bunch of things wider so now is the time to autofit columns. Any hiding has to come AFTER this, because it unhides things
$sheet.Cells.AutoFitColumns() $sheet.Cells.AutoFitColumns()
#if we have a key field (we didn't concatenate all fields) use what we built up in $sameChecks to apply conditional formatting to it (Row no will be in column A, Key in Column B) #if we have a key field (we didn't concatenate all fields) use what we built up in $sameChecks to apply conditional formatting to it (Row no will be in column A, Key in Column B)
if ($Key -ne '*') { if ($Key -ne '*') {
Add-ConditionalFormatting -WorkSheet $sheet -Range "B2:B1048576" -ForeGroundColor $KeyFontColor -BackgroundPattern 'None' -RuleType Expression -ConditionValue ("OR(" +($sameChecks -join ",") +")" ) Add-ConditionalFormatting -Worksheet $sheet -Range "B2:B1048576" -ForeGroundColor $KeyFontColor -BackgroundPattern 'None' -RuleType Expression -ConditionValue ("OR(" +($sameChecks -join ",") +")" )
$sheet.view.FreezePanes(2, 3) $sheet.view.FreezePanes(2, 3)
} }
else {$sheet.view.FreezePanes(2, 2) } else {$sheet.view.FreezePanes(2, 2) }
@@ -473,8 +529,8 @@ Function Merge-MultipleSheets {
$sheet.Column($cell.start.Column).HIDDEN = $true $sheet.Column($cell.start.Column).HIDDEN = $true
} }
} }
if ($Passthru) {$excel}
Close-ExcelPackage -ExcelPackage $excel -Show:$Show else {Close-ExcelPackage -ExcelPackage $excel -Show:$Show}
Write-Progress -Activity "Merging sheets" -Completed Write-Progress -Activity "Merging sheets" -Completed
} }
} }

View File

@@ -1,16 +1,16 @@
function New-ConditionalFormattingIconSet { function New-ConditionalFormattingIconSet {
<# <#
.SYNOPSIS .SYNOPSIS
Creates an object which describes a conditional formatting rule a for 3,4 or 5 icon set Creates an object which describes a conditional formatting rule a for 3,4 or 5 icon set.
.DESCRIPTION .DESCRIPTION
Export-Excel takes a -ConditionalFormat parameter which can hold one or more descriptions for conditional formats; Export-Excel takes a -ConditionalFormat parameter which can hold one or more descriptions for conditional formats;
this command builds the this command builds the defintion of a Conditional formatting rule for an icon set.
.PARAMETER Range .PARAMETER Range
The range of cells that the conditional format applies to The range of cells that the conditional format applies to.
.PARAMETER ConditionalFormat .PARAMETER ConditionalFormat
The type of rule: one of "ThreeIconSet","FourIconSet" or "FiveIconSet" The type of rule: one of "ThreeIconSet","FourIconSet" or "FiveIconSet"
.PARAMETER IconType .PARAMETER IconType
The name of an iconSet - different icons are available depending on whether 3,4 or 5 icon set is selected The name of an iconSet - different icons are available depending on whether 3,4 or 5 icon set is selected.
.PARAMETER Reverse .PARAMETER Reverse
Use the icons in the reverse order. Use the icons in the reverse order.
.Example .Example
@@ -18,9 +18,14 @@ function New-ConditionalFormattingIconSet {
$cfdef = New-ConditionalFormattingIconSet -Range $cfrange -ConditionalFormat ThreeIconSet -IconType Arrows $cfdef = New-ConditionalFormattingIconSet -Range $cfrange -ConditionalFormat ThreeIconSet -IconType Arrows
Export-Excel -ExcelPackage $excel -ConditionalFormat $cfdef -show Export-Excel -ExcelPackage $excel -ConditionalFormat $cfdef -show
The first line creates a range - one column wide in the column $column, running from $topRow to $lastDataRow. The first line creates a range - one column wide in the column $column, running
The second creates a definition object using this range from $topRow to $lastDataRow.
and the third uses Export-Excel with an open package to apply the format and save and open the file. The second line creates a definition object using this range
and the third uses Export-Excel with an open package to apply the format and
save and open the file.
.Link
Add-Add-ConditionalFormatting
New-ConditionalText
#> #>
param( param(
[Parameter(Mandatory=$true)] [Parameter(Mandatory=$true)]

View File

@@ -1,47 +1,56 @@
function New-ConditionalText { function New-ConditionalText {
<# <#
.SYNOPSIS .SYNOPSIS
Creates an object which describes a conditional formatting rule for single valued rules Creates an object which describes a conditional formatting rule for single valued rules.
.DESCRIPTION .DESCRIPTION
Some Conditional formatting rules don't apply styles to a cell (IconSets and Databars) Some Conditional formatting rules don't apply styles to a cell (IconSets and Databars).
Some take two parameters (Between) Some take two parameters (Between).
Some take none (ThisWeek , containsErrors, AboveAverage etc.) Some take none (ThisWeek, ContainsErrors, AboveAverage etc).
The others take a single paramter (top, BottomPercent, GreaterThan, Contains etc) The others take a single parameter (Top, BottomPercent, GreaterThan, Contains etc).
This command creates an object to describe the last two categories, which can be passed to Export-Excel This command creates an object to describe the last two categories, which can then be passed to Export-Excel.
.PARAMETER Range .PARAMETER Range
The range of cells that the conditional format applies to; if none is specified the range will be apply to all the data in the sheet The range of cells that the conditional format applies to; if none is specified the range will be apply to all the data in the sheet.
.PARAMETER ConditionalType .PARAMETER ConditionalType
One the supported rules by default - "ContainsText" is selected One of the supported rules; by default "ContainsText" is selected.
.PARAMETER Text .PARAMETER Text
The text (or other value) to use in the rule. Not that Equals, GreaterThan/LessThan rules require text to wrapped in double quotes The text (or other value) to use in the rule. Note that Equals, GreaterThan/LessThan rules require text to wrapped in double quotes.
.PARAMETER ConditionalTextColor .PARAMETER ConditionalTextColor
The font color for the cell - by default: Dark red The font color for the cell - by default: "DarkRed".
.PARAMETER BackgroundColor .PARAMETER BackgroundColor
The fill color for the cell - by default: light pink The fill color for the cell - by default: "LightPink".
.PARAMETER PatternType .PARAMETER PatternType
The Background pattern for the cell - by deault: Solid The background pattern for the cell - by default: "Solid"
.EXAMPLE .EXAMPLE
>
$ct = New-ConditionalText -Text 'Ferrari' $ct = New-ConditionalText -Text 'Ferrari'
Export-Excel -ExcelPackage $excel -ConditionalTest $ct -show Export-Excel -ExcelPackage $excel -ConditionalTest $ct -show
The first line creates a definition object which will highlight the word "Ferrari" in any cell. The first line creates a definition object which will highlight the word
and the secind uses Export-Excel with an open package to apply the format and save and open the file. "Ferrari" in any cell. and the second uses Export-Excel with an open package
to apply the format and save and open the file.
.EXAMPLE .EXAMPLE
>
$ct = New-ConditionalText -Text "Ferrari" $ct = New-ConditionalText -Text "Ferrari"
$ct2 = New-ConditionalText -Range $worksheet.Names["FinishPosition"].Address -ConditionalType LessThanOrEqual -Text 3 -ConditionalTextColor Red -BackgroundColor White $ct2 = New-ConditionalText -Range $worksheet.Names["FinishPosition"].Address -ConditionalType LessThanOrEqual -Text 3 -ConditionalTextColor Red -BackgroundColor White
Export-Excel -ExcelPackage $excel -ConditionalText $ct,$ct2 -show Export-Excel -ExcelPackage $excel -ConditionalText $ct,$ct2 -show
This builds on the previous example, and specifies a condition of <=3 with a format of Red text on a white background; this applies to a named range "Finish Position" This builds on the previous example, and specifies a condition of <=3 with
the range could be written "C:C" to specify a named column, or "C2:C102" to specify certain cells in the column. a format of red text on a white background; this applies to a named range
"Finish Position". The range could be written "C:C" to specify a named
column, or "C2:C102" to specify certain cells in the column.
.Link
Add-Add-ConditionalFormatting
New-ConditionalFormattingIconSet
#> #>
[cmdletbinding()] [cmdletbinding()]
param( param(
#[Parameter(Mandatory=$true)] #[Parameter(Mandatory=$true)]
[Alias("ConditionValue")] [Alias("ConditionValue")]
$Text, $Text,
[Alias("ForeGroundColor")] [Alias("ForeGroundColor")]
[System.Drawing.Color]$ConditionalTextColor="DarkRed", $ConditionalTextColor=[System.Drawing.Color]::DarkRed,
[System.Drawing.Color]$BackgroundColor="LightPink", $BackgroundColor=[System.Drawing.Color]::LightPink,
[String]$Range, [String]$Range,
[OfficeOpenXml.Style.ExcelFillStyle]$PatternType=[OfficeOpenXml.Style.ExcelFillStyle]::Solid, [OfficeOpenXml.Style.ExcelFillStyle]$PatternType=[OfficeOpenXml.Style.ExcelFillStyle]::Solid,
[ValidateSet( [ValidateSet(

View File

@@ -1,10 +1,12 @@
function New-ExcelChartDefinition { function New-ExcelChartDefinition {
<# <#
.SYNOPSIS .SYNOPSIS
Creates a Definition of a chart which can be added using Export Excel Creates a Definition of a chart which can be added using Export-Excel, or Add-PivotTable
.DESCRIPTION .DESCRIPTION
All the parameters which are passed to Add-ExcelChart can be added to an object and All the parameters which are passed to Add-ExcelChart can be added to an object and
passed to Export-Excel with the -ExcelChartDefinition parameter. This command sets up those objects. passed to Export-Excel with the -ExcelChartDefinition parameter,
or to Add-PivotTable with the -PivotChartDefinition parameter.
This command sets up those definitions.
.PARAMETER Title .PARAMETER Title
The title for the chart. The title for the chart.
.PARAMETER TitleBold .PARAMETER TitleBold
@@ -12,85 +14,86 @@ function New-ExcelChartDefinition {
.PARAMETER TitleSize .PARAMETER TitleSize
Sets the point size for the title. Sets the point size for the title.
.PARAMETER ChartType .PARAMETER ChartType
One of the built in chart types, such as Pie, ClusteredColumn, Line etc. Defaults to "ColumnStacked". One of the built-in chart types, such as Pie, ClusteredColumn, Line etc. Defaults to "ColumnStacked".
.PARAMETER XRange .PARAMETER XRange
The range of cells containing values for the X-Axis - usually labels. The range of cells containing values for the X-Axis - usually labels.
.PARAMETER YRange .PARAMETER YRange
The range(s) of cells holding values for the Y-Axis - usually "data". The range(s) of cells holding values for the Y-Axis - usually "data".
.PARAMETER Width .PARAMETER Width
Width of the chart in Pixels. Defaults to 500. Width of the chart in pixels. Defaults to 500.
.PARAMETER Height .PARAMETER Height
Height of the chart in Pixels. Defaults to 350. Height of the chart in pixels. Defaults to 350.
.PARAMETER Row .PARAMETER Row
Row position of the top left corner of the chart. 0 places at the top of the sheet, 1 below row 1 and so on. Row position of the top left corner of the chart. 0 places at the top of the sheet, 1 below row 1 and so on.
.PARAMETER RowOffSetPixels .PARAMETER RowOffSetPixels
Offset to postion the chart by a fraction of of a row . Offset to position the chart by a fraction of a row.
.PARAMETER Column .PARAMETER Column
Column Postion of the top left corner of the chart. 0 places at the edge of the sheet 1 to the right of column A and so on. Column position of the top left corner of the chart. 0 places at the edge of the sheet 1 to the right of column A and so on.
.PARAMETER ColumnOffSetPixels .PARAMETER ColumnOffSetPixels
Offset to postion the chart by a fraction of of a column. Offset to position the chart by a fraction of a column.
.PARAMETER NoLegend .PARAMETER NoLegend
If specified, turns of display of the key. If you only have one data series it may be preferable to use the title to say what the chart is. If specified, turns off display of the key. If you only have one data series it may be preferable to use the title to say what the chart is.
.PARAMETER SeriesHeader .PARAMETER SeriesHeader
Specify explicit name(s) for the data series, which will appear in the legend/key Specifies explicit name(s) for the data series, which will appear in the legend/key
.PARAMETER LegendPostion .PARAMETER LegendPosition
Location of the key, either left, right, top, bottom or TopRight. Location of the key, either "Left", "Right", "Top", "Bottom" or "TopRight".
.PARAMETER LegendSize .PARAMETER LegendSize
Font size for the key Font size for the key.
.PARAMETER LegendBold .PARAMETER LegendBold
Sets the key in bold type. Sets the key in bold type.
.PARAMETER ShowCategory .PARAMETER ShowCategory
Attaches a category label in charts which support this. Attaches a category label in charts which support this.
.PARAMETER ShowPercent .PARAMETER ShowPercent
Attaches a pecentage label in charts which support this. Attaches a percentage label in charts which support this.
.PARAMETER XAxisTitleText .PARAMETER XAxisTitleText
Specifies a title for the X axis. Specifies a title for the X-axis.
.PARAMETER XAxisTitleBold .PARAMETER XAxisTitleBold
Sets the X axis title in bold face. Sets the X-axis title in bold face.
.PARAMETER XAxisTitleSize .PARAMETER XAxisTitleSize
Sets the font size for the axis title Sets the font size for the axis title.
.PARAMETER XAxisNumberformat .PARAMETER XAxisNumberformat
A number formatting string, like "#,##0.00" for numbers along the X axis A number formatting string, like "#,##0.00", for numbers along the X-axis.
.PARAMETER XMajorUnit .PARAMETER XMajorUnit
Spacing for the major gridlines / tick marks along the X axis Spacing for the major gridlines / tick marks along the X-axis.
.PARAMETER XMinorUnit .PARAMETER XMinorUnit
Spacing for the major gridlines / tick marks along the X axis Spacing for the minor gridlines / tick marks along the X-axis.
.PARAMETER XMaxValue .PARAMETER XMaxValue
Maximum value for the scale along the Xaxis Maximum value for the scale along the X-axis.
.PARAMETER XMinValue .PARAMETER XMinValue
Minimum value for the scale along the Xaxis Minimum value for the scale along the X-axis.
.PARAMETER xAxisPosition .PARAMETER xAxisPosition
Postion for the X axis (top or bottom) Position for the X-axis ("Top" or" Bottom").
.PARAMETER YAxisTitleText .PARAMETER YAxisTitleText
Specifies a title for the Y axis. Specifies a title for the Y-axis.
.PARAMETER YAxisTitleBold .PARAMETER YAxisTitleBold
Sets the Y axis title in bold face. Sets the Y-axis title in bold face.
.PARAMETER YAxisTitleSize .PARAMETER YAxisTitleSize
Sets the font size for the Y axis title Sets the font size for the Y-axis title.
.PARAMETER YAxisNumberformat .PARAMETER YAxisNumberformat
A number formatting string, like "#,##0.00" for numbers on the Y axis A number formatting string, like "#,##0.00", for numbers on the Y-axis
.PARAMETER YMajorUnit .PARAMETER YMajorUnit
Spacing for the major gridlines / tick marks on the Y axis Spacing for the major gridlines / tick marks on the Y-axis.
.PARAMETER YMinorUnit .PARAMETER YMinorUnit
Spacing for the major gridlines / tick marks on the Y axis Spacing for the minor gridlines / tick marks on the Y-axis.
.PARAMETER YMaxValue .PARAMETER YMaxValue
Maximum value on the Yaxis Maximum value on the Y-axis.
.PARAMETER YMinValue .PARAMETER YMinValue
Minimum value on the Yaxis Minimum value on the Y-axis.
.PARAMETER YAxisPosition .PARAMETER YAxisPosition
Postion for the Y axis (left or right) Position for the Y-axis ("Left" or "Right").
.PARAMETER Header .PARAMETER Header
No longer used. This may be removed in future versions No longer used. This may be removed in future versions.
.Example .Example
> >
PS> $cDef = New-ExcelChartDefinition -ChartType line -XRange "X" -YRange "Sinx" -Title "Graph of Sine X" -TitleBold -TitleSize 14 ` PS> $cDef = New-ExcelChartDefinition -ChartType line -XRange "X" -YRange "Sinx" -Title "Graph of Sine X" -TitleBold -TitleSize 14 `
-Column 2 -ColumnOffSetPixels 35 -Width 800 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -XAxisNumberformat "000" ` -Column 2 -ColumnOffSetPixels 35 -Width 800 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -XAxisNumberformat "000" `
-YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -YAxisTitleText "Sine" -YAxisTitleBold -YAxisTitleSize 12 ` -YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -YAxisTitleText "Sine" -YAxisTitleBold -YAxisTitleSize 12 `
-SeriesHeader "Sin(x)" -LegendSize 8 -legendBold -LegendPostion Bottom -SeriesHeader "Sin(x)" -LegendSize 8 -legendBold -LegendPosition Bottom
0..360 | ForEach-Object {[pscustomobject][ordered]@{x = $_; Sinx = "=Sin(Radians(x)) "}} | Export-Excel -AutoNameRange -now -WorkSheetname SinX -ExcelChartDefinition $cDef -Show 0..360 | ForEach-Object {[pscustomobject][ordered]@{x = $_; Sinx = "=Sin(Radians(x)) "}} | Export-Excel -AutoNameRange -now -WorkSheetname SinX -ExcelChartDefinition $cDef -Show
This reworks an example from Add-Excel-Chart but here the chart definition is defined and then it is used in a call to Export-Excel. This reworks an example from Add-Excel-Chart but here the chart is defined
and the defintion stored in $cDef and then Export-Excel uses $cDef .
#> #>
[Alias("New-ExcelChart")] #This was the former name. The new name reflects that we are defining a chart, not making one in the workbook. [Alias("New-ExcelChart")] #This was the former name. The new name reflects that we are defining a chart, not making one in the workbook.
[cmdletbinding()] [cmdletbinding()]
@@ -106,7 +109,7 @@ function New-ExcelChartDefinition {
$RowOffSetPixels = 10, $RowOffSetPixels = 10,
$Column = 6, $Column = 6,
$ColumnOffSetPixels = 5, $ColumnOffSetPixels = 5,
[OfficeOpenXml.Drawing.Chart.eLegendPosition]$LegendPostion, [OfficeOpenXml.Drawing.Chart.eLegendPosition]$LegendPosition,
$LegendSize, $LegendSize,
[Switch]$LegendBold, [Switch]$LegendBold,
[Switch]$NoLegend, [Switch]$NoLegend,
@@ -147,7 +150,7 @@ function New-ExcelChartDefinition {
RowOffSetPixels = $RowOffSetPixels RowOffSetPixels = $RowOffSetPixels
Column = $Column Column = $Column
ColumnOffSetPixels = $ColumnOffSetPixels ColumnOffSetPixels = $ColumnOffSetPixels
LegendPostion = $LegendPostion LegendPosition = $LegendPosition
LegendSize = $LegendSize LegendSize = $LegendSize
Legendbold = $LegendBold Legendbold = $LegendBold
NoLegend = $NoLegend -as [Boolean] NoLegend = $NoLegend -as [Boolean]
@@ -180,13 +183,13 @@ function New-ExcelChartDefinition {
function Add-ExcelChart { function Add-ExcelChart {
<# <#
.SYNOPSIS .SYNOPSIS
Creates a chart in an existing Excel worksheet Creates a chart in an existing Excel worksheet.
.DESCRIPTION .DESCRIPTION
Creates a chart. It is possible to configure the type of chart, the range of X values (labels) and Y values. Creates a chart. It is possible to configure the type of chart, the range of X values (labels) and Y values.
the title, the legend, the ranges for both axes, the format and postion of the axes. the title, the legend, the ranges for both axes, the format and position of the axes.
Normally the command does not return anything, but if -passthru is specified the chart is returned so that it can be customized. Normally the command does not return anything, but if -passthru is specified the chart is returned so that it can be customized.
.PARAMETER Worksheet .PARAMETER Worksheet
An exisiting Sheet where the chart will be created. An existing Sheet where the chart will be created.
.PARAMETER Title .PARAMETER Title
The title for the chart. The title for the chart.
.PARAMETER TitleBold .PARAMETER TitleBold
@@ -194,7 +197,7 @@ function Add-ExcelChart {
.PARAMETER TitleSize .PARAMETER TitleSize
Sets the point size for the title. Sets the point size for the title.
.PARAMETER ChartType .PARAMETER ChartType
One of the built in chart types, such as Pie, ClusteredColumn, Line etc. Defaults to "ColumnStacked". One of the built-in chart types, such as Pie, ClusteredColumn, Line etc. Defaults to "ColumnStacked".
.PARAMETER XRange .PARAMETER XRange
The range of cells containing values for the X-Axis - usually labels. The range of cells containing values for the X-Axis - usually labels.
.PARAMETER YRange .PARAMETER YRange
@@ -208,63 +211,63 @@ function Add-ExcelChart {
.PARAMETER Row .PARAMETER Row
Row position of the top left corner of the chart. 0 places at the top of the sheet, 1 below row 1 and so on. Row position of the top left corner of the chart. 0 places at the top of the sheet, 1 below row 1 and so on.
.PARAMETER RowOffSetPixels .PARAMETER RowOffSetPixels
Offset to postion the chart by a fraction of of a row . Offset to position the chart by a fraction of a row.
.PARAMETER Column .PARAMETER Column
Column Postion of the top left corner of the chart. 0 places at the edge of the sheet 1 to the right of column A and so on. Column position of the top left corner of the chart. 0 places at the edge of the sheet 1 to the right of column A and so on.
.PARAMETER ColumnOffSetPixels .PARAMETER ColumnOffSetPixels
Offset to postion the chart by a fraction of of a column. Offset to position the chart by a fraction of a column.
.PARAMETER NoLegend .PARAMETER NoLegend
If specified, turns of display of the key. If you only have one data series it may be preferable to use the title to say what the chart is. If specified, turns of display of the key. If you only have one data series it may be preferable to use the title to say what the chart is.
.PARAMETER SeriesHeader .PARAMETER SeriesHeader
Specify explicit name(s) for the data series, which will appear in the legend/key Specify explicit name(s) for the data series, which will appear in the legend/key. The contents of a cell can be specified in the from =Sheet9!Z10 .
.PARAMETER LegendPostion .PARAMETER LegendPosition
Location of the key, either left, right, top, bottom or TopRight. Location of the key, either left, right, top, bottom or TopRight.
.PARAMETER LegendSize .PARAMETER LegendSize
Font size for the key Font size for the key.
.PARAMETER LegendBold .PARAMETER LegendBold
Sets the key in bold type. Sets the key in bold type.
.PARAMETER ShowCategory .PARAMETER ShowCategory
Attaches a category label in charts which support this. Attaches a category label in charts which support this.
.PARAMETER ShowPercent .PARAMETER ShowPercent
Attaches a pecentage label in charts which support this. Attaches a percentage label in charts which support this.
.PARAMETER XAxisTitleText .PARAMETER XAxisTitleText
Specifies a title for the X axis. Specifies a title for the X-axis.
.PARAMETER XAxisTitleBold .PARAMETER XAxisTitleBold
Sets the X axis title in bold face. Sets the X-axis title in bold face.
.PARAMETER XAxisTitleSize .PARAMETER XAxisTitleSize
Sets the font size for the axis title Sets the font size for the axis title.
.PARAMETER XAxisNumberformat .PARAMETER XAxisNumberformat
A number formatting string, like "#,##0.00" for numbers along the X axis A number formatting string, like "#,##0.00", for numbers along the X-axis.
.PARAMETER XMajorUnit .PARAMETER XMajorUnit
Spacing for the major gridlines / tick marks along the X axis Spacing for the major gridlines / tick marks along the X-axis.
.PARAMETER XMinorUnit .PARAMETER XMinorUnit
Spacing for the major gridlines / tick marks along the X axis Spacing for the minor gridlines / tick marks along the X-axis.
.PARAMETER XMaxValue .PARAMETER XMaxValue
Maximum value for the scale along the Xaxis Maximum value for the scale along the X-axis.
.PARAMETER XMinValue .PARAMETER XMinValue
Minimum value for the scale along the Xaxis Minimum value for the scale along the X-axis.
.PARAMETER xAxisPosition .PARAMETER xAxisPosition
Postion for the X axis (top or bottom) Position for the X-axis (Top or Bottom).
.PARAMETER YAxisTitleText .PARAMETER YAxisTitleText
Specifies a title for the Y axis. Specifies a title for the Y-axis.
.PARAMETER YAxisTitleBold .PARAMETER YAxisTitleBold
Sets the Y axis title in bold face. Sets the Y-axis title in bold face.
.PARAMETER YAxisTitleSize .PARAMETER YAxisTitleSize
Sets the font size for the Y axis title Sets the font size for the Y-axis title
.PARAMETER YAxisNumberformat .PARAMETER YAxisNumberformat
A number formatting string, like "#,##0.00" for numbers on the Y axis A number formatting string, like "#,##0.00", for numbers on the Y-axis.
.PARAMETER YMajorUnit .PARAMETER YMajorUnit
Spacing for the major gridlines / tick marks on the Y axis Spacing for the major gridlines / tick marks on the Y-axis.
.PARAMETER YMinorUnit .PARAMETER YMinorUnit
Spacing for the major gridlines / tick marks on the Y axis Spacing for the minor gridlines / tick marks on the Y-axis.
.PARAMETER YMaxValue .PARAMETER YMaxValue
Maximum value on the Yaxis Maximum value on the Y-axis.
.PARAMETER YMinValue .PARAMETER YMinValue
Minimum value on the Yaxis Minimum value on the Y-axis.
.PARAMETER YAxisPosition .PARAMETER YAxisPosition
Postion for the Y axis (left or right) Position for the Y-axis (Left or Right).
.PARAMETER PassThru .PARAMETER PassThru
Add-Excel chart doesn't normally return anything, but if -PassThru is specified it returns the newly created chart to allow it to be fine tuned Add-Excel chart doesn't normally return anything, but if -PassThru is specified it returns the newly created chart to allow it to be fine tuned.
.EXAMPLE .EXAMPLE
> >
PS> $Excel = ConvertFrom-Csv @" PS> $Excel = ConvertFrom-Csv @"
@@ -280,8 +283,8 @@ function Add-ExcelChart {
Close-ExcelPackage -Show $Excel Close-ExcelPackage -Show $Excel
The first command expands a multi-line string into 6 rows of data which is exported to new Excel file; leaving an ExcelPackage object in $excel The first command expands a multi-line string into 6 rows of data which is exported to new Excel file; leaving an ExcelPackage object in $excel
The second command adds a chart - the cell ranges are explitly specified. Note the at the XRange (labels) is TWO columns wide and the chart will The second command adds a chart - the cell ranges are explicitly specified. Note that the XRange (labels) is TWO columns wide and the chart will
combine the name of the product and the name of the City to create the table. combine the name of the product and the name of the City to create the label.
The width of the chart is set explictly, the default legend is used and there is no Chart title. The width of the chart is set explictly, the default legend is used and there is no Chart title.
.EXAMPLE .EXAMPLE
> >
@@ -307,16 +310,20 @@ function Add-ExcelChart {
Add-ExcelChart -Worksheet $excel.Workbook.Worksheets["Sinx"] -ChartType line -XRange "X" -YRange "Sinx" -Title "Graph of Sine X" -TitleBold -TitleSize 14 ` Add-ExcelChart -Worksheet $excel.Workbook.Worksheets["Sinx"] -ChartType line -XRange "X" -YRange "Sinx" -Title "Graph of Sine X" -TitleBold -TitleSize 14 `
-Column 2 -ColumnOffSetPixels 35 -Width 800 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -XAxisNumberformat "000" ` -Column 2 -ColumnOffSetPixels 35 -Width 800 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -XAxisNumberformat "000" `
-YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -YAxisTitleText "Sine" -YAxisTitleBold -YAxisTitleSize 12 ` -YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -YAxisTitleText "Sine" -YAxisTitleBold -YAxisTitleSize 12 `
-SeriesHeader "Sin(x)" -LegendSize 8 -legendBold -LegendPostion Bottom -SeriesHeader "Sin(x)" -LegendSize 8 -legendBold -LegendPosition Bottom
Close-ExcelPackage $Excel -Show Close-ExcelPackage $Excel -Show
The first line puts numbers from 0 to 360 into a sheet, as the first column, and a formula to calculate the Sine of that number of number of degrees in the second column. The first line puts numbers from 0 to 360 into a sheet, as the first column, and
It creates ranges for the two columns - "X" and "SinX" respectively a formula to calculate the Sine of that number of number of degrees in the second column.
The Add-Excel chart colum adds a chart to that work sheet, specifying a line chart with the X values comming from named range "X" and the the Y values comming the range named "SinX". It creates named-ranges for the two columns - "X" and "SinX" respectively
The chart has a title, and is positioned to the right of column 2 and sized 8000 pixels wide The Add-ExcelChart command adds a chart to that worksheet, specifying a line chart
Thed X axis s labeled "Degrees", in bold 12 point type and runs from 0 to 361 with labels every 30, and minor tick marks every 10. Degres are shown badded to 3 didits. with the X values coming from named-range "X" and the Y values coming from named-range "SinX".
The Y axis is labeled "Sine" and to allow some room above and below its scale runs from -1.25 to 1.25, and is marked off in units of 0.25 show to two decimal places. The chart has a title, and is positioned to the right of column 2 and sized 800 pixels wide
The key will for the chart will be at the bottom in 8 point bold type and the line will be named "Sin(x)" The X-axis is labelled "Degrees", in bold 12 point type and runs from 0 to 361 with labels every 30,
and minor tick marks every 10. Degrees are shown padded to 3 digits.
The Y-axis is labelled "Sine" and to allow some room above and below its scale runs from -1.25 to 1.25,
and is marked off in units of 0.25 shown to two decimal places.
The key will for the chart will be at the bottom in 8 point bold type and the line will be named "Sin(x)".
#> #>
[cmdletbinding(DefaultParameterSetName='Worksheet')] [cmdletbinding(DefaultParameterSetName='Worksheet')]
[OutputType([OfficeOpenXml.Drawing.Chart.ExcelChart])] [OutputType([OfficeOpenXml.Drawing.Chart.ExcelChart])]
@@ -336,13 +343,13 @@ function Add-ExcelChart {
[int]$RowOffSetPixels = 10, [int]$RowOffSetPixels = 10,
[int]$Column = 6, [int]$Column = 6,
[int]$ColumnOffSetPixels = 5, [int]$ColumnOffSetPixels = 5,
[OfficeOpenXml.Drawing.Chart.eLegendPosition]$LegendPostion, [OfficeOpenXml.Drawing.Chart.eLegendPosition]$LegendPosition,
$LegendSize, $LegendSize,
[Switch]$LegendBold, [Switch]$LegendBold,
[Switch]$NoLegend, [Switch]$NoLegend,
[Switch]$ShowCategory, [Switch]$ShowCategory,
[Switch]$ShowPercent, [Switch]$ShowPercent,
$SeriesHeader, [String[]]$SeriesHeader,
[Switch]$TitleBold, [Switch]$TitleBold,
[Int]$TitleSize , [Int]$TitleSize ,
[String]$XAxisTitleText, [String]$XAxisTitleText,
@@ -381,8 +388,16 @@ function Add-ExcelChart {
} }
else { else {
for ($idx = 0; $idx -lt $chartDefCount; $idx += 1) { for ($idx = 0; $idx -lt $chartDefCount; $idx += 1) {
if ($Yrange.count -eq $xrange.count) {
$Series = $chart.Series.Add($YRange[$idx], $XRange[$idx])
}
else {
$Series = $chart.Series.Add($YRange[$idx], $XRange) $Series = $chart.Series.Add($YRange[$idx], $XRange)
if ($SeriesHeader.Count -gt 0) { $Series.Header = $SeriesHeader[$idx] } }
if ($SeriesHeader.Count -gt 0) {
if ($SeriesHeader[$idx] -match '^=') {$Series.HeaderAddress = $SeriesHeader[$idx] -replace '^=',''}
else {$Series.Header = $SeriesHeader[$idx] }
}
else { $Series.Header = "Series $($idx)"} else { $Series.Header = "Series $($idx)"}
} }
} }
@@ -394,17 +409,19 @@ function Add-ExcelChart {
} }
if ($NoLegend) { $chart.Legend.Remove() } if ($NoLegend) { $chart.Legend.Remove() }
else { else {
if ($LegendPostion) {$Chart.Legend.Position = $LegendPostion} if ($PSBoundParameters.ContainsKey('LegendPosition')) {$chart.Legend.Position = $LegendPosition}
if ($PSBoundParameters.ContainsKey('LegendBold')) {$chart.Legend.Font.Bold = [boolean]$LegendBold}
if ($LegendSize) {$chart.Legend.Font.Size = $LegendSize} if ($LegendSize) {$chart.Legend.Font.Size = $LegendSize}
if ($legendBold) {$chart.Legend.Font.Bold = $true}
} }
if ($XAxisTitleText) { if ($XAxisTitleText) {
$chart.XAxis.Title.Text = $XAxisTitleText $chart.XAxis.Title.Text = $XAxisTitleText
if ($XAxisTitleBold) {$chart.XAxis.Title.Font.Bold = $true} if ($PSBoundParameters.ContainsKey('XAxisTitleBold')) {
$chart.XAxis.Title.Font.Bold = [boolean]$XAxisTitleBold
}
if ($XAxisTitleSize) {$chart.XAxis.Title.Font.Size = $XAxisTitleSize} if ($XAxisTitleSize) {$chart.XAxis.Title.Font.Size = $XAxisTitleSize}
} }
if ($XAxisPosition) {Write-Warning "X Axis position is not being set propertly at the moment, parameter ignored" } if ($XAxisPosition) {Write-Warning "X-axis position is not being set propertly at the moment, parameter ignored" }
#$chart.ChartXml.chartSpace.chart.plotArea.catAx.axPos.val = $XAxisPosition.ToString().substring(0,1)} #$chart.ChartXml.chartSpace.chart.plotArea.catAx.axPos.val = $XAxisPosition.ToString().substring(0,1)}
if ($XMajorUnit) {$chart.XAxis.MajorUnit = $XMajorUnit} if ($XMajorUnit) {$chart.XAxis.MajorUnit = $XMajorUnit}
if ($XMinorUnit) {$chart.XAxis.MinorUnit = $XMinorUnit} if ($XMinorUnit) {$chart.XAxis.MinorUnit = $XMinorUnit}
@@ -414,10 +431,12 @@ function Add-ExcelChart {
if ($YAxisTitleText) { if ($YAxisTitleText) {
$chart.YAxis.Title.Text = $YAxisTitleText $chart.YAxis.Title.Text = $YAxisTitleText
if ($YAxisTitleBold) {$chart.YAxis.Title.Font.Bold = $true} if ($PSBoundParameters.ContainsKey('YAxisTitleBold')) {
$chart.YAxis.Title.Font.Bold = [boolean]$YAxisTitleBold
}
if ($YAxisTitleSize) {$chart.YAxis.Title.Font.Size = $YAxisTitleSize} if ($YAxisTitleSize) {$chart.YAxis.Title.Font.Size = $YAxisTitleSize}
} }
if ($YAxisPosition) {Write-Warning "Y Axis position is not being set propertly at the moment, parameter ignored" } if ($YAxisPosition) {Write-Warning "Y-axis position is not being set propertly at the moment, parameter ignored" }
#$chart.ChartXml.chartSpace.chart.plotArea.valAx.axPos.val= $YAxisPosition.ToString().substring(0,1)} #$chart.ChartXml.chartSpace.chart.plotArea.valAx.axPos.val= $YAxisPosition.ToString().substring(0,1)}
if ($YMajorUnit) {$chart.YAxis.MajorUnit = $YMajorUnit} if ($YMajorUnit) {$chart.YAxis.MajorUnit = $YMajorUnit}
if ($YMinorUnit) {$chart.YAxis.MinorUnit = $YMinorUnit} if ($YMinorUnit) {$chart.YAxis.MinorUnit = $YMinorUnit}

View File

@@ -1,19 +1,22 @@
Function Open-ExcelPackage { Function Open-ExcelPackage {
<# <#
.Synopsis .Synopsis
Returns an Excel Package Object for the specified XLSX file Returns an ExcelPackage object for the specified XLSX fil.e
.Description .Description
Import-Excel and Export-Excel open an Excel file, carry out their tasks and close it again. Import-Excel and Export-Excel open an Excel file, carry out their tasks and close it again.
Sometimes it is necessary to open a file and do other work on it. Open-Excel package allows the file to be opened for these tasks. Sometimes it is necessary to open a file and do other work on it.
It takes a KillExcel switch to make sure Excel is not holding the file open; a password parameter for existing protected files, Open-ExcelPackage allows the file to be opened for these tasks.
and a create switch to set-up a new file if no file already exists. It takes a -KillExcel switch to make sure Excel is not holding the file open;
a -Password parameter for existing protected files,
and a -Create switch to set-up a new file if no file already exists.
.Example .Example
> >
PS> $excel = Open-ExcelPackage -Path "$env:TEMP\test99.xlsx" -Create PS> $excel = Open-ExcelPackage -Path "$env:TEMP\test99.xlsx" -Create
$ws = Add-WorkSheet -ExcelPackage $excel $ws = Add-WorkSheet -ExcelPackage $excel
This will create a new file in the temp folder if it doesn't already exist. It then adds a worksheet - This will create a new file in the temp folder if it doesn't already exist.
because no name is specified it will use the default name of "Sheet1" It then adds a worksheet - because no name is specified it will use the
default name of "Sheet1"
.Example .Example
> >
PS> $excel = Open-ExcelPackage -path "$xlPath" -Password $password PS> $excel = Open-ExcelPackage -path "$xlPath" -Password $password
@@ -21,20 +24,21 @@
Set-ExcelRange -Range $sheet1.Cells["E1:S1048576"], $sheet1.Cells["V1:V1048576"] -NFormat ([cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern) Set-ExcelRange -Range $sheet1.Cells["E1:S1048576"], $sheet1.Cells["V1:V1048576"] -NFormat ([cultureinfo]::CurrentCulture.DateTimeFormat.ShortDatePattern)
Close-ExcelPackage $excel -Show Close-ExcelPackage $excel -Show
This will open the password protected file at $xlPath using the password stored in $Password. This will open the password protected file at $xlPath using the password stored
Sheet1 is selected and formatting applied to two blocks of the sheet; then the file is and saved and loaded into Excel. in $Password. Sheet1 is selected and formatting applied to two blocks of the sheet;
then the file is and saved and loaded into Excel.
#> #>
[CmdLetBinding()] [CmdLetBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword","")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword","")]
[OutputType([OfficeOpenXml.ExcelPackage])] [OutputType([OfficeOpenXml.ExcelPackage])]
Param ( Param (
#The Path to the file to open #The path to the file to open.
[Parameter(Mandatory=$true)]$Path, [Parameter(Mandatory=$true)]$Path,
#If specified, any running instances of Excel will be terminated before opening the file. #If specified, any running instances of Excel will be terminated before opening the file.
[switch]$KillExcel, [switch]$KillExcel,
#The password for a protected worksheet, as a [normal] string (not a secure string.) #The password for a protected worksheet, as a [normal] string (not a secure string).
[String]$Password, [String]$Password,
#By default open only opens an existing file; -Create instructs it to create a new file if required. #By default Open-ExcelPackage will only opens an existing file; -Create instructs it to create a new file if required.
[switch]$Create [switch]$Create
) )
@@ -73,9 +77,10 @@ Function Close-ExcelPackage {
.Synopsis .Synopsis
Closes an Excel Package, saving, saving under a new name or abandoning changes and opening the file in Excel as required. Closes an Excel Package, saving, saving under a new name or abandoning changes and opening the file in Excel as required.
.Description .Description
When working with an Excel packaage object the workbook is held in memory and not saved until the Save() method of the package is called. When working with an ExcelPackage object, the Workbook is held in memory and not saved until the .Save() method of the package is called.
Close package saves and disposes of the package object. It can be called with -NoSave to abandon the file without saving, with a new "SaveAs" filename Close-ExcelPackage saves and disposes of the Package object. It can be called with -NoSave to abandon the file without saving, with a new "SaveAs" filename,
with a password to protect the file. And with Show to open it in Excel. -Calculate will try to update the workbook, although not everything can be recalculated and/or with a password to protect the file. And -Show will open the file in Excel;
-Calculate will try to update the workbook, although not everything can be recalculated
.Example .Example
Close-ExcelPackage -show $excel Close-ExcelPackage -show $excel
$excel holds a package object, this saves the workbook and loads it into Excel. $excel holds a package object, this saves the workbook and loads it into Excel.

View File

@@ -1,9 +1,9 @@
function Add-PivotTable { function Add-PivotTable {
<# <#
.Synopsis .Synopsis
Adds a Pivot table (and optional pivot chart) to a workbook Adds a PivotTable (and optional PivotChart) to a workbook.
.Description .Description
If the pivot table already exists, the source data will be updated. If the PivotTable already exists, the source data will be updated.
.Example .Example
> >
PS> $excel = Get-Service | Export-Excel -Path test.xlsx -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName ServiceTable -Title "Services on $Env:COMPUTERNAME" PS> $excel = Get-Service | Export-Excel -Path test.xlsx -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName ServiceTable -Title "Services on $Env:COMPUTERNAME"
@@ -15,7 +15,7 @@
.Example .Example
> >
PS> $chartdef = New-ExcelChartDefinition -Title "Gross and net by city and product" -ChartType ColumnClustered ` PS> $chartdef = New-ExcelChartDefinition -Title "Gross and net by city and product" -ChartType ColumnClustered `
-Column 11 -Width 500 -Height 360 -YMajorUnit 500 -YMinorUnit 100 -YAxisNumberformat "$#,##0" -LegendPostion Bottom -Column 11 -Width 500 -Height 360 -YMajorUnit 500 -YMinorUnit 100 -YAxisNumberformat "$#,##0" -LegendPosition Bottom
$excel = ConvertFrom-Csv @" $excel = ConvertFrom-Csv @"
Product, City, Gross, Net Product, City, Gross, Net
@@ -29,71 +29,71 @@
Add-PivotTable -PivotTableName Sales -Address $excel.Workbook.Worksheets[1].Cells["F1"] ` Add-PivotTable -PivotTableName Sales -Address $excel.Workbook.Worksheets[1].Cells["F1"] `
-SourceWorkSheet $excel.Workbook.Worksheets[1] -PivotRows City -PivotColumns Product -PivotData @{Gross="Sum";Net="Sum"} ` -SourceWorkSheet $excel.Workbook.Worksheets[1] -PivotRows City -PivotColumns Product -PivotData @{Gross="Sum";Net="Sum"} `
-PivotNumberFormat "$#,##0.00" -PivotTotals Both -PivotTableSyle Medium12 -PivotChartDefinition $chartdef -PivotNumberFormat "$#,##0.00" -PivotTotals Both -PivotTableStyle Medium12 -PivotChartDefinition $chartdef
Close-ExcelPackage -show $excel Close-ExcelPackage -show $excel
This script starts by defining a chart. Then it exports some data to an XLSX file and keeps the file open. This script starts by defining a chart. Then it exports some data to an XLSX file and keeps the file open.
The next step is to add the pivot table, normally this would be on its own sheeet in the workbook, The next step is to add the pivot table, normally this would be on its own sheet in the workbook,
but here -Address is specified to place it beside the data. The Add-Pivot table is given the chart definition and told to create a tale but here -Address is specified to place it beside the data. The Add-Pivot table is given the chart definition and told to create a tale
using the City field to create rows, the Product field to create columns and the data should be the sum of the gross field and the sum of the net field; using the City field to create rows, the Product field to create columns and the data should be the sum of the gross field and the sum of the net field;
grand totals for both gross and net are included for rows (Cities) and columns (product) and the the data is explicitly formatted as a currency. grand totals for both gross and net are included for rows (Cities) and columns (product) and the data is explicitly formatted as a currency.
Not that in thee the chart definition the number format for the axis does not include any fraction part Not that in the chart definition the number format for the axis does not include any fraction part.
#> #>
[cmdletbinding(defaultParameterSetName='ChartbyParams')] [cmdletbinding(defaultParameterSetName='ChartbyParams')]
[OutputType([OfficeOpenXml.Table.PivotTable.ExcelPivotTable])] [OutputType([OfficeOpenXml.Table.PivotTable.ExcelPivotTable])]
param ( param (
#Name for the new Pivot table - this will be the name of a sheet in the workbook #Name for the new PivotTable - this will be the name of a sheet in the Workbook.
[Parameter(Mandatory = $true)] [Parameter(Mandatory = $true)]
[string]$PivotTableName, [string]$PivotTableName,
#By default a pivot table will be created on its own sheet, but it can be created on an existing sheet by giving the address where the top left corner of the table should go. (Allow two rows for the filter if one is used.) #By default, a PivotTable will be created on its own sheet, but it can be created on an existing sheet by giving the address where the top left corner of the table should go. (Allow two rows for the filter if one is used.)
[OfficeOpenXml.ExcelAddressBase] [OfficeOpenXml.ExcelAddressBase]
$Address, $Address,
#An excel package object for the workbook. #An excel package object for the workbook.
$ExcelPackage, $ExcelPackage,
#Worksheet where the data is found #Worksheet where the data is found.
$SourceWorkSheet, $SourceWorkSheet,
#Address range in the worksheet e.g "A10:F20" - the first row must be column names: if not specified the whole sheet will be used. #Address range in the worksheet e.g "A10:F20" - the first row must be column names: if not specified the whole sheet will be used.
$SourceRange, $SourceRange,
#Fields to set as rows in the Pivot table #Fields to set as rows in the PivotTable.
$PivotRows, $PivotRows,
#A hash table in form "FieldName"="Function", where function is one of #A hash table in form "FieldName"="Function", where function is one of
#Average, Count, CountNums, Max, Min, Product, None, StdDev, StdDevP, Sum, Var, VarP #Average, Count, CountNums, Max, Min, Product, None, StdDev, StdDevP, Sum, Var, VarP.
$PivotData, $PivotData,
#Fields to set as columns in the Pivot table #Fields to set as columns in the PivotTable.
$PivotColumns, $PivotColumns,
#Fields to use to filter in the Pivot table #Fields to use to filter in the PivotTable.
$PivotFilter, $PivotFilter,
#If there are multiple datasets in a PivotTable, by default they are shown seperatate rows under the given row heading; this switch makes them seperate columns. #If there are multiple data items in a PivotTable, by default they are shown on separate rows; this switch makes them separate columns.
[Switch]$PivotDataToColumn, [Switch]$PivotDataToColumn,
#Define whther totals should be added to rows, columns neither, or both (the default is both) #Define whether totals should be added to rows, columns neither, or both (the default is both).
[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,
#Number format to apply to the data cells in the Pivot table #Number format to apply to the data cells in the PivotTable.
[string]$PivotNumberFormat, [string]$PivotNumberFormat,
#Apply a table style to the PivotTable #Apply a table style to the PivotTable.
[OfficeOpenXml.Table.TableStyles]$PivotTableSyle, [OfficeOpenXml.Table.TableStyles]$PivotTableStyle,
#Use a chart definition instead of specifying chart settings one by one #Use a chart definition instead of specifying chart settings one by one.
[Parameter(ParameterSetName='ChartbyDef', Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [Parameter(ParameterSetName='ChartbyDef', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
$PivotChartDefinition, $PivotChartDefinition,
#If specified a chart Will be included. #If specified, a chart will be included.
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
[Switch]$IncludePivotChart, [Switch]$IncludePivotChart,
#Optional title for the pivot chart, by default the title omitted. #Optional title for the pivot chart, by default the title omitted.
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
[String]$ChartTitle = "", [String]$ChartTitle = "",
#Height of the chart in Pixels (400 by default) #Height of the chart in Pixels (400 by default).
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
[int]$ChartHeight = 400 , [int]$ChartHeight = 400 ,
#Width of the chart in Pixels (600 by default) #Width of the chart in Pixels (600 by default).
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
[int]$ChartWidth = 600, [int]$ChartWidth = 600,
#Cell position of the top left corner of the chart, there will be this number of rows above the top edge of the chart (default is 0, chart starts at top edge of row 1). #Cell position of the top left corner of the chart, there will be this number of rows above the top edge of the chart (default is 0, chart starts at top edge of row 1).
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
[Int]$ChartRow = 0 , [Int]$ChartRow = 0 ,
#Cell position of the top left corner of the chart, there will be this number of cells to the left of the chart (default is 4, chart starts at left edge of column E) #Cell position of the top left corner of the chart, there will be this number of cells to the left of the chart (default is 4, chart starts at left edge of column E).
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
[Int]$ChartColumn = 4, [Int]$ChartColumn = 4,
#Vertical offset of the chart from the cell corner. #Vertical offset of the chart from the cell corner.
@@ -102,25 +102,25 @@
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
#Horizontal offset of the chart from the cell corner. #Horizontal offset of the chart from the cell corner.
[Int]$ChartColumnOffSetPixels = 0, [Int]$ChartColumnOffSetPixels = 0,
#Type of chart #Type of chart; defaults to "Pie".
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
[OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = 'Pie', [OfficeOpenXml.Drawing.Chart.eChartType]$ChartType = 'Pie',
#If specified hides the chart legend #If specified hides the chart legend.
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
[Switch]$NoLegend, [Switch]$NoLegend,
#if specified attaches the category to slices in a pie chart : not supported on all chart types, this may give errors if applied to an unsupported type. #If specified attaches the category to slices in a pie chart : not supported on all chart types, this may give errors if applied to an unsupported type.
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
[Switch]$ShowCategory, [Switch]$ShowCategory,
#If specified attaches percentages to slices in a pie chart. #If specified attaches percentages to slices in a pie chart.
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
[Switch]$ShowPercent, [Switch]$ShowPercent,
#If there is already content in the workbook the sheet with the Pivot table will not be active UNLESS Activate is specified #If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified.
[switch]$Activate, [switch]$Activate,
#Return the pivot table so it can be customized #Return the PivotTable so it can be customized.
[Switch]$PassThru [Switch]$PassThru
) )
if ($PivotTableName.length -gt 250) { if ($PivotTableName.length -gt 250) {
Write-warning -Message "Pivot table name will be truncated" Write-warning -Message "PivotTable name will be truncated"
$PivotTableName = $PivotTableName.Substring(0,250) $PivotTableName = $PivotTableName.Substring(0,250)
} }
if ($Address) { if ($Address) {
@@ -130,13 +130,13 @@
try { try {
if (-not $ExcelPackage) {Write-Warning -message "This combination of Parameters needs to include the ExcelPackage." ; return } if (-not $ExcelPackage) {Write-Warning -message "This combination of Parameters needs to include the ExcelPackage." ; return }
[OfficeOpenXml.ExcelWorksheet]$wsPivot = Add-WorkSheet -ExcelPackage $ExcelPackage -WorksheetName $pivotTableName -Activate:$Activate [OfficeOpenXml.ExcelWorksheet]$wsPivot = Add-WorkSheet -ExcelPackage $ExcelPackage -WorksheetName $pivotTableName -Activate:$Activate
if ($wsPivot.Name -ne $PivotTableName) {Write-Warning -Message "The Worksheet name for the pivot table does not match the table name '$PivotTableName'; probably because excess or illegal characters were removed." } if ($wsPivot.Name -ne $PivotTableName) {Write-Warning -Message "The Worksheet name for the PivotTable does not match the table name '$PivotTableName'; probably because excess or illegal characters were removed." }
if ($PivotFilter) {$Address = $wsPivot.Cells["A3"]} else { $Address = $wsPivot.Cells["A1"]} if ($PivotFilter) {$Address = $wsPivot.Cells["A3"]} else { $Address = $wsPivot.Cells["A1"]}
} }
catch {throw "Could not create the sheet for the Pivot table. $_" } catch {throw "Could not create the sheet for the PivotTable. $_" }
} }
#if the pivot doesn't exist, create it. #if the pivot doesn't exist, create it.
if (-not $wsPivot) {throw "There was a problem getting the worksheet for the pivot table"} if (-not $wsPivot) {throw "There was a problem getting the worksheet for the PivotTable"}
if (-not $wsPivot.PivotTables[$pivotTableName] ) { if (-not $wsPivot.PivotTables[$pivotTableName] ) {
try { try {
#Accept a string or a worksheet object as $SourceWorksheet - we don't need a worksheet if we have a Rangebase . #Accept a string or a worksheet object as $SourceWorksheet - we don't need a worksheet if we have a Rangebase .
@@ -160,7 +160,7 @@
elseif ( $SourceRange -is [String] -or $SourceRange -is [OfficeOpenXml.ExcelAddress]) { elseif ( $SourceRange -is [String] -or $SourceRange -is [OfficeOpenXml.ExcelAddress]) {
$pivotTable = $wsPivot.PivotTables.Add($Address,$SourceWorkSheet.Cells[$SourceRange], $pivotTableName) $pivotTable = $wsPivot.PivotTables.Add($Address,$SourceWorkSheet.Cells[$SourceRange], $pivotTableName)
} }
else {Write-warning "Could not create a pivot table with the Source Range provided."; return} else {Write-warning "Could not create a PivotTable with the Source Range provided."; return}
foreach ($Row in $PivotRows) { foreach ($Row in $PivotRows) {
try {$null = $pivotTable.RowFields.Add($pivotTable.Fields[$Row]) } try {$null = $pivotTable.RowFields.Add($pivotTable.Fields[$Row]) }
catch {Write-Warning -message "Could not add '$row' to Rows in PivotTable $pivotTableName." } catch {Write-Warning -message "Could not add '$row' to Rows in PivotTable $pivotTableName." }
@@ -198,12 +198,12 @@
if ($PivotTotals -eq "None" -or $PivotTotals -eq "Rows") { $pivotTable.ColumGrandTotals = $false } # Epplus spelling mistake, not mine! if ($PivotTotals -eq "None" -or $PivotTotals -eq "Rows") { $pivotTable.ColumGrandTotals = $false } # Epplus spelling mistake, not mine!
elseif ($PivotTotals -eq "Both" -or $PivotTotals -eq "Columns") { $pivotTable.ColumGrandTotals = $true } elseif ($PivotTotals -eq "Both" -or $PivotTotals -eq "Columns") { $pivotTable.ColumGrandTotals = $true }
if ($PivotDataToColumn ) { $pivotTable.DataOnRows = $false } if ($PivotDataToColumn ) { $pivotTable.DataOnRows = $false }
if ($PivotTableSyle) { $pivotTable.TableStyle = $PivotTableSyle} if ($PivotTableStyle) { $pivotTable.TableStyle = $PivotTableStyle}
} }
catch {Write-Warning -Message "Failed adding PivotTable '$pivotTableName': $_"} catch {Write-Warning -Message "Failed adding PivotTable '$pivotTableName': $_"}
} }
else { else {
Write-Warning -Message "Pivot table defined in $($pivotTableName) already exists, only the data range will be changed." Write-Warning -Message "PivotTable defined in $($pivotTableName) already exists, only the data range will be changed."
$pivotTable = $wsPivot.PivotTables[$pivotTableName] $pivotTable = $wsPivot.PivotTables[$pivotTableName]
if (-not $SourceRange) { $SourceRange = $SourceWorkSheet.Dimension.Address} if (-not $SourceRange) { $SourceRange = $SourceWorkSheet.Dimension.Address}
$pivotTable.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref = $SourceRange $pivotTable.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref = $SourceRange
@@ -230,11 +230,11 @@
function New-PivotTableDefinition { function New-PivotTableDefinition {
<# <#
.Synopsis .Synopsis
Creates Pivot table definitons for Export-Excel Creates PivotTable definitons for Export-Excel
.Description .Description
Export-Excel allows a single Pivot table to be defined using the parameters -IncludePivotTable, -PivotColumns -PivotRows, Export-Excel allows a single PivotTable to be defined using the parameters -IncludePivotTable, -PivotColumns -PivotRows,
=PivotData, -PivotFilter, -PivotTotals, -PivotDataToColumn, -IncludePivotChart and -ChartType. -PivotData, -PivotFilter, -PivotTotals, -PivotDataToColumn, -IncludePivotChart and -ChartType.
Its -PivotTableDefintion paramater allows multiple pivot tables to be defined, with additional parameters. Its -PivotTableDefintion paramater allows multiple PivotTables to be defined, with additional parameters.
New-PivotTableDefinition is a convenient way to build these definitions. New-PivotTableDefinition is a convenient way to build these definitions.
.Example .Example
> >
@@ -254,27 +254,27 @@ function New-PivotTableDefinition {
$SourceWorkSheet, $SourceWorkSheet,
#Address range in the worksheet e.g "A10:F20" - the first row must be column names: if not specified the whole sheet will be used/ #Address range in the worksheet e.g "A10:F20" - the first row must be column names: if not specified the whole sheet will be used/
$SourceRange, $SourceRange,
#Fields to set as rows in the Pivot table #Fields to set as rows in the PivotTable
$PivotRows, $PivotRows,
#A hash table in form "FieldName"="Function", where function is one of #A hash table in form "FieldName"="Function", where function is one of
#Average, Count, CountNums, Max, Min, Product, None, StdDev, StdDevP, Sum, Var, VarP #Average, Count, CountNums, Max, Min, Product, None, StdDev, StdDevP, Sum, Var, VarP
[hashtable]$PivotData, [hashtable]$PivotData,
#Fields to set as columns in the Pivot table #Fields to set as columns in the PivotTable
$PivotColumns, $PivotColumns,
#Fields to use to filter in the Pivot table #Fields to use to filter in the PivotTable
$PivotFilter, $PivotFilter,
#If there are multiple datasets in a PivotTable, by default they are shown seperatate rows under the given row heading; this switch makes them seperate columns. #If there are multiple datasets in a PivotTable, by default they are shown seperatate rows under the given row heading; this switch makes them seperate columns.
[Switch]$PivotDataToColumn, [Switch]$PivotDataToColumn,
#By default Pivot tables 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.
#Define whther totals should be added to rows, columns neither, or both (the default is both) #Define whther totals should be added to rows, columns neither, or both (the default is both)
[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,
#Number format to apply to the data cells in the Pivot table #Number format to apply to the data cells in the PivotTable
[string]$PivotNumberFormat, [string]$PivotNumberFormat,
#Apply a table style to the PivotTable #Apply a table style to the PivotTable
[OfficeOpenXml.Table.TableStyles]$PivotTableSyle, [OfficeOpenXml.Table.TableStyles]$PivotTableStyle,
#Use a chart definition instead of specifying chart settings one by one #Use a chart definition instead of specifying chart settings one by one
[Parameter(ParameterSetName='ChartbyDef', Mandatory=$true, ValueFromPipelineByPropertyName=$true)] [Parameter(ParameterSetName='ChartbyDef', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
$PivotChartDefinition, $PivotChartDefinition,
@@ -314,7 +314,7 @@ function New-PivotTableDefinition {
#If specified attaches percentages to slices in a pie chart. #If specified attaches percentages to slices in a pie chart.
[Parameter(ParameterSetName='ChartbyParams')] [Parameter(ParameterSetName='ChartbyParams')]
[Switch]$ShowPercent, [Switch]$ShowPercent,
#If there is already content in the workbook the sheet with the Pivot table will not be active UNLESS Activate is specified #If there is already content in the workbook the sheet with the PivotTable will not be active UNLESS Activate is specified
[switch]$Activate [switch]$Activate
) )
$validDataFuntions = [system.enum]::GetNames([OfficeOpenXml.Table.PivotTable.DataFieldFunctions]) $validDataFuntions = [system.enum]::GetNames([OfficeOpenXml.Table.PivotTable.DataFieldFunctions])

View File

@@ -13,6 +13,7 @@ If this project helped you reduce the time to get your job done, let me know.
<br/> <br/>
<p align="center"> <p align="center">
<a href="https://ci.appveyor.com/project/dfinke/importexcel/branch/master"><img src="https://ci.appveyor.com/api/projects/status/21hko6eqtpccrkba/branch/master?svg=true"></a> <a href="https://ci.appveyor.com/project/dfinke/importexcel/branch/master"><img src="https://ci.appveyor.com/api/projects/status/21hko6eqtpccrkba/branch/master?svg=true"></a>
<a href="https://dougfinke.visualstudio.com/ImportExcel/_build?definitionId=10"><img src="https://dougfinke.visualstudio.com/ImportExcel/_apis/build/status/ImportExcel-CI?branchName=master"></a>
</p> </p>
<p align="center"> <p align="center">
@@ -52,6 +53,37 @@ Install-Module ImportExcel -scope CurrentUser
Install-Module ImportExcel Install-Module ImportExcel
``` ```
# What's new 5.4
- Thank you to Conrad Agramont, Twitter: [@AGramont](https://twitter.com/@AGramont) for the `AddMultiWorkSheet.ps1` example. Much appreciated!
- Fixed several more bugs where parameters were ignored if passed a zero value
- Fixed bug where chart series headers could not come form a cell reference (=Sheet1!Z10 now works as a header reference)
- Add-Chart will now allow a single X range, or as many X ranges as there are Y ranges.
- Merge-MultipleSheets is more robust.
- Set-ExcelRow and Set-ExcelColumn trap attempts to process a sheet with no rows/columns.
- Help has been proof-read (thanks to Mrs. @Jhoneill !).
# What's new 5.3.4
- HotFix for parameter PivotTableSyle should be PivotTableStyle https://github.com/dfinke/ImportExcel/issues/453
# What's new 5.3.3
- Thank you to (lazywinadmin)[https://github.com/lazywinadmin] - Expand aliases in examples and elsewhere
- In Export-Excel fixed a bug where -AutoNameRange on pre-existing data included the header in the range.
- In Export-Excel fixed a bug which caused a zero, null, or empty string in a list of simple objects to be skipped.
- In Export-Excel improved the behaviour when a new worksheet is created without data, and Tables etc are added to it.
- In Join-Worksheet: added argument completer to -TitleBackgroundColor and set default for -TitleBackgroundStyle to 'Solid'.
- In Add-Excel chart, New-ExcelChart, tests and Examples fixed mis-spelling of "Position"
- In Send-SqlDataToExcel: improved robustness of check for no data returned.
- In Set-ExcelColumn: -column can come from the pipeline (supporting an array introduces complications for supporting script blocks); -AutoNameRange no longer requires heading to specified (so you can do 1..10 | Set-ExcelColumn -AutoNameRange ); In Set-ExcelRow: -Row can come from the pipeline
- Improved test coverage (back over 80%).
- Help and example improvements. In "Index - music.ps1" the module for querying the index can be downloaded from PowerShell gallery #requires set to demand it. In SQL+FillColumns+Pivot\example2.ps1 the GetSQL module can be downloaded and #Requires has been set. The F1 results spreadsheet is available from one drive and a link is provided.
- Added Azure DevOps continuous integration and badges <a href="https://dougfinke.visualstudio.com/ImportExcel/_build?definitionId=10"><img src="https://dougfinke.visualstudio.com/ImportExcel/_apis/build/status/ImportExcel-CI?branchName=master"></a>
# What's new in Release 5.3 # What's new in Release 5.3
- Help improvements and tidying up of examples and extra examples - Help improvements and tidying up of examples and extra examples

View File

@@ -29,6 +29,6 @@
Import-Module .\ImportExcel.psd1 -Force Import-Module .\ImportExcel.psd1 -Force
$names = Get-ExcelSheetInfo C:\Temp\testDelete.xlsx $names = Get-ExcelSheetInfo C:\Temp\testDelete.xlsx
$names | % { Remove-WorkSheet C:\Temp\testDelete.xlsx $_.Name} $names | Foreach-Object { Remove-WorkSheet C:\Temp\testDelete.xlsx $_.Name}
##Remove-WorkSheet C:\Temp\testDelete.xlsx sheet6 ##Remove-WorkSheet C:\Temp\testDelete.xlsx sheet6

View File

@@ -3,21 +3,26 @@
.SYNOPSIS .SYNOPSIS
Inserts a DataTable - returned by SQL query into an ExcelSheet, more efficiently than sending it via Export-Excel Inserts a DataTable - returned by SQL query into an ExcelSheet, more efficiently than sending it via Export-Excel
.DESCRIPTION .DESCRIPTION
This command can accept a data table object or take a SQL command and run it against a database connection. This command can accept a data table object or take a SQL statement and run it against a database connection.
If running the SQL command, it accepts an object representing a session with a SQL server or ODBC database, or a connection String to make a session. If running a SQL statement, the accepts either
It the DataTable is inserted into the Excel sheet * an object representing a session with a SQL server or ODBC database, or
It takes most of the parameters of Export-Excel, but it is more efficient than getting dataRows and piping them into Export-Excel, * a connection String to make a session.
data-rows have additional properties which need to be stripped off. The command takes most of the parameters of Export-Excel, and after inserting the table into the worksheet it
calls Export-Excel to carry out other tasks on the sheet. It is more efficient to do this than to get data-rows
and pipe them into Export-Excel, stripped off the database 'housekeeping' properties.
.PARAMETER DataTable .PARAMETER DataTable
A System.Data.DataTable object containing the data to be inserted into the spreadsheet without running a query. A System.Data.DataTable object containing the data to be inserted into the spreadsheet without running a query.
.PARAMETER Session .PARAMETER Session
An active ODBC Connection or SQL connection object representing a session with a database which will be queried to get the data . An active ODBC Connection or SQL connection object representing a session with a database which will be queried to get the data .
.PARAMETER Connection .PARAMETER Connection
Database connection string; either DSN=ODBC_Data_Source_Name, a full odbc or SQL Connection string, or the name of a SQL server. This is used to create a database session. A database connection string to be used to create a database session; either
* A Data source name written in the form DSN=ODBC_Data_Source_Name, or
* A full odbc or SQL Connection string, or
* The name of a SQL server.
.PARAMETER MSSQLServer .PARAMETER MSSQLServer
Specifies the connection string is for SQL server, not ODBC . Specifies the connection string is for SQL server, not ODBC.
.PARAMETER SQL .PARAMETER SQL
The SQL query to run against the session which was passed in -Session or set up from $Connection. The SQL query to run against the session which was passed in -Session or set up from -Connection.
.PARAMETER Database .PARAMETER Database
Switches to a specific database on a SQL server. Switches to a specific database on a SQL server.
.PARAMETER QueryTimeout .PARAMETER QueryTimeout
@@ -25,9 +30,9 @@
.PARAMETER Path .PARAMETER Path
Path to a new or existing .XLSX file. Path to a new or existing .XLSX file.
.PARAMETER WorkSheetName .PARAMETER WorkSheetName
The name of a sheet within the workbook - "Sheet1" by default . The name of a sheet within the workbook - "Sheet1" by default.
.PARAMETER KillExcel .PARAMETER KillExcel
Closes Excel - prevents errors writing to the file because Excel has it open Closes Excel - prevents errors writing to the file because Excel has it open.
.PARAMETER Title .PARAMETER Title
Text of a title to be placed in the top left cell. Text of a title to be placed in the top left cell.
.PARAMETER TitleBold .PARAMETER TitleBold
@@ -123,20 +128,32 @@
.EXAMPLE .EXAMPLE
C:\> Send-SQLDataToExcel -MsSQLserver -Connection localhost -SQL "select name,type,type_desc from [master].[sys].[all_objects]" -Path .\temp.xlsx -WorkSheetname master -AutoSize -FreezeTopRow -AutoFilter -BoldTopRow C:\> Send-SQLDataToExcel -MsSQLserver -Connection localhost -SQL "select name,type,type_desc from [master].[sys].[all_objects]" -Path .\temp.xlsx -WorkSheetname master -AutoSize -FreezeTopRow -AutoFilter -BoldTopRow
Connects to the local SQL server and selects 3 columns from [Sys].[all_objects] and exports then to a sheet named master with some basic header manager
Connects to the local SQL server and selects 3 columns from [Sys].[all_objects] and exports then to a sheet named master with some basic header management
.EXAMPLE
C:\> $SQL="SELECT top 25 Name,Length From TestData ORDER BY Length DESC"
C:\> $Connection = ' Driver={Microsoft Access Driver (*.mdb, *.accdb)};Dbq=C:\Users\James\Documents\Database1.accdb;'
C:\> Send-SQLDataToExcel -Connection $connection -SQL $sql -path .\demo1.xlsx -WorkSheetname "Sizes" -AutoSize
This declares a SQL statement and creates an ODBC connection string to read from an Access file and extracts data from it and sends it to a new worksheet
.EXAMPLE .EXAMPLE
C:\> $SQL="SELECT top 25 DriverName, Count(RaceDate) as Races, Count(Win) as Wins, Count(Pole) as Poles, Count(FastestLap) as Fastlaps FROM Results GROUP BY DriverName ORDER BY (count(win)) DESC" C:\> $SQL="SELECT top 25 DriverName, Count(RaceDate) as Races, Count(Win) as Wins, Count(Pole) as Poles, Count(FastestLap) as Fastlaps FROM Results GROUP BY DriverName ORDER BY (count(win)) DESC"
C:\> $Connection = 'Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DriverId=790;ReadOnly=0;Dbq=C:\users\James\Documents\f1Results.xlsx;' C:\> $Connection = 'Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};Dbq=C:\users\James\Documents\f1Results.xlsx;'
C:\> Send-SQLDataToExcel -Connection $connection -SQL $sql -path .\demo1.xlsx -WorkSheetname "Winners" -AutoSize -AutoNameRange
C:\> Send-SQLDataToExcel -Connection $connection -SQL $sql -path .\demo1.xlsx -WorkSheetname "Winners" -AutoSize -AutoNameRange -ConditionalFormat @{DataBarColor="Blue"; Range="Wins"}
This declares a SQL statement and creates an ODBC connection string to read from an Excel file, it then runs the statement and outputs the resulting data to a new spreadsheet. This declares a SQL statement and creates an ODBC connection string to read from an Excel file, it then runs the statement and outputs the resulting data to a new spreadsheet.
The spreadsheet is formatted and a data bar added to show make the drivers' wins clearer.
(the F1 results database is available from https://1drv.ms/x/s!AhfYu7-CJv4ehNdZWxJE9LMAX_N5sg ) (the F1 results database is available from https://1drv.ms/x/s!AhfYu7-CJv4ehNdZWxJE9LMAX_N5sg )
.EXAMPLE .EXAMPLE
C:\> $SQL = "SELECT top 25 DriverName, Count(RaceDate) as Races, Count(Win) as Wins, Count(Pole) as Poles, Count(FastestLap) as Fastlaps FROM Results GROUP BY DriverName ORDER BY (count(win)) DESC" C:\> $SQL = "SELECT top 25 DriverName, Count(RaceDate) as Races, Count(Win) as Wins, Count(Pole) as Poles, Count(FastestLap) as Fastlaps FROM Results GROUP BY DriverName ORDER BY (count(win)) DESC"
C:\> Get-SQL -Session F1 -excel -Connection "C:\Users\mcp\OneDrive\public\f1\f1Results.xlsx" -sql $sql -OutputVariable Table | out-null C:\> Get-SQL -Session F1 -excel -Connection "C:\Users\mcp\OneDrive\public\f1\f1Results.xlsx" -sql $sql -OutputVariable Table | out-null
C:\> Send-SQLDataToExcel -DataTable $Table -Path ".\demo3.xlsx" -WorkSheetname Gpwinners -autosize -TableName winners -TableStyle Light6 -show C:\> Send-SQLDataToExcel -DataTable $Table -Path ".\demo3.xlsx" -WorkSheetname Gpwinners -autosize -TableName winners -TableStyle Light6 -show
This uses Get-SQL (at least V1.1 download from the gallery with Install-Module -Name GetSQL - note the function is get-SQL the module is GetSQL without the "-" ) This uses Get-SQL (at least V1.1 - download from the gallery with Install-Module -Name GetSQL - note the function is Get-SQL the module is GetSQL without the "-" )
to simplify making database connections and building /submitting SQL statements. to simplify making database connections and building /submitting SQL statements.
Here it uses the same SQL statement as before; -OutputVariable leaves a System.Data.DataTable object in $table Here it uses the same SQL statement as before; -OutputVariable leaves a System.Data.DataTable object in $table
and Send-SQLDataToExcel puts $table into the worksheet and sets it as an Excel table. and Send-SQLDataToExcel puts $table into the worksheet and sets it as an Excel table.
@@ -145,7 +162,7 @@
C:\> $SQL = "SELECT top 25 DriverName, Count(Win) as Wins FROM Results GROUP BY DriverName ORDER BY (count(win)) DESC" C:\> $SQL = "SELECT top 25 DriverName, Count(Win) as Wins FROM Results GROUP BY DriverName ORDER BY (count(win)) DESC"
C:\> Send-SQLDataToExcel -Session $DbSessions["f1"] -SQL $sql -Path ".\demo3.xlsx" -WorkSheetname Gpwinners -autosize -ColumnChart C:\> Send-SQLDataToExcel -Session $DbSessions["f1"] -SQL $sql -Path ".\demo3.xlsx" -WorkSheetname Gpwinners -autosize -ColumnChart
Like the previous example, this uses Get-SQL (download from the gallery with Install-Module -Name GetSQL).It uses the connection which Get-SQL made rather than an ODFBC connection string Like the previous example, this uses Get-SQL (download from the gallery with Install-Module -Name GetSQL). It uses the connection which Get-SQL made rather than an ODFBC connection string
Here the data is presented as a quick chart. Here the data is presented as a quick chart.
.EXAMPLE .EXAMPLE
C:\> Send-SQLDataToExcel -path .\demo3.xlsx -WorkSheetname "LR" -Connection "DSN=LR" -sql "SELECT name AS CollectionName FROM AgLibraryCollection Collection ORDER BY CollectionName" C:\> Send-SQLDataToExcel -path .\demo3.xlsx -WorkSheetname "LR" -Connection "DSN=LR" -sql "SELECT name AS CollectionName FROM AgLibraryCollection Collection ORDER BY CollectionName"
@@ -179,7 +196,7 @@
[OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'None', [OfficeOpenXml.Style.ExcelFillStyle]$TitleFillPattern = 'None',
[Switch]$TitleBold, [Switch]$TitleBold,
[Int]$TitleSize = 22, [Int]$TitleSize = 22,
[System.Drawing.Color]$TitleBackgroundColor, $TitleBackgroundColor,
[String]$Password, [String]$Password,
[Hashtable]$PivotTableDefinition, [Hashtable]$PivotTableDefinition,
[Switch]$IncludePivotTable, [Switch]$IncludePivotTable,
@@ -254,7 +271,7 @@
$rowCount = $dataAdapter.fill($dataTable) $rowCount = $dataAdapter.fill($dataTable)
Write-Verbose -Message "Query returned $rowCount row(s)" Write-Verbose -Message "Query returned $rowCount row(s)"
} }
if ($DataTable.Rows) { if ($DataTable.Rows.Count) {
#ExportExcel user a -NoHeader parameter so that's what we use here, but needs to be the other way around. #ExportExcel user a -NoHeader parameter so that's what we use here, but needs to be the other way around.
$printHeaders = -not $NoHeader $printHeaders = -not $NoHeader
if ($Title) {$r = $StartRow +1 } if ($Title) {$r = $StartRow +1 }
@@ -263,6 +280,13 @@
$excelPackage = Export-Excel -Path $Path -WorkSheetname $WorkSheetname -PassThru $excelPackage = Export-Excel -Path $Path -WorkSheetname $WorkSheetname -PassThru
$excelPackage.Workbook.Worksheets[$WorkSheetname].Cells[$r,$StartColumn].LoadFromDataTable($dataTable, $printHeaders ) | Out-Null $excelPackage.Workbook.Worksheets[$WorkSheetname].Cells[$r,$StartColumn].LoadFromDataTable($dataTable, $printHeaders ) | Out-Null
#Apply date format
for ($c=0 ; $c -lt $DataTable.Columns.Count ; $c++) {
if ($DataTable.Columns[$c].DataType -eq [datetime]) {
Set-ExcelColumn -Worksheet $excelPackage.Workbook.Worksheets[$WorkSheetname] -Column ($c +1) -NumberFormat 'Date-Time'
}
}
#Call export-excel with any parameters which don't relate to the SQL query #Call export-excel with any parameters which don't relate to the SQL query
"Connection", "Database" , "Session", "MsSQLserver", "Destination" , "SQL" , "DataTable", "Path" | ForEach-Object {$null = $PSBoundParameters.Remove($_) } "Connection", "Database" , "Session", "MsSQLserver", "Destination" , "SQL" , "DataTable", "Path" | ForEach-Object {$null = $PSBoundParameters.Remove($_) }
Export-Excel -ExcelPackage $excelPackage @PSBoundParameters Export-Excel -ExcelPackage $excelPackage @PSBoundParameters

View File

@@ -4,9 +4,9 @@
$Row, $Row,
$LastColumn, $LastColumn,
[OfficeOpenXml.Style.ExcelFillStyle]$Pattern, [OfficeOpenXml.Style.ExcelFillStyle]$Pattern,
[System.Drawing.Color]$Color $Color
) )
if ($Color -is [string]) {$Color = [System.Drawing.Color]::$Color }
$t=$WorkSheet.Cells["A$($Row):$($LastColumn)$($Row)"] $t=$WorkSheet.Cells["A$($Row):$($LastColumn)$($Row)"]
$t.Style.Fill.PatternType=$Pattern $t.Style.Fill.PatternType=$Pattern
$t.Style.Fill.BackgroundColor.SetColor($Color) $t.Style.Fill.BackgroundColor.SetColor($Color)

View File

@@ -1,108 +1,125 @@
Function Set-ExcelColumn { Function Set-ExcelColumn {
<# <#
.SYNOPSIS .SYNOPSIS
Adds a column to the existing data area in an Excel sheet, fills values and sets formatting Adds or modifies a column in an Excel worksheet, filling values, setting formatting and/or creating named ranges.
.DESCRIPTION .DESCRIPTION
Set-ExcelColumn takes a value which is either a string containing a value or formula or a scriptblock Set-ExcelColumn can take a value which is either a string containing a
which evaluates to a string, and optionally a column number and fills that value down the column. value or formula or a scriptblock which evaluates to a string,
A column heading can be specified and the new column can be made a named range. and optionally a column number and fills that value down the column.
A column heading can be specified, and the column can be made a named range.
The column can be formatted in the same operation. The column can be formatted in the same operation.
.EXAMPLE .EXAMPLE
Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'Currency' Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'Currency'
$ws contains a worksheet object - and column E is set to use the local currecy format. $ws contains a worksheet object - and column "E" is set to use the
Intelisense will complete predefined number formats. You can see how currency is interpreted on the local computer with the command local currency format. Intelisense will complete the names of predefined
number formats. You can see how currency is interpreted on the
local computer with the command
Expand-NumberFormat currency Expand-NumberFormat currency
.EXAMPLE .EXAMPLE
Set-ExcelColumn -Worksheet $ws -Heading "WinsToFastLaps" -Value {"=E$row/C$row"} -Column 7 -AutoSize -AutoNameRange Set-ExcelColumn -Worksheet $ws -Heading "WinsToFastLaps" -Value {"=E$row/C$row"} -Column 7 -AutoSize -AutoNameRange
Here $WS already contains a worksheet which contains counts of races won and fastest laps recorded by racing drivers (in columns C and E) Here, $WS already contains a worksheet which holds counts of races won
Set-ExcelColumn specifies that Column 7 should have a heading of "WinsToFastLaps" and the data cells should contain =E2/C2 , =E3/C3 etc and fastest laps recorded by racing drivers (in columns C and E).
the data cells should become a named range, which will also be "WinsToFastLaps" the column width will be set automatically Set-ExcelColumn specifies that Column 7 should have a heading of
"WinsToFastLaps" and the data cells should contain =E2/C2 , =E3/C3 etc
the new data cells should become a named range, which will also be
named "WinsToFastLaps" and the column width will be set automatically.
.EXAMPLE .EXAMPLE
Set-ExcelColumn -Worksheet $ws -Heading "Link" -Value {"https://en.wikipedia.org" + $worksheet.cells["B$Row"].value } -AutoSize Set-ExcelColumn -Worksheet $ws -Heading "Link" -Value {"https://en.wikipedia.org" + $worksheet.cells["B$Row"].value } -AutoSize
In this example, the worksheet in $ws has partial links to wikipedia pages in column B. In this example, the worksheet in $ws has partial links to Wikipedia
The Value parameter is is a script block and it outputs a string which begins https... and ends with the value of cell at column B in the current row. pages in column B. The -Value parameter is a script block which
When given a valid URI, Set-ExcelColumn makes it a hyperlink. The column will be autosized to fit the links. outputs a string beginning "https..." and ending with the value of
the cell at column B in the current row.
When given a valid URI, Set-ExcelColumn makes it a hyperlink.
The column will be autosized to fit the links.
.EXAMPLE
4..6 | Set-ExcelColumn -Worksheet $ws -AutoNameRange
Again $ws contains a worksheet. Here columns 4 to 6 are made into
named ranges, row 1 is used for the range name
and the rest of the column becomes the range.
#> #>
[cmdletbinding()] [cmdletbinding()]
[Alias(" Set-Column")] [Alias("Set-Column")]
[OutputType([OfficeOpenXml.ExcelColumn],[String])] [OutputType([OfficeOpenXml.ExcelColumn],[String])]
Param ( Param (
#If specifing the worksheet by name the ExcelPackage object which contains it needs to be passed #If specifying the worksheet by name, the ExcelPackage object which contains the worksheet also needs to be passed.
[Parameter(ParameterSetName="Package",Mandatory=$true)] [Parameter(ParameterSetName="Package",Mandatory=$true)]
[OfficeOpenXml.ExcelPackage]$ExcelPackage, [OfficeOpenXml.ExcelPackage]$ExcelPackage,
#The sheet to update can be a given as a name or an Excel Worksheet object - this sets it by name #The sheet to update can be given as a name or an Excel Worksheet object - this sets it by name.
[Parameter(ParameterSetName="Package")] [Parameter(ParameterSetName="Package")]
#The sheet to update can be a given as a name or an Excel Worksheet object - $workSheet contains the object
[String]$Worksheetname = "Sheet1", [String]$Worksheetname = "Sheet1",
#The worksheet object can be passed instead of passing a sheet name and a package. #This passes the worksheet object instead of passing a sheet name and an Excelpackage object.
[Parameter(ParameterSetName="sheet",Mandatory=$true)] [Parameter(ParameterSetName="sheet",Mandatory=$true)]
[OfficeOpenXml.ExcelWorksheet]$Worksheet, [OfficeOpenXml.ExcelWorksheet]$Worksheet,
#Column to fill down - first column is 1. 0 will be interpreted as first unused column #Column to fill down - the first column is 1. 0 will be interpreted as first empty column.
[Parameter(ValueFromPipeline=$true)]
[ValidateRange(0,16384)] [ValidateRange(0,16384)]
$Column = 0 , $Column = 0 ,
#First row to fill data in #First row to fill data in.
[ValidateRange(1,1048576)] [ValidateRange(1,1048576)]
[Int]$StartRow , [Int]$StartRow ,
#value, formula or script block to fill in. Script block can use $row, $column [number], $columnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn #A value, formula or scriptblock to fill in. A script block can use $worksheet, $row, $column [number], $columnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn.
$Value , $Value ,
#Optional column heading #Optional column heading.
$Heading , $Heading ,
#Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc #Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc.
[Alias("NFormat")] [Alias("NFormat")]
$NumberFormat, $NumberFormat,
#Style of border to draw around the row #Style of border to draw around the row.
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround, [OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround,
#Colour for the text - if none specified it will be left as it it is #Colour for the text - if none specified it will be left as it it is.
[System.Drawing.Color]$FontColor, $FontColor,
#Make text bold; use -Bold:$false to remove bold #Make text bold; use -Bold:$false to remove bold.
[Switch]$Bold, [Switch]$Bold,
#Make text italic; use -Italic:$false to remove italic #Make text italic; use -Italic:$false to remove italic.
[Switch]$Italic, [Switch]$Italic,
#Underline the text using the underline style in -underline type; use -Underline:$false to remove underlining #Underline the text using the underline style in -UnderlineType; use -Underline:$false to remove underlining.
[Switch]$Underline, [Switch]$Underline,
#Should Underline use single or double, normal or accounting mode : default is single normal #Specifies whether underlining should be single or double, normal or accounting mode. The default is "Single".
[OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single,
#Strike through text; use -Strikethru:$false to remove Strike through #Strike through text; use -StrikeThru:$false to remove strike through.
[Switch]$StrikeThru, [Switch]$StrikeThru,
#Subscript or superscript (or none) #Subscript or Superscript (or None).
[OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift,
#Font to use - Excel defaults to Calibri #Font to use - Excel defaults to Calibri.
[String]$FontName, [String]$FontName,
#Point size for the text #Point size for the text.
[float]$FontSize, [float]$FontSize,
#Change background colour #Change background color.
[System.Drawing.Color]$BackgroundColor, $BackgroundColor,
#Background pattern - solid by default #Background pattern - "Solid" by default.
[OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid , [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid ,
#Secondary colour for background pattern #Secondary color for background pattern.
[Alias("PatternColour")] [Alias("PatternColour")]
[System.Drawing.Color]$PatternColor, $PatternColor,
#Turn on text wrapping; use -WrapText:$false to turn off word wrapping #Turn on Text-Wrapping; use -WrapText:$false to turn off wrapping.
[Switch]$WrapText, [Switch]$WrapText,
#Position cell contents to left, right, center etc. default is 'General' #Position cell contents to Left, Right, Center etc. Default is "General".
[OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment,
#Position cell contents to top bottom or centre #Position cell contents to Top, Bottom or Center.
[OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment, [OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment,
#Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. #Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise.
[ValidateRange(-90, 90)] [ValidateRange(-90, 90)]
[int]$TextRotation , [int]$TextRotation ,
#Autofit cells to width #Attempt to auto-fit cells to the width their contents.
[Alias("AutoFit")] [Alias("AutoFit")]
[Switch]$AutoSize, [Switch]$AutoSize,
#Set cells to a fixed width, ignored if Autosize is specified #Set cells to a fixed width, ignored if -AutoSize is specified.
[float]$Width, [float]$Width,
#Set the inserted data to be a named range (ignored if header is not specified) #Set the inserted data to be a named range.
[Switch]$AutoNameRange, [Switch]$AutoNameRange,
#Hide the column #Hide the column.
[Switch]$Hide, [Switch]$Hide,
#If Sepecified returns the range of cells which were affected #If specified, returns the range of cells which were affected.
[Switch]$ReturnRange, [Switch]$Specified,
#If Specified, return an ExcelPackage object to allow further work to be done on the file. #If specified, return an object representing the Column, to allow further work to be done on it.
[Switch]$PassThru [Switch]$PassThru
) )
begin {
#if we were passed a package object and a worksheet name , get the worksheet. #if we were passed a package object and a worksheet name , get the worksheet.
if ($ExcelPackage) {$Worksheet = $ExcelPackage.Workbook.Worksheets[$Worksheetname] } if ($ExcelPackage) {$Worksheet = $ExcelPackage.Workbook.Worksheets[$Worksheetname] }
@@ -112,18 +129,25 @@
$startColumn = $Worksheet.Dimension.Start.Column $startColumn = $Worksheet.Dimension.Start.Column
$endColumn = $Worksheet.Dimension.End.Column $endColumn = $Worksheet.Dimension.End.Column
$endRow = $Worksheet.Dimension.End.Row $endRow = $Worksheet.Dimension.End.Row
}
process {
if ($null -eq $workSheet.Dimension) {Write-Warning "Can't format an empty worksheet."; return}
if ($Column -eq 0 ) {$Column = $endColumn + 1 } if ($Column -eq 0 ) {$Column = $endColumn + 1 }
$columnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1","" $columnName = [OfficeOpenXml.ExcelCellAddress]::new(1,$column).Address -replace "1",""
Write-Verbose -Message "Updating Column $columnName" Write-Verbose -Message "Updating Column $columnName"
#If there is a heading, insert it and use it as the name for a range (if we're creating one) #If there is a heading, insert it and use it as the name for a range (if we're creating one)
if ($Heading) { if ($PSBoundParameters.ContainsKey('Heading')) {
$Worksheet.Cells[$StartRow, $Column].Value = $Heading $Worksheet.Cells[$StartRow, $Column].Value = $Heading
$StartRow ++ $StartRow ++
if ($AutoNameRange) { Add-ExcelName -Range $Worksheet.Cells[$StartRow, $Column, $endRow, $Column] -RangeName $Heading } if ($AutoNameRange) {
Add-ExcelName -Range $Worksheet.Cells[$StartRow, $Column, $endRow, $Column] -RangeName $Heading
} }
#Fill in the data }
elseif ($AutoNameRange) {
Add-ExcelName -Range $Worksheet.Cells[($StartRow+1), $Column, $endRow, $Column] -RangeName $Worksheet.Cells[$StartRow, $Column].Value
}
#Fill in the data -it can be zero null or and empty string.
if ($PSBoundParameters.ContainsKey('Value')) { foreach ($row in ($StartRow..$endRow)) { if ($PSBoundParameters.ContainsKey('Value')) { foreach ($row in ($StartRow..$endRow)) {
if ($Value -is [scriptblock]) { #re-create the script block otherwise variables from this function are out of scope. if ($Value -is [scriptblock]) { #re-create the script block otherwise variables from this function are out of scope.
$cellData = & ([scriptblock]::create( $Value )) $cellData = & ([scriptblock]::create( $Value ))
@@ -147,20 +171,22 @@
if ($cellData -is [datetime]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = 'm/d/yy h:mm' } # This is not a custom format, but a preset recognized as date and localized. if ($cellData -is [datetime]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = 'm/d/yy h:mm' } # This is not a custom format, but a preset recognized as date and localized.
if ($cellData -is [timespan]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = '[h]:mm:ss' } if ($cellData -is [timespan]) { $Worksheet.Cells[$Row, $Column].Style.Numberformat.Format = '[h]:mm:ss' }
}} }}
#region Apply formatting #region Apply formatting
$params = @{} $params = @{}
foreach ($p in @('Underline','Bold','Italic','StrikeThru','FontSize','FontShift','NumberFormat','TextRotation', foreach ($p in @('Underline','Bold','Italic','StrikeThru', 'FontName', 'FontSize','FontShift','NumberFormat','TextRotation',
'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Autosize', 'Width', 'FontColor' 'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Autosize', 'Width', 'FontColor'
'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { 'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) {
if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]}
} }
$theRange = "$columnName$StartRow`:$columnName$endRow"
if ($params.Count) { if ($params.Count) {
$theRange = "$columnName$StartRow`:$columnName$endRow"
Set-ExcelRange -WorkSheet $Worksheet -Range $theRange @params Set-ExcelRange -WorkSheet $Worksheet -Range $theRange @params
} }
#endregion #endregion
if ($PSBoundParameters["Hide"]) {$workSheet.Column($Column).Hidden = [bool]$Hide} if ($PSBoundParameters.ContainsKey('Hide')) {$workSheet.Column($Column).Hidden = [bool]$Hide}
#return the new data if -passthru was specified. #return the new data if -passthru was specified.
if ($passThru) { $Worksheet.Column($Column)} if ($PassThru) { $Worksheet.Column($Column)}
elseif ($ReturnRange) { $theRange} elseif ($ReturnRange) { $theRange}
}
} }

View File

@@ -1,111 +1,120 @@
Function Set-ExcelRow { Function Set-ExcelRow {
<# <#
.Synopsis .Synopsis
Fills values into a [new] row in an Excel spreadsheet. And sets row formmats. Fills values into a [new] row in an Excel spreadsheet, and sets row formats.
.Description .Description
Set-ExcelRow accepts either a Worksheet object or an Excel package object returned by Export-Excel and the name of a sheet, Set-ExcelRow accepts either a Worksheet object or an ExcelPackage object
and inserts the chosen contents into a row of the sheet. returned by Export-Excel and the name of a sheet, and inserts the chosen
The contents can be a constant "42" , a formula or a script block which is converted into a constant or formula. contents into a row of the sheet. The contents can be a constant,
like "42", a formula or a script block which is converted into a
constant or a formula.
The first cell of the row can optionally be given a heading. The first cell of the row can optionally be given a heading.
.Example .Example
Set-ExcelRow -Worksheet $ws -Heading Total -Value {"=sum($columnName`2:$columnName$endrow)" } Set-ExcelRow -Worksheet $ws -Heading Total -Value {"=sum($columnName`2:$columnName$endrow)" }
$Ws contains a worksheet object, and no Row number is specified so Set-ExcelRow will select the next row after the end of the data in the sheet $Ws contains a worksheet object, and no Row number is specified so
The first cell will contain "Total", and each other cell will contain Set-ExcelRow will select the next row after the endof the data in
=Sum(xx2:xx99) - where xx is the column name, and 99 is the last row of data. the sheet. The first cell in the row will contain "Total", and
each of the other cells will contain
=Sum(xx2:xx99)
where xx is the column name, and 99 is the last row of data.
Note the use of `2 to Prevent 2 becoming part of the variable "ColumnName" Note the use of `2 to Prevent 2 becoming part of the variable "ColumnName"
The script block can use $row, $column, $ColumnName, $startRow/Column $endRow/Column The script block can use $Worksheet, $Row, $Column (number),
$ColumnName (letter), $StartRow/Column and $EndRow/Column.
.Example .Example
Set-ExcelRow -Worksheet $ws -Heading Total -HeadingBold -Value {"=sum($columnName`2:$columnName$endrow)" } -NumberFormat 'Currency' -StartColumn 2 -Bold -BorderTop Double -BorderBottom Thin Set-ExcelRow -Worksheet $ws -Heading Total -HeadingBold -Value {"=sum($columnName`2:$columnName$endrow)" } -NumberFormat 'Currency' -StartColumn 2 -Bold -BorderTop Double -BorderBottom Thin
This builds on the previous example, but this time the label "Total" appears in column 2 and the formula fills from column 3 onwards; This builds on the previous example, but this time the label "Total"
the formula and heading are set in bold face, and the formula is formatted for the local currency, appears in column 2 and the formula fills from column 3 onwards.
and given a double line border above and single line border below. The formula and heading are set in bold face, and the formula is
formatted for the local currency, and given a double line border
above and single line border below.
#> #>
[cmdletbinding()] [cmdletbinding()]
[Alias(" Set-Row")] [Alias("Set-Row")]
[OutputType([OfficeOpenXml.ExcelRow],[String])] [OutputType([OfficeOpenXml.ExcelRow],[String])]
Param ( Param (
#An Excel package object - e.g. from Export-Excel -passthru - requires a sheet name #An Excel package object - e.g. from Export-Excel -PassThru - requires a sheet name.
[Parameter(ParameterSetName="Package",Mandatory=$true)] [Parameter(ParameterSetName="Package",Mandatory=$true)]
[OfficeOpenXml.ExcelPackage]$ExcelPackage, [OfficeOpenXml.ExcelPackage]$ExcelPackage,
#the name to update in the package #The name of the sheet to update in the package.
[Parameter(ParameterSetName="Package")] [Parameter(ParameterSetName="Package")]
$Worksheetname = "Sheet1", $Worksheetname = "Sheet1",
#A worksheet object #A worksheet object instead of passing a name and package.
[Parameter(ParameterSetName="Sheet",Mandatory=$true)] [Parameter(ParameterSetName="Sheet",Mandatory=$true)]
[OfficeOpenXml.Excelworksheet] $Worksheet, [OfficeOpenXml.Excelworksheet] $Worksheet,
#Row to fill right - first row is 1. 0 will be interpreted as first unused row #Row to fill right - first row is 1. 0 will be interpreted as first unused row.
[Parameter(ValueFromPipeline = $true)]
$Row = 0 , $Row = 0 ,
#Position in the row to start from #Position in the row to start from.
[int]$StartColumn, [int]$StartColumn,
#Value, formula or script block to fill in. Script block can use $worksheet, $row, $Column [number], $ColumnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn #Value, Formula or ScriptBlock to fill in. A ScriptBlock can use $worksheet, $row, $Column [number], $ColumnName [letter(s)], $startRow, $startColumn, $endRow, $endColumn.
$Value, $Value,
#Optional Row heading #Optional row-heading.
$Heading , $Heading ,
#Set the heading in bold type #Set the heading in bold type.
[Switch]$HeadingBold, [Switch]$HeadingBold,
#Change the size of the heading type #Change the font-size of the heading.
[Int]$HeadingSize , [Int]$HeadingSize ,
#Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc #Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc.
[Alias("NFormat")] [Alias("NFormat")]
$NumberFormat, $NumberFormat,
#Style of border to draw around the row #Style of border to draw around the row.
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround, [OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround,
#Color of the border #Color of the border.
[System.Drawing.Color]$BorderColor=[System.Drawing.Color]::Black, $BorderColor=[System.Drawing.Color]::Black,
#Style for the bottom border #Style for the bottom border.
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderBottom, [OfficeOpenXml.Style.ExcelBorderStyle]$BorderBottom,
#Style for the top border #Style for the top border.
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderTop, [OfficeOpenXml.Style.ExcelBorderStyle]$BorderTop,
#Style for the left border #Style for the left border.
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderLeft, [OfficeOpenXml.Style.ExcelBorderStyle]$BorderLeft,
#Style for the right border #Style for the right border.
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderRight, [OfficeOpenXml.Style.ExcelBorderStyle]$BorderRight,
#Colour for the text - if none specified it will be left as it it is #Color for the text - if none specified it will be left as it it is.
[System.Drawing.Color]$FontColor, $FontColor,
#Make text bold; use -Bold:$false to remove bold #Make text bold; use -Bold:$false to remove bold.
[Switch]$Bold, [Switch]$Bold,
#Make text italic; use -Italic:$false to remove italic #Make text italic; use -Italic:$false to remove italic.
[Switch]$Italic, [Switch]$Italic,
#Underline the text using the underline style in -underline type; use -Underline:$false to remove underlining #Underline the text using the underline style in -UnderlineType; use -Underline:$false to remove underlining.
[Switch]$Underline, [Switch]$Underline,
#Should Underline use single or double, normal or accounting mode : default is single normal #Specifies whether underlining should be single or double, normal or accounting mode. The default is "Single".
[OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single,
#Strike through text; use -Strikethru:$false to remove Strike through #Strike through text; use -StrikeThru:$false to remove strike through.
[Switch]$StrikeThru, [Switch]$StrikeThru,
#Subscript or superscript (or none) #Subscript or Superscript (or none).
[OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift,
#Font to use - Excel defaults to Calibri #Font to use - Excel defaults to Calibri.
[String]$FontName, [String]$FontName,
#Point size for the text #Point size for the text.
[float]$FontSize, [float]$FontSize,
#Change background colour #Change background color.
[System.Drawing.Color]$BackgroundColor, $BackgroundColor,
#Background pattern - solid by default #Background pattern - solid by default.
[OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid , [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid ,
#Secondary colour for background pattern #Secondary color for background pattern.
[Alias("PatternColour")] [Alias("PatternColour")]
[System.Drawing.Color]$PatternColor, $PatternColor,
#Turn on text wrapping; use -WrapText:$false to turn off word wrapping #Turn on Text-Wrapping; use -WrapText:$false to turn off wrapping.
[Switch]$WrapText, [Switch]$WrapText,
#Position cell contents to left, right, center etc. default is 'General' #Position cell contents to Left, Right, Center etc. default is 'General'.
[OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment,
#Position cell contents to top bottom or centre #Position cell contents to Top, Bottom or Center.
[OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment, [OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment,
#Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise #Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise.
[ValidateRange(-90, 90)] [ValidateRange(-90, 90)]
[int]$TextRotation , [int]$TextRotation ,
#Set cells to a fixed hieght #Set cells to a fixed height.
[float]$Height, [float]$Height,
#Hide the Row #Hide the row.
[Switch]$Hide, [Switch]$Hide,
#If Sepecified returns the range of cells which were affected #If sepecified, returns the range of cells which were affected.
[Switch]$ReturnRange, [Switch]$ReturnRange,
#If Specified, return a row object to allow further work to be done #If Specified, return a row object to allow further work to be done.
[Switch]$PassThru [Switch]$PassThru
) )
begin {
#if we were passed a package object and a worksheet name , get the worksheet. #if we were passed a package object and a worksheet name , get the worksheet.
if ($ExcelPackage) {$Worksheet = $ExcelPackage.Workbook.worksheets[$Worksheetname] } if ($ExcelPackage) {$Worksheet = $ExcelPackage.Workbook.worksheets[$Worksheetname] }
@@ -115,6 +124,9 @@
$startRow = $Worksheet.Dimension.Start.Row + 1 $startRow = $Worksheet.Dimension.Start.Row + 1
$endColumn = $Worksheet.Dimension.End.Column $endColumn = $Worksheet.Dimension.End.Column
$endRow = $Worksheet.Dimension.End.Row $endRow = $Worksheet.Dimension.End.Row
}
process {
if ($null -eq $workSheet.Dimension) {Write-Warning "Can't format an empty worksheet."; return}
if ($Row -eq 0 ) {$Row = $endRow + 1 } if ($Row -eq 0 ) {$Row = $endRow + 1 }
Write-Verbose -Message "Updating Row $Row" Write-Verbose -Message "Updating Row $Row"
#Add a row label #Add a row label
@@ -153,19 +165,20 @@
}} }}
#region Apply formatting #region Apply formatting
$params = @{} $params = @{}
foreach ($p in @('Underline','Bold','Italic','StrikeThru','FontSize', 'FontShift','NumberFormat','TextRotation', foreach ($p in @('Underline','Bold','Italic','StrikeThru', 'FontName', 'FontSize', 'FontShift','NumberFormat','TextRotation',
'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Height', 'FontColor' 'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Height', 'FontColor'
'BorderAround', 'BorderBottom', 'BorderTop', 'BorderLeft', 'BorderRight', 'BorderColor', 'BorderAround', 'BorderBottom', 'BorderTop', 'BorderLeft', 'BorderRight', 'BorderColor',
'BackgroundColor', 'BackgroundPattern', 'PatternColor')) { 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) {
if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]} if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]}
} }
$theRange = [OfficeOpenXml.ExcelAddress]::New($Row, $StartColumn, $Row, $endColumn)
if ($params.Count) { if ($params.Count) {
$theRange = [OfficeOpenXml.ExcelAddress]::New($Row, $StartColumn, $Row, $endColumn)
Set-ExcelRange -WorkSheet $Worksheet -Range $theRange @params Set-ExcelRange -WorkSheet $Worksheet -Range $theRange @params
} }
#endregion #endregion
if ($PSBoundParameters["Hide"]) {$workSheet.Row($Row).Hidden = [bool]$Hide} if ($PSBoundParameters.ContainsKey('Hide')) {$workSheet.Row($Row).Hidden = [bool]$Hide}
#return the new data if -passthru was specified. #return the new data if -passthru was specified.
if ($passThru) {$Worksheet.Row($Row)} if ($passThru) {$Worksheet.Row($Row)}
elseif ($ReturnRange) {$theRange} elseif ($ReturnRange) {$theRange}
}
} }

View File

@@ -1,101 +1,109 @@
Function Set-ExcelRange { Function Set-ExcelRange {
<# <#
.SYNOPSIS .SYNOPSIS
Applies Number, font, alignment and colour formatting, values or formulas to a range of Excel Cells Applies number, font, alignment and/or color formatting, values or formulas to a range of Excel cells.
.DESCRIPTION .DESCRIPTION
Set-ExcelRange was created to set the style elements for a range of cells, this includes autosizing and hiding, setting Set-ExcelRange was created to set the style elements for a range of cells,
font elements (Name, Size, Bold, Italic, Underline & UnderlineStyle and Subscript & SuperScript), font and background colors, this includes auto-sizing and hiding, setting font elements (Name, Size,
borders, text wrapping, rotation, aliginment within cells, and number format. It was orignally named "Set-ExcelRange" Bold, Italic, Underline & UnderlineStyle and Subscript & SuperScript),
It has been extended to set Values, Formulas and set ArrayFormulas (sometimes called Ctrl-shift-Enter [CSE] formulas); because of this font and background colors, borders, text wrapping, rotation, alignment
the name has become Set-ExcelRange - but the old name of Set-Format is preserved as an alias name may swapped. within cells, and number format.
It was orignally named "Set-Format", but it has been extended to set
Values, Formulas and ArrayFormulas (sometimes called Ctrl-shift-Enter
[CSE] formulas); because of this, the name has become Set-ExcelRange
but the old name of Set-Format is preserved as an alias.
.EXAMPLE .EXAMPLE
$sheet.Column(3) | Set-ExcelRange -HorizontalAlignment Right -NumberFormat "#,###" -AutoFit $sheet.Column(3) | Set-ExcelRange -HorizontalAlignment Right -NumberFormat "#,###" -AutoFit
Selects column 3 from a sheet object (within a workbook object, which is a child of the ExcelPackage object) and passes it to Set-ExcelRange Selects column 3 from a sheet object (within a workbook object, which
which formats as an integer with comma seperated groups, aligns it right, and auto-fits the column to the contents. is a child of the ExcelPackage object) and passes it to Set-ExcelRange
which formats numbers as a integers with comma-separated groups,
aligns it right, and auto-fits the column to the contents.
.EXAMPLE .EXAMPLE
Set-ExcelRange -Range $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NumberFormat "#,###" Set-ExcelRange -Range $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NumberFormat "#,###"
Instead of piping the address in this version specifies a block of cells and applies similar formatting Instead of piping the address, this version specifies a block of cells
and applies similar formatting.
.EXAMPLE .EXAMPLE
Set-ExcelRange $excel.Workbook.Worksheets[1].Tables["Processes"] -Italic Set-ExcelRange $excel.Workbook.Worksheets[1].Tables["Processes"] -Italic
This time instead of specifying a range of cells, a table is selected by name and formatted as italic. This time instead of specifying a range of cells, a table is selected
by name and formatted as italic.
#> #>
[cmdletbinding()] [cmdletbinding()]
[Alias("Set-Format")] [Alias("Set-Format")]
Param ( Param (
#One or more row(s), Column(s) and/or block(s) of cells to format #One or more row(s), Column(s) and/or block(s) of cells to format.
[Parameter(ValueFromPipeline = $true,Position=0)] [Parameter(ValueFromPipeline = $true,Position=0)]
[Alias("Address")] [Alias("Address")]
$Range , $Range ,
#The worksheet where the format is to be applied #The worksheet where the format is to be applied.
[OfficeOpenXml.ExcelWorksheet]$WorkSheet , [OfficeOpenXml.ExcelWorksheet]$WorkSheet ,
#Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc #Number format to apply to cells e.g. "dd/MM/yyyy HH:mm", "£#,##0.00;[Red]-£#,##0.00", "0.00%" , "##/##" , "0.0E+0" etc.
[Alias("NFormat")] [Alias("NFormat")]
$NumberFormat, $NumberFormat,
#Style of border to draw around the range #Style of border to draw around the range.
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround, [OfficeOpenXml.Style.ExcelBorderStyle]$BorderAround,
#Color of the border #Color of the border.
[System.Drawing.Color]$BorderColor=[System.Drawing.Color]::Black, $BorderColor=[System.Drawing.Color]::Black,
#Style for the bottom border #Style for the bottom border.
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderBottom, [OfficeOpenXml.Style.ExcelBorderStyle]$BorderBottom,
#Style for the top border #Style for the top border.
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderTop, [OfficeOpenXml.Style.ExcelBorderStyle]$BorderTop,
#Style for the left border #Style for the left border.
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderLeft, [OfficeOpenXml.Style.ExcelBorderStyle]$BorderLeft,
#Style for the right border #Style for the right border.
[OfficeOpenXml.Style.ExcelBorderStyle]$BorderRight, [OfficeOpenXml.Style.ExcelBorderStyle]$BorderRight,
#Colour for the text - if none specified it will be left as it it is #Colour for the text - if none is specified it will be left as it is.
[System.Drawing.Color]$FontColor, $FontColor,
#Value for the cell #Value for the cell.
$Value, $Value,
#Formula for the cell #Formula for the cell.
$Formula, $Formula,
#Specifies formula should be an array formula (a.k.a CSE [ctrl-shift-enter] formula ) #Specifies formula should be an array formula (a.k.a CSE [ctrl-shift-enter] formula).
[Switch]$ArrayFormula, [Switch]$ArrayFormula,
#Clear Bold, Italic, StrikeThrough and Underline and set colour to black #Clear Bold, Italic, StrikeThrough and Underline and set color to Black.
[Switch]$ResetFont, [Switch]$ResetFont,
#Make text bold; use -Bold:$false to remove bold #Make text bold; use -Bold:$false to remove bold.
[Switch]$Bold, [Switch]$Bold,
#Make text italic; use -Italic:$false to remove italic #Make text italic; use -Italic:$false to remove italic.
[Switch]$Italic, [Switch]$Italic,
#Underline the text using the underline style in -underline type; use -Underline:$false to remove underlining #Underline the text using the underline style in -UnderlineType; use -Underline:$false to remove underlining.
[Switch]$Underline, [Switch]$Underline,
#Should Underline use single or double, normal or accounting mode : default is single normal #Specifies whether underlining should be single or double, normal or accounting mode. The default is "Single".
[OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single, [OfficeOpenXml.Style.ExcelUnderLineType]$UnderLineType = [OfficeOpenXml.Style.ExcelUnderLineType]::Single,
#Strike through text; use -Strikethru:$false to remove Strike through #Strike through text; use -Strikethru:$false to remove Strike through
[Switch]$StrikeThru, [Switch]$StrikeThru,
#Subscript or superscript (or none) #Subscript or Superscript (or none).
[OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift, [OfficeOpenXml.Style.ExcelVerticalAlignmentFont]$FontShift,
#Font to use - Excel defaults to Calibri #Font to use - Excel defaults to Calibri.
[String]$FontName, [String]$FontName,
#Point size for the text #Point size for the text.
[float]$FontSize, [float]$FontSize,
#Change background colour #Change background color.
[System.Drawing.Color]$BackgroundColor, $BackgroundColor,
#Background pattern - solid by default #Background pattern - Solid by default.
[OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid , [OfficeOpenXml.Style.ExcelFillStyle]$BackgroundPattern = [OfficeOpenXml.Style.ExcelFillStyle]::Solid ,
#Secondary colour for background pattern #Secondary color for background pattern.
[Alias("PatternColour")] [Alias("PatternColour")]
[System.Drawing.Color]$PatternColor, $PatternColor,
#Turn on text wrapping; use -WrapText:$false to turn off word wrapping #Turn on Text-Wrapping; use -WrapText:$false to turn off wrapping.
[Switch]$WrapText, [Switch]$WrapText,
#Position cell contents to left, right, center etc. default is 'General' #Position cell contents to Left, Right, Center etc. default is 'General'.
[OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment, [OfficeOpenXml.Style.ExcelHorizontalAlignment]$HorizontalAlignment,
#Position cell contents to top bottom or center #Position cell contents to Top, Bottom or Center.
[OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment, [OfficeOpenXml.Style.ExcelVerticalAlignment]$VerticalAlignment,
#Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise. #Degrees to rotate text. Up to +90 for anti-clockwise ("upwards"), or to -90 for clockwise.
[ValidateRange(-90, 90)] [ValidateRange(-90, 90)]
[int]$TextRotation , [int]$TextRotation ,
#Autofit cells to width (columns or ranges only) #Autofit cells to width (columns or ranges only).
[Alias("AutoFit")] [Alias("AutoFit")]
[Switch]$AutoSize, [Switch]$AutoSize,
#Set cells to a fixed width (columns or ranges only), ignored if Autosize is specified #Set cells to a fixed width (columns or ranges only), ignored if Autosize is specified.
[float]$Width, [float]$Width,
#Set cells to a fixed hieght (rows or ranges only) #Set cells to a fixed height (rows or ranges only).
[float]$Height, [float]$Height,
#Hide a row or column (not a range); use -Hidden:$false to unhide #Hide a row or column (not a range); use -Hidden:$false to unhide.
[Switch]$Hidden [Switch]$Hidden
) )
process { process {
@@ -112,7 +120,7 @@
elseif ($Range -is [string]) {Write-Warning -Message "The range pararameter you have specified also needs a worksheet parameter."} elseif ($Range -is [string]) {Write-Warning -Message "The range pararameter you have specified also needs a worksheet parameter."}
if ($ResetFont) { if ($ResetFont) {
$Range.Style.Font.Color.SetColor("Black") $Range.Style.Font.Color.SetColor( ([System.Drawing.Color]::Black))
$Range.Style.Font.Bold = $false $Range.Style.Font.Bold = $false
$Range.Style.Font.Italic = $false $Range.Style.Font.Italic = $false
$Range.Style.Font.UnderLine = $false $Range.Style.Font.UnderLine = $false
@@ -135,10 +143,14 @@
if ($PSBoundParameters.ContainsKey('FontSize')){ if ($PSBoundParameters.ContainsKey('FontSize')){
$Range.Style.Font.Size = $FontSize $Range.Style.Font.Size = $FontSize
} }
if ($PSBoundParameters.ContainsKey('FontName')){
$Range.Style.Font.Name = $FontName
}
if ($PSBoundParameters.ContainsKey('FontShift')){ if ($PSBoundParameters.ContainsKey('FontShift')){
$Range.Style.Font.VerticalAlign = $FontShift $Range.Style.Font.VerticalAlign = $FontShift
} }
if ($PSBoundParameters.ContainsKey('FontColor')){ if ($PSBoundParameters.ContainsKey('FontColor')){
if ($FontColor -is [string]) {$FontColor = [System.Drawing.Color]::$FontColor }
$Range.Style.Font.Color.SetColor( $FontColor) $Range.Style.Font.Color.SetColor( $FontColor)
} }
if ($PSBoundParameters.ContainsKey('TextRotation')) { if ($PSBoundParameters.ContainsKey('TextRotation')) {
@@ -168,6 +180,7 @@
if ($PSBoundParameters.ContainsKey('NumberFormat')) { if ($PSBoundParameters.ContainsKey('NumberFormat')) {
$Range.Style.Numberformat.Format = (Expand-NumberFormat $NumberFormat) $Range.Style.Numberformat.Format = (Expand-NumberFormat $NumberFormat)
} }
if ($BorderColor -is [string]) {$BorderColor = [System.Drawing.Color]::$BorderColor }
if ($PSBoundParameters.ContainsKey('BorderAround')) { if ($PSBoundParameters.ContainsKey('BorderAround')) {
$Range.Style.Border.BorderAround($BorderAround, $BorderColor) $Range.Style.Border.BorderAround($BorderAround, $BorderColor)
} }
@@ -189,8 +202,10 @@
} }
if ($PSBoundParameters.ContainsKey('BackgroundColor')) { if ($PSBoundParameters.ContainsKey('BackgroundColor')) {
$Range.Style.Fill.PatternType = $BackgroundPattern $Range.Style.Fill.PatternType = $BackgroundPattern
if ($BackgroundColor -is [string]) {$BackgroundColor = [System.Drawing.Color]::$BackgroundColor }
$Range.Style.Fill.BackgroundColor.SetColor($BackgroundColor) $Range.Style.Fill.BackgroundColor.SetColor($BackgroundColor)
if ($PatternColor) { if ($PatternColor) {
if ($PatternColor -is [string]) {$PatternColor = [System.Drawing.Color]::$PatternColor }
$Range.Style.Fill.PatternColor.SetColor( $PatternColor) $Range.Style.Fill.PatternColor.SetColor( $PatternColor)
} }
} }
@@ -287,12 +302,15 @@ if (Get-Command -ErrorAction SilentlyContinue -name Register-ArgumentCompleter)
Function Expand-NumberFormat { Function Expand-NumberFormat {
<# <#
.SYNOPSIS .SYNOPSIS
Converts short names for Number formats to the formatting strings used in Excel Converts short names for number formats to the formatting strings used in Excel
.DESCRIPTION .DESCRIPTION
Where you can type a number format you can write, for example 'Short-Date' and the module will translate it into the format string used by excel Where you can type a number format you can write, for example, 'Short-Date'
Some formats, like Short-Date change how they are presented when Excel loads. (So date will use the local ordering of year, month and Day) and the module will translate it into the format string used by Excel.
Other formats change how they appear when loaded with different cultures (depending on the country "," or "." or " " may be the thousand seperator Some formats, like Short-Date change how they are presented when Excel
although excel always stores it as ",") loads (so date will use the local ordering of year, month and Day). Other
formats change how they appear when loaded with different cultures
(depending on the country "," or "." or " " may be the thousand seperator
although Excel always stores it as ",")
.EXAMPLE .EXAMPLE
Expand-NumberFormat percentage Expand-NumberFormat percentage
@@ -300,11 +318,15 @@ Function Expand-NumberFormat {
.EXAMPLE .EXAMPLE
Expand-NumberFormat Currency Expand-NumberFormat Currency
Returns the currency format specified in the local regional settings. This may not be the same as Excel uses Returns the currency format specified in the local regional settings. This
The regional settings set the currency symbol and then whether it is before or after the number and seperated with a space or not; may not be the same as Excel uses. The regional settings set the currency
for negative numbers the number by wrapped in parentheses or a - sign might appear before or after the number and symbol. symbol and then whether it is before or after the number and separated with
So this returns $#,##0.00;($#,##0.00) for English US, #,##0.00 €;€#,##0.00- for French. (Note some Eurozone countries write €1,23 and others 1,23€ ) a space or not; for negative numbers the number may be wrapped in parentheses
In French the decimal point will be rendered as a "," and the thousand seperator as a space. or a - sign might appear before or after the number and symbol.
So this returns $#,##0.00;($#,##0.00) for English US, #,##0.00 €;€#,##0.00-
for French. (Note some Eurozone countries write €1,23 and others 1,23€ )
In French the decimal point will be rendered as a "," and the thousand
separator as a space.
#> #>
[cmdletbinding()] [cmdletbinding()]
[OutputType([String])] [OutputType([String])]

View File

@@ -1,4 +0,0 @@
- [ ] Investigate regional support for number conversion & possible date conversion. Also investigate feasablity of preserving number format when converting string to number
- [ ] Add help to ConvertToExcelXLSx.ps1, Get-HTMLTable.ps1, GetRange.PS1, GetExcelTable.Ps1, Import-HTML.PS1, New-Psitem.PS1 and Remove-Worksheet.ps1
- [ ] Add Examples and tests for new "Quick charts" in Export Excel (is it possible to replace examples that use Charting.ps1, GetXYRange.ps1, InferData.PS1 ? ).
- [ ] Increase Test code-covereage for import-excel

View File

@@ -1,19 +0,0 @@
$xlFile = ".\testExport.xlsx"
Remove-Item -ErrorAction Ignore $xlFile
$ExportOptions = @{
Path = $xlFile
Show = $true
IncludePivotTable = $true
IncludePivotChart = $true
PivotRows = echo Company Name
PivotData = "PM"
ChartType = "BarClustered3D"
#Password = "Test"
}
Get-Process |
Where Company |
Select Company, Name, Handles, PM |
Export-Excel @ExportOptions

View File

@@ -1,13 +1,12 @@
#Requires -Modules Pester #Requires -Modules Pester
Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force
if ($PSVersionTable.PSVersion.Major -gt 5) { Write-Warning "Can't test grid view on V6" }
Add-Type -AssemblyName System.Windows.Forms else {Add-Type -AssemblyName System.Windows.Forms }
Describe "Compare Worksheet" { Describe "Compare Worksheet" {
Context "Simple comparison output" { Context "Simple comparison output" {
BeforeAll { BeforeAll {
Remove-Item -Path "$env:temp\server*.xlsx" Remove-Item -Path "$env:temp\server*.xlsx"
[System.Collections.ArrayList]$s = get-service | Select-Object -first 25 -Property * [System.Collections.ArrayList]$s = get-service | Select-Object -first 25 -Property Name, RequiredServices, CanPauseAndContinue, CanShutdown, CanStop, DisplayName, DependentServices, MachineName
$s | Export-Excel -Path $env:temp\server1.xlsx $s | Export-Excel -Path $env:temp\server1.xlsx
#$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s #$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s
$row4Displayname = $s[2].DisplayName $row4Displayname = $s[2].DisplayName
@@ -51,8 +50,9 @@ Describe "Compare Worksheet" {
Context "Setting the background to highlight different rows, use of grid view." { Context "Setting the background to highlight different rows, use of grid view." {
BeforeAll { BeforeAll {
Compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -BackgroundColor LightGreen -GridView $useGrid = ($PSVersionTable.PSVersion.Major -LE 5)
Start-Sleep -sec 5; [System.Windows.Forms.SendKeys]::Sendwait("%{F4}") $null = Compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -BackgroundColor ([System.Drawing.Color]::LightGreen) -GridView:$useGrid
if ($useGrid) {Start-Sleep -sec 5; [System.Windows.Forms.SendKeys]::Sendwait("%{F4}") }
$xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx" $xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx"
$xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx" $xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx"
$s1Sheet = $xl1.Workbook.Worksheets[1] $s1Sheet = $xl1.Workbook.Worksheets[1]
@@ -78,7 +78,7 @@ Describe "Compare Worksheet" {
Context "Setting the forgound to highlight changed properties" { Context "Setting the forgound to highlight changed properties" {
BeforeAll { BeforeAll {
$null = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -AllDataBackgroundColor white -BackgroundColor LightGreen -FontColor DarkRed $null = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -AllDataBackgroundColor([System.Drawing.Color]::white) -BackgroundColor ([System.Drawing.Color]::LightGreen) -FontColor ([System.Drawing.Color]::DarkRed)
$xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx" $xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx"
$xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx" $xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx"
$s1Sheet = $xl1.Workbook.Worksheets[1] $s1Sheet = $xl1.Workbook.Worksheets[1]
@@ -107,7 +107,8 @@ Describe "Compare Worksheet" {
Context "More complex comparison: output check and different worksheet names " { Context "More complex comparison: output check and different worksheet names " {
BeforeAll { BeforeAll {
[System.Collections.ArrayList]$s = get-service | Select-Object -first 25 -Property * -ExcludeProperty Name [System.Collections.ArrayList]$s = get-service | Select-Object -first 25 -Property RequiredServices, CanPauseAndContinue, CanShutdown, CanStop,
DisplayName, DependentServices, MachineName, ServiceName, ServicesDependedOn, ServiceHandle, Status, ServiceType, StartType -ExcludeProperty Name
$s | Export-Excel -Path $env:temp\server1.xlsx -WorkSheetname Server1 $s | Export-Excel -Path $env:temp\server1.xlsx -WorkSheetname Server1
#$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s #$s is a zero based array, excel rows are 1 based and excel has a header row so Excel rows will be 2 + index in $s
$row4Displayname = $s[2].DisplayName $row4Displayname = $s[2].DisplayName
@@ -119,9 +120,10 @@ Describe "Compare Worksheet" {
$row6Name = $s[5].ServiceName $row6Name = $s[5].ServiceName
$s.RemoveAt(5) $s.RemoveAt(5)
$s[10].ServiceType = "Changed should not matter" $s[10].ServiceType = "Changed should not matter"
$s | Select-Object -Property ServiceName, DisplayName, StartType, ServiceType | Export-Excel -Path $env:temp\server2.xlsx -WorkSheetname server2 $s | Select-Object -Property ServiceName, DisplayName, StartType, ServiceType | Export-Excel -Path $env:temp\server2.xlsx -WorkSheetname server2
#Assume default worksheet name, (sheet1) and column header for key ("name") #Assume default worksheet name, (sheet1) and column header for key ("name")
$comp = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -WorkSheetName Server1,Server2 -Key ServiceName -Property DisplayName,StartType -AllDataBackgroundColor AliceBlue -BackgroundColor White -FontColor Red | Sort-Object _row,_file $comp = compare-WorkSheet "$env:temp\Server1.xlsx" "$env:temp\Server2.xlsx" -WorkSheetName Server1,Server2 -Key ServiceName -Property DisplayName,StartType -AllDataBackgroundColor ([System.Drawing.Color]::AliceBlue) -BackgroundColor ([System.Drawing.Color]::White) -FontColor ([System.Drawing.Color]::Red) | Sort-Object _row,_file
$xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx" $xl1 = Open-ExcelPackage -Path "$env:temp\Server1.xlsx"
$xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx" $xl2 = Open-ExcelPackage -Path "$env:temp\Server2.xlsx"
$s1Sheet = $xl1.Workbook.Worksheets["server1"] $s1Sheet = $xl1.Workbook.Worksheets["server1"]
@@ -170,8 +172,8 @@ Describe "Compare Worksheet" {
$s2Sheet.Cells["F4"].Style.Font.Color.Rgb | Should beNullOrEmpty $s2Sheet.Cells["F4"].Style.Font.Color.Rgb | Should beNullOrEmpty
} }
AfterAll { AfterAll {
Close-ExcelPackage -ExcelPackage $xl1 -NoSave -Show # Close-ExcelPackage -ExcelPackage $xl1 -NoSave -Show
Close-ExcelPackage -ExcelPackage $xl2 -NoSave -Show # Close-ExcelPackage -ExcelPackage $xl2 -NoSave -Show
} }
} }
} }
@@ -321,19 +323,21 @@ Describe "Merge Multiple sheets" {
} }
it "Creared Conditional formatting rules " { it "Creared Conditional formatting rules " {
$cf=$ws.ConditionalFormatting $cf=$ws.ConditionalFormatting
$cf.Count | Should be 15 $cf.Count | Should be 17
$cf[14].Address.Address | Should be 'B2:B1048576' $cf[16].Address.Address | Should be 'B2:B1048576'
$cf[16].Type | Should be 'Expression'
$cf[16].Formula | Should be 'OR(G2<>"Same",K2<>"Same")'
$cf[16].Style.Font.Color.Color.Name | Should be "FFFF0000"
$cf[14].Address.Address | Should be 'D2:D1048576'
$cf[14].Type | Should be 'Expression' $cf[14].Type | Should be 'Expression'
$cf[14].Formula | Should be 'OR(G2<>"Same",K2<>"Same")' $cf[14].Formula | Should be 'OR(G2="Added",K2="Added")'
$cf[14].Style.Font.Color.Color.Name | Should be "FFFF0000" $cf[14].Style.Fill.BackgroundColor.Color.Name | Should be 'ffffb6c1'
$cf[13].Address.Address | Should be 'D2:D1048576' $cf[14].Style.Fill.PatternType.ToString() | Should be 'Solid'
$cf[13].Type | Should be 'Expression'
$cf[13].Formula | Should be 'OR(G2="Added",K2="Added")'
$cf[13].Style.Fill.BackgroundColor.Color.Name | Should be 'ffffb6c1'
$cf[ 0].Address.Address | Should be 'F1:F1048576' $cf[ 0].Address.Address | Should be 'F1:F1048576'
$cf[ 0].Type | Should be 'Expression' $cf[ 0].Type | Should be 'Expression'
$cf[ 0].Formula | Should be 'G1="Added"' $cf[ 0].Formula | Should be 'G1="Added"'
$cf[ 0].Style.Fill.BackgroundColor.Color.Name | Should be 'ffffa500' $cf[ 0].Style.Fill.BackgroundColor.Color.Name | Should be 'ffffa500'
$cf[ 0].Style.Fill.PatternType.ToString() | Should be 'Solid'
} }
} }
} }

View File

@@ -9,7 +9,7 @@ Describe ExportExcel {
$path = "$env:TEMP\Test.xlsx" $path = "$env:TEMP\Test.xlsx"
Remove-item -Path $path -ErrorAction SilentlyContinue Remove-item -Path $path -ErrorAction SilentlyContinue
#Test with a maximum of 100 processes for speed; export all properties, then export smaller subsets. #Test with a maximum of 100 processes for speed; export all properties, then export smaller subsets.
$processes = Get-Process | select-object -first 100 $processes = Get-Process | select-object -first 100 -Property * -excludeProperty Parent
$propertyNames = $Processes[0].psobject.properties.name $propertyNames = $Processes[0].psobject.properties.name
$rowcount = $Processes.Count $rowcount = $Processes.Count
$Processes | Export-Excel $path #-show $Processes | Export-Excel $path #-show
@@ -120,10 +120,10 @@ Describe ExportExcel {
$path = "$env:TEMP\Test.xlsx" $path = "$env:TEMP\Test.xlsx"
Remove-item -Path $path -ErrorAction SilentlyContinue Remove-item -Path $path -ErrorAction SilentlyContinue
#testing -ReturnRange switch and applying number format to Formulas as well as values. #testing -ReturnRange switch and applying number format to Formulas as well as values.
$returnedRange = Write-Output -1 668 34 777 860 -0.5 119 -0.1 234 788,"=A9+A10" | Export-Excel -NumberFormat '[Blue]$#,##0.00;[Red]-$#,##0.00' -Path $path -ReturnRange $returnedRange = @($null, -1, 0, 34, 777, "", -0.5, 119, -0.1, 234, 788,"=A9+A10") | Export-Excel -NumberFormat '[Blue]$#,##0.00;[Red]-$#,##0.00' -Path $path -ReturnRange
it "Created a new file and returned the expected range " { it "Created a new file and returned the expected range " {
Test-Path -Path $path -ErrorAction SilentlyContinue | Should be $true Test-Path -Path $path -ErrorAction SilentlyContinue | Should be $true
$returnedRange | Should be "A1:A11" $returnedRange | Should be "A1:A12"
} }
$Excel = Open-ExcelPackage -Path $path $Excel = Open-ExcelPackage -Path $path
@@ -135,16 +135,22 @@ Describe ExportExcel {
it "Created the worksheet with the expected name, number of rows and number of columns " { it "Created the worksheet with the expected name, number of rows and number of columns " {
$ws.Name | Should be "sheet1" $ws.Name | Should be "sheet1"
$ws.Dimension.Columns | Should be 1 $ws.Dimension.Columns | Should be 1
$ws.Dimension.Rows | Should be 11 $ws.Dimension.Rows | Should be 12
} }
it "Set the default style for the sheet as expected " { it "Set the default style for the sheet as expected " {
$ws.cells.Style.Numberformat.Format | Should be '[Blue]$#,##0.00;[Red]-$#,##0.00' $ws.cells.Style.Numberformat.Format | Should be '[Blue]$#,##0.00;[Red]-$#,##0.00'
} }
it "Set the default style and value for Cell A1 as expected " { it "Set the default style and set values for Cells as expected, handling null,0 and '' " {
$ws.cells[1, 1].Style.Numberformat.Format | Should be '[Blue]$#,##0.00;[Red]-$#,##0.00' $ws.cells[1, 1].Style.Numberformat.Format | Should be '[Blue]$#,##0.00;[Red]-$#,##0.00'
$ws.cells[1, 1].Value | Should be -1 $ws.cells[1, 1].Value | Should beNullorEmpty
$ws.cells[2, 1].Value | Should be -1
$ws.cells[3, 1].Value | Should be 0
$ws.cells[5, 1].Value | Should be 777
$ws.cells[6, 1].Value | Should be ""
$ws.cells[4, 1].Style.Numberformat.Format | Should be '[Blue]$#,##0.00;[Red]-$#,##0.00'
} }
} }
@@ -279,12 +285,12 @@ Describe ExportExcel {
($ws.Cells[2, 20].Value -is [valuetype] ) | Should be $true ($ws.Cells[2, 20].Value -is [valuetype] ) | Should be $true
} }
it "Converted a nested object to a string (Y2) " { it "Converted a nested object to a string (Y2) " {
$ws.Cells[2, 26].Value | should match '^System\.Diagnostics\.Process\s+\(.*\)$' $ws.Cells[2, 26].Value | Should match '^System\.Diagnostics\.Process\s+\(.*\)$'
} }
it "Processed a timespan object (Z2) " { it "Processed a timespan object (Z2) " {
$ws.cells[2, 27].Value.ToOADate() | should beGreaterThan 0 $ws.cells[2, 27].Value.ToOADate() | Should beGreaterThan 0
$ws.cells[2, 27].Value.ToOADate() | should beLessThan 1 $ws.cells[2, 27].Value.ToOADate() | Should beLessThan 1
$ws.cells[2, 27].Style.Numberformat.Format | should be '[h]:mm:ss' $ws.cells[2, 27].Style.Numberformat.Format | Should be '[h]:mm:ss'
} }
} }
@@ -349,13 +355,7 @@ Describe ExportExcel {
Context "#Example 5 # Adding a single conditional format " { Context "#Example 5 # Adding a single conditional format " {
#Test New-ConditionalText builds correctly #Test New-ConditionalText builds correctly
$ct = New-ConditionalText -ConditionalType GreaterThan 525 -ConditionalTextColor DarkRed -BackgroundColor LightPink $ct = New-ConditionalText -ConditionalType GreaterThan 525 -ConditionalTextColor ([System.Drawing.Color]::DarkRed) -BackgroundColor ([System.Drawing.Color]::LightPink)
it "Created a Conditional format description " {
$ct.BackgroundColor -is [System.Drawing.Color] | Should be $true
$ct.ConditionalTextColor -is [System.Drawing.Color] | Should be $true
$ct.ConditionalType -in [enum]::GetNames( [OfficeOpenXml.ConditionalFormatting.eExcelConditionalFormattingRuleType] ) |
Should be $true
}
$path = "$env:TEMP\Test.xlsx" $path = "$env:TEMP\Test.xlsx"
Remove-item -Path $path -ErrorAction SilentlyContinue Remove-item -Path $path -ErrorAction SilentlyContinue
@@ -392,8 +392,8 @@ Describe ExportExcel {
#Testing -Passthrough #Testing -Passthrough
$Excel = Get-Service | Select-Object Name, Status, DisplayName, ServiceName | $Excel = Get-Service | Select-Object Name, Status, DisplayName, ServiceName |
Export-Excel $path -PassThru -ConditionalText $( Export-Excel $path -PassThru -ConditionalText $(
New-ConditionalText Stop DarkRed LightPink New-ConditionalText Stop ([System.Drawing.Color]::DarkRed) ([System.Drawing.Color]::LightPink)
New-ConditionalText Running Blue Cyan New-ConditionalText Running ([System.Drawing.Color]::Blue) ([System.Drawing.Color]::Cyan)
) )
$ws = $Excel.Workbook.Worksheets[1] $ws = $Excel.Workbook.Worksheets[1]
it "Added two blocks of conditional formating for the data range " { it "Added two blocks of conditional formating for the data range " {
@@ -452,7 +452,7 @@ Describe ExportExcel {
#Test -passthru and -worksheetName creating a new, named, sheet in an existing file. #Test -passthru and -worksheetName creating a new, named, sheet in an existing file.
$Excel = Get-Process | Select-Object -first 20 -Property Name, cpu, pm, handles, company | Export-Excel $path -WorkSheetname Processes -PassThru $Excel = Get-Process | Select-Object -first 20 -Property Name, cpu, pm, handles, company | Export-Excel $path -WorkSheetname Processes -PassThru
#Testing -Excel Pacakage and adding a Pivot-table as a second step. Want to save and re-open it ... #Testing -Excel Pacakage and adding a Pivot-table as a second step. Want to save and re-open it ...
Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -NoTotalsInPivot Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -NoTotalsInPivot -PivotDataToColumn -Activate
$Excel = Open-ExcelPackage $path $Excel = Open-ExcelPackage $path
$PTws = $Excel.Workbook.Worksheets["ProcessesPivotTable"] $PTws = $Excel.Workbook.Worksheets["ProcessesPivotTable"]
@@ -461,6 +461,7 @@ Describe ExportExcel {
$excel.ProcessesPivotTable | Should not beNullOrEmpty $excel.ProcessesPivotTable | Should not beNullOrEmpty
$PTws | Should not beNullOrEmpty $PTws | Should not beNullOrEmpty
$PTws.PivotTables.Count | Should be 1 $PTws.PivotTables.Count | Should be 1
$PTws.View.TabSelected | Should be $true
$Excel.Workbook.Worksheets["Processes"] | Should not beNullOrEmpty $Excel.Workbook.Worksheets["Processes"] | Should not beNullOrEmpty
$Excel.Workbook.Worksheets.Count | Should beGreaterThan 2 $Excel.Workbook.Worksheets.Count | Should beGreaterThan 2
$excel.Workbook.Worksheets["Processes"].Dimension.rows | Should be 21 #20 data + 1 header $excel.Workbook.Worksheets["Processes"].Dimension.rows | Should be 21 #20 data + 1 header
@@ -476,7 +477,7 @@ Describe ExportExcel {
} }
#test adding pivot chart using the already open sheet #test adding pivot chart using the already open sheet
$warnvar = $null $warnvar = $null
Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -ShowCategory -NoLegend -WarningAction SilentlyContinue -WarningVariable warnvar Export-Excel -ExcelPackage $Excel -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -ShowCategory -ShowPercent -NoLegend -WarningAction SilentlyContinue -WarningVariable warnvar
$Excel = Open-ExcelPackage $path $Excel = Open-ExcelPackage $path
it "Added a chart to the pivot table without rebuilding " { it "Added a chart to the pivot table without rebuilding " {
$ws = $Excel.Workbook.Worksheets["ProcessesPivotTable"] $ws = $Excel.Workbook.Worksheets["ProcessesPivotTable"]
@@ -512,7 +513,8 @@ Describe ExportExcel {
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "NewSheet" -MoveAfter "*" -CopySource ($excel.Workbook.Worksheets["Sheet1"]) # Now its NewSheet, Sheet1, ProcessesPivotTable, Processes $null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "NewSheet" -MoveAfter "*" -CopySource ($excel.Workbook.Worksheets["Sheet1"]) # Now its NewSheet, Sheet1, ProcessesPivotTable, Processes
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "Sheet1" -MoveAfter "Processes" # Now its NewSheet, ProcessesPivotTable, Processes, Sheet1 $null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "Sheet1" -MoveAfter "Processes" # Now its NewSheet, ProcessesPivotTable, Processes, Sheet1
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "Another" -MoveToStart # Now its Another, NewSheet, ProcessesPivotTable, Processes, Sheet1 $null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "Another" -MoveToStart # Now its Another, NewSheet, ProcessesPivotTable, Processes, Sheet1
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "OneLast" -MoveBefore "ProcessesPivotTable" # Now its Another, NewSheet, Onelast, ProcessesPivotTable, Processes, Sheet1 $null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "NearDone" -MoveBefore 5 # Now its Another, NewSheet, ProcessesPivotTable, Processes, NearDone ,Sheet1
$null = Add-WorkSheet -ExcelPackage $Excel -WorkSheetname "OneLast" -MoveBefore "ProcessesPivotTable" # Now its Another, NewSheet, Onelast, ProcessesPivotTable, Processes,NearDone ,Sheet1
Close-ExcelPackage $Excel Close-ExcelPackage $Excel
$Excel = Open-ExcelPackage $path $Excel = Open-ExcelPackage $path
@@ -523,7 +525,8 @@ Describe ExportExcel {
$excel.Workbook.Worksheets[3].Name | Should be "Onelast" $excel.Workbook.Worksheets[3].Name | Should be "Onelast"
$excel.Workbook.Worksheets[4].Name | Should be "ProcessesPivotTable" $excel.Workbook.Worksheets[4].Name | Should be "ProcessesPivotTable"
$excel.Workbook.Worksheets[5].Name | Should be "Processes" $excel.Workbook.Worksheets[5].Name | Should be "Processes"
$excel.Workbook.Worksheets[6].Name | Should be "Sheet1" $excel.Workbook.Worksheets[6].Name | Should be "NearDone"
$excel.Workbook.Worksheets[7].Name | Should be "Sheet1"
} }
it "Cloned 'Sheet1' to 'NewSheet' " { it "Cloned 'Sheet1' to 'NewSheet' " {
@@ -553,32 +556,33 @@ Describe ExportExcel {
$dataWs.Cells[3, 3].Value | Should not beNullOrEmpty $dataWs.Cells[3, 3].Value | Should not beNullOrEmpty
$dataWs.Cells[3, 3].Style.Font.Bold | Should be $true $dataWs.Cells[3, 3].Style.Font.Bold | Should be $true
$dataWs.Dimension.End.Row | Should be 23 $dataWs.Dimension.End.Row | Should be 23
$dataWs.names[0].end.row | Should be 23 $dataWs.names[0].Start.row | Should be 4 # StartRow + 1
$dataWs.names[0].name | Should be 'Name' $dataWs.names[0].End.row | Should be $dataWs.Dimension.End.Row
$dataWs.names[0].Name | Should be 'Name'
$dataWs.names.Count | Should be 7 # Name, cpu, pm, handles & company + Named Range "Procs" + xl one for autofilter $dataWs.names.Count | Should be 7 # Name, cpu, pm, handles & company + Named Range "Procs" + xl one for autofilter
$dataWs.cells[$dataws.Dimension].AutoFilter | Should be true $dataWs.cells[$dataws.Dimension].AutoFilter | Should be true
} }
it "Applied and auto-extended an autofilter " { it "Applied and auto-extended an autofilter " {
$dataWs.Names["_xlnm._FilterDatabase"].Start.Row | should be 3 #offset $dataWs.Names["_xlnm._FilterDatabase"].Start.Row | Should be 3 #offset
$dataWs.Names["_xlnm._FilterDatabase"].Start.Column | should be 3 $dataWs.Names["_xlnm._FilterDatabase"].Start.Column | Should be 3
$dataWs.Names["_xlnm._FilterDatabase"].Rows | should be 21 #2 x 10 data + 1 header $dataWs.Names["_xlnm._FilterDatabase"].Rows | Should be 21 #2 x 10 data + 1 header
$dataWs.Names["_xlnm._FilterDatabase"].Columns | should be 5 #Name, cpu, pm, handles & company $dataWs.Names["_xlnm._FilterDatabase"].Columns | Should be 5 #Name, cpu, pm, handles & company
$dataWs.Names["_xlnm._FilterDatabase"].AutoFilter | should be $true $dataWs.Names["_xlnm._FilterDatabase"].AutoFilter | Should be $true
} }
it "Created and auto-extended the named ranges " { it "Created and auto-extended the named ranges " {
$dataWs.names["procs"].rows | should be 21 $dataWs.names["procs"].rows | Should be 21
$dataWs.names["procs"].Columns | should be 5 $dataWs.names["procs"].Columns | Should be 5
$dataWs.Names["CPU"].Rows | should be 20 $dataWs.Names["CPU"].Rows | Should be 20
$dataWs.Names["CPU"].Columns | should be 1 $dataWs.Names["CPU"].Columns | Should be 1
} }
it "Created and extended the pivot table " { it "Created and extended the pivot table " {
$pt.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref | $pt.CacheDefinition.CacheDefinitionXml.pivotCacheDefinition.cacheSource.worksheetSource.ref |
Should be "C3:G23" Should be "C3:G23"
$pt.ColumGrandTotals | should be $false $pt.ColumGrandTotals | Should be $false
$pt.RowGrandTotals | should be $false $pt.RowGrandTotals | Should be $false
$pt.Fields["Company"].IsRowField | should be $true $pt.Fields["Company"].IsRowField | Should be $true
$pt.Fields["PM"].IsDataField | should be $true $pt.Fields["PM"].IsDataField | Should be $true
$pt.Fields["Name"].IsPageField | should be $true $pt.Fields["Name"].IsPageField | Should be $true
} }
it "Generated a message on extending the Pivot table " { it "Generated a message on extending the Pivot table " {
$warnVar | Should not beNullOrEmpty $warnVar | Should not beNullOrEmpty
@@ -587,18 +591,22 @@ Describe ExportExcel {
Context " # Create and append explicit and auto table and range extension" { Context " # Create and append explicit and auto table and range extension" {
$path = "$env:TEMP\Test.xlsx" $path = "$env:TEMP\Test.xlsx"
#Test -Append automatically extends a table, even when it is not specified in the append command #Test -Append automatically extends a table, even when it is not specified in the append command;
Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company | Export-Excel -Path $path -TableName ProcTab -AutoNameRange -WorkSheetname NoOffset -ClearSheet Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company | Export-Excel -Path $path -TableName ProcTab -AutoNameRange -WorkSheetname NoOffset -ClearSheet
Get-Process | Select-Object -last 10 -Property Name, cpu, pm, handles, company | Export-Excel -Path $path -AutoNameRange -WorkSheetname NoOffset -Append #Test number format applying to new data
Get-Process | Select-Object -last 10 -Property Name, cpu, pm, handles, company | Export-Excel -Path $path -AutoNameRange -WorkSheetname NoOffset -Append -Numberformat 'Number'
$Excel = Open-ExcelPackage $path $Excel = Open-ExcelPackage $path
$dataWs = $Excel.Workbook.Worksheets["NoOffset"] $dataWs = $Excel.Workbook.Worksheets["NoOffset"]
it "Created a new sheet and auto-extended a table and explicitly extended named ranges " { it "Created a new sheet and auto-extended a table and explicitly extended named ranges " {
$dataWs.Tables["ProcTab"].Address.Address | should be "A1:E21" $dataWs.Tables["ProcTab"].Address.Address | Should be "A1:E21"
$dataWs.Names["CPU"].Rows | should be 20 $dataWs.Names["CPU"].Rows | Should be 20
$dataWs.Names["CPU"].Columns | should be 1 $dataWs.Names["CPU"].Columns | Should be 1
}
it "Set the expected number formats " {
$dataWs.cells["C2"].Style.Numberformat.Format | Should be "General"
$dataWs.cells["C12"].Style.Numberformat.Format | Should be "0.00"
} }
#Test extneding autofilter and range when explicitly specified in the append #Test extneding autofilter and range when explicitly specified in the append
$excel = Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company | Export-Excel -ExcelPackage $excel -RangeName procs -AutoFilter -WorkSheetname NoOffset -ClearSheet -PassThru $excel = Get-Process | Select-Object -first 10 -Property Name, cpu, pm, handles, company | Export-Excel -ExcelPackage $excel -RangeName procs -AutoFilter -WorkSheetname NoOffset -ClearSheet -PassThru
Get-Process | Select-Object -last 10 -Property Name, cpu, pm, handles, company | Export-Excel -ExcelPackage $excel -RangeName procs -AutoFilter -WorkSheetname NoOffset -Append Get-Process | Select-Object -last 10 -Property Name, cpu, pm, handles, company | Export-Excel -ExcelPackage $excel -RangeName procs -AutoFilter -WorkSheetname NoOffset -Append
@@ -606,11 +614,11 @@ Describe ExportExcel {
$dataWs = $Excel.Workbook.Worksheets["NoOffset"] $dataWs = $Excel.Workbook.Worksheets["NoOffset"]
it "Created a new sheet and explicitly extended named range and autofilter " { it "Created a new sheet and explicitly extended named range and autofilter " {
$dataWs.names["procs"].rows | should be 21 $dataWs.names["procs"].rows | Should be 21
$dataWs.names["procs"].Columns | should be 5 $dataWs.names["procs"].Columns | Should be 5
$dataWs.Names["_xlnm._FilterDatabase"].Rows | should be 21 #2 x 10 data + 1 header $dataWs.Names["_xlnm._FilterDatabase"].Rows | Should be 21 #2 x 10 data + 1 header
$dataWs.Names["_xlnm._FilterDatabase"].Columns | should be 5 #Name, cpu, pm, handles & company $dataWs.Names["_xlnm._FilterDatabase"].Columns | Should be 5 #Name, cpu, pm, handles & company
$dataWs.Names["_xlnm._FilterDatabase"].AutoFilter | should be $true $dataWs.Names["_xlnm._FilterDatabase"].AutoFilter | Should be $true
} }
} }
@@ -635,7 +643,7 @@ Describe ExportExcel {
$warnvar = $null $warnvar = $null
#Test create two data pages; as part of adding the second give both their own pivot table, test -autosize switch #Test create two data pages; as part of adding the second give both their own pivot table, test -autosize switch
Get-Service | Select-Object -Property Status, Name, DisplayName, StartType, CanPauseAndContinue | Export-Excel -Path $path -AutoSize -TableName "All Services" -TableStyle Medium1 -WarningAction SilentlyContinue -WarningVariable warnvar Get-Service | Select-Object -Property Status, Name, DisplayName, StartType, CanPauseAndContinue | Export-Excel -Path $path -AutoSize -TableName "All Services" -TableStyle Medium1 -WarningAction SilentlyContinue -WarningVariable warnvar
Get-Process | Select-Object -Property Name, Company, Handles, CPU, VM | Export-Excel -Path $path -AutoSize -WorkSheetname 'sheet2' -TableName "Processes" -TableStyle Light1 -Title "Processes" -TitleFillPattern Solid -TitleBackgroundColor AliceBlue -TitleBold -TitleSize 22 -PivotTableDefinition $ptDef Get-Process | Select-Object -Property Name, Company, Handles, CPU, VM | Export-Excel -Path $path -AutoSize -WorkSheetname 'sheet2' -TableName "Processes" -TableStyle Light1 -Title "Processes" -TitleFillPattern Solid -TitleBackgroundColor ([System.Drawing.Color]::AliceBlue) -TitleBold -TitleSize 22 -PivotTableDefinition $ptDef
$Excel = Open-ExcelPackage $path $Excel = Open-ExcelPackage $path
$ws1 = $Excel.Workbook.Worksheets["Sheet1"] $ws1 = $Excel.Workbook.Worksheets["Sheet1"]
$ws2 = $Excel.Workbook.Worksheets["Sheet2"] $ws2 = $Excel.Workbook.Worksheets["Sheet2"]
@@ -680,10 +688,10 @@ Describe ExportExcel {
$pt1.RowFields[0].Name | Should be 'Status' $pt1.RowFields[0].Name | Should be 'Status'
$pt1.DataFields[0].Field.name | Should be 'Status' $pt1.DataFields[0].Field.name | Should be 'Status'
$pt1.DataFields[0].Function | Should be 'Count' $pt1.DataFields[0].Function | Should be 'Count'
$pt1.ColumGrandTotals | should be $true $pt1.ColumGrandTotals | Should be $true
$pt1.RowGrandTotals | should be $false $pt1.RowGrandTotals | Should be $false
$pt2.ColumGrandTotals | should be $false $pt2.ColumGrandTotals | Should be $false
$pt2.RowGrandTotals | should be $true $pt2.RowGrandTotals | Should be $true
$pc1.ChartType | Should be 'BarClustered3D' $pc1.ChartType | Should be 'BarClustered3D'
$pc1.From.Column | Should be 0 #chart 1 at 0,10 chart 2 at 4,0 (default) $pc1.From.Column | Should be 0 #chart 1 at 0,10 chart 2 at 4,0 (default)
$pc2.From.Column | Should be 4 $pc2.From.Column | Should be 4
@@ -708,21 +716,21 @@ Describe ExportExcel {
Set-ExcelRange -Address $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NFormat "#,###" Set-ExcelRange -Address $sheet.Cells["E1:H1048576"] -HorizontalAlignment Right -NFormat "#,###"
Set-ExcelRange -Address $sheet.Column(4) -HorizontalAlignment Right -NFormat "#,##0.0" -Bold Set-ExcelRange -Address $sheet.Column(4) -HorizontalAlignment Right -NFormat "#,##0.0" -Bold
Set-ExcelRange -Address $sheet.Row(1) -Bold -HorizontalAlignment Center Set-ExcelRange -Address $sheet.Row(1) -Bold -HorizontalAlignment Center
Add-ConditionalFormatting -WorkSheet $sheet -Range "D2:D1048576" -DataBarColor Red Add-ConditionalFormatting -WorkSheet $sheet -Range "D2:D1048576" -DataBarColor ([System.Drawing.Color]::Red)
#test Add-ConditionalFormatting -passthru and using a range (and no worksheet) #test Add-ConditionalFormatting -passthru and using a range (and no worksheet)
$rule = Add-ConditionalFormatting -passthru -Address $sheet.cells["C:C"] -RuleType TopPercent -ConditionValue 20 -Bold -StrikeThru $rule = Add-ConditionalFormatting -passthru -Address $sheet.cells["C:C"] -RuleType TopPercent -ConditionValue 20 -Bold -StrikeThru
Add-ConditionalFormatting -WorkSheet $sheet -Range "G2:G1048576" -RuleType GreaterThan -ConditionValue "104857600" -ForeGroundColor Red -Bold -Italic -Underline -BackgroundColor Beige -BackgroundPattern LightUp -PatternColor Gray Add-ConditionalFormatting -WorkSheet $sheet -Range "G2:G1048576" -RuleType GreaterThan -ConditionValue "104857600" -ForeGroundColor ([System.Drawing.Color]::Red) -Bold -Italic -Underline -BackgroundColor ([System.Drawing.Color]::Beige) -BackgroundPattern LightUp -PatternColor ([System.Drawing.Color]::Gray)
#Test Set-ExcelRange with a column #Test Set-ExcelRange with a column
foreach ($c in 5..9) {Set-ExcelRange $sheet.Column($c) -AutoFit } foreach ($c in 5..9) {Set-ExcelRange $sheet.Column($c) -AutoFit }
Add-PivotTable -PivotTableName "PT_Procs" -ExcelPackage $excel -SourceWorkSheet 1 -PivotRows Company -PivotData @{'Name' = 'Count'} -IncludePivotChart -ChartType ColumnClustered -NoLegend Add-PivotTable -PivotTableName "PT_Procs" -ExcelPackage $excel -SourceWorkSheet 1 -PivotRows Company -PivotData @{'Name' = 'Count'} -IncludePivotChart -ChartType ColumnClustered -NoLegend
Close-ExcelPackage $excel Export-Excel -ExcelPackage $excel -WorksheetName "Processes" -AutoNameRange #Test adding named ranges seperately from adding data.
$excel = Open-ExcelPackage $path $excel = Open-ExcelPackage $path
$sheet = $excel.Workbook.Worksheets["Processes"] $sheet = $excel.Workbook.Worksheets["Processes"]
it "Returned the rule when calling Add-ConditionalFormatting -passthru " { it "Returned the rule when calling Add-ConditionalFormatting -passthru " {
$rule | should not beNullOrEmpty $rule | Should not beNullOrEmpty
$rule.getType().fullname | should be "OfficeOpenXml.ConditionalFormatting.ExcelConditionalFormattingTopPercent" $rule.getType().fullname | Should be "OfficeOpenXml.ConditionalFormatting.ExcelConditionalFormattingTopPercent"
$rule.Style.Font.Strike | should be true $rule.Style.Font.Strike | Should be true
} }
it "Applied the formating " { it "Applied the formating " {
$sheet | Should not beNullOrEmpty $sheet | Should not beNullOrEmpty
@@ -750,6 +758,17 @@ Describe ExportExcel {
$sheet.ConditionalFormatting[2].Formula | Should be '104857600' $sheet.ConditionalFormatting[2].Formula | Should be '104857600'
$sheet.ConditionalFormatting[2].Style.Font.Color.Color.Name | Should be 'ffff0000' $sheet.ConditionalFormatting[2].Style.Font.Color.Color.Name | Should be 'ffff0000'
} }
it "Created the named ranges " {
$sheet.Names.Count | Should be 7
$sheet.Names[0].Start.Column | Should be 1
$sheet.Names[0].Start.Row | Should be 2
$sheet.Names[0].End.Row | Should be $sheet.Dimension.End.Row
$sheet.Names[0].Name | Should be $sheet.Cells['A1'].Value
$sheet.Names[6].Start.Column | Should be 7
$sheet.Names[6].Start.Row | Should be 2
$sheet.Names[6].End.Row | Should be $sheet.Dimension.End.Row
$sheet.Names[6].Name | Should be $sheet.Cells['G1'].Value
}
it "Froze the panes " { it "Froze the panes " {
$sheet.view.Panes.Count | Should be 3 $sheet.view.Panes.Count | Should be 3
} }
@@ -831,8 +850,8 @@ Describe ExportExcel {
Add-ExcelChart -Worksheet $excel.Workbook.Worksheets["Sinx"] -ChartType line -XRange "X" -YRange "Sinx" -SeriesHeader "Sin(x)" -Title "Graph of Sine X" -TitleBold -TitleSize 14 ` Add-ExcelChart -Worksheet $excel.Workbook.Worksheets["Sinx"] -ChartType line -XRange "X" -YRange "Sinx" -SeriesHeader "Sin(x)" -Title "Graph of Sine X" -TitleBold -TitleSize 14 `
-Column 2 -ColumnOffSetPixels 35 -Width 800 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -XAxisNumberformat "000" ` -Column 2 -ColumnOffSetPixels 35 -Width 800 -XAxisTitleText "Degrees" -XAxisTitleBold -XAxisTitleSize 12 -XMajorUnit 30 -XMinorUnit 10 -XMinValue 0 -XMaxValue 361 -XAxisNumberformat "000" `
-YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -YAxisTitleText "Sine" -YAxisTitleBold -YAxisTitleSize 12 ` -YMinValue -1.25 -YMaxValue 1.25 -YMajorUnit 0.25 -YAxisNumberformat "0.00" -YAxisTitleText "Sine" -YAxisTitleBold -YAxisTitleSize 12 `
-LegendSize 8 -legendBold -LegendPostion Bottom -LegendSize 8 -legendBold -LegendPosition Bottom
Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets["Sinx"] -Range "B2:B362" -RuleType LessThan -ConditionValue "=B1" -ForeGroundColor Red Add-ConditionalFormatting -WorkSheet $excel.Workbook.Worksheets["Sinx"] -Range "B2:B362" -RuleType LessThan -ConditionValue "=B1" -ForeGroundColor ([System.Drawing.Color]::Red)
$ws = $Excel.Workbook.Worksheets["Sinx"] $ws = $Excel.Workbook.Worksheets["Sinx"]
$d = $ws.Drawings[0] $d = $ws.Drawings[0]
It "Controled the axes and title and legend of the chart " { It "Controled the axes and title and legend of the chart " {
@@ -864,6 +883,24 @@ Describe ExportExcel {
} }
Close-ExcelPackage -ExcelPackage $excel -nosave Close-ExcelPackage -ExcelPackage $excel -nosave
} }
Context " # Quick line chart" {
$path = "$env:TEMP\Test.xlsx"
Remove-Item -Path $path -ErrorAction SilentlyContinue
#test drawing a chart when data doesn't have a string
0..360 | ForEach-Object {[pscustomobject][ordered]@{x = $_; Sinx = "=Sin(Radians(x)) "}} | Export-Excel -AutoNameRange -Path $path -LineChart
$excel = Open-ExcelPackage -Path $path
$ws = $excel.Sheet1
$d = $ws.Drawings[0]
it "Created the chart " {
$d.Title.text | Should beNullOrEmpty
$d.ChartType | Should be "line"
$d.Series[0].Header | Should be "Sinx"
$d.Series[0].xSeries | Should be "'Sheet1'!A2:A362"
$d.Series[0].Series | Should be "'Sheet1'!B2:B362"
}
}
Context " # Quick Pie chart and three icon conditional formating" { Context " # Quick Pie chart and three icon conditional formating" {
$path = "$Env:TEMP\Pie.xlsx" $path = "$Env:TEMP\Pie.xlsx"
@@ -873,10 +910,10 @@ Describe ExportExcel {
Select-Object -Property Name, @{n="TotalPm";e={($_.group | Measure-Object -sum -Property pm).sum }} | Select-Object -Property Name, @{n="TotalPm";e={($_.group | Measure-Object -sum -Property pm).sum }} |
Export-Excel -NoHeader -AutoNameRange -path $path -ReturnRange -PieChart -ShowPercent Export-Excel -NoHeader -AutoNameRange -path $path -ReturnRange -PieChart -ShowPercent
$Cf = New-ConditionalFormattingIconSet -Range ($range -replace "^.*:","B2:") -ConditionalFormat ThreeIconSet -Reverse -IconType Flags $Cf = New-ConditionalFormattingIconSet -Range ($range -replace "^.*:","B2:") -ConditionalFormat ThreeIconSet -Reverse -IconType Flags
$ct = New-ConditionalText -Text "Microsoft" -ConditionalTextColor red -BackgroundColor AliceBlue -ConditionalType ContainsText $ct = New-ConditionalText -Text "Microsoft" -ConditionalTextColor ([System.Drawing.Color]::Red) -BackgroundColor([System.Drawing.Color]::AliceBlue) -ConditionalType ContainsText
it "Created the Conditional formatting rules " { it "Created the Conditional formatting rules " {
$cf.Formatter | should be "ThreeIconSet" $cf.Formatter | Should be "ThreeIconSet"
$cf.IconType | should be "Flags" $cf.IconType | Should be "Flags"
$cf.Range | Should be ($range -replace "^.*:","B2:") $cf.Range | Should be ($range -replace "^.*:","B2:")
$cf.Reverse | Should be $true $cf.Reverse | Should be $true
$ct.BackgroundColor.Name | Should be "AliceBlue" $ct.BackgroundColor.Name | Should be "AliceBlue"
@@ -891,13 +928,13 @@ Describe ExportExcel {
$chart = $excel.Workbook.Worksheets["sheet1"].Drawings[0] $chart = $excel.Workbook.Worksheets["sheet1"].Drawings[0]
$cFmt = $excel.Workbook.Worksheets["sheet1"].ConditionalFormatting $cFmt = $excel.Workbook.Worksheets["sheet1"].ConditionalFormatting
it "Created the chart with the right series " { it "Created the chart with the right series " {
$chart.ChartType | should be "PieExploded3D" $chart.ChartType | Should be "PieExploded3D"
$chart.series.series | should be "'Sheet1'!B1:B$rows" #would be B2 and A2 if we had a header. $chart.series.series | Should be "'Sheet1'!B1:B$rows" #would be B2 and A2 if we had a header.
$chart.series.Xseries | should be "'Sheet1'!A1:A$rows" $chart.series.Xseries | Should be "'Sheet1'!A1:A$rows"
$chart.DataLabel.ShowPercent | should be $true $chart.DataLabel.ShowPercent | Should be $true
} }
it "Created two Conditional formatting rules " { it "Created two Conditional formatting rules " {
$cFmt.Count | should be $true $cFmt.Count | Should be $true
$cFmt.Where({$_.type -eq "ContainsText"}) | Should not beNullOrEmpty $cFmt.Where({$_.type -eq "ContainsText"}) | Should not beNullOrEmpty
$cFmt.Where({$_.type -eq "ThreeIconSet"}) | Should not beNullOrEmpty $cFmt.Where({$_.type -eq "ThreeIconSet"}) | Should not beNullOrEmpty
} }
@@ -923,17 +960,17 @@ Describe ExportExcel {
$excel = Open-ExcelPackage -Path $path $excel = Open-ExcelPackage -Path $path
$ws = $excel.Workbook.Worksheets[1] $ws = $excel.Workbook.Worksheets[1]
it "Created 3 tables " { it "Created 3 tables " {
$ws.tables.count | should be 3 $ws.tables.count | Should be 3
} }
it "Created the FileSize table in the right place with the right size and style " { it "Created the FileSize table in the right place with the right size and style " {
$ws.Tables["FileSize"].Address.Address | should be "G2:H16" #Insert at row 2, Column 7, 14 rows x 2 columns of data $ws.Tables["FileSize"].Address.Address | Should be "G2:H16" #Insert at row 2, Column 7, 14 rows x 2 columns of data
$ws.Tables["FileSize"].StyleName | should be "TableStyleMedium2" $ws.Tables["FileSize"].StyleName | Should be "TableStyleMedium2"
} }
it "Created the ExtSize table in the right place with the right size " { it "Created the ExtSize table in the right place with the right size " {
$ws.Tables["ExtSize"].Address.Address | should be "A2:B14" #tile, then 12 rows x 2 columns of data $ws.Tables["ExtSize"].Address.Address | Should be "A2:B14" #tile, then 12 rows x 2 columns of data
} }
it "Created the ExtCount table in the right place with the right size " { it "Created the ExtCount table in the right place with the right size " {
$ws.Tables["ExtCount"].Address.Address | should be "D2:E12" #title, then 10 rows x 2 columns of data $ws.Tables["ExtCount"].Address.Address | Should be "D2:E12" #title, then 10 rows x 2 columns of data
} }
} }

View File

@@ -10,9 +10,11 @@ Banana, London , 300, 200
Orange, Paris, 600, 500 Orange, Paris, 600, 500
Banana, Paris, 300, 200 Banana, Paris, 300, 200
Apple, New York, 1200,700 Apple, New York, 1200,700
"@ | Export-Excel -Path $path -TableStyle Medium13 -tablename "RawData" -ConditionalFormat @{Range="C2:C7"; DataBarColor="Green"} -ExcelChartDefinition @{ChartType="Doughnut";XRange="A2:B7"; YRange="C2:C7"; width=800; } -PivotTableDefinition @{Sales=@{ "@ | Export-Excel -Path $path -TableStyle Medium13 -tablename "RawData" -ConditionalFormat @{Range="C2:C7"; DataBarColor="Green"} -ExcelChartDefinition @{ChartType="Doughnut";XRange="A2:B7"; YRange="C2:C7"; width=800; } -PivotTableDefinition @{Sales=@{
PivotRows="City"; PivotColumns="Product"; PivotData=@{Gross="Sum";Net="Sum"}; PivotNumberFormat="$#,##0.00"; PivotTotals="Both"; PivotTableSyle="Medium12"; Activate=$true PivotRows="City"; PivotColumns="Product"; PivotData=@{Gross="Sum";Net="Sum"}; PivotNumberFormat="$#,##0.00"; PivotTotals="Both"; PivotTableStyle="Medium12"; Activate=$true
PivotChartDefinition=@{Title="Gross and net by city and product"; ChartType="ColumnClustered"; Column=6; Width=600; Height=360; YMajorUnit=500; YMinorUnit=100; YAxisNumberformat="$#,##0"; LegendPostion="Bottom"}}}
PivotChartDefinition=@{Title="Gross and net by city and product"; ChartType="ColumnClustered"; Column=6; Width=600; Height=360; YMajorUnit=500; YMinorUnit=100; YAxisNumberformat="$#,##0"; LegendPosition="Bottom"}}}
$excel = Open-ExcelPackage $path $excel = Open-ExcelPackage $path
$ws1 = $excel.Workbook.Worksheets[1] $ws1 = $excel.Workbook.Worksheets[1]

View File

@@ -18,7 +18,7 @@ Describe "Creating small named ranges with hyperlinks" {
$worksheet = $excel.Workbook.Worksheets[1] $worksheet = $excel.Workbook.Worksheets[1]
$columns = $worksheet.Dimension.Columns $columns = $worksheet.Dimension.Columns
1..$columns | foreach {Add-ExcelName -Range $worksheet.cells[$topRow,$_,$lastDataRow,$_]} #Test Add-Excel Name on its own (outside Export-Excel) 1..$columns | ForEach-Object {Add-ExcelName -Range $worksheet.cells[$topRow,$_,$lastDataRow,$_]} #Test Add-Excel Name on its own (outside Export-Excel)
$scwarnVar = $null $scwarnVar = $null
Set-ExcelColumn -Worksheet $worksheet -StartRow $topRow -Heading "PlacesGained/Lost" ` Set-ExcelColumn -Worksheet $worksheet -StartRow $topRow -Heading "PlacesGained/Lost" `
@@ -34,12 +34,12 @@ Describe "Creating small named ranges with hyperlinks" {
$cf.Icon2.Type = $cf.Icon3.Type = "Num" $cf.Icon2.Type = $cf.Icon3.Type = "Num"
$cf.Icon2.Value = 0 $cf.Icon2.Value = 0
$cf.Icon3.Value = 1 $cf.Icon3.Value = 1
Add-ConditionalFormatting -Address $worksheet.cells["FinishPosition"] -RuleType Equal -ConditionValue 1 -ForeGroundColor Purple -Bold -Priority 1 -StopIfTrue #Test Priority and stopIfTrue and using range name Add-ConditionalFormatting -Address $worksheet.cells["FinishPosition"] -RuleType Equal -ConditionValue 1 -ForeGroundColor ([System.Drawing.Color]::Purple) -Bold -Priority 1 -StopIfTrue #Test Priority and stopIfTrue and using range name
Add-ConditionalFormatting -Address $worksheet.Cells["GridPosition"] -RuleType ThreeColorScale -Reverse #Test Reverse Add-ConditionalFormatting -Address $worksheet.Cells["GridPosition"] -RuleType ThreeColorScale -Reverse #Test Reverse
$ct = New-ConditionalText -Text "Ferrari" $ct = New-ConditionalText -Text "Ferrari"
$ct2 = New-ConditionalText -Range $worksheet.Names["FinishPosition"].Address -ConditionalType LessThanOrEqual -Text 3 -ConditionalText Red -Background White #Test new-conditionalText in shortest and longest forms. $ct2 = New-ConditionalText -Range $worksheet.Names["FinishPosition"].Address -ConditionalType LessThanOrEqual -Text 3 -ConditionalText ([System.Drawing.Color]::Red) -Background ([System.Drawing.Color]::White) #Test new-conditionalText in shortest and longest forms.
#Create links for each group name (race) and Export them so they start at Cell A1; create a pivot table with definition just created, save the file and open in Excel #Create links for each group name (race) and Export them so they start at Cell A1; create a pivot table with definition just created, save the file and open in Excel
$results | foreach {(New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList "Sheet1!$($_.Name)" , "$($_.name) GP")} | #Test Exporting Hyperlinks with display property. $results | ForEach-Object {(New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList "Sheet1!$($_.Name)" , "$($_.name) GP")} | #Test Exporting Hyperlinks with display property.
Export-Excel -ExcelPackage $excel -AutoSize -PivotTableDefinition $pt -Calculate -ConditionalFormat $ct,$ct2 #Test conditional text rules in conditional format (orignally icon sets only ) Export-Excel -ExcelPackage $excel -AutoSize -PivotTableDefinition $pt -Calculate -ConditionalFormat $ct,$ct2 #Test conditional text rules in conditional format (orignally icon sets only )
$excel = Open-ExcelPackage $path $excel = Open-ExcelPackage $path

View File

@@ -0,0 +1,28 @@
#Requires -Modules Pester
remove-module importExcel -erroraction silentlyContinue
Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force
Describe "Check if Function aliases exist" {
It "Set-Column should exist" {
${Alias:Set-Column} | Should Not BeNullOrEmpty
}
It "Set-Row should exist" {
${Alias:Set-Row} | Should Not BeNullOrEmpty
}
It "Set-Format should exist" {
${Alias:Set-Format} | Should Not BeNullOrEmpty
}
<#It "Merge-MulipleSheets should exist" {
Get-Command Merge-MulipleSheets | Should Not Be $null
}
#>
It "New-ExcelChart should exist" {
${Alias:New-ExcelChart} | Should Not BeNullOrEmpty
}
}

View File

@@ -22,7 +22,7 @@ ID,Product,Quantity,Price,Total
12012,Pliers,3,14.99,44.97 12012,Pliers,3,14.99,44.97
"@ "@
Describe "Join Worksheet" { Describe "Join Worksheet part 1" {
BeforeAll { BeforeAll {
$path = "$Env:TEMP\test.xlsx" $path = "$Env:TEMP\test.xlsx"
Remove-Item -Path $path -ErrorAction SilentlyContinue Remove-Item -Path $path -ErrorAction SilentlyContinue
@@ -30,9 +30,9 @@ Describe "Join Worksheet" {
$data2 | Export-Excel -Path $path -WorkSheetname Abingdon $data2 | Export-Excel -Path $path -WorkSheetname Abingdon
$data3 | Export-Excel -Path $path -WorkSheetname Banbury $data3 | Export-Excel -Path $path -WorkSheetname Banbury
$ptdef = New-PivotTableDefinition -PivotTableName "SummaryPivot" -PivotRows "Store" -PivotColumns "Product" -PivotData @{"Total"="SUM"} -IncludePivotChart -ChartTitle "Sales Breakdown" -ChartType ColumnStacked -ChartColumn 10 $ptdef = New-PivotTableDefinition -PivotTableName "SummaryPivot" -PivotRows "Store" -PivotColumns "Product" -PivotData @{"Total"="SUM"} -IncludePivotChart -ChartTitle "Sales Breakdown" -ChartType ColumnStacked -ChartColumn 10
Join-Worksheet -Path $path -WorkSheetName "Total" -Clearsheet -FromLabel "Store" -TableName "SummaryTable" -TableStyle Light1 -AutoSize -BoldTopRow -FreezePane 2,1 -Title "Store Sales Summary" -TitleBold -TitleSize 14 -PivotTableDefinition $ptdef Join-Worksheet -Path $path -WorkSheetName "Total" -Clearsheet -FromLabel "Store" -TableName "SummaryTable" -TableStyle Light1 -AutoSize -BoldTopRow -FreezePane 2,1 -Title "Store Sales Summary" -TitleBold -TitleSize 14 -TitleBackgroundColor ([System.Drawing.Color]::AliceBlue) -PivotTableDefinition $ptdef
$excel = Export-Excel -path $path -WorkSheetname SummaryPivot -Activate -HideSheet * -UnHideSheet "Total","SummaryPivot" -PassThru $excel = Export-Excel -path $path -WorkSheetname SummaryPivot -Activate -NoTotalsInPivot -PivotDataToColumn -HideSheet * -UnHideSheet "Total","SummaryPivot" -PassThru
# Open-ExcelPackage -Path $path # Open-ExcelPackage -Path $path
$ws = $excel.Workbook.Worksheets["Total"] $ws = $excel.Workbook.Worksheets["Total"]
@@ -52,28 +52,31 @@ Describe "Join Worksheet" {
it "Activated the correct worksheet " { it "Activated the correct worksheet " {
$excel.Workbook.worksheets["SummaryPivot"].View.TabSelected | Should be $true $excel.Workbook.worksheets["SummaryPivot"].View.TabSelected | Should be $true
$excel.Workbook.worksheets["Total"].View.TabSelected | Should be $false $excel.Workbook.worksheets["Total"].View.TabSelected | Should be $false
} }
} }
Context "Merging 3 blocks" { Context "Merging 3 blocks" {
it "Created sheet of the right size with a title and a table " { it "Created sheet of the right size with a title and a table " {
$ws.Dimension.Address | Should be "A1:F16" $ws.Dimension.Address | Should be "A1:F16"
$ws.Tables[0].Address.Address | Should be "A2:F16" $ws.Tables[0].Address.Address | Should be "A2:F16"
$ws.cells["A1"].Value | Should be "Store Sales Summary" $ws.Cells["A1"].Value | Should be "Store Sales Summary"
$ws.cells["A1"].Style.Font.Size | Should be 14 $ws.Cells["A1"].Style.Font.Size | Should be 14
$ws.Cells["A1"].Style.Font.Bold | Should be $True
$ws.Cells["A1"].Style.Fill.BackgroundColor.Rgb | Should be "FFF0F8FF"
$ws.Cells["A1"].Style.Fill.PatternType.ToString() | Should be "Solid"
$ws.Tables[0].StyleName | Should be "TableStyleLight1" $ws.Tables[0].StyleName | Should be "TableStyleLight1"
$ws.cells["A2:F2"].Style.Font.Bold | Should be $True $ws.Cells["A2:F2"].Style.Font.Bold | Should be $True
} }
it "Added a from column with the right heading " { it "Added a from column with the right heading " {
$ws.cells["F2" ].Value | Should be "Store" $ws.Cells["F2" ].Value | Should be "Store"
$ws.cells["F3" ].Value | Should be "Oxford" $ws.Cells["F3" ].Value | Should be "Oxford"
$ws.cells["F8" ].Value | Should be "Abingdon" $ws.Cells["F8" ].Value | Should be "Abingdon"
$ws.cells["F13"].Value | Should be "Banbury" $ws.Cells["F13"].Value | Should be "Banbury"
} }
it "Filled in the data " { it "Filled in the data " {
$ws.cells["C3" ].Value | Should be $data1[0].quantity $ws.Cells["C3" ].Value | Should be $data1[0].quantity
$ws.cells["C8" ].Value | Should be $data2[0].quantity $ws.Cells["C8" ].Value | Should be $data2[0].quantity
$ws.cells["C13"].Value | Should be $data3[0].quantity $ws.Cells["C13"].Value | Should be $data3[0].quantity
} }
it "Created the pivot table " { it "Created the pivot table " {
$pt | Should not beNullOrEmpty $pt | Should not beNullOrEmpty
@@ -85,8 +88,11 @@ Describe "Join Worksheet" {
$pc.Title.text | Should be "Sales Breakdown" $pc.Title.text | Should be "Sales Breakdown"
} }
} }
}
$path = "$env:TEMP\Test.xlsx" $path = "$env:TEMP\Test.xlsx"
Remove-item -Path $path -ErrorAction SilentlyContinue Remove-item -Path $path -ErrorAction SilentlyContinue
IF ($PSVersionTable.PSVersion.Major -gt 5) {Write-warning -message "Part 2 Does not run on V6"; return}
Describe "Join Worksheet part 2" {
Get-WmiObject -Class win32_logicaldisk | Get-WmiObject -Class win32_logicaldisk |
Select-Object -Property DeviceId,VolumeName, Size,Freespace | Select-Object -Property DeviceId,VolumeName, Size,Freespace |
Export-Excel -Path $path -WorkSheetname Volumes -NumberFormat "0,000" Export-Excel -Path $path -WorkSheetname Volumes -NumberFormat "0,000"

View File

@@ -19,7 +19,7 @@ describe "Consistent passing of ranges." {
$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 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
@@ -32,7 +32,7 @@ describe "Consistent passing of ranges." {
-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 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
@@ -62,7 +62,7 @@ describe "Consistent passing of ranges." {
$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 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

View File

@@ -135,17 +135,18 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" {
$excel = $data| Export-Excel -Path $path -AutoNameRange -PassThru $excel = $data| Export-Excel -Path $path -AutoNameRange -PassThru
$ws = $excel.Workbook.Worksheets["Sheet1"] $ws = $excel.Workbook.Worksheets["Sheet1"]
$c = Set-ExcelColumn -PassThru -Worksheet $ws -Heading "Total" -Value "=Quantity*Price" -NumberFormat "£#,###.00" -FontColor Blue -Bold -HorizontalAlignment Right -VerticalAlignment Top $c = Set-ExcelColumn -PassThru -Worksheet $ws -Heading "Total" -Value "=Quantity*Price" -NumberFormat "£#,###.00" -FontColor ([System.Drawing.Color]::Blue) -Bold -HorizontalAlignment Right -VerticalAlignment Top
$r = Set-ExcelRow -PassThru -Worksheet $ws -StartColumn 3 -BorderAround Thin -Italic -Underline -FontSize 14 -Value {"=sum($columnName`2:$columnName$endrow)" } -VerticalAlignment Bottom $r = Set-ExcelRow -PassThru -Worksheet $ws -StartColumn 3 -BorderAround Thin -Italic -Underline -FontSize 14 -Value {"=sum($columnName`2:$columnName$endrow)" } -VerticalAlignment Bottom
Set-ExcelRange -Address $excel.Workbook.Worksheets["Sheet1"].cells["b3"] -HorizontalAlignment Right -VerticalAlignment Center -BorderAround Thick -BorderColor Red -StrikeThru Set-ExcelRange -Address $excel.Workbook.Worksheets["Sheet1"].Cells["b3"] -HorizontalAlignment Right -VerticalAlignment Center -BorderAround Thick -BorderColor ([System.Drawing.Color]::Red) -StrikeThru
Set-ExcelRange -Address $excel.Workbook.Worksheets["Sheet1"].cells["c3"] -BorderColor Red -BorderTop DashDot -BorderLeft DashDotDot -BorderBottom Dashed -BorderRight Dotted Set-ExcelRange -Address $excel.Workbook.Worksheets["Sheet1"].Cells["c3"] -BorderColor ([System.Drawing.Color]::Red) -BorderTop DashDot -BorderLeft DashDotDot -BorderBottom Dashed -BorderRight Dotted
Set-ExcelRange -WorkSheet $ws -Range "E3" -Bold:$false -FontShift Superscript -HorizontalAlignment Left Set-ExcelRange -WorkSheet $ws -Range "E3" -Bold:$false -FontShift Superscript -HorizontalAlignment Left
Set-ExcelRange -WorkSheet $ws -Range "E1" -ResetFont -HorizontalAlignment General Set-ExcelRange -WorkSheet $ws -Range "E1" -ResetFont -HorizontalAlignment General -FontName "Courier New" -fontSize 9
Set-ExcelRange -Address $ws.cells["E7"] -ResetFont -WrapText -BackgroundColor AliceBlue -BackgroundPattern DarkTrellis -PatternColor Red -NumberFormat "£#,###.00" Set-ExcelRange -Address $ws.Cells["E7"] -ResetFont -WrapText -BackgroundColor ([System.Drawing.Color]::AliceBlue) -BackgroundPattern DarkTrellis -PatternColor ([System.Drawing.Color]::Red) -NumberFormat "£#,###.00"
Set-ExcelRange -Address $ws.Column(1) -Width 0 Set-ExcelRange -Address $ws.Column(1) -Width 0
Set-ExcelRange -Address $ws.Column(2) -AutoFit Set-ExcelRange -Address $ws.Column(2) -AutoFit
Set-ExcelRange -Address $ws.Cells["E:E"] -AutoFit Set-ExcelRange -Address $ws.Cells["E:E"] -AutoFit
Set-ExcelRange -Address $ws.row(5) -Height 0 #Test alias
Set-Format -Address $ws.row(5) -Height 0
$rr = $r.row $rr = $r.row
Set-ExcelRange -WorkSheet $ws -Range "B$rr" -Value "Total" Set-ExcelRange -WorkSheet $ws -Range "B$rr" -Value "Total"
$BadHideWarnvar = $null $BadHideWarnvar = $null
@@ -166,50 +167,52 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" {
$ws.Row(5).height | Should be 0 $ws.Row(5).height | Should be 0
} }
it "Set a column formula, with numberformat, color, bold face and alignment " { it "Set a column formula, with numberformat, color, bold face and alignment " {
$ws.cells["e2"].Formula | Should be "Quantity*Price" $ws.Cells["e2"].Formula | Should be "Quantity*Price"
$ws.cells["e2"].Value | Should be 147.63 $ws.Cells["e2"].Value | Should be 147.63
$ws.cells["e2"].Style.Font.Color.rgb | Should be "FF0000FF" $ws.Cells["e2"].Style.Font.Color.rgb | Should be "FF0000FF"
$ws.cells["e2"].Style.Font.Bold | Should be $true $ws.Cells["e2"].Style.Font.Bold | Should be $true
$ws.cells["e2"].Style.Font.VerticalAlign | Should be "None" $ws.Cells["e2"].Style.Font.VerticalAlign | Should be "None"
$ws.cells["e2"].Style.Numberformat.format | Should be "£#,###.00" $ws.Cells["e2"].Style.Numberformat.format | Should be "£#,###.00"
$ws.cells["e2"].Style.HorizontalAlignment | Should be "Right" $ws.Cells["e2"].Style.HorizontalAlignment | Should be "Right"
} }
} }
Context "Other formatting" { Context "Other formatting" {
it "Trapped an attempt to hide a range instead of a Row/Column " { it "Trapped an attempt to hide a range instead of a Row/Column " {
$BadHideWarnvar | Should not beNullOrEmpty $BadHideWarnvar | Should not beNullOrEmpty
} }
it "Set a row formula with border font size and underline " { it "Set and calculated a row formula with border font size and underline " {
$ws.cells["b7"].style.Border.Top.Style | Should be "None" $ws.Cells["b7"].Style.Border.Top.Style | Should be "None"
$ws.cells["F7"].style.Border.Top.Style | Should be "None" $ws.Cells["F7"].Style.Border.Top.Style | Should be "None"
$ws.cells["C7"].style.Border.Top.Style | Should be "Thin" $ws.Cells["C7"].Style.Border.Top.Style | Should be "Thin"
$ws.cells["C7"].style.Border.Bottom.Style | Should be "Thin" $ws.Cells["C7"].Style.Border.Bottom.Style | Should be "Thin"
$ws.cells["C7"].style.Border.Right.Style | Should be "None" $ws.Cells["C7"].Style.Border.Right.Style | Should be "None"
$ws.cells["C7"].style.Border.Left.Style | Should be "Thin" $ws.Cells["C7"].Style.Border.Left.Style | Should be "Thin"
$ws.cells["E7"].style.Border.Left.Style | Should be "None" $ws.Cells["E7"].Style.Border.Left.Style | Should be "None"
$ws.cells["E7"].style.Border.Right.Style | Should be "Thin" $ws.Cells["E7"].Style.Border.Right.Style | Should be "Thin"
$ws.cells["C7"].style.Font.size | Should be 14 $ws.Cells["C7"].Style.Font.size | Should be 14
$ws.cells["C7"].Formula | Should be "sum(C2:C6)" $ws.Cells["C7"].Formula | Should be "sum(C2:C6)"
$ws.cells["C7"].value | Should be 81 $ws.Cells["C7"].value | Should be 81
$ws.cells["C7"].style.Font.UnderLine | Should be $true $ws.Cells["C7"].Style.Font.UnderLine | Should be $true
$ws.cells["C6"].style.Font.UnderLine | Should be $false $ws.Cells["C6"].Style.Font.UnderLine | Should be $false
} }
it "Set custom text wrapping, alignment, superscript, border and Fill " { it "Set custom font, size, text-wrapping, alignment, superscript, border and Fill " {
$ws.cells["e3"].Style.HorizontalAlignment | Should be "Left" $ws.Cells["b3"].Style.Border.Left.Color.Rgb | Should be "FFFF0000"
$ws.cells["e3"].Style.Font.VerticalAlign | Should be "Superscript" $ws.Cells["b3"].Style.Border.Left.Style | Should be "Thick"
$ws.cells["b3"].style.Border.Left.Color.Rgb | Should be "FFFF0000" $ws.Cells["b3"].Style.Border.Right.Style | Should be "Thick"
$ws.cells["b3"].style.Border.Left.Style | Should be "Thick" $ws.Cells["b3"].Style.Border.Top.Style | Should be "Thick"
$ws.cells["b3"].style.Border.Right.Style | Should be "Thick" $ws.Cells["b3"].Style.Border.Bottom.Style | Should be "Thick"
$ws.cells["b3"].style.Border.Top.Style | Should be "Thick" $ws.Cells["b3"].Style.Font.Strike | Should be $true
$ws.cells["b3"].style.Border.Bottom.Style | Should be "Thick" $ws.Cells["e1"].Style.Font.Color.Rgb | Should be "ff000000"
$ws.cells["b3"].style.Font.Strike | Should be $true $ws.Cells["e1"].Style.Font.Bold | Should be $false
$ws.cells["e1"].Style.Font.Color.rgb | Should be "ff000000" $ws.Cells["e1"].Style.Font.Name | Should be "Courier New"
$ws.cells["e1"].Style.Font.Bold | Should be $false $ws.Cells["e1"].Style.Font.Size | Should be 9
$ws.cells["C6"].style.WrapText | Should be $false $ws.Cells["e3"].Style.Font.VerticalAlign | Should be "Superscript"
$ws.cells["e7"].style.WrapText | Should be $true $ws.Cells["e3"].Style.HorizontalAlignment | Should be "Left"
$ws.cells["e7"].Style.Fill.BackgroundColor.Rgb | Should be "FFF0F8FF" $ws.Cells["C6"].Style.WrapText | Should be $false
$ws.cells["e7"].Style.Fill.PatternColor.Rgb | Should be "FFFF0000" $ws.Cells["e7"].Style.WrapText | Should be $true
$ws.cells["e7"].Style.Fill.PatternType | Should be "DarkTrellis" $ws.Cells["e7"].Style.Fill.BackgroundColor.Rgb | Should be "FFF0F8FF"
$ws.Cells["e7"].Style.Fill.PatternColor.Rgb | Should be "FFFF0000"
$ws.Cells["e7"].Style.Fill.PatternType | Should be "DarkTrellis"
} }
} }
@@ -232,9 +235,9 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" {
$excel = $DriverData | Export-Excel -PassThru -Path $path -AutoSize -AutoNameRange $excel = $DriverData | Export-Excel -PassThru -Path $path -AutoSize -AutoNameRange
$ws = $excel.Workbook.Worksheets[1] $ws = $excel.Workbook.Worksheets[1]
Set-ExcelColumn -Worksheet $ws -Heading "Link" -AutoSize -Value {"https://en.wikipedia.org" + $worksheet.cells["B$Row"].value } Set-ExcelColumn -Worksheet $ws -Heading "Link" -AutoSize -Value {"https://en.wikipedia.org" + $worksheet.Cells["B$Row"].value }
$c = Set-ExcelColumn -PassThru -Worksheet $ws -Heading "NextBirthday" -Value { $c = Set-ExcelColumn -PassThru -Worksheet $ws -Heading "NextBirthday" -Value {
$bmonth = $worksheet.cells["C$Row"].value.month ; $bDay = $worksheet.cells["C$Row"].value.day $bmonth = $worksheet.Cells["C$Row"].value.month ; $bDay = $worksheet.Cells["C$Row"].value.day
$cMonth = [datetime]::Now.Month ; $cday = [datetime]::Now.day ; $cyear = [datetime]::Now.Year $cMonth = [datetime]::Now.Month ; $cday = [datetime]::Now.day ; $cyear = [datetime]::Now.Year
if (($cmonth -gt $bmonth) -or (($cMonth -eq $bmonth) -and ($cday -ge $bDay))){ if (($cmonth -gt $bmonth) -or (($cMonth -eq $bmonth) -and ($cday -ge $bDay))){
[datetime]::new($cyear+1, $bmonth, $bDay) [datetime]::new($cyear+1, $bmonth, $bDay)
@@ -242,7 +245,10 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" {
else {[datetime]::new($cyear, $bmonth, $bday) } else {[datetime]::new($cyear, $bmonth, $bday) }
} }
Set-ExcelColumn -Worksheet $ws -Heading "Age" -Value "=INT((NOW()-DateOfBirth)/365)" Set-ExcelColumn -Worksheet $ws -Heading "Age" -Value "=INT((NOW()-DateOfBirth)/365)"
Set-ExcelRange -Address $c,$ws.column(3) -NumberFormat 'Short Date' -AutoSize # Test Piping column Numbers into Set excelColumn
3, $c.ColumnMin | Set-ExcelColumn -Worksheet $ws -NumberFormat 'Short Date' -AutoSize
4..6 | Set-ExcelColumn -Worksheet $ws -AutoNameRange
Close-ExcelPackage -ExcelPackage $excel -Calculate Close-ExcelPackage -ExcelPackage $excel -Calculate
$excel = Open-ExcelPackage $path $excel = Open-ExcelPackage $path
@@ -251,9 +257,8 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" {
It "Inserted Hyperlinks " { It "Inserted Hyperlinks " {
$ws.Cells["D2"].Hyperlink | Should not beNullorEmpty $ws.Cells["D2"].Hyperlink | Should not beNullorEmpty
$ws.Cells["D2"].Style.Font.UnderLine | Should be $true $ws.Cells["D2"].Style.Font.UnderLine | Should be $true
} }
It "Inserted Dates " { It "Inserted and formatted Dates " {
$ws.Cells["C2"].Value.GetType().name | should be "DateTime" $ws.Cells["C2"].Value.GetType().name | should be "DateTime"
$ws.Cells["C2"].Style.Numberformat.NumFmtID | should be 14 $ws.Cells["C2"].Style.Numberformat.NumFmtID | should be 14
$ws.Cells["E2"].Value.GetType().name | should be "DateTime" $ws.Cells["E2"].Value.GetType().name | should be "DateTime"
@@ -262,6 +267,17 @@ Describe "Set-ExcelColumn, Set-ExcelRow and Set-ExcelRange" {
It "Inserted Formulas " { It "Inserted Formulas " {
$ws.Cells["F2"].Formula | Should not beNullorEmpty $ws.Cells["F2"].Formula | Should not beNullorEmpty
} }
It "Created Named ranges " {
$ws.Names.Count | Should be 6
$ws.Names["Age"] | Should not beNullorEmpty
$ws.Names["Age"].Start.Column | Should be 6
$ws.Names["Age"].Start.Row | Should be 2
$ws.Names["Age"].End.Row | Should be 7
$ws.names[0].name | Should be "Name"
$ws.Names[0].Start.Column | Should be 1
$ws.Names[0].Start.Row | Should be 2
}
} }
} }
@@ -308,11 +324,11 @@ Describe "Table Formatting" {
$excel = $data2 | Export-excel -path $path -WorksheetName Hardware -AutoNameRange -AutoSize -BoldTopRow -FreezeTopRow -PassThru $excel = $data2 | Export-excel -path $path -WorksheetName Hardware -AutoNameRange -AutoSize -BoldTopRow -FreezeTopRow -PassThru
$ws = $excel.Workbook.Worksheets[1] $ws = $excel.Workbook.Worksheets[1]
#test showfilter & TotalSettings #test showfilter & TotalSettings
$Table = Add-ExcelTable -PassThru -Range $ws.cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName HardwareTable -TotalSettings @{"Total"="Sum"} -ShowFirstColumn -ShowFilter:$false $Table = Add-ExcelTable -PassThru -Range $ws.Cells[$($ws.Dimension.address)] -TableStyle Light1 -TableName HardwareTable -TotalSettings @{"Total"="Sum"} -ShowFirstColumn -ShowFilter:$false
#test expnading named number formats #test expnading named number formats
Set-ExcelColumn -Worksheet $ws -Column 4 -NumberFormat 'Currency' Set-ExcelColumn -Worksheet $ws -Column 4 -NumberFormat 'Currency'
Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'Currency' Set-ExcelColumn -Worksheet $ws -Column 5 -NumberFormat 'Currency'
$PtDef =New-PivotTableDefinition -PivotTableName Totals -PivotRows Product -PivotData @{"Total"="Sum"} -PivotNumberFormat Currency -PivotTotals None -PivotTableSyle Dark2 $PtDef =New-PivotTableDefinition -PivotTableName Totals -PivotRows Product -PivotData @{"Total"="Sum"} -PivotNumberFormat Currency -PivotTotals None -PivotTableStyle Dark2
Export-excel -ExcelPackage $excel -WorksheetName Hardware -PivotTableDefinition $PtDef Export-excel -ExcelPackage $excel -WorksheetName Hardware -PivotTableDefinition $PtDef
$excel= Open-ExcelPackage -Path $path $excel= Open-ExcelPackage -Path $path
$ws1 = $excel.Workbook.Worksheets["Hardware"] $ws1 = $excel.Workbook.Worksheets["Hardware"]

Binary file not shown.

15
azure-pipelines.yml Normal file
View File

@@ -0,0 +1,15 @@
resources:
- repo: self
queue:
name: Hosted VS2017
steps:
- powershell: ./ '.\DoTests.ps1'
displayName: 'PowerShell Script'
- task: ArchiveFiles@2
displayName: 'Archive $(Build.BinariesDirectory)'
trigger:
paths:
exclude:
- README.md

View File

@@ -1,91 +1,114 @@
Function Compare-WorkSheet { Function Compare-WorkSheet {
<# <#
.Synopsis .Synopsis
Compares two worksheets with the same name in different files. Compares two worksheets and shows the differences.
.Description .Description
This command takes two file names, a worksheet name and a name for a key column. This command takes two file names, one or two worksheet names and a name
It reads the worksheet from each file and decides the column names. for a "key" column. It reads the worksheet from each file and decides the
It builds as hashtable of the key column values and the rows they appear in column names and builds a hashtable of the key-column values and the
It then uses PowerShell's compare object command to compare the sheets (explicity checking all column names which have not been excluded) rows in which they appear.
For the difference rows it adds the row number for the key of that row - we have to add the key after doing the comparison, It then uses PowerShell's Compare-Object command to compare the sheets
otherwise rows will be considered as different simply because they have different row numbers (explicitly checkingall the column names which have not been excluded).
We also add the name of the file in which the difference occurs. For the difference rows it adds the row number for the key of that row -
If -BackgroundColor is specified the difference rows will be changed to that background. we have to add the key after doing the comparison, otherwise identical
rows at different positions in the file will not be considered a match.
We also add the name of the file and sheet in which the difference occurs.
If -BackgroundColor is specified the difference rows will be changed to
that background in the orginal file.
.Example .Example
Compare-WorkSheet -Referencefile 'Server56.xlsx' -Differencefile 'Server57.xlsx' -WorkSheetName Products -key IdentifyingNumber -ExcludeProperty Install* | format-table Compare-WorkSheet -Referencefile 'Server56.xlsx' -Differencefile 'Server57.xlsx' -WorkSheetName Products -key IdentifyingNumber -ExcludeProperty Install* | Format-Table
The two workbooks in this example contain the result of redirecting a subset of properties from Get-WmiObject -Class win32_product to Export-Excel
The command compares the "products" pages in the two workbooks, but we don't want to register a differnce if if the software was installed on a The two workbooks in this example contain the result of redirecting a subset
different date or from a different place, so Excluding Install* removes InstallDate and InstallSource. of properties from Get-WmiObject -Class win32_product to Export-Excel.
This data doesn't have a "name" column" so we specify the "IdentifyingNumber" column as the key. The command compares the "Products" pages in the two workbooks, but we
don't want to register a difference if the software was installed on a
different date or from a different place, and excluding Install* removes
InstallDate and InstallSource. This data doesn't have a "Name" column, so
we specify the "IdentifyingNumber" column as the key.
The results will be presented as a table. The results will be presented as a table.
.Example .Example
compare-WorkSheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName services -GridView Compare-WorkSheet "Server54.xlsx" "Server55.xlsx" -WorkSheetName Services -GridView
This time two workbooks contain the result of redirecting Get-WmiObject -Class win32_service to Export-Excel
Here the -Differencefile and -Referencefile parameter switches are assumed , and the default setting for -key ("Name") works for services This time two workbooks contain the result of redirecting the command
This will display the differences between the "services" sheets using a grid view Get-WmiObject -Class win32_service to Export-Excel. Here the -Differencefile
and -Referencefile parameter switches are assumed and the default setting for
-Key ("Name") works for services. This will display the differences between
the "Services" sheets using a grid view
.Example .Example
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen
This version of the command outputs the differences between the "services" pages and also highlights any different rows in the spreadsheet files.
This version of the command outputs the differences between the "services" pages and highlights any different rows in the spreadsheet files.
.Example .Example
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen -FontColor Red -Show Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName Services -BackgroundColor lightGreen -FontColor Red -Show
This builds on the previous example: this time Where two changed rows have the value in the "name" column (the default value for -key),
this version adds highlighting of the changed cells in red; and then opens the Excel file. This example builds on the previous one: this time where two changed rows have
the value in the "Name" column (the default value for -Key), this version adds
highlighting of the changed cells in red; and then opens the Excel file.
.Example .Example
Compare-WorkSheet 'Pester-tests.xlsx' 'Pester-tests.xlsx' -WorkSheetName 'Server1','Server2' -Property "full Description","Executed","Result" -Key "full Description" Compare-WorkSheet 'Pester-tests.xlsx' 'Pester-tests.xlsx' -WorkSheetName 'Server1','Server2' -Property "full Description","Executed","Result" -Key "full Description"
This time the reference file and the difference file are the same file and two different sheets are used. Because the tests include the
machine name and time the test was run the command specifies a limited set of columns should be used. This time the reference file and the difference file are the same file and
two different sheets are used. Because the tests include the machine name
and time the test was run, the command specifies that a limited set of
columns should be used.
.Example .Example
Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -GridView -ExcludeDifferent Compare-WorkSheet 'Server54.xlsx' 'Server55.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -GridView -ExcludeDifferent
The "General" page has a title and two unlabelled columns with a row forCPU, Memory, Domain, Disk and so on
So the command is instructed to starts at row 2 to skip the title and to name the columns: the first is "label" and the Second "Value"; The "General" page in the two workbooks has a title and two unlabelled columns
the label acts as the key. This time we interested the rows which are the same in both sheets, with a row each for CPU, Memory, Domain, Disk and so on. So the command is
and the result is displayed using grid view. Note that grid view works best when the number of columns is small. told to start at row 2 in order to skip the title and given names for the
columns: the first is "label" and the second "Value"; the label acts as the key.
This time we are interested in those rows which are the same in both sheets,
and the result is displayed using grid view.
Note that grid view works best when the number of columns is small.
.Example .Example
Compare-WorkSheet 'Server1.xlsx' 'Server2.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -BackgroundColor White -Show -AllDataBackgroundColor LightGray Compare-WorkSheet 'Server1.xlsx' 'Server2.xlsx' -WorkSheetName general -Startrow 2 -Headername Label,value -Key Label -BackgroundColor White -Show -AllDataBackgroundColor LightGray
This version of the previous command lightlights all the cells in lightgray and then sets the changed rows back to white; only
the unchanged rows are highlighted This version of the previous command highlights all the cells in LightGray
and then sets the changed rows back to white.
Only the unchanged rows are highlighted.
#> #>
[cmdletbinding(DefaultParameterSetName)] [cmdletbinding(DefaultParameterSetName)]
Param( Param(
#First file to compare #First file to compare.
[parameter(Mandatory=$true,Position=0)] [parameter(Mandatory=$true,Position=0)]
$Referencefile , $Referencefile ,
#Second file to compare #Second file to compare.
[parameter(Mandatory=$true,Position=1)] [parameter(Mandatory=$true,Position=1)]
$Differencefile , $Differencefile ,
#Name(s) of worksheets to compare. #Name(s) of worksheets to compare.
$WorkSheetName = "Sheet1", $WorkSheetName = "Sheet1",
#Properties to include in the DIFF - supports wildcards, default is "*" #Properties to include in the comparison - supports wildcards, default is "*".
$Property = "*" , $Property = "*" ,
#Properties to exclude from the the search - supports wildcards #Properties to exclude from the comparison - supports wildcards.
$ExcludeProperty , $ExcludeProperty ,
#Specifies custom property names to use, instead of the values defined in the column headers of the TopRow. #Specifies custom property names to use, instead of the values defined in the starting row of the sheet.
[Parameter(ParameterSetName='B', Mandatory)] [Parameter(ParameterSetName='B', Mandatory)]
[String[]]$Headername, [String[]]$Headername,
#Automatically generate property names (P1, P2, P3, ..) instead of the using the values the top row of the sheet #Automatically generate property names (P1, P2, P3 ...) instead of the using the values the starting row of the sheet.
[Parameter(ParameterSetName='C', Mandatory)] [Parameter(ParameterSetName='C', Mandatory)]
[switch]$NoHeader, [switch]$NoHeader,
#The row from where we start to import data, all rows above the StartRow are disregarded. By default this is the first row. #The row from where we start to import data: all rows above the start row are disregarded. By default, this is the first row.
[int]$Startrow = 1, [int]$Startrow = 1,
#If specified, highlights all the cells - so you can make Equal cells one colour, and Diff cells another. #If specified, highlights all the cells - so you can make Equal cells one color, and Different cells another.
[System.Drawing.Color]$AllDataBackgroundColor, $AllDataBackgroundColor,
#If specified, highlights the DIFF rows #If specified, highlights the rows with differences.
[System.Drawing.Color]$BackgroundColor, $BackgroundColor,
#If specified identifies the tabs which contain DIFF rows (ignored if -backgroundColor is omitted) #If specified identifies the tabs which contain difference rows (ignored if -BackgroundColor is omitted).
[System.Drawing.Color]$TabColor, $TabColor,
#Name of a column which is unique and will be used to add a row to the DIFF object, default is "Name" #Name of a column which is unique and will be used to add a row to the DIFF object, defaults to "Name".
$Key = "Name" , $Key = "Name" ,
#If specified, highlights the DIFF columns in rows which have the same key. #If specified, highlights the DIFF columns in rows which have the same key.
[System.Drawing.Color]$FontColor, $FontColor,
#If specified opens the Excel workbooks instead of outputting the diff to the console (unless -passthru is also specified) #If specified, opens the Excel workbooks instead of outputting the diff to the console (unless -PassThru is also specified).
[Switch]$Show, [Switch]$Show,
#If specified, the command tries to the show the DIFF in a Gridview and not on the console. (unless-Passthru is also specified). This Works best with few columns selected, and requires a key #If specified, the command tries to the show the DIFF in a Grid-View and not on the console. (unless-PassThru is also specified). This works best with few columns selected, and requires a key.
[switch]$GridView, [switch]$GridView,
#If specified -Passthrough full set of diff data is returned without filtering to the specified properties #If specifieda full set of DIFF data is returned without filtering to the specified properties.
[Switch]$PassThru, [Switch]$PassThru,
#If specified the result will include equal rows as well. By default only different rows are returned #If specified the result will include equal rows as well. By default only different rows are returned.
[Switch]$IncludeEqual, [Switch]$IncludeEqual,
#If Specified the result includes only the rows where both are equal #If specified, the result includes only the rows where both are equal.
[Switch]$ExcludeDifferent [Switch]$ExcludeDifferent
) )
@@ -145,7 +168,7 @@ Function Compare-WorkSheet {
foreach ($file in $updates) { foreach ($file in $updates) {
try {$xl = Open-ExcelPackage -Path $file.name } try {$xl = Open-ExcelPackage -Path $file.name }
catch {Write-warning -Message "Can't open $($file.Name) for writing." ; return} catch {Write-warning -Message "Can't open $($file.Name) for writing." ; return}
if ($AllDataBackgroundColor) { if ($PSBoundParameters.ContainsKey("AllDataBackgroundColor")) {
$file.Group._sheet | Sort-Object -Unique | ForEach-Object { $file.Group._sheet | Sort-Object -Unique | ForEach-Object {
$ws = $xl.Workbook.Worksheets[$_] $ws = $xl.Workbook.Worksheets[$_]
if ($headerName) {$range = "A" + $startrow + ":" + $ws.dimension.end.address} if ($headerName) {$range = "A" + $startrow + ":" + $ws.dimension.end.address}
@@ -158,7 +181,8 @@ Function Compare-WorkSheet {
$range = $ws.Dimension -replace "\d+",$row._row $range = $ws.Dimension -replace "\d+",$row._row
Set-Format -WorkSheet $ws -Range $range -BackgroundColor $BackgroundColor Set-Format -WorkSheet $ws -Range $range -BackgroundColor $BackgroundColor
} }
if ($TabColor) { if ($PSBoundParameters.ContainsKey("TabColor")) {
if ($TabColor -is [string]) {$TabColor = [System.Drawing.Color]::$TabColor }
foreach ($tab in ($file.group._sheet | Select-Object -Unique)) { foreach ($tab in ($file.group._sheet | Select-Object -Unique)) {
$xl.Workbook.Worksheets[$tab].TabColor = $TabColor $xl.Workbook.Worksheets[$tab].TabColor = $TabColor
} }
@@ -166,7 +190,7 @@ Function Compare-WorkSheet {
$xl.save() ; $xl.Stream.Close() ; $xl.Dispose() $xl.save() ; $xl.Stream.Close() ; $xl.Dispose()
} }
} }
#if font colour was specified, set it on changed properties where the same key appears in both sheets. #if font color was specified, set it on changed properties where the same key appears in both sheets.
if ($diff -and $FontColor -and ($propList -contains $Key) ) { if ($diff -and $FontColor -and ($propList -contains $Key) ) {
$updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property $Key | Where-Object {$_.count -eq 2} $updates = $diff.where({$_.SideIndicator -ne "=="}) | Group-object -Property $Key | Where-Object {$_.count -eq 2}
if ($updates) { if ($updates) {
@@ -198,6 +222,8 @@ Function Compare-WorkSheet {
#if nothing was found write a message which wont be redirected #if nothing was found write a message which wont be redirected
if (-not $diff) {Write-Host "Comparison of $Referencefile::$worksheet1 and $Differencefile::$WorkSheet2 returned no results." } if (-not $diff) {Write-Host "Comparison of $Referencefile::$worksheet1 and $Differencefile::$WorkSheet2 returned no results." }
if ($Show) { if ($Show) {
Start-Process -FilePath $Referencefile Start-Process -FilePath $Referencefile
if (-not $oneFile) { Start-Process -FilePath $Differencefile } if (-not $oneFile) { Start-Process -FilePath $Differencefile }

BIN
fib.xlsx

Binary file not shown.

View File

@@ -30,6 +30,7 @@ New-ExcelChart.ps1
New-PSItem.ps1 New-PSItem.ps1
Open-ExcelPackage.ps1 Open-ExcelPackage.ps1
Pivot.ps1 Pivot.ps1
PivotTable.ps1
Plot.ps1 Plot.ps1
Send-SQLDataToExcel.ps1 Send-SQLDataToExcel.ps1
Set-CellStyle.ps1 Set-CellStyle.ps1

View File

@@ -155,7 +155,7 @@ class PSPlot {
$sum=0 $sum=0
$columnName.ToCharArray() | $columnName.ToCharArray() |
ForEach { ForEach-Object {
$sum*=26 $sum*=26
$sum+=[char]$_.tostring().toupper()-[char]'A'+1 $sum+=[char]$_.tostring().toupper()-[char]'A'+1
} }

View File

@@ -3,7 +3,7 @@ function ConvertFrom-ExcelColumnName {
$sum=0 $sum=0
$columnName.ToCharArray() | $columnName.ToCharArray() |
ForEach { ForEach-Object {
$sum*=26 $sum*=26
$sum+=[char]$_.tostring().toupper()-[char]'A'+1 $sum+=[char]$_.tostring().toupper()-[char]'A'+1
} }