Compare commits

...

309 Commits

Author SHA1 Message Date
dfinke
b67801e983 wip 2023-06-07 17:59:03 -04:00
Doug Finke
ab4d03c984 Merge pull request #1392 from stahler/patch-7
minor spelling edit
2023-02-05 06:41:07 -05:00
Doug Finke
ca4dfb7040 Merge pull request #1391 from stahler/patch-6
minor syntax changes
2023-02-05 06:40:54 -05:00
Wes Stahler
a9eca05303 minor spelling edit 2023-02-04 22:16:22 -05:00
Wes Stahler
195efdea54 minor syntax changes 2023-02-04 22:04:08 -05:00
Doug Finke
24e5fccafe Merge pull request #1361 from dfinke/thkn-hofa-Issue1344
Fix Issue 1344 with Freeze Top Row
2022-12-28 15:58:09 -05:00
dfinke
840870df11 Resolve conflict 2022-12-28 14:26:43 -05:00
dfinke
0fe6654233 Add additional test 2022-12-28 14:16:14 -05:00
dfinke
7598b75538 update 2022-12-27 16:20:50 -05:00
Doug Finke
ed6c87e8de Merge pull request #1357 from thkn-hofa/Issue1316
Add -NoHyperLinkConversion
2022-12-27 16:11:17 -05:00
dfinke
2642211e12 Added some hyperlink tests 2022-12-27 16:06:07 -05:00
Thomas Hofkens
9373765e10 Introduced tests for Freezing panes 2022-12-26 13:10:24 +01:00
Thomas Hofkens
16820a30c4 Add -NoHyperLinkConversion 2022-12-26 01:22:22 +01:00
Thomas Hofkens
438d7e2b03 Fix Issue 1344 2022-12-25 23:44:21 +01:00
dfinke
c617d96322 Tweak both 2022-12-11 10:26:47 -05:00
Doug Finke
15679a0d82 Merge pull request #1341 from dfinke/DoNotShowValues-for-Conditional
Add -ShowOnlyIcon to New-ConditionalFormattingIconSet. Base on https:…
2022-12-11 10:17:36 -05:00
dfinke
3c23a064bc Add -ShowOnlyIcon to New-ConditionalFormattingIconSet. Base on https://github.com/dfinke/ImportExcel/discussions/1340 2022-12-10 18:22:36 -05:00
Doug Finke
c848497f53 Merge pull request #1305 from thkn-hofa/master
TotalSettings improvements
2022-11-19 08:09:35 -05:00
dfinke
ba374ec558 tweak test 2022-11-19 08:03:37 -05:00
Doug Finke
3f772ce726 Merge pull request #1285 from steve-daedilus/master
#1281 Grammar error update
2022-11-19 07:47:58 -05:00
Thomas Hofkens
3ea6fde928 changelog update + Pester test fix for powershell 5.1 2022-11-14 17:54:15 +01:00
Thomas Hofkens
81ece62494 Fix Pester errors for countries with ',' as decimal separator 2022-11-14 17:33:21 +01:00
Thomas Hofkens
828b2caf9f Implement Set Column by range in Add-ExcelTable + simplify adding table from Export-Excel 2022-11-14 17:32:39 +01:00
Thomas Hofkens
f760b63818 Update Set-CellComment to use 'Range' parameter + Create tests file 2022-11-14 17:31:36 +01:00
Thomas Hofkens
fe016f732d Bugfix example script 2022-11-12 00:52:15 +01:00
Thomas Hofkens
c719cc3d32 Doc update 2022-11-12 00:42:36 +01:00
Thomas Hofkens
5558f48732 Changelog update: TableTotalSettings in stead of TotalSettings 2022-11-12 00:42:24 +01:00
Thomas Hofkens
4dfd211bb6 Newlines after ```text because of help build failures 2022-11-12 00:41:57 +01:00
Thomas Hofkens
90bc047267 Updated Documentation 2022-11-12 00:26:49 +01:00
Thomas Hofkens
4c0e7970cf Updated Examples 2022-11-12 00:26:40 +01:00
Thomas Hofkens
b191f16e3e Updated Tests 2022-11-12 00:26:19 +01:00
Thomas Hofkens
ce49038b75 Changed TotalSettings to TableTotalSettings + Changed the way custom formulas are added + added possibility to add comments tot totals row 2022-11-12 00:25:56 +01:00
Thomas Hofkens
652a611137 Added new function 'Set-CellComment' 2022-11-12 00:24:17 +01:00
Doug Finke
3b73ce24ae Merge pull request #1300 from thkn-hofa/master
Add TotalSettings parameter to Export-Excel
2022-11-11 10:01:17 -05:00
dfinke
5e8afa48fc Add a Sales Data example, known data and diff criteria in the COUNTIF 2022-11-11 09:38:56 -05:00
Thomas Hofkens
f494635b48 Added custom formula for totals row + Example File 2022-11-09 11:35:19 +01:00
Thomas Hofkens
dcb67b4518 Merged Export-Excel-TotalSettings.Tests.ps1 with Export-Excel.Tests.ps1 2022-11-08 16:31:02 +01:00
Thomas Hofkens
06c00cb0b2 Expanded Unit Tests 2022-11-06 12:07:05 +01:00
Thomas Hofkens
d987437ad6 Unit Tests 2022-11-06 11:52:34 +01:00
Thomas Hofkens
fe27ff81c8 bump version, update changelog 2022-11-04 15:26:23 +01:00
Thomas Hofkens
9f4307f6c0 Add TotalSettings parameter to Export-Excel 2022-11-04 15:05:28 +01:00
Stephen Brown
a1fccf914f Merge remote-tracking branch 'upstream/master' 2022-10-22 00:44:36 +01:00
Doug Finke
0b4c2b81db Merge pull request #1283 from stahler/patch-5
Update add-excelchart.md
2022-10-21 10:48:13 -04:00
Stephen Brown
8ee34217a4 #1281 Grammar error update 2022-10-21 13:53:13 +01:00
Wes Stahler
c01601910d Update add-excelchart.md
Correct minor spelling
2022-10-20 21:11:27 -04:00
dfinke
63f6543784 update 2022-10-20 20:35:50 -04:00
Doug Finke
306e10c348 Merge pull request #1273 from steve-daedilus/master
Set Validate Range for rows to max rows available
2022-10-20 20:23:05 -04:00
dfinke
970febd6d3 The orignal test took too long to run 2022-10-20 20:13:27 -04:00
Stephen Brown
e703a21dec Pester test setup for Max Rows retrieval 2022-10-20 18:06:08 +01:00
Stephen Brown
c1be6a8d82 Merge branch 'dfinke:master' into master 2022-10-18 09:51:53 +01:00
dfinke
201b9cd984 Add Sheet visibility property 2022-10-15 19:34:58 -04:00
dfinke
559bfa2a7f bump version update log 2022-10-15 19:34:24 -04:00
Stephen Brown
4bd3efa1ef Set Validate Range for rows to max rows available
$StartRow parameter had ValidateRange(1,9999) which was limiting the start row to a maximum of 9999. There's no good reason this cannot be any row in the spreadsheet, of which the maximum is 1048576 in modern instances of Excel.
2022-10-14 19:00:42 +01:00
Doug Finke
926042e5b6 Merge pull request #1266 from stahler/patch-4
Update Export-Excel.ps1
2022-10-11 16:25:24 -04:00
Wes Stahler
be1e55cf8d Update Export-Excel.ps1
Fixed case on -BarChart switch.
2022-10-11 16:18:16 -04:00
Doug Finke
a86c55b3ac update 2022-09-24 13:08:43 -04:00
Doug Finke
fa14695fb9 Merge pull request #1254 from WilsonStewart/master
Fixed typo of 'pararameter' to 'parameter'
2022-09-24 13:07:32 -04:00
WilsonStewart
6322bafaed Fixed typo of 'pararameter' to 'parameter' 2022-09-21 16:25:40 -06:00
Doug Finke
c7a6f4ba35 update changelog 2022-09-20 10:36:49 -04:00
Doug Finke
49a6805727 Merge pull request #1253 from stahler/patch-3
Update convertfrom-exceltosqlinsert.md
2022-09-20 10:21:03 -04:00
Wes Stahler
c124ee199d Update convertfrom-exceltosqlinsert.md
fix spelling
2022-09-19 20:46:43 -04:00
Doug Finke
858cf60a2f Merge pull request #1251 from JeremiahTheFirst/master
Update Add-Worksheet.ps1 - 'worsheet' to 'worksheet' in warnings
2022-09-16 16:01:12 -04:00
Jeremiah Adams
fcde64780e Update Add-Worksheet.ps1 - 'worsheet' to 'worksheet' in warnings 2022-09-15 09:04:08 -05:00
dfinke
be5d270f44 update change log 2022-09-03 16:51:59 -04:00
Doug Finke
f9fb49ad04 Merge pull request #1234 from stahler/patch-2
Update open-excelpackage.md
2022-08-25 13:51:21 -04:00
Wes Stahler
4727bb3b2b Update open-excelpackage.md
Small changes to Example 2
2022-08-24 21:34:46 -04:00
dfinke
ac435fc1e1 bump version 2022-08-24 18:37:24 -04:00
dfinke
340ffc560b Use EZOut to format data form Excel to Mardown tables and Yaml 2022-08-24 18:37:14 -04:00
Doug Finke
069c227391 Merge pull request #1233 from g-pearl/master
Update Bottom Spelling Error
2022-08-24 18:21:38 -04:00
g-pearl
fa4f3a23cd Update Bottom Spelling Error 2022-08-24 08:54:36 -06:00
Doug Finke
f54db0e2d9 Merge pull request #1220 from dfinke/Add-Group-Column-Tests
Added Group Column tests
2022-07-20 07:15:46 -04:00
dfinke
8c1388a799 Added Group Column tests 2022-07-17 11:24:51 -04:00
dfinke
7c473d1fb6 bump version 2022-07-16 13:45:40 -04:00
dfinke
31366057df Add images for changelog 2022-07-16 13:45:34 -04:00
Doug Finke
f102ece700 Merge pull request #1219 from jhoneill/PivotTableUpdates
Pivot table updates
2022-07-16 13:25:17 -04:00
dfinke
950b9ab078 update with examples that were added 2022-07-16 12:19:23 -04:00
Doug Finke
869ab59a8a tweak README 2022-07-16 11:47:33 -04:00
Doug Finke
1e9a73d176 Merge pull request #1214 from dbrennand/feat/vba-pivotable-tabular-repeat-label-no-subtotals
Feat/VBA-PivotTable-Tabular-Repeat-Label-No-Subtotals
2022-07-16 11:30:19 -04:00
James O'Neill
37e6896741 Merge branch 'dfinke:master' into PivotTableUpdates 2022-07-14 20:27:59 +01:00
Doug Finke
c39e6cc24c Merge pull request #1216 from chadmando/fixtypo
Fix typo in help
2022-07-14 14:15:16 -04:00
James O'Neill
5ab9d6f23f Add column to GroupNumeric/Date in PivotTables. 2022-07-14 17:43:55 +01:00
chadmando
81e60be51d Fix typo in help
Open-ExcelPackage Example #2 Line#48
remove 'and'
2022-07-13 15:36:17 -05:00
dfinke
943ca7e6d1 Added -Show 2022-07-13 14:13:22 -04:00
Doug Finke
513ff59ba8 Merge pull request #1208 from kkazala/kkazala/exportformatting
Kkazala/exportformatting
2022-07-13 12:09:55 -04:00
dbrennand
45fc5a2631 fix: add missing -Path parameter 2022-07-13 16:59:18 +01:00
dbrennand
8b30fce81a feat: add VBA example to modify PivotTables
Excel macro example for changing all PivotTables in the workbook to Tabular form, repeats labels and disables Subtotals.
2022-07-13 16:57:22 +01:00
dfinke
0990c0ef09 used $PSScriptRoot instead 2022-07-13 09:50:02 -04:00
Kinga Kazala
724ed6b197 Get-ConditionalFormatting function added 2022-07-13 09:34:30 +02:00
Kinga Kazala
087feedde6 fix: corrected the script to include sheet name, and to add '=' in the ConditionValue 2022-07-13 09:26:19 +02:00
Kinga Kazala
b92ea56fe9 GetConditionalFormatting.xlsx added 2022-07-11 07:58:29 +02:00
Kinga Kazala
c4eed8c25d GetConditionalFormatting.ps1 example added: exports conditional formatting rules in a 'ready to use' format 2022-07-05 16:05:40 +02:00
Kinga Kazala
9051ffc0e5 example update: format both cells, plus format whole row 2022-07-05 15:59:32 +02:00
Doug Finke
050613eede Merge pull request #1206 from dfinke/Investigate-underlinetype-not-being-set
Fix -UnderLineType parameter is ignored in Set-ExcelColumn #1204
2022-07-04 10:47:10 -04:00
Doug Finke
84f51c4823 Merge branch 'master' into Investigate-underlinetype-not-being-set 2022-07-04 10:41:02 -04:00
dfinke
f2544ed1ec Fix -UnderLineType parameter is ignored in Set-ExcelColumn #1204 2022-07-04 10:29:39 -04:00
James O'Neill
5b4857d7a0 New subtotals, tweak module stats example 2022-06-21 16:58:42 +02:00
Doug Finke
45449650c7 Merge pull request #1202 from kkazala/compareCells
Compare cells
2022-06-20 13:07:58 -04:00
Doug Finke
d7348250fc Updated 2022-06-20 13:00:33 -04:00
Kinga Kazala
b53881fd02 Merge branch 'compareCells' of https://github.com/kkazala/ImportExcel into compareCells 2022-06-20 17:20:17 +02:00
Kinga Kazala
632bb263cc docs: Highlight-DiffCells.ps1 example added 2022-06-20 17:19:01 +02:00
Kinga Kazala
658a6b543a docs: Highlight-DiffCells.ps1 example added 2022-06-20 17:12:48 +02:00
Doug Finke
0f301ff619 fix formatting 2022-06-17 12:20:32 -04:00
Doug Finke
115fbb23a7 Merge pull request #1200 from jhoneill/master
Update to Get-HTMLTable, added Import-ByColuumns function and example
2022-06-17 12:04:06 -04:00
dfinke
2b30537c20 update change log 2022-06-17 11:56:47 -04:00
dfinke
22f50d2659 fix spelling 2022-06-17 11:50:02 -04:00
dfinke
f0a2d076e3 Update Import-Html with better defaults 2022-06-17 11:38:19 -04:00
dfinke
835a11bbb3 Update HTML example 2022-06-17 11:37:54 -04:00
James O'Neill
701b8e2062 Fix Get-HTMLTable for .NET core 2022-06-17 09:42:36 +01:00
James O'Neill
6f2bfaff4e Merge branch 'dfinke:master' into master 2022-06-16 14:19:30 +01:00
Doug Finke
ba6cee12d9 Merge pull request #1198 from dfinke/Set-up-GHA-CI/CD
Set up gha ci/cd
2022-06-12 15:28:04 -04:00
Doug Finke
5d36945708 remove fail tests 2022-06-12 15:18:56 -04:00
Doug Finke
6cbf4efd1d try mac 2022-06-12 15:14:27 -04:00
Doug Finke
4feaee46d2 fail tests on windows 2022-06-12 15:11:36 -04:00
Doug Finke
89f90b77fb try failing tests 2022-06-12 15:06:53 -04:00
Doug Finke
98256c61e8 include test for Invoke-ExcelQuery 2022-06-12 14:48:37 -04:00
Doug Finke
ebde9269aa just windows 2022-06-12 14:44:17 -04:00
Doug Finke
e3149b7b40 install ace 2022-06-12 14:42:41 -04:00
Doug Finke
64ff97b486 fix yml 2022-06-12 14:30:16 -04:00
Doug Finke
12f1f23d51 chk platform 2022-06-12 14:19:49 -04:00
Doug Finke
e279cd785e sudo 2022-06-12 13:59:37 -04:00
Doug Finke
04b5a9a096 install dependencies for autosize 2022-06-12 13:57:27 -04:00
Doug Finke
c6a06cc325 see what fails 2022-06-12 13:55:10 -04:00
Doug Finke
a4bed31e1e list pester version 2022-06-12 13:52:12 -04:00
dfinke
c385ca9012 add branches 2022-06-12 13:46:54 -04:00
Doug Finke
2a8cbbba7c Merge pull request #1197 from dfinke/fix-1194-EndRow-and-EndColumn-Parameters-Ignored
Fix 1194 end row and end column parameters ignored
2022-06-12 11:43:33 -04:00
dfinke
b789db9ba3 bump version 2022-06-12 11:32:12 -04:00
dfinke
89a4cfde0d fix test 2022-06-12 10:49:05 -04:00
dfinke
ab56ae4409 Add additional tests 2022-06-12 10:42:16 -04:00
dfinke
ef35c4fca8 Fix for EndRow and EndColumn Parameters Ignored in Import-Excel #1194 2022-06-12 09:53:52 -04:00
James O'Neill
9fad33c7a6 Merge branch 'master' of https://github.com/dfinke/ImportExcel 2022-06-07 22:14:27 +01:00
dfinke
8bb3d50052 Add sample - How to convert abbreviate or shorten long numbers in Excel 2022-05-29 09:54:02 -04:00
dfinke
d5b807d3cb Don't publish images folder and more - Suggestion: Remove unnecessary files when publishing to the gallery #1187 2022-05-28 06:32:01 -04:00
Doug Finke
e2053e4998 fix casing 2022-05-07 17:19:15 -04:00
Doug Finke
8c6c7eeaf6 update 2022-05-07 17:15:24 -04:00
Doug Finke
31abd215dc Merge pull request #1181 from dfinke/update-read-me
Update read me
2022-05-07 09:50:06 -04:00
dfinke
cafaafd53d add link to original readme 2022-05-07 09:45:16 -04:00
dfinke
ee3c8e7680 use / 2022-05-07 09:40:18 -04:00
dfinke
0b207548e0 fix link 2022-05-07 09:39:52 -04:00
dfinke
6628b55ce5 update link 2022-05-07 09:38:28 -04:00
dfinke
f6bfabd96a remove encoding 2022-05-07 09:34:02 -04:00
dfinke
980631df8b update xlsx link 2022-05-07 09:33:08 -04:00
dfinke
4f9b83f0e6 update logo 2022-05-07 08:17:19 -04:00
dfinke
59cf89b451 Additional updates 2022-05-07 08:08:49 -04:00
dfinke
5777d907c4 added Azure pipeline badge 2022-05-06 13:11:56 -04:00
dfinke
d7c516d35e Merge branch 'update-read-me' of https://github.com/dfinke/ImportExcel into update-read-me 2022-05-06 13:01:21 -04:00
dfinke
27d69e7531 Update pointing to examples 2022-05-06 13:01:12 -04:00
Doug Finke
8ae92fba54 spelling 2022-05-05 21:19:24 -04:00
dfinke
aa0f0cf4e2 layout 2022-05-05 18:36:19 -04:00
dfinke
6e38d97498 fix header 2022-05-05 18:35:59 -04:00
dfinke
ef7c8331f5 add links for versions, donate etc 2022-05-05 18:34:56 -04:00
dfinke
267d15f99a Add videos and articles 2022-05-05 18:21:27 -04:00
dfinke
390aca0496 update 2022-05-05 16:58:15 -04:00
dfinke
4fa34ae257 Rename switch NotAsDictionary to Raw 2022-05-04 18:33:19 -04:00
dfinke
0b3b382c4e update 2022-05-04 18:32:27 -04:00
dfinke
415be5bca3 bump version 2022-05-04 18:32:19 -04:00
dfinke
79e5bdf8ba update 2022-05-03 17:54:21 -04:00
dfinke
b03d9b048a bump version 2022-05-03 17:54:16 -04:00
dfinke
aea90aa8d6 Fix reading multiple sheets in the xlsx where row/col count is diff 2022-05-03 17:53:58 -04:00
dfinke
d4ebc9e95d Use explicit parameter names 2022-04-30 13:17:20 -04:00
Doug Finke
6ece4483e2 Merge pull request #1171 from dfinke/add-helper-functions
Add helper functions `Enable-ExcelAutoFilter`,  `Enable-ExcelAutofit`, `Get-ExcelSheetDimensionAddress`
2022-04-30 08:35:08 -04:00
dfinke
ba14511254 update changelog 2022-04-30 08:21:24 -04:00
dfinke
964cf9e9c6 Merge branch 'master' of https://github.com/dfinke/ImportExcel into add-helper-functions 2022-04-30 08:21:18 -04:00
Doug Finke
8d56a351ff Merge pull request #1161 from dfinke/adding-to-import-excel
Update and improve Import-Excel for reading nultiple sheets
2022-04-30 08:04:39 -04:00
dfinke
b2119f08f5 add example for importing an xlsx and multiple sheets 2022-04-30 07:59:22 -04:00
dfinke
634aaacc55 update change log 2022-04-30 07:58:55 -04:00
dfinke
61b44f826d Merge branch 'master' of https://github.com/dfinke/ImportExcel into adding-to-import-excel 2022-04-30 07:25:58 -04:00
Doug Finke
9273261b34 Merge pull request #1173 from dfinke/fix-bug-#1172
Fix bug #1172
2022-04-30 07:10:57 -04:00
dfinke
e55dfdd10e Update changes 2022-04-30 07:05:10 -04:00
dfinke
59e40d62d0 bump version 2022-04-30 07:05:04 -04:00
dfinke
f478e8a134 Add Enable-ExcelAutoFilter and Enable-ExcelAutofit example 2022-04-29 22:11:24 -04:00
dfinke
b634bf9d93 Fix fir #1172 2022-04-29 20:39:51 -04:00
dfinke
a10ade898a Remove xl file after use in test 2022-04-29 20:39:15 -04:00
dfinke
eb10364722 Add helpers 2022-04-28 19:44:49 -04:00
dfinke
b0024cf2c4 bump version 2022-04-28 19:44:40 -04:00
dfinke
91b0e8b0ed update https://github.com/dfinke/ImportExcel/pull/1145 2022-04-19 09:26:20 -04:00
dfinke
b997e90e78 bump version 2022-04-19 09:23:36 -04:00
Doug Finke
4d8710d017 Merge pull request #1145 from jamesmmueller/master
Allow for escaping of single quote in data.
2022-04-19 09:12:20 -04:00
dfinke
7f36b44fa8 renamed to NotAsDictionary 2022-04-12 18:08:11 -04:00
dfinke
483f761016 Add switch to not return data as a dictionary 2022-04-12 18:03:34 -04:00
dfinke
d55f0e64d4 WIP - Add sheets and contents to a hashtable 2022-04-11 18:48:17 -04:00
dfinke
f83f654c4a Update how Import-Excel reads sheets, and remain backward compatible 2022-04-11 16:58:55 -04:00
dfinke
6a956dbd7e delete xlsx after tests run 2022-04-11 16:58:13 -04:00
Doug Finke
0929a442a5 Merge pull request #1149 from caosborn/CO_Examples-AddWorksheetVBA
Adding VBA examples for worksheets
2022-03-27 10:21:15 -04:00
Doug Finke
895a5c0cb2 Merge pull request #1150 from dfinke/isolate-build-issues
Fixes `Get-Service` fail on Windows 2022
2022-03-27 09:44:52 -04:00
dfinke
d7901af8f3 try always importing the clixml 2022-03-27 09:37:15 -04:00
dfinke
34f55a3659 suspect Get-Service 2022-03-25 19:32:53 -04:00
dfinke
606988bcf6 rigger build 2022-03-25 18:45:06 -04:00
Craig Osborn
441f2ada22 fix: Typo in filename 2022-03-25 08:43:48 +00:00
Craig Osborn
29ea7012d7 examples: Add VBA module and call in all worksheets 2022-03-25 08:36:02 +00:00
Craig Osborn
67ac63ddcf examples: Add VBA to single worksheet 2022-03-25 08:35:13 +00:00
James Mueller
c939c6ecb0 Merge pull request #1 from jamesmmueller/jamesmmueller-patch-1
ConvertFrom-ExcelToSQLInsert fix single quotes
2022-03-17 10:55:37 -05:00
James Mueller
96493e059b ConvertFrom-ExcelToSQLInsert fix single quotes
If data in the Excel file contains single quotes, then the insert will bomb as it will be malformed. Quotes would need escaped. Not all languages will support the same escape method, so I recommend it being set by an optional parameter.

Example of what will fail:
  Name
  -----------
  Fry's

INSERT INTO [Name] Values ( 'Fry's' ) 

Corrected for quotes (such as needing to escape a single quote with an additional single quote)

INSERT INTO [Name] Values ('Fry''s') 


Example code:
$ConvertToSqlParams = @{TableName = ‘dbo.Names’
Path = ‘C:\temp\data.xlsx’
ConvertEmptyStringsToNull = $true
UseMSSQLSyntax = $true
SingleQuoteStyle = "''"
}

$SQLInsert = ConvertFrom-ExcelToSqlInsert @ConvertToSqlParams
2022-03-11 16:09:38 -06:00
Doug Finke
cb7f2a06f4 Remove vscode badge 2022-03-06 14:52:37 -05:00
Doug Finke
99beda7a10 Move to mixed case folders 2022-03-06 14:51:30 -05:00
dfinke
0c8bb2300a update links 2022-02-04 17:31:39 -05:00
dfinke
c09083d350 updated 2022-02-04 17:30:40 -05:00
dfinke
556f0ac51e Updated changelog 2022-02-04 17:28:30 -05:00
Doug Finke
1e4fc59a25 Merge pull request #1133 from joshooaj/master
Add Add-ExcelImage example
2022-02-04 15:48:05 -05:00
dfinke
5ab6a9116d @joshooaj added throw if not on Windows, pls review 2022-02-03 18:43:15 -05:00
Josh Hendricks
f33215382a docs: rename to AddImage for consistency 2022-02-02 08:31:35 -08:00
Josh Hendricks
cf5d3f83d6 docs: Update readme 2022-02-02 08:16:22 -08:00
Josh Hendricks
91da711635 docs: add Add-ExcelImage example 2022-02-01 21:37:55 -08:00
Doug Finke
eec5e343d4 Merge pull request #1118 from dfinke/add-freeze-pane-example
Add FreezePane Example
2021-12-30 14:46:52 -05:00
dfinke
d69b640edc Add FreezePane Example 2021-12-30 14:39:33 -05:00
Doug Finke
2ca870a889 Merge pull request #1112 from dfinke/refactor-rezip 2021-11-30 18:44:24 -05:00
Doug Finke
a320cfd28c Merge pull request #1110 from DavisHenckel/FAQ_Docs 2021-11-30 18:32:59 -05:00
dfinke
aa1b042767 Add -ReZip to Close-ExcelPackage like in Export-Excel #1111 2021-11-30 15:50:11 -05:00
dfinke
7e8416d67c Bump version and update change log 2021-11-30 15:49:07 -05:00
Davis Henckel
229b60b25d Remove Unnecessary Import & Add Header
Removed unnecessary import-module statement. Added a header to match the styling of other documents.
2021-11-28 20:03:07 -08:00
Davis Henckel
5700989321 Explain functionality of Open/Close-ExcelPackage 2021-11-28 11:36:37 -08:00
Davis Henckel
56e1704e7e Added missing " || improved readability. 2021-11-28 11:25:21 -08:00
Davis Henckel
8268bbc2e1 Merge pull request #1 from DavisHenckel/FAQ_Docs_2
Faq docs 2
2021-11-26 14:56:17 -08:00
Davis Henckel
5657659331 Add additional dbg info, Doc complete.
Changed variable name in example code, added additional info to Data structure explanation. Final proofread for punctuation and style. Document complete.
2021-11-26 14:53:21 -08:00
Davis Henckel
0d4a32e266 Change phrasing to show better MD style
Added additional headings to read more easily.
2021-11-26 14:42:44 -08:00
Davis Henckel
1c8f8d2a3d Update image to include row/col data num 2021-11-26 14:41:37 -08:00
Davis Henckel
f6a65677df Merge branch 'FAQ_Docs_2' of https://github.com/DavisHenckel/ImportExcel into FAQ_Docs_2 2021-11-26 14:34:23 -08:00
Davis Henckel
86a7865fb2 Add multiple images. 2021-11-26 14:34:17 -08:00
Davis Henckel
8b3bf4f14f Added Debug image showing var contents 2021-11-26 14:33:48 -08:00
Davis Henckel
4d6193f549 Complete Majority of Write to ExistingExcelFile md 2021-11-26 14:28:04 -08:00
Davis Henckel
6ebac7b6dc Add newlines 2021-11-26 12:18:05 -08:00
Davis Henckel
d71dd36d56 First version of file, with Image. 2021-11-26 12:17:39 -08:00
Davis Henckel
3697cdfeee Merge branch 'FAQ_Docs_2' of https://github.com/DavisHenckel/ImportExcel into FAQ_Docs_2 2021-11-26 12:17:06 -08:00
Davis Henckel
1e172cf21f Add Excel Pkg Data Img 2021-11-26 12:16:41 -08:00
Davis Henckel
6da7553c98 Merge branch 'FAQ_Docs' of https://github.com/DavisHenckel/ImportExcel into FAQ_Docs_2 2021-11-26 10:55:43 -08:00
Davis Henckel
5a444c620b Punctuation change 2021-11-26 10:25:30 -08:00
Davis Henckel
4a09fc3570 Punctuation change 2021-11-26 10:25:14 -08:00
Davis Henckel
d706a10276 Complete Document
Demonstrates how to create a blank excel file.
2021-11-26 10:23:09 -08:00
Davis Henckel
1fd2f422cd Create 2 more MD files to create 2021-11-26 10:15:01 -08:00
Davis Henckel
283e50547d Styling Consistency & Punctuation 2021-11-26 09:11:56 -08:00
Davis Henckel
15211a6297 Update Wording.
Punctuation and wording changes.
2021-11-26 09:08:31 -08:00
Davis Henckel
8905b8d401 Fix small typo
Comment in first image should have read "#Loads the Excel file into a PSCustomObject"
2021-11-26 08:58:44 -08:00
Davis Henckel
e9b437af4e Complete first version of ExistingExcelFile FAQ
Added loading a row/col, then mapping to HashTable
2021-11-26 06:56:08 -08:00
Davis Henckel
330e237727 Update Image Paths so they are Relative 2021-11-26 06:31:53 -08:00
Davis Henckel
c56b2cd33a Add first 2 images
Images display debugger and contents of excel file.
2021-11-21 16:56:52 -08:00
Davis Henckel
1aa5c6da45 add initial 2 images for first md FAQ doc 2021-11-21 16:51:14 -08:00
Davis Henckel
9eb894cf59 create directory, add initial md file w/first doc 2021-11-21 16:50:34 -08:00
dfinke
3a4c2d7bd9 bump version 2021-11-20 16:18:12 -05:00
dfinke
42cb5a316a update changelog 2021-11-20 16:18:05 -05:00
dfinke
536cdaa841 tweaked spelling 2021-11-20 15:53:23 -05:00
Doug Finke
6cd9fad7ba Merge pull request #1106 from royashbrook/CI-Updates
Add ACE into testing pipeline
2021-11-20 15:44:13 -05:00
Doug Finke
829d854c3d Merge pull request #1102 from muschebubusche/AddSelectiveColumnImport
Add selective column import
2021-11-20 15:36:05 -05:00
muschebubusche
b33a282740 Add new pester test 2021-11-20 16:51:49 +01:00
muschebubusche
73fc96166c Refactor selective column import
Move code into the function Get-PropertyNames and remove the rest.
Now it only replaces $Columns with $ImportColumns after a couple of checks. So the heavy work like arranging and getting the right values is done in the original way of Import-Excel.
2021-11-20 16:51:40 +01:00
Roy Ashbrook
00f7278115 add back *nix tests 2021-11-16 16:28:03 -05:00
Roy Ashbrook
956cf5aa49 fix 2021-11-16 16:23:54 -05:00
Roy Ashbrook
877310e015 add back pscore 2021-11-16 16:20:59 -05:00
Roy Ashbrook
08bf877535 add back in normal win testing 2021-11-16 16:11:32 -05:00
Roy Ashbrook
88e28a1d6c change path 2021-11-16 16:05:33 -05:00
Roy Ashbrook
eb63fe259a testing caching 2021-11-16 16:02:19 -05:00
Roy Ashbrook
6d97efc5c2 fun with curl... maybe 2021-11-16 15:43:57 -05:00
Roy Ashbrook
c567526eac testing caching 2021-11-16 15:34:36 -05:00
Roy Ashbrook
ed210cc730 testing 2021-11-16 15:29:32 -05:00
Roy Ashbrook
72f44ebcb9 trying a folder 2021-11-16 15:18:37 -05:00
Roy Ashbrook
f1d20ed163 test pipeline cache 2021-11-16 15:13:52 -05:00
Roy Ashbrook
02cf6bb3f3 test ace 2021-11-16 09:03:53 -05:00
dfinke
5cd3897dfa fix png 2021-11-12 19:26:57 -05:00
dfinke
fe4f2848ad bump version 2021-11-12 19:23:36 -05:00
dfinke
4e89b3321a update change log 2021-11-12 19:23:31 -05:00
Doug Finke
43b6ebf84f Merge pull request #1101 from royashbrook/Read-OleDbData
Add ability to query with Oledb
2021-11-12 18:59:41 -05:00
dfinke
1ee9493bc0 Minor tweak. Display query executed 2021-11-12 17:25:45 -05:00
muschebubusche
8f0fc7397d Add example and automatic column arrangement
Add example and automatic column arrangement
2021-11-09 22:40:40 +01:00
Roy Ashbrook
4fa6fbda01 update warning msg for Read-OleDbData 2021-11-09 09:05:15 -05:00
Roy Ashbrook
7177623104 add silent continue to cmd check tests 2021-11-08 18:21:11 -05:00
Roy Ashbrook
487cf51abc fix test skip label name 2021-11-08 18:19:23 -05:00
Roy Ashbrook
ae31e9d39b update skip/help msgs in invoke cmd 2021-11-08 18:08:45 -05:00
Roy Ashbrook
9ba20b8ec8 add back invoke tests, sync skip methods 2021-11-08 17:57:44 -05:00
Roy Ashbrook
9daefc2925 fix typo in skip logic 2021-11-08 17:45:33 -05:00
Roy Ashbrook
f0b4cb28f6 update tests to skip other pre-checks if linux/mac 2021-11-08 17:44:03 -05:00
Roy Ashbrook
5f00f5cbbc update tests 2021-11-08 17:40:33 -05:00
Roy Ashbrook
d41fbf8a05 updating tests 2021-11-08 17:13:40 -05:00
Roy Ashbrook
ebe49f1650 fix or/and 2021-11-08 16:56:23 -05:00
Roy Ashbrook
a3dced10e4 update tests 2021-11-08 16:37:00 -05:00
Roy Ashbrook
1e522c562b test skips for linux/macos, switch to warnings 2021-11-08 16:00:06 -05:00
Roy Ashbrook
5ec299ff2d some debugging messages for troubleshooting CI 2021-11-08 15:43:36 -05:00
Roy Ashbrook
676ecc17e0 update tests to match 2021-11-08 15:25:26 -05:00
Roy Ashbrook
aa1b0018ab Add examples 2021-11-08 15:14:46 -05:00
Roy Ashbrook
eabaab79c5 add ace check 2021-11-08 14:43:57 -05:00
Roy Ashbrook
7a8bbb9771 add to exported functions, formatting, fix typo. 2021-11-04 20:54:51 -04:00
Roy Ashbrook
85f2433ffc Rename helper function to make it more helpful. =) 2021-11-04 10:44:14 -04:00
muschebubusche
62c8d74a59 Add selective column import 2021-11-03 23:15:18 +01:00
Roy Ashbrook
5e7b404daf Add helper method 2021-11-03 10:35:22 -04:00
Roy Ashbrook
91a1240408 add skip test check for ace 2021-10-30 11:20:27 -04:00
Roy Ashbrook
e8c3d96f43 Tests relocated and updated. All passing. 2021-10-29 21:58:05 -04:00
Roy Ashbrook
9417b25af1 move tests into test folder 2021-10-29 16:58:16 -04:00
Roy Ashbrook
a942f2133d Add basic function, tests, and sample file 2021-10-29 13:21:52 -04:00
Doug Finke
533ed07ac8 Remove lowercase public
used for GitBook, no longer needed. #1082
2021-09-17 08:07:56 -04:00
Doug Finke
09f35b5fd5 Merge pull request #1078 from dfinke/Add-Checks-And-Warnings-for-Add-Member-Open-Excel-Package
Add-Checks-And-Warnings-for-Add-Member-Open-Excel-Package
2021-09-14 18:15:47 -04:00
dfinke
23a2ac394f Add try/catch, warning, and tests 2021-09-14 15:44:32 -04:00
dfinke
50928e8e3b Update 2021-09-14 15:44:11 -04:00
dfinke
26827b0764 bump version 2021-09-14 15:44:03 -04:00
Doug Finke
6c35d5b018 Updated 2021-09-10 18:41:03 -04:00
Doug Finke
ab5600c9ba bump version 2021-09-10 18:40:57 -04:00
Doug Finke
47dcc636d9 Merge pull request #1077 from stahler/Open-ExcelPackage
Update open-excelpackage.md
2021-09-10 18:39:00 -04:00
Stahler
1768c0ac92 Update open-excelpackage.md 2021-09-10 14:17:44 -04:00
jhoneill
f348088b62 Improved Import By Columns example 2021-08-13 12:13:42 +01:00
Doug Finke
694fcdd8c1 Merge pull request #1059 from dfinke/add-test-for-ps-5-to-7-and-linux
Improved checks for Linux, Mac and PS 5.1 - #1056, #1057
2021-07-30 19:27:06 -04:00
dfinke
0192f4d822 Improved checks for Linux, Mac and PS 5.1 - #1056, #1057 2021-07-30 19:21:37 -04:00
dfinke
c641eea10a Improve auto-detection of data on the clipboard 2021-07-24 19:41:57 -04:00
dfinke
99de9a9854 Pass parameters from Read-Clipboard to implementation 2021-07-24 13:48:18 -04:00
Doug Finke
3121c5eaed Merge pull request #1054 from dfinke/Add-new-function-Read-Clipboard
Added Read-Clipboard
2021-07-24 13:37:32 -04:00
dfinke
d02f757568 add change log 2021-07-24 13:26:06 -04:00
dfinke
a693725949 Add Tests 2021-07-24 13:01:51 -04:00
dfinke
5e19d0ca1a Add ReadClipboardImpl function 2021-07-24 13:01:48 -04:00
dfinke
204b82144f Refactor for testing 2021-07-24 13:01:32 -04:00
dfinke
91eefbd48b Added Read-Clipboard 2021-07-24 11:20:04 -04:00
dfinke
f86556a89d Updated, added Open in VS Code badge 2021-07-10 08:46:36 -04:00
dfinke
14e1dfd8db Bump version. Use ProviderPath 2021-06-20 12:11:14 -04:00
Doug Finke
1d961c679e Merge pull request #1031 from sporkabob/master
Fix UNC paths for ConvertFrom-ExcelSheet
2021-05-13 15:54:39 -04:00
sporkabob
7026803415 Fix UNC paths for ConvertFrom-ExcelSheet 2021-05-13 15:22:15 -04:00
180 changed files with 8719 additions and 8506 deletions

27
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
on:
push:
branches:
- master
- Set-up-GHA-CI/CD
pull_request:
jobs:
validate:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [windows-latest, ubuntu-latest, macos-latest]
steps:
- uses: actions/checkout@v1
- name: Run Continuous Integration
shell: pwsh
run : |
if($PSVersionTable.Platform -eq 'Win32NT') {
$null = mkdir ./ace
Invoke-Restmethod https://download.microsoft.com/download/3/5/C/35C84C36-661A-44E6-9324-8786B8DBE231/accessdatabaseengine_X64.exe -OutFile ./ace/ace.exe
Start-Process ./ace/ace.exe -Wait -ArgumentList "/quiet /passive /norestart"
}
cd ./__tests__
Invoke-Pester -Output Detailed

56
.vscode/launch.json vendored
View File

@@ -1,56 +0,0 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "PowerShell",
"request": "launch",
"name": "PowerShell Pester Tests",
"script": "Import-Module -Name '.\\' -Force ; Invoke-Pester", // Change to '.\\ModuleName.psd1' if Git name different
"args": [""],
"cwd": "${workspaceFolder}"
},
{
"type": "PowerShell",
"request": "launch",
"name": "PowerShell Launch Current File",
"script": "${file}",
"args": [],
"cwd": "${file}"
},
{
"type": "PowerShell",
"request": "launch",
"name": "PowerShell Launch Current File in Temporary Console",
"script": "${file}",
"args": [],
"cwd": "${file}",
"createTemporaryIntegratedConsole": true
},
{
"type": "PowerShell",
"request": "launch",
"name": "PowerShell Launch Current File w/Args Prompt",
"script": "${file}",
"args": [
"${command:SpecifyScriptArgs}"
],
"cwd": "${file}"
},
{
"type": "PowerShell",
"request": "attach",
"name": "PowerShell Attach to Host Process",
"processId": "${command:PickPSHostProcess}",
"runspaceId": 1
},
{
"type": "PowerShell",
"request": "launch",
"name": "PowerShell Interactive Session",
"cwd": ""
}
]
}

133
Add-Subtotals.ps1 Normal file
View File

@@ -0,0 +1,133 @@
Function Add-Subtotals {
param(
[Parameter(Mandatory=$true, Position=0)]
$ChangeColumnName , # = "Location"
[Parameter(Mandatory=$true, Position=1)]
[hashtable]$AggregateColumn , #= @{"Sales" = "SUM" }
[Parameter(Position=2)]
$ExcelPath = ([System.IO.Path]::GetTempFileName() -replace "\.tmp", ".xlsx") ,
[Parameter(Position=3)]
$WorksheetName = "Sheet1",
[Parameter(ValueFromPipeline=$true)]
$InputObject, #$DataToPivot | Sort location, product
[switch]$HideSingleRows,
[switch]$NoSort,
[switch]$NoOutLine,
[switch]$Show
)
begin {
if (-not $PSBoundParameters.ContainsKey('ExcelPath')) {$Show = $true}
$data = @()
$aggFunctions = [ordered]@{
"AVERAGE" = 1; "COUNT" = 2; "COUNTA" = 3 #(non empty cells) f
"MAX" = 4; "MIN" = 5; "PRODUCT" = 6; "STDEV" = 7 # (sample)
"STDEVP" = 8 # (whole population);
"SUM" = 9; "VAR" = 10 # (Variance sample)
"VARP" = 11 # (whole population) #add 100 to ignore hidden cells
}
}
process {
$data += $InputObject
}
end {
if (-not $NoSort) {$data = $data | Sort-Object $changeColumnName}
$Header = $data[0].PSObject.Properties.Name
#region turn each entry in $AggregateColumn "=SUBTOTAL(a,x{0}}:x{1})" where a is the aggregate function number and x is the column letter
$aggFormulas = @{}
foreach ($k in $AggregateColumn.Keys) {
$columnNo = 0 ;
while ($columnNo -lt $header.count -and $header[$columnNo] -ne $k) {$columnNo ++}
if ($columnNo -eq $header.count) {
throw "'$k' isn't a property of the first row of data."; return
}
if ($AggregateColumn[$k] -is [string]) {
$aggfn = $aggFunctions[$AggregateColumn[$k]]
if (-not $aggfn) {
throw "$($AggregateColumn[$k]) is not a valid aggregation function - these are $($aggFunctions.keys -join ', ')" ; return
}
}
else {$aggfn = $AggregateColumn[$k]}
$aggFormulas[$k] = "=SUBTOTAL({0},{1}{{0}}:{1}{{1}})" -f $aggfn , (Get-ExcelColumnName ($columnNo+1) ).ColumnName
}
if ($aggformulas.count -lt 1) {throw "We didn't get any aggregation formulas"}
$aggFormulas | out-string -Stream | Write-Verbose -Verbose
#endregion
$insertedRows = @()
$singleRows = @()
$previousValue = $data[0].$changeColumnName
$currentRow = $lastChangeRow = 2
#region insert subtotals and send to excel:
#each time there is a change in the column we're intetersted in.
#either Add a row with the value and subtotal(s) function(s) if there is more than one row to total
#or note the row if there was only one row with that value (we may hide it later.)
$excel = $data |
ForEach-Object -process {
if ($_.$changeColumnName -ne $previousValue) {
if ($lastChangeRow -lt ($currentrow - 1)) {
$NewObj = @{$changeColumnName = $previousValue}
foreach ($k in $aggFormulas.Keys) {
$newobj[$k] = $aggformulas[$k] -f $lastChangeRow, ($currentRow - 1)
}
$insertedRows += $currentRow
[pscustomobject]$newobj
$currentRow += 1
}
else {$singleRows += $currentRow }
$lastChangeRow = $currentRow
$previousValue = $_.$changeColumnName
}
$_
$currentRow += 1
} -end { # the process block won't output the last row
if ($lastChangeRow -lt ($currentrow - 1)) {
$NewObj = @{$changeColumnName = $previousValue}
foreach ($k in $aggFormulas.Keys) {
$newobj[$k] = $aggformulas[$k] -f $lastChangeRow, ($currentRow - 1)
}
$insertedRows += $currentRow
[pscustomobject]$newobj
}
else {$singleRows += $currentRow }
} | Export-Excel -Path $ExcelPath -PassThru -AutoSize -AutoFilter -AutoNameRange -BoldTopRow -WorksheetName $WorksheetName -Activate -ClearSheet #-MaxAutoSizeRows 10000
#endregion
#Put the subtotal rows in bold optionally hide rows where only one has the value of interest.
$ws = $excel.$WorksheetName
#We kept lists of the total rows Since 1 rows won't get expand/collapse we can hide them.
foreach ($r in $insertedrows) {$ws.Row($r).style.font.bold = $true }
if ($HideSingleRows) {
foreach ($r in $hideRows) { $ws.Row($r).hidden = $true}
}
$range = $ws.Dimension.Address
$ExcelPath = $excel.File.FullName
$SheetIndex = $ws.index
if ($NoOutline) {
Close-ExcelPackage $excel -show:$Show
return
}
else {
Close-ExcelPackage $excel
try { $excelApp = New-Object -ComObject "Excel.Application" }
catch { Write-Warning "Could not start Excel application - which usually means it is not installed." ; return }
try { $excelWorkBook = $excelApp.Workbooks.Open($ExcelPath) }
catch { Write-Warning -Message "Could not Open $ExcelPath." ; return }
$ws = $excelWorkBook.Worksheets.item($SheetIndex)
$null = $ws.Range($range).Select()
$null = $excelapp.ActiveCell.AutoOutline()
$null = $ws.Outline.ShowLevels(1,$null)
$excelWorkBook.Save()
if ($show) {$excelApp.Visible = $true}
else {
[void]$excelWorkBook.close()
$excelapp.Quit()
}
}
}
}

View File

@@ -0,0 +1,119 @@
function Add-ExcelImage {
<#
.SYNOPSIS
Adds an image to a worksheet in an Excel package.
.DESCRIPTION
Adds an image to a worksheet in an Excel package using the
`WorkSheet.Drawings.AddPicture(name, image)` method, and places the
image at the location specified by the Row and Column parameters.
Additional position adjustment can be made by providing RowOffset and
ColumnOffset values in pixels.
.EXAMPLE
$image = [System.Drawing.Image]::FromFile($octocat)
$xlpkg = $data | Export-Excel -Path $path -PassThru
$xlpkg.Sheet1 | Add-ExcelImage -Image $image -Row 4 -Column 6 -ResizeCell
Where $octocat is a path to an image file, and $data is a collection of
data to be exported, and $path is the output path for the Excel document,
Add-Excel places the image at row 4 and column 6, resizing the column
and row as needed to fit the image.
.INPUTS
[OfficeOpenXml.ExcelWorksheet]
.OUTPUTS
None
#>
[CmdletBinding()]
param(
# Specifies the worksheet to add the image to.
[Parameter(Mandatory, ValueFromPipeline)]
[OfficeOpenXml.ExcelWorksheet]
$WorkSheet,
# Specifies the Image to be added to the worksheet.
[Parameter(Mandatory)]
[System.Drawing.Image]
$Image,
# Specifies the row where the image will be placed. Rows are counted from 1.
[Parameter(Mandatory)]
[ValidateRange(1, [int]::MaxValue)]
[int]
$Row,
# Specifies the column where the image will be placed. Columns are counted from 1.
[Parameter(Mandatory)]
[ValidateRange(1, [int]::MaxValue)]
[int]
$Column,
# Specifies the name to associate with the image. Names must be unique per sheet.
# Omit the name and a GUID will be used instead.
[Parameter()]
[string]
$Name,
# Specifies the number of pixels to offset the image on the Y-axis. A
# positive number moves the image down by the specified number of pixels
# from the top border of the cell.
[Parameter()]
[int]
$RowOffset = 1,
# Specifies the number of pixels to offset the image on the X-axis. A
# positive number moves the image to the right by the specified number
# of pixels from the left border of the cell.
[Parameter()]
[int]
$ColumnOffset = 1,
# Increase the column width and row height to fit the image if the current
# dimensions are smaller than the image provided.
[Parameter()]
[switch]
$ResizeCell
)
begin {
if ($IsWindows -eq $false) {
throw "This only works on Windows and won't run on $([environment]::OSVersion)"
}
<#
These ratios work on my machine but it feels fragile. Need to better
understand how row and column sizing works in Excel and what the
width and height units represent.
#>
$widthFactor = 1 / 7
$heightFactor = 3 / 4
}
process {
if ([string]::IsNullOrWhiteSpace($Name)) {
$Name = (New-Guid).ToString()
}
if ($null -ne $WorkSheet.Drawings[$Name]) {
Write-Error "A picture with the name `"$Name`" already exists in worksheet $($WorkSheet.Name)."
return
}
<#
The row and column offsets of 1 ensures that the image lands just
inside the gray cell borders at the top left.
#>
$picture = $WorkSheet.Drawings.AddPicture($Name, $Image)
$picture.SetPosition($Row - 1, $RowOffset, $Column - 1, $ColumnOffset)
if ($ResizeCell) {
<#
Adding 1 to the image height and width ensures that when the
row and column are resized, the bottom right of the image lands
just inside the gray cell borders at the bottom right.
#>
$width = $widthFactor * ($Image.Width + 1)
$height = $heightFactor * ($Image.Height + 1)
$WorkSheet.Column($Column).Width = [Math]::Max($width, $WorkSheet.Column($Column).Width)
$WorkSheet.Row($Row).Height = [Math]::Max($height, $WorkSheet.Row($Row).Height)
}
}
}

View File

@@ -0,0 +1,39 @@
if ($IsWindows -eq $false) {
throw "This only works on Windows and won't run on $([environment]::OSVersion)"
}
Add-Type -AssemblyName System.Drawing
. $PSScriptRoot\Add-ExcelImage.ps1
$data = ConvertFrom-Csv @"
Region,State,Units,Price
West,Texas,927,923.71
North,Tennessee,466,770.67
East,Florida,520,458.68
East,Maine,828,661.24
West,Virginia,465,053.58
North,Missouri,436,235.67
South,Kansas,214,992.47
North,North Dakota,789,640.72
South,Delaware,712,508.55
"@
$path = "$PSScriptRoot/Add-Picture-test.xlsx"
Remove-Item $path -ErrorAction SilentlyContinue
try {
$octocat = "$PSScriptRoot/Octocat.jpg"
$image = [System.Drawing.Image]::FromFile($octocat)
$xlpkg = $data | Export-Excel -Path $path -PassThru
$xlpkg.Sheet1 | Add-ExcelImage -Image $image -Row 4 -Column 6 -ResizeCell
}
finally {
if ($image) {
$image.Dispose()
}
if ($xlpkg) {
Close-ExcelPackage -ExcelPackage $xlpkg -Show
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

View File

@@ -0,0 +1,33 @@
# Add-ExcelImage Example
Adding pictures to an Excel worksheet is possible by calling the `AddPicture(name, image)`
method on the `Drawings` property of an `ExcelWorksheet` object.
The `Add-ExcelImage` example here demonstrates how to add a picture at a given
cell location, and optionally resize the row and column to fit the image.
## Running the example
To try this example, run the script `AddImage.ps1`. The `Add-ExcelImage`
function will be dot-sourced, and an Excel document will be created in the same
folder with a sample data set. The Octocat image will then be embedded into
Sheet1.
The creation of the Excel document and the `System.Drawing.Image` object
representing Octocat are properly disposed within a `finally` block to ensure
that the resources are released, even if an error occurs in the `try` block.
## Note about column and row sizing
Care has been taken in this example to get the image placement to be just inside
the cell border, and if the `-ResizeCell` switch is present, the height and width
of the row and column will be increased, if needed, so that the bottom right of
the image also lands just inside the cell border.
The Excel row and column sizes are measured in "point" units rather than pixels,
and a fixed multiplication factor is used to convert the size of the image in
pixels, to the corresponding height and width values in Excel.
It's possible that different DPI or text scaling options could result in
imperfect column and row sizing and if a better strategy is found for converting
the image dimensions to column and row sizes, this example will be updated.

View File

@@ -0,0 +1,22 @@
try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return }
$data = ConvertFrom-Csv @"
Region,State,Other,Units,Price,InStock
West,Texas,1,927,923.71,1
North,Tennessee,3,466,770.67,0
East,Florida,0,1520,458.68,1
East,Maine,1,1828,661.24,0
West,Virginia,1,465,053.58,1
North,Missouri,1,436,235.67,1
South,Kansas,0,214,992.47,1
North,North Dakota,1,789,640.72,0
South,Delaware,-1,712,508.55,1
"@
$xlfile = "$PSScriptRoot\test.xlsx"
Remove-Item $xlfile -ErrorAction SilentlyContinue
$cfi1 = New-ConditionalFormattingIconSet -Range C:C -ConditionalFormat ThreeIconSet -IconType Symbols -ShowIconOnly
$cfi2 = New-ConditionalFormattingIconSet -Range F:F -ConditionalFormat ThreeIconSet -IconType Symbols2 -ShowIconOnly
$data | Export-Excel $xlfile -AutoSize -ConditionalFormat $cfi1, $cfi2 -Show

View File

@@ -0,0 +1,21 @@
try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return}
# This example is using Excel generated by Highlight-DiffCells.ps1
# The displayed rule should be the same as in the PS script
function Get-ConditionalFormatting {
param (
[string] $xlSourcefile
)
$excel = Open-ExcelPackage -Path $xlSourcefile
$excel.Workbook.Worksheets | ForEach-Object {
$wsNme = $_.Name
$_.ConditionalFormatting | ForEach-Object {
"Add-ConditionalFormatting -Worksheet `$excel[""$wsNme""] -Range '$($_.Address)' -ConditionValue '=$($_.Formula)' -RuleType $($_.Type) "
}
}
}
$xlSourcefile = "$PSScriptRoot\GetConditionalFormatting.xlsx"
Get-ConditionalFormatting -xlSourcefile $xlSourcefile

View File

@@ -0,0 +1,26 @@
try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return }
$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx"
Write-Verbose -Verbose -Message "Save location: $xlSourcefile"
Remove-Item $xlSourcefile -ErrorAction Ignore
$data = ConvertFrom-Csv @"
Region,State,Units2021,Units2022
West,Texas,927,925
North,Tennessee,466,466
East,Florida,520,458
East,Maine,828,661
West,Virginia,465,465
North,Missouri,436,235
South,Kansas,214,214
North,North Dakota,789,640
South,Delaware,712,508
"@
$excel = $data | Export-Excel $xlSourcefile -AutoSize -PassThru
Add-ConditionalFormatting -Worksheet $excel.sheet1 -Range "C2:D10" -ConditionValue '=$C2=$D2' -RuleType Expression -BackgroundColor ([System.Drawing.Color]::Thistle) -Bold
Add-ConditionalFormatting -Worksheet $excel.sheet1 -Range "A2:D10" -ConditionValue '=$C2=$D2' -RuleType Expression -BackgroundColor ([System.Drawing.Color]::LavenderBlush)
Close-ExcelPackage $excel -Show

View File

@@ -0,0 +1,23 @@
# How to convert abbreviate or shorten long numbers in Excel
Remove-Item .\custom.xlsx -ErrorAction SilentlyContinue
$data = $(
12000
1000
2000
3000
2400
3600
6000
13000
40000
400000
1000000
)
$excel = $data | Export-Excel .\custom.xlsx -PassThru
Set-ExcelRange -Worksheet $excel.Sheet1 -Range "A:A" -NumberFormat '[>999999]#,,"M";#,"K"'
Close-ExcelPackage $excel -Show

View File

@@ -6,15 +6,16 @@
#>
param(
[Parameter(Mandatory=$true)]
$moduleName,
$moduleName = "ImportExcel",
[ValidateSet('Column','Bar','Line','Pie')]
$chartType="Line"
)
$galleryUrl = "https://www.powershellgallery.com/packages/$moduleName"
$nolegend = '-nolegend'
if($chartType -eq 'pie') {$nolegend = $null}
$code = "$($chartType)Chart (Get-HtmlTable $galleryUrl 0 | sort lastupdated -desc) -title 'Download stats for $moduleName' $nolegend"
$download = Get-HtmlTable "https://www.powershellgallery.com/packages/$moduleName" -FirstDataRow 1 |
Select-Object @{n="Version";e={$v = $Null ; if ($_.version -is [valuetype]) {[string][version]($_.version.tostring("0.0")) }
elseif ($_.version -is [string] -and [version]::TryParse($_.version.trim(),[ref]$v)) {$v}
else {$_.Version.trim() -replace "\s+"," " } }},
Downloads, @{n="LastUpdated";e={[datetime]$_.last_updated}} |
Sort-Object lastupdated -Descending
$code | Invoke-Expression
& "$($chartType)Chart" $download "Download stats for $moduleName" -nolegend:($chartype -ne 'pie')

View File

@@ -0,0 +1,10 @@
param(
[Alias('FullName')]
[String[]]$Path
)
if ($PSVersionTable.PSVersion.Major -gt 5 -and -not (Get-Command Format-Markdown -ErrorAction SilentlyContinue)) {
throw "This requires EZOut. Install-Module EZOut -AllowClobber -Scope CurrentUser"
}
Import-Excel $Path | Format-Markdown

View File

@@ -0,0 +1,10 @@
param(
[Alias('FullName')]
[String[]]$Path
)
if ($PSVersionTable.PSVersion.Major -gt 5 -and -not (Get-Command Format-YAML -ErrorAction SilentlyContinue)) {
throw "This requires EZOut. Install-Module EZOut -AllowClobber -Scope CurrentUser"
}
Import-Excel $Path | Format-YAML

View File

@@ -0,0 +1,11 @@
"OrderId","Category","Sales","Quantity","Discount"
"1","Cosmetics","744.01","7","0.7"
"2","Grocery","349.13","25","0.3"
"3","Apparels","535.11","88","0.2"
"4","Electronics","524.69","60","0.1"
"5","Electronics","439.1","41","0"
"6","Apparels","56.84","54","0.8"
"7","Electronics","326.66","97","0.7"
"8","Cosmetics","17.25","74","0.6"
"9","Grocery","199.96","39","0.4"
"10","Grocery","731.77","20","0.3"
1 OrderId Category Sales Quantity Discount
2 1 Cosmetics 744.01 7 0.7
3 2 Grocery 349.13 25 0.3
4 3 Apparels 535.11 88 0.2
5 4 Electronics 524.69 60 0.1
6 5 Electronics 439.1 41 0
7 6 Apparels 56.84 54 0.8
8 7 Electronics 326.66 97 0.7
9 8 Cosmetics 17.25 74 0.6
10 9 Grocery 199.96 39 0.4
11 10 Grocery 731.77 20 0.3

Binary file not shown.

View File

@@ -0,0 +1,54 @@
# Freeze the columns/rows to left and above the cell
$data = ConvertFrom-Csv @"
Region,State,Units,Price,Name,NA,EU,JP,Other
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
West,Texas,927,923.71,Wii Sports,41.49,29.02,3.77,8.46
"@
$xlfilename = "test.xlsx"
Remove-Item $xlfilename -ErrorAction SilentlyContinue
<#
Freezes the top two rows and the two leftmost column
#>
$data | Export-Excel $xlfilename -Show -Title 'Sales Data' -FreezePane 3, 3

View File

@@ -0,0 +1,13 @@
try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return}
#Get rid of pre-exisiting sheet
$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx"
Write-Verbose -Verbose -Message "Save location: $xlSourcefile"
Remove-Item $xlSourcefile -ErrorAction Ignore
$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Points `
-PivotRows Driver -PivotColumns Date -PivotData @{Points = "SUM"} -GroupDateColumn Date -GroupDatePart Years, Months
Import-Csv "$PSScriptRoot\First10Races.csv" |
Select-Object Race, @{n = "Date"; e = {[datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture))}}, FinishPosition, Driver, GridPosition, Team, Points |
Export-Excel $xlSourcefile -Show -AutoSize -PivotTableDefinition $PivotTableDefinition

View File

@@ -0,0 +1,13 @@
try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return}
#Get rid of pre-exisiting sheet
$xlSourcefile = "$env:TEMP\ImportExcelExample.xlsx"
Write-Verbose -Verbose -Message "Save location: $xlSourcefile"
Remove-Item $xlSourcefile -ErrorAction Ignore
$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Places `
-PivotRows Driver -PivotColumns FinishPosition -PivotData @{Date = "Count"} -GroupNumericColumn FinishPosition -GroupNumericMin 1 -GroupNumericMax 25 -GroupNumericInterval 3
Import-Csv "$PSScriptRoot\First10Races.csv" |
Select-Object Race, @{n = "Date"; e = {[datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture))}}, FinishPosition, Driver, GridPosition, Team, Points |
Export-Excel $xlSourcefile -Show -AutoSize -PivotTableDefinition $PivotTableDefinition

View File

@@ -0,0 +1,7 @@
Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force
$xlfile = "$PSScriptRoot\yearlySales.xlsx"
$result = Import-Excel -Path $xlfile -WorksheetName * -Raw
$result | Measure-Object

View File

@@ -0,0 +1,9 @@
Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force
$xlfile = "$PSScriptRoot\yearlySales.xlsx"
$result = Import-Excel -Path $xlfile -WorksheetName *
foreach ($sheet in $result.Values) {
$sheet
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,146 @@
function Import-ByColumns {
<#
.synopsis
Works like Import-Excel but with data in columns instead of the conventional rows.
.Description.
Import-excel will read the sample file in this folder like this
> Import-excel FruitCity.xlsx | ft *
GroupAs Apple Orange Banana
------- ----- ------ ------
London 1 4 9
Paris 2 4 10
NewYork 6 5 11
Munich 7 8 12
Import-ByColumns transposes it
> Import-Bycolumns FruitCity.xlsx | ft *
GroupAs London Paris NewYork Munich
------- ------ ----- ------- ------
Apple 1 2 6 7
Orange 4 4 5 8
Banana 9 10 11 12
.Example
C:\> Import-Bycolumns -path .\VM_Build_Example.xlsx -StartRow 7 -EndRow 21 -EndColumn 7 -HeaderName Desc,size,type,
cpu,ram,NetAcc,OS,OSDiskSize,DataDiskSize,LogDiskSize,TempDbDiskSize,BackupDiskSize,ImageDiskDize,AzureBackup,AzureReplication | ft -a *
This reads a spreadsheet which has a block from row 7 to 21 containing 14 properties of virtual machines.
The properties names are in column A and the 6 VMS are in columns B-G
Because the property names are written for easy reading by the person completing the spreadsheet, they are replaced with new names.
All the parameters work as they would for Import-Excel
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")]
param(
[Alias('FullName')]
[Parameter(ParameterSetName = "PathA", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )]
[Parameter(ParameterSetName = "PathB", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )]
[Parameter(ParameterSetName = "PathC", Mandatory, ValueFromPipelineByPropertyName, ValueFromPipeline, Position = 0 )]
[String]$Path,
[Parameter(ParameterSetName = "PackageA", Mandatory)]
[Parameter(ParameterSetName = "PackageB", Mandatory)]
[Parameter(ParameterSetName = "PackageC", Mandatory)]
[OfficeOpenXml.ExcelPackage]$ExcelPackage,
[Alias('Sheet')]
[Parameter(Position = 1)]
[ValidateNotNullOrEmpty()]
[String]$WorksheetName,
[Parameter(ParameterSetName = 'PathB' , Mandatory)]
[Parameter(ParameterSetName = 'PackageB', Mandatory)]
[String[]]$HeaderName ,
[Parameter(ParameterSetName = 'PathC' , Mandatory)]
[Parameter(ParameterSetName = 'PackageC', Mandatory)]
[Switch]$NoHeader,
[Alias('TopRow')]
[ValidateRange(1, 9999)]
[Int]$StartRow = 1,
[Alias('StopRow', 'BottomRow')]
[Int]$EndRow ,
[Alias('LeftColumn','LabelColumn')]
[Int]$StartColumn = 1,
[Int]$EndColumn,
[switch]$DataOnly,
[switch]$AsHash,
[ValidateNotNullOrEmpty()]
[String]$Password
)
function Get-PropertyNames {
<#
.SYNOPSIS
Create objects containing the row number and the row name for each of the different header types.
#>
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = "Name would be incorrect, and command is not exported")]
param(
[Parameter(Mandatory)]
[Int[]]$Rows,
[Parameter(Mandatory)]
[Int]$StartColumn
)
if ($HeaderName) {
$i = 0
foreach ($h in $HeaderName) {
$h | Select-Object @{n='Row'; e={$rows[$i]}}, @{n='Value'; e={$h} }
$i++
}
}
elseif ($NoHeader) {
$i = 0
foreach ($r in $rows) {
$i++
$r | Select-Object @{n='Row'; e={$_}}, @{n='Value'; e={"P$i"} }
}
}
else {
foreach ($r in $Rows) {
#allow "False" or "0" to be headings
$Worksheet.Cells[$r, $StartColumn] | Where-Object {-not [string]::IsNullOrEmpty($_.Value) } | Select-Object @{n='Row'; e={$r} }, Value
}
}
}
#region open file if necessary, find worksheet and ensure we have start/end row/columns
if ($Path -and -not $ExcelPackage -and $Password) {
$ExcelPackage = Open-ExcelPackage -Path $Path -Password $Password
}
elseif ($Path -and -not $ExcelPackage ) {
$ExcelPackage = Open-ExcelPackage -Path $Path
}
if (-not $ExcelPackage) {
throw 'Could not get an Excel workbook to work on' ; return
}
if (-not $WorksheetName) { $Worksheet = $ExcelPackage.Workbook.Worksheets[1] }
elseif (-not ($Worksheet = $ExcelPackage.Workbook.Worksheets[$WorkSheetName])) {
throw "Worksheet '$WorksheetName' not found, the workbook only contains the worksheets '$($ExcelPackage.Workbook.Worksheets)'. If you only wish to select the first worksheet, please remove the '-WorksheetName' parameter." ; return
}
if (-not $EndRow ) { $EndRow = $Worksheet.Dimension.End.Row }
if (-not $EndColumn) { $EndColumn = $Worksheet.Dimension.End.Column }
#endregion
$Rows = $Startrow .. $EndRow ;
$Columns = (1 + $StartColumn)..$EndColumn
if ((-not $rows) -or (-not ($PropertyNames = Get-PropertyNames -Rows $Rows -StartColumn $StartColumn))) {
throw "No headers found in left coulmn '$Startcolumn'. "; return
}
if (-not $Columns) {
Write-Warning "Worksheet '$WorksheetName' in workbook contains no data in the rows after left column '$StartColumn'"
}
else {
foreach ($c in $Columns) {
$NewColumn = [Ordered]@{ }
foreach ($p in $PropertyNames) {
$NewColumn[$p.Value] = $Worksheet.Cells[$p.row,$c].text
}
if ($AsHash) {$NewColumn}
elseif (($NewColumn.Values -ne "") -or -not $dataonly) {[PSCustomObject]$NewColumn}
}
}
}

View File

@@ -0,0 +1,9 @@
try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return}
# Create example file
$xlFile = "$PSScriptRoot\ImportColumns.xlsx"
Get-Process | Export-Excel -Path $xlFile
# -ImportColumns will also arrange columns
Import-Excel -Path $xlFile -ImportColumns @(1,3,2) -NoHeader -StartRow 1
# Get only pm, npm, cpu, id, processname
Import-Excel -Path $xlFile -ImportColumns @(6,7,12,25,46) | Format-Table -AutoSize

View File

@@ -0,0 +1,14 @@
try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return }
$queries =
'select * from [sheet1$A:A]',
'select * from [sheet1$]',
'select * from [sheet1$A2:E11]',
'select F2,F5 from [sheet1$A2:E11]',
'select * from [sheet1$A2:E11] where F2 = "Grocery"',
'select F2 as [Category], F5 as [Discount], F5*2 as [DiscountPlus] from [sheet1$A2:E11]'
foreach ($query in $queries) {
"query: $($query)"
Invoke-ExcelQuery .\testOleDb.xlsx $query | Format-Table
}

Binary file not shown.

View File

@@ -0,0 +1,28 @@
# How to use Enable-ExcelAutoFilter and Enable-ExcelAutofit
try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return }
$data = ConvertFrom-Csv @"
RegionInfo,StateInfo,Units,Price
West,Texas,927,923.71
North,Tennessee,466,770.67
East,Florida,520,458.68
East,Maine,828,661.24
West,Virginia,465,053.58
North,Missouri,436,235.67
South,Kansas,214,992.47
North,North Dakota,789,640.72
South,Delaware,712,508.55
"@
$xlfile = "$PSScriptRoot\enableFeatures.xlsx"
Remove-Item $xlfile -ErrorAction SilentlyContinue
$data | Export-Excel $xlfile
$excel = Open-ExcelPackage $xlfile
Enable-ExcelAutoFilter -Worksheet $excel.Sheet1
Enable-ExcelAutofit -Worksheet $excel.Sheet1
Close-ExcelPackage $excel -Show

View File

@@ -0,0 +1,29 @@
try { Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 } catch { throw ; return }
$data = ConvertFrom-Csv @"
OrderId,Category,Sales,Quantity,Discount
1,Cosmetics,744.01,07,0.7
2,Grocery,349.13,25,0.3
3,Apparels,535.11,88,0.2
4,Electronics,524.69,60,0.1
5,Electronics,439.10,41,0.0
6,Apparels,56.84,54,0.8
7,Electronics,326.66,97,0.7
8,Cosmetics,17.25,74,0.6
9,Grocery,199.96,39,0.4
10,Grocery,731.77,20,0.3
"@
$xlfile = "$PSScriptRoot\TotalsRow.xlsx"
Remove-Item $xlfile -ErrorAction SilentlyContinue
$TableTotalSettings = @{
Quantity = 'Sum'
Category = '=COUNTIF([Category],"<>Electronics")' # Count the number of categories not equal to Electronics
Sales = @{
Function = '=SUMIF([Category],"<>Electronics",[Sales])'
Comment = "Sum of sales for everything that is NOT Electronics"
}
}
$data | Export-Excel -Path $xlfile -TableName Sales -TableStyle Medium10 -TableTotalSettings $TableTotalSettings -AutoSize -Show

View File

@@ -0,0 +1,16 @@
try {Import-Module $PSScriptRoot\..\..\ImportExcel.psd1} catch {throw ; return}
$r = Get-ChildItem C:\WINDOWS\system32 -File
$TotalSettings = @{
Name = "Count"
# You can create the formula in an Excel workbook first and copy-paste it here
# This syntax can only be used for the Custom type
Extension = "=COUNTIF([Extension];`".exe`")"
Length = @{
Function = "=SUMIF([Extension];`".exe`";[Length])"
Comment = "Sum of all exe sizes"
}
}
$r | Export-Excel -TableName system32files -TableStyle Medium10 -TableTotalSettings $TotalSettings -Show

View File

@@ -0,0 +1,64 @@
$xlfile = "$env:temp\test.xlsm"
Remove-Item $xlfile -ErrorAction SilentlyContinue
ConvertFrom-Csv @"
Region,Item,TotalSold
West,screwdriver,98
West,kiwi,19
North,kiwi,47
West,screws,48
West,avocado,52
East,avocado,40
South,drill,61
North,orange,92
South,drill,29
South,saw,36
"@ | Export-Excel $xlfile -TableName 'Sales' -WorksheetName 'Sales' -AutoSize
$Excel = ConvertFrom-Csv @"
Supplier,Item,TotalBought
Hardware,screwdriver,98
Groceries,kiwi,19
Hardware,screws,48
Groceries,avocado,52
Hardware,drill,61
Groceries,orange,92
Hardware,drill,29
HArdware,saw,36
"@ | Export-Excel $xlfile -TableName 'Purchases' -WorksheetName 'Purchases' -PassThru -AutoSize
$wb = $Excel.Workbook
$wb.CreateVBAProject()
# Create a module with a sub to highlight the selected row & column of the active table.
# https://docs.microsoft.com/en-gb/office/vba/excel/Concepts/Cells-and-Ranges/highlight-the-active-cell-row-or-column
$codeModule = @"
Public Sub HighlightSelection(ByVal Target As Range)
' Clear the color of all the cells
Cells.Interior.ColorIndex = 0
If Target.Cells.Count > 1 Then Exit Sub
Application.ScreenUpdating = False
With ActiveCell
' Highlight the row and column that contain the active cell, within the current region
Range(Cells(.Row, .CurrentRegion.Column), Cells(.Row, .CurrentRegion.Columns.Count + .CurrentRegion.Column - 1)).Interior.ColorIndex = 38
Range(Cells(.CurrentRegion.Row, .Column), Cells(.CurrentRegion.Rows.Count + .CurrentRegion.Row - 1, .Column)).Interior.ColorIndex = 24
End With
Application.ScreenUpdating = True
End Sub
"@
$module = $wb.VbaProject.Modules.AddModule("PSExcelModule")
$module.Code = $codeModule
# Add a call to the row & column highlight sub on each worksheet.
$codeSheet = @"
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
HighlightSelection Target
End Sub
"@
foreach ($sheet in $wb.Worksheets) {
$sheet.CodeModule.Code = $codeSheet
}
Close-ExcelPackage $Excel -Show

View File

@@ -0,0 +1,41 @@
$xlfile = "$env:temp\test.xlsm"
Remove-Item $xlfile -ErrorAction SilentlyContinue
$Excel = ConvertFrom-Csv @"
Region,Item,TotalSold
West,screwdriver,98
West,kiwi,19
North,kiwi,47
West,screws,48
West,avocado,52
East,avocado,40
South,drill,61
North,orange,92
South,drill,29
South,saw,36
"@ | Export-Excel $xlfile -TableName 'Sales' -WorksheetName 'Sales' -AutoSize -PassThru
$wb = $Excel.Workbook
$sheet = $wb.Worksheets["Sales"]
$wb.CreateVBAProject()
# Add a sub to the 'Worksheet_SelectionChange' event of the worksheet to highlight the selected row & column of the active table.
# https://docs.microsoft.com/en-gb/office/vba/excel/Concepts/Cells-and-Ranges/highlight-the-active-cell-row-or-column
$code = @"
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' Clear the color of all the cells
Cells.Interior.ColorIndex = 0
If Target.Cells.Count > 1 Then Exit Sub
Application.ScreenUpdating = False
With ActiveCell
' Highlight the row and column that contain the active cell, within the current region
Range(Cells(.Row, .CurrentRegion.Column), Cells(.Row, .CurrentRegion.Columns.Count + .CurrentRegion.Column - 1)).Interior.ColorIndex = 38
Range(Cells(.CurrentRegion.Row, .Column), Cells(.CurrentRegion.Rows.Count + .CurrentRegion.Row - 1, .Column)).Interior.ColorIndex = 24
End With
Application.ScreenUpdating = True
End Sub
"@
$sheet.CodeModule.Code = $code
Close-ExcelPackage $Excel -Show

View File

@@ -0,0 +1,62 @@
<#
Excel VBA macro which changes all PivotTables in the workbook to Tabular form, disables subtotals and repeats item labels.
https://github.com/dfinke/ImportExcel/issues/1196#issuecomment-1156320581
#>
$ExcelFile = "$ENV:TEMP\test.xlsm"
Remove-Item -Path $ExcelFile -ErrorAction SilentlyContinue
$Macro = @"
Private Sub Workbook_Open()
'
' ChangePivotTables Macro
' Runs when the Excel workbook is opened.
'
' Changes all PivotTables in the workbook to Tabular form, repeats labels
' and disables Subtotals.
'
' Declare variables
Dim Ws As Worksheet
Dim Pt As PivotTable
Dim Pf As PivotField
' Disable screen updates
Application.ScreenUpdating = False
' Continue even if an error occurs
On Error Resume Next
For Each Ws In ActiveWorkbook.Worksheets
For Each Pt In Ws.PivotTables
Pt.RowAxisLayout xlTabularRow
Pt.RepeatAllLabels xlRepeatLabels
For Each Pf In Pt.PivotFields
Pf.Subtotals(1) = False
Next
Next
Next
Application.ScreenUpdating = True
End Sub
"@
$Data = ConvertFrom-Csv -InputObject @"
Region,Item,TotalSold
West,screwdriver,98
West,kiwi,19
North,kiwi,47
West,screws,48
West,avocado,52
East,avocado,40
South,drill,61
North,orange,92
South,drill,29
South,saw,36
"@
$ExcelPackage = $Data | Export-Excel -Path $ExcelFile -TableName "Sales" -WorksheetName "Sales" -AutoSize -PassThru
# Add Macro to the ThisWorkbook module
$ExcelPackage.Workbook.CreateVBAProject()
$VBAThisWorkbookModule = $ExcelPackage.Workbook.VbaProject.Modules | Where-Object -FilterScript { $_.Name -eq "ThisWorkbook" }
$VBAThisWorkbookModule.Code = $Macro
# Create PivotTable example
Add-PivotTable -PivotTableName "SalesPivot" -Address $ExcelPackage.Sales.Cells["E1"] -SourceWorksheet $ExcelPackage.Sales `
-SourceRange $ExcelPackage.Sales.Tables[0].Address -PivotRows "Region", "Item" -PivotData @{ "TotalSold" = "Sum" }
Close-ExcelPackage -ExcelPackage $ExcelPackage -Show

View File

@@ -1,52 +0,0 @@
Function Import-Bycolumns {
Param(
[Parameter(Mandatory=$true)]
[OfficeOpenXml.ExcelPackage]$ExcelPackage,
[Int]$StartRow = 1,
[String]$WorksheetName,
[Int]$EndRow ,
[Int]$StartColumn = 1,
[Int]$EndColumn
)
Function Get-RowNames {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseSingularNouns', '', Justification = "Name would be incorrect, and command is not exported")]
param(
[Parameter(Mandatory)]
[Int[]]$Rows,
[Parameter(Mandatory)]
[Int]$StartColumn
)
foreach ($R in $Rows) {
#allow "False" or "0" to be headings
$Worksheet.Cells[$R, $StartColumn] | Where-Object {-not [string]::IsNullOrEmpty($_.Value) } | Select-Object @{N = 'Row'; E = { $R } }, Value
}
}
if (-not $WorksheetName) { $Worksheet = $ExcelPackage.Workbook.Worksheets[1] }
elseif (-not ($Worksheet = $ExcelPackage.Workbook.Worksheets[$WorkSheetName])) {
throw "Worksheet '$WorksheetName' not found, the workbook only contains the worksheets '$($ExcelPackage.Workbook.Worksheets)'. If you only wish to select the first worksheet, please remove the '-WorksheetName' parameter." ; return
}
if (-not $EndRow ) { $EndRow = $Worksheet.Dimension.End.Row }
if (-not $EndColumn) { $EndColumn = $Worksheet.Dimension.End.Column }
$Rows = $Startrow .. $EndRow ;
$Columns = (1 + $StartColumn)..$EndColumn
if ((-not $rows) -or (-not ($PropertyNames = Get-RowNames -Rows $Rows -StartColumn $StartColumn))) {
throw "No headers found in left coulmn '$Startcolumn'. "; return
}
if (-not $Columns) {
Write-Warning "Worksheet '$WorksheetName' in workbook contains no data in the rows after left column '$StartColumn'"
}
else {
foreach ($c in $Columns) {
$NewColumn = [Ordered]@{ }
foreach ($p in $PropertyNames) {
$NewColumn[$p.Value] = $Worksheet.Cells[$p.row,$c].text
}
[PSCustomObject]$NewColumn
}
}
}

View File

@@ -0,0 +1,6 @@
# Create an Empty Excel File
Use an empty string to export to an excel file.
```powershell
#Build an Excel file named: "file.xlsx" containing a worksheet: "MyWorksheet"
"" | Export-Excel -Path "C:\Test\file.xlsx" -WorksheetName "MyWorksheet"
```

View File

@@ -0,0 +1,41 @@
# How to Read an Existing Excel File
## Enumerate the Excel File Contents
```powershell
#Load the Excel file into a PSCustomObject
$ExcelFile = Import-Excel "C:\Test\file.xlsx" -WorksheetName "Sheet1"
```
## Visual of Data Structure
The File C:\Test\file.xlsx contains
![ExcelFileContents](/images/FAQ_Images/ExcelFileContents.png)
After loading this data into ```$ExcelFile``` the data is stored like:
![ExcelFileDebugImg](/images/FAQ_Images/ExcelFileDebugImg.jpg)
## Other Common Operations
### Load a Column
```powershell
$SpecificColumn = $ExcelFile."anotherHeader" #loads column with the header "anotherHeader" -- data stored in an array
```
### Load a Row
```powershell
$SpecificRow = $ExcelFile[1] #Loads row at index 1. Index 1 is the first row instead of 0.
```
### Map Contents to Hashtable to Interpret Data
Sometimes mapping to a Hashtable is more convenient to have access to common Hashtable operations. Enumerate a Hashtable with the row's data by:
```powershell
$HashTable = @{}
$SpecificRow= $ExcelFile[2]
$SpecificRow.psobject.properties | ForEach-Object {
$HashTable[$_.Name] = $_.Value
}
```
To then iterate through the enumerated Hashtable:
```powershell
ForEach ($Key in ($HashTable.GetEnumerator()) | Where-Object {$_.Value -eq "x"}){ #Only grabs a key where the value is "x"
#values accessible with $Key.Name or $Key.Value
}
```

View File

@@ -0,0 +1,34 @@
# Write to an Existing Excel File
### Enumerate the Excel File
The cmdlets ```Open-ExcelPackage``` and ```Close-ExcelPackage``` allow for direct modification to Excel file contents.
```powershell
$ExcelPkg = Open-ExcelPackage -Path "C:\Test\file.xlsx"
```
Contents of file.xlsx:
![ExcelFileContents](/images/FAQ_Images/ExcelFileContents.png)
### Enumerate the Worksheet to View or Modify the Data
```powershell
$WorkSheet = $ExcelPkg.Workbook.Worksheets["sheet1"].Cells #open excel worksheet cells from worksheet "sheet1"
```
Visual of data structure:
![DataStructureExcelPkg](/images/FAQ_Images/DataStructureExcelPkg.png)
A1 contains "someHeader", A2 contains "data1" etc.
### Modify a Specific Value in a File
Values can be accessed by row, column. Similar to a 2D array.
```powershell
$WorkSheet[1,4].Value = "New Column Header" #Starts at index 1 not 0
```
Contents of file.xlsx after modifying:
![ExcelFileContentsPostAdd](/images/FAQ_Images/ExcelFileContentsPostAdd.png)
### Load Value at Specific Index
```powershell
$ValueAtIndex = $WorkSheet[2,1].Value #Loads the value at row 2, column A
```
```$ValueAtIndex``` now contains: ![ValueAtIndexData](/images/FAQ_Images/ValueAtIndexData.png)
### Save File After Modifying
The changes will not display in the Excel file until Close-ExcelPackage is called.
```powershell
Close-ExcelPackage $ExcelPkg #close and save changes made to the Excel file.
```
**Note**: If the file is currently in use, Close-ExcelPackage will return an error and will not save the information.

View File

@@ -6,7 +6,7 @@
RootModule = 'ImportExcel.psm1'
# Version number of this module.
ModuleVersion = '7.1.2'
ModuleVersion = '7.8.4'
# ID used to uniquely identify this module
GUID = '60dd4136-feff-401a-ba27-a84458c57ede'
@@ -48,11 +48,14 @@ Check out the How To Videos https://www.youtube.com/watch?v=U3Ne_yX4tYo&list=PL5
'ConvertTo-ExcelXlsx',
'Copy-ExcelWorksheet',
'DoChart',
'Enable-ExcelAutoFilter',
'Enable-ExcelAutofit',
'Expand-NumberFormat',
'Export-Excel',
'Export-ExcelSheet',
'Get-ExcelColumnName',
'Get-ExcelFileSummary',
'Get-ExcelFileSummary',
'Get-ExcelSheetDimensionAddress',
'Get-ExcelSheetInfo',
'Get-ExcelWorkbookInfo',
'Get-HtmlTable',
@@ -63,6 +66,7 @@ Check out the How To Videos https://www.youtube.com/watch?v=U3Ne_yX4tYo&list=PL5
'Import-UPS',
'Import-USPS',
'Invoke-AllTests',
'Invoke-ExcelQuery',
'Invoke-Sum',
'Join-Worksheet',
'LineChart',
@@ -78,9 +82,13 @@ Check out the How To Videos https://www.youtube.com/watch?v=U3Ne_yX4tYo&list=PL5
'Open-ExcelPackage',
'PieChart',
'Pivot',
'Remove-Worksheet'
'Read-Clipboard',
'Read-OleDbData',
'ReadClipboardImpl',
'Remove-Worksheet',
'Select-Worksheet',
'Send-SQLDataToExcel',
'Set-CellComment',
'Set-CellStyle',
'Set-ExcelColumn',
'Set-ExcelRange',
@@ -114,8 +122,7 @@ Check out the How To Videos https://www.youtube.com/watch?v=U3Ne_yX4tYo&list=PL5
'.\GetExcelTable.ps1',
'.\ImportExcel.psd1',
'.\ImportExcel.psm1',
'.\LICENSE.txt',
'.\README.md',
'.\LICENSE.txt',
'.\Plot.ps1',
'.\Private',
'.\Public',
@@ -124,9 +131,8 @@ Check out the How To Videos https://www.youtube.com/watch?v=U3Ne_yX4tYo&list=PL5
'.\Charting\Charting.ps1',
'.\InferData\InferData.ps1',
'.\Pivot\Pivot.ps1',
'.\spikes\ConvertFrom-ExcelColumnName.ps1',
'.\Examples', '.\images', '.\Testimonials'
'.\Examples',
'.\Testimonials'
)
# Private data to pass to the module specified in RootModule/ModuleToProcess

View File

@@ -7,5 +7,5 @@ if (-not $fullPath) {
$fullPath = Join-Path $fullPath -ChildPath "ImportExcel"
}
Push-location $PSScriptRoot
Robocopy . $fullPath /mir /XD .vscode .git CI __tests__ data mdHelp /XF appveyor.yml azure-pipelines.yml .gitattributes .gitignore filelist.txt install.ps1 InstallModule.ps1
Robocopy . $fullPath /mir /XD .vscode images .git .github CI __tests__ data mdHelp spikes /XF README.md README.original.md appveyor.yml azure-pipelines.yml .gitattributes .gitignore filelist.txt install.ps1 InstallModule.ps1 PublishToGallery.ps1
Pop-Location

View File

@@ -0,0 +1,25 @@
function Invoke-ExcelReZipFile {
<#
#>
param(
[Parameter(Mandatory)]
[OfficeOpenXml.ExcelPackage]$ExcelPackage
)
Write-Verbose -Message "Re-Zipping $($ExcelPackage.file) using .NET ZIP library"
try {
Add-Type -AssemblyName 'System.IO.Compression.Filesystem' -ErrorAction stop
}
catch {
Write-Error "The -ReZip parameter requires .NET Framework 4.5 or later to be installed. Recommend to install Powershell v4+"
continue
}
try {
$TempZipPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath ([System.IO.Path]::GetRandomFileName())
$null = [io.compression.zipfile]::ExtractToDirectory($ExcelPackage.File, $TempZipPath)
Remove-Item $ExcelPackage.File -Force
$null = [io.compression.zipfile]::CreateFromDirectory($TempZipPath, $ExcelPackage.File)
Remove-Item $TempZipPath -Recurse -Force
}
catch { throw "Error resizipping $path : $_" }
}

View File

@@ -23,6 +23,7 @@
[Parameter(ParameterSetName = "FourIconSet")]
[Parameter(ParameterSetName = "FiveIconSet")]
[switch]$Reverse,
[switch]$ShowIconOnly,
[Parameter(ParameterSetName = "NamedRule",Position = 2)]
$ConditionValue,
[Parameter(ParameterSetName = "NamedRule",Position = 3)]
@@ -84,6 +85,9 @@
elseif ($PSBoundParameters.ContainsKey("FourIconsSet" ) ) {$rule = $Worksheet.ConditionalFormatting.AddFourIconSet( $Address , $FourIconsSet )}
elseif ($PSBoundParameters.ContainsKey("FiveIconsSet" ) ) {$rule = $Worksheet.ConditionalFormatting.AddFiveIconSet( $Address , $FiveIconsSet )}
else {$rule = ($Worksheet.ConditionalFormatting)."Add$RuleType"($Address ) }
If($ShowIconOnly) {
$rule.ShowValue = $false
}
if ($Reverse) {
if ($rule.type -match 'IconSet$' ) {$rule.reverse = $true}
elseif ($rule.type -match 'ColorScale$') {$temp =$rule.LowValue.Color ; $rule.LowValue.Color = $rule.HighValue.Color; $rule.HighValue.Color = $temp}
@@ -118,7 +122,7 @@
Write-Warning -Message "The condition will look for the quotes at the start and end."
}
if ($PSBoundParameters.ContainsKey("ConditionValue" ) -and
$RuleType -match "Top|Botom" ) {$rule.Rank = $ConditionValue }
$RuleType -match "Top|Bottom" ) {$rule.Rank = $ConditionValue }
if ($PSBoundParameters.ContainsKey("ConditionValue" ) -and
$RuleType -match "StdDev" ) {$rule.StdDev = $ConditionValue }
if ($PSBoundParameters.ContainsKey("ConditionValue" ) -and

View File

@@ -9,7 +9,7 @@ function Add-ExcelTable {
[Switch]$ShowHeader ,
[Switch]$ShowFilter,
[Switch]$ShowTotal,
[hashtable]$TotalSettings,
[hashtable]$TableTotalSettings,
[Switch]$ShowFirstColumn,
[Switch]$ShowLastColumn,
[Switch]$ShowRowStripes,
@@ -51,14 +51,65 @@ function Add-ExcelTable {
}
#it seems that show total changes some of the others, so the sequence matters.
if ($PSBoundParameters.ContainsKey('ShowHeader')) {$tbl.ShowHeader = [bool]$ShowHeader}
if ($PSBoundParameters.ContainsKey('TotalSettings')) {
if ($PSBoundParameters.ContainsKey('TableTotalSettings') -And $Null -ne $TableTotalSettings) {
$tbl.ShowTotal = $true
foreach ($k in $TotalSettings.keys) {
if (-not $tbl.Columns[$k]) {Write-Warning -Message "Table does not have a Column '$k'."}
elseif ($TotalSettings[$k] -notin @("Average", "Count", "CountNums", "Max", "Min", "None", "StdDev", "Sum", "Var") ) {
Write-Warning -Message "'$($TotalSettings[$k])' is not a valid total function."
foreach ($k in $TableTotalSettings.keys) {
# Get the Function to be added in the totals row
if ($TableTotalSettings[$k] -is [HashTable]) {
If ($TableTotalSettings[$k].Keys -contains "Function") {
$TotalFunction = $TableTotalSettings[$k]["Function"]
}
Else { Write-Warning -Message "TableTotalSettings parameter for column '$k' needs a key 'Function'" }
}
else {
$TotalFunction = [String]($TableTotalSettings[$k])
}
# Add the totals row
if (-not $tbl.Columns[$k]) {Write-Warning -Message "Table does not have a Column '$k'."}
elseif ($TotalFunction -match "^=") {
### A function in Excel uses ";" between parameters but the OpenXML parameter separator is ","
### Only replace semicolon when it's NOT somewhere between quotes quotes.
# Get all text between quotes
$QuoteMatches = [Regex]::Matches($TotalFunction,"`"[^`"]*`"|'[^']*'")
# Create array with all indexes of characters between quotes (and the quotes themselves)
$QuoteCharIndexes = $(
Foreach ($QuoteMatch in $QuoteMatches) {
(($QuoteMatch.Index)..($QuoteMatch.Index + $QuoteMatch.Length - 1))
}
)
# Get all semicolons
$SemiColonMatches = [Regex]::Matches($TotalFunction, ";")
# Replace the semicolons of which the index is not in the list of quote-text indexes
Foreach ($SemiColonMatch in $SemiColonMatches.Index) {
If ($QuoteCharIndexes -notcontains $SemiColonMatch) {
$TotalFunction = $TotalFunction.remove($SemiColonMatch,1).Insert($SemiColonMatch,",")
}
}
# Configure the formula. The TotalsRowFunction is automatically set to "Custom" when the TotalsRowFormula is set.
$tbl.Columns[$k].TotalsRowFormula = $TotalFunction
}
elseif ($TotalFunction -notin @("Average", "Count", "CountNums", "Max", "Min", "None", "StdDev", "Sum", "Var") ) {
Write-Warning -Message "'$($TotalFunction)' is not a valid total function."
}
else {$tbl.Columns[$k].TotalsRowFunction = $TotalFunction}
# Set comment on totals row
If ($TableTotalSettings[$k] -is [HashTable] -and $TableTotalSettings[$k].Keys -contains "Comment" -and ![String]::IsNullOrEmpty($TableTotalSettings[$k]["Comment"])) {
$ColumnLetter = [officeOpenXml.ExcelAddress]::GetAddressCol(($tbl.columns | ? { $_.name -eq $k }).Id, $False)
$CommentRange = "{0}{1}" -f $ColumnLetter, $tbl.Address.End.Row
$CellCommentParams = @{
Worksheet = $tbl.WorkSheet
Range = $CommentRange
Text = $TableTotalSettings[$k]["Comment"]
}
Set-CellComment @CellCommentParams
}
else {$tbl.Columns[$k].TotalsRowFunction = $TotalSettings[$k]}
}
}
elseif ($PSBoundParameters.ContainsKey('ShowTotal')) {$tbl.ShowTotal = [bool]$ShowTotal}

View File

@@ -18,8 +18,10 @@
[String]$PivotTotals = "Both",
[Switch]$NoTotalsInPivot,
[String]$GroupDateRow,
[String]$GroupDateColumn,
[OfficeOpenXml.Table.PivotTable.eDateGroupBy[]]$GroupDatePart,
[String]$GroupNumericRow,
[String]$GroupNumericColumn,
[double]$GroupNumericMin = 0 ,
[double]$GroupNumericMax = [Double]::MaxValue ,
[double]$GroupNumericInterval = 100 ,
@@ -139,11 +141,21 @@
if (-not $r ) {Write-Warning -Message "Could not find a Row field named '$GroupNumericRow'; no numeric grouping will be done."}
else {$r.AddNumericGrouping($GroupNumericMin, $GroupNumericMax, $GroupNumericInterval)}
}
elseif ($GroupNumericColumn) {
$c = $pivotTable.ColumnFields.Where( {$_.name -eq $GroupNumericColumn })
if (-not $c ) {Write-Warning -Message "Could not find a Column field named '$GroupNumericColumn'; no numeric grouping will be done."}
else {$c.AddNumericGrouping($GroupNumericMin, $GroupNumericMax, $GroupNumericInterval)}
}
if ($GroupDateRow -and $PSBoundParameters.ContainsKey("GroupDatePart")) {
$r = $pivotTable.RowFields.Where( {$_.name -eq $GroupDateRow })
if (-not $r ) {Write-Warning -Message "Could not find a Row field named '$GroupDateRow'; no date grouping will be done."}
else {$r.AddDateGrouping($GroupDatePart)}
}
elseif ($GroupDateColumn -and $PSBoundParameters.ContainsKey("GroupDatePart")) {
$c = $pivotTable.ColumnFields.Where( {$_.name -eq $GroupDateColumn })
if (-not $c ) {Write-Warning -Message "Could not find a Column field named '$GroupDateColumn'; no date grouping will be done."}
else {$c.AddDateGrouping($GroupDatePart)}
}
}
catch {Write-Warning -Message "Failed adding PivotTable '$pivotTableName': $_"}
}

View File

@@ -49,7 +49,7 @@ function Add-Worksheet {
}
else {$ExcelWorkbook.Worksheets.MoveBefore($WorksheetName, $MoveBefore)}
}
else {Write-Warning "Can't find worksheet '$MoveBefore'; worsheet '$WorksheetName' will not be moved."}
else {Write-Warning "Can't find worksheet '$MoveBefore'; worksheet '$WorksheetName' will not be moved."}
}
elseif ($MoveAfter ) {
if ($MoveAfter -eq "*") {
@@ -68,7 +68,7 @@ function Add-Worksheet {
$ExcelWorkbook.Worksheets.MoveAfter($WorksheetName, $MoveAfter)
}
}
else {Write-Warning "Can't find worksheet '$MoveAfter'; worsheet '$WorksheetName' will not be moved."}
else {Write-Warning "Can't find worksheet '$MoveAfter'; worksheet '$WorksheetName' will not be moved."}
}
#endregion
if ($Activate) {Select-Worksheet -ExcelWorksheet $ws }

View File

@@ -1,33 +1,38 @@
function Close-ExcelPackage {
[CmdLetBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword","")]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")]
param (
[parameter(Mandatory=$true, ValueFromPipeline=$true)]
[parameter(Mandatory = $true, ValueFromPipeline = $true)]
[OfficeOpenXml.ExcelPackage]$ExcelPackage,
[switch]$Show,
[Switch]$Show,
[Switch]$NoSave,
$SaveAs,
[ValidateNotNullOrEmpty()]
[String]$Password,
[switch]$Calculate
[Switch]$Calculate,
[Switch]$ReZip
)
if ( $NoSave) {$ExcelPackage.Dispose()}
if ( $NoSave) { $ExcelPackage.Dispose() }
else {
if ($Calculate) {
try { [OfficeOpenXml.CalculationExtension]::Calculate($ExcelPackage.Workbook) }
catch { Write-Warning "One or more errors occured while calculating, save will continue, but there may be errors in the workbook."}
try { [OfficeOpenXml.CalculationExtension]::Calculate($ExcelPackage.Workbook) }
catch { Write-Warning "One or more errors occured while calculating, save will continue, but there may be errors in the workbook." }
}
if ($SaveAs) {
$SaveAs = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($SaveAs)
if ($Password) {$ExcelPackage.SaveAs( $SaveAs, $Password ) }
else {$ExcelPackage.SaveAs( $SaveAs)}
if ($Password) { $ExcelPackage.SaveAs( $SaveAs, $Password ) }
else { $ExcelPackage.SaveAs( $SaveAs) }
}
else {
if ($Password) {$ExcelPackage.Save($Password) }
else {$ExcelPackage.Save() }
else {
if ($Password) { $ExcelPackage.Save($Password) }
else { $ExcelPackage.Save() }
$SaveAs = $ExcelPackage.File.FullName
}
if ($ReZip) {
Invoke-ExcelReZipFile -ExcelPackage $ExcelPackage
}
$ExcelPackage.Dispose()
if ($Show) {Start-Process -FilePath $SaveAs }
if ($Show) { Start-Process -FilePath $SaveAs }
}
}

View File

@@ -19,7 +19,7 @@ function ConvertFrom-ExcelSheet {
[string[]]$AsDate = @()
)
$Path = (Resolve-Path $Path).Path
$Path = (Resolve-Path $Path).ProviderPath
$xl = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path
$workbook = $xl.Workbook

View File

@@ -16,12 +16,15 @@ function ConvertFrom-ExcelToSQLInsert {
[switch]$NoHeader,
[switch]$DataOnly,
[switch]$ConvertEmptyStringsToNull,
[switch]$UseMsSqlSyntax
[switch]$UseMsSqlSyntax,
[Parameter(Mandatory = $false)]
$SingleQuoteStyle
)
$null = $PSBoundParameters.Remove('TableName')
$null = $PSBoundParameters.Remove('ConvertEmptyStringsToNull')
$null = $PSBoundParameters.Remove('UseMsSqlSyntax')
$null = $PSBoundParameters.Remove('SingleQuoteStyle')
$params = @{} + $PSBoundParameters
@@ -38,11 +41,16 @@ function ConvertFrom-ExcelToSQLInsert {
'NULL'
}
else {
"'" + $record.$propertyName + "'"
if ( $SingleQuoteStyle ) {
"'" + $record.$propertyName.ToString().Replace("'",${SingleQuoteStyle}) + "'"
}
else {
"'" + $record.$propertyName + "'"
}
}
}
$targetValues = ($values -join ", ")
"INSERT INTO {0} ({1}) Values({2});" -f $TableName, $ColumnNames, $targetValues
}
}
}

View File

@@ -0,0 +1,16 @@
function Enable-ExcelAutoFilter {
<#
.SYNOPSIS
Enable the Excel AutoFilter
.EXAMPLE
Enable-ExcelAutoFilter $targetSheet
#>
param(
[Parameter(Mandatory)]
[OfficeOpenXml.ExcelWorksheet]$Worksheet
)
$range = Get-ExcelSheetDimensionAddress $Worksheet
$Worksheet.Cells[$range].AutoFilter = $true
}

View File

@@ -0,0 +1,16 @@
function Enable-ExcelAutofit {
<#
.SYNOPSIS
Make all text fit the cells
.EXAMPLE
Enable-ExcelAutofit $excel.Sheet1
#>
param(
[Parameter(Mandatory)]
[OfficeOpenXml.ExcelWorksheet]$Worksheet
)
$range = Get-ExcelSheetDimensionAddress $Worksheet
$Worksheet.Cells[$range].AutoFitColumns()
}

View File

@@ -22,7 +22,7 @@
[Switch]$TitleBold,
[Int]$TitleSize = 22,
$TitleBackgroundColor,
[parameter(DontShow=$true)]
[parameter(DontShow = $true)]
[Switch]$IncludePivotTable,
[String]$PivotTableName,
[String[]]$PivotRows,
@@ -48,15 +48,16 @@
[Switch]$BoldTopRow,
[Switch]$NoHeader,
[ValidateScript( {
if (-not $_) { throw 'RangeName is null or empty.' }
elseif ($_[0] -notmatch '[a-z]') { throw 'RangeName starts with an invalid character.' }
if (-not $_) { throw 'RangeName is null or empty.' }
elseif ($_[0] -notmatch '[a-z]') { throw 'RangeName starts with an invalid character.' }
else { $true }
})]
})]
[String]$RangeName,
[Alias('Table')]
$TableName,
[OfficeOpenXml.Table.TableStyles]$TableStyle = [OfficeOpenXml.Table.TableStyles]::Medium6,
[Switch]$Barchart,
[OfficeOpenXml.Table.TableStyles]$TableStyle = [OfficeOpenXml.Table.TableStyles]::Medium6,
[HashTable]$TableTotalSettings,
[Switch]$BarChart,
[Switch]$PieChart,
[Switch]$LineChart ,
[Switch]$ColumnChart ,
@@ -78,6 +79,7 @@
[Switch]$NoAliasOrScriptPropeties,
[Switch]$DisplayPropertySet,
[String[]]$NoNumberConversion,
[String[]]$NoHyperLinkConversion,
[Object[]]$ConditionalFormat,
[Object[]]$ConditionalText,
[Object[]]$Style,
@@ -88,7 +90,7 @@
[Switch]$Now,
[Switch]$ReturnRange,
#By default PivotTables have Totals for each Row (on the right) and for each column at the bottom. This allows just one or neither to be selected.
[ValidateSet("Both","Columns","Rows","None")]
[ValidateSet("Both", "Columns", "Rows", "None")]
[String]$PivotTotals = "Both",
#Included for compatibility - equivalent to -PivotTotals "None"
[Switch]$NoTotalsInPivot,
@@ -98,13 +100,13 @@
begin {
$numberRegex = [Regex]'\d'
$isDataTypeValueType = $false
if ($NoClobber) {Write-Warning -Message "-NoClobber parameter is no longer used" }
if ($NoClobber) { Write-Warning -Message "-NoClobber parameter is no longer used" }
#Open the file, get the worksheet, and decide where in the sheet we are writing, and if there is a number format to apply.
try {
try {
$script:Header = $null
if ($Append -and $ClearSheet) {throw "You can't use -Append AND -ClearSheet." ; return}
if ($Append -and $ClearSheet) { throw "You can't use -Append AND -ClearSheet." ; return }
#To force -Now not to format as a table, allow $false in -TableName to be "No table"
$TableName = if ($null -eq $TableName -or ($TableName -is [bool] -and $false -eq $TableName)) { $null } else {[String]$TableName}
$TableName = if ($null -eq $TableName -or ($TableName -is [bool] -and $false -eq $TableName)) { $null } else { [String]$TableName }
if ($Now -or (-not $Path -and -not $ExcelPackage) ) {
if (-not $PSBoundParameters.ContainsKey("Path")) { $Path = [System.IO.Path]::GetTempFileName() -replace '\.tmp', '.xlsx' }
if (-not $PSBoundParameters.ContainsKey("Show")) { $Show = $true }
@@ -120,59 +122,59 @@
$pkg = $ExcelPackage
$Path = $pkg.File
}
Else { $pkg = Open-ExcelPackage -Path $Path -Create -KillExcel:$KillExcel -Password:$Password}
Else { $pkg = Open-ExcelPackage -Path $Path -Create -KillExcel:$KillExcel -Password:$Password }
}
catch {throw "Could not open Excel Package $path"}
try {
$params = @{WorksheetName=$WorksheetName}
foreach ($p in @("ClearSheet", "MoveToStart", "MoveToEnd", "MoveBefore", "MoveAfter", "Activate")) {if ($PSBoundParameters[$p]) {$params[$p] = $PSBoundParameters[$p]}}
catch { throw "Could not open Excel Package $path" }
try {
$params = @{WorksheetName = $WorksheetName }
foreach ($p in @("ClearSheet", "MoveToStart", "MoveToEnd", "MoveBefore", "MoveAfter", "Activate")) { if ($PSBoundParameters[$p]) { $params[$p] = $PSBoundParameters[$p] } }
$ws = $pkg | Add-Worksheet @params
if ($ws.Name -ne $WorksheetName) {
Write-Warning -Message "The Worksheet name has been changed from $WorksheetName to $($ws.Name), this may cause errors later."
$WorksheetName = $ws.Name
}
}
catch {throw "Could not get worksheet $WorksheetName"}
try {
catch { throw "Could not get worksheet $WorksheetName" }
try {
if ($Append -and $ws.Dimension) {
#if there is a title or anything else above the header row, append needs to be combined wih a suitable startrow parameter
$headerRange = $ws.Dimension.Address -replace "\d+$", $StartRow
#using a slightly odd syntax otherwise header ends up as a 2D array
$ws.Cells[$headerRange].Value | ForEach-Object -Begin {$Script:header = @()} -Process {$Script:header += $_ }
$ws.Cells[$headerRange].Value | ForEach-Object -Begin { $Script:header = @() } -Process { $Script:header += $_ }
$NoHeader = $true
#if we did not get AutoNameRange, but headers have ranges of the same name make autoNameRange True, otherwise make it false
if (-not $AutoNameRange) {
$AutoNameRange = $true ; foreach ($h in $header) {if ($ws.names.name -notcontains $h) {$AutoNameRange = $false} }
$AutoNameRange = $true ; foreach ($h in $header) { if ($ws.names.name -notcontains $h) { $AutoNameRange = $false } }
}
#if we did not get a Rangename but there is a Range which covers the active part of the sheet, set Rangename to that.
if (-not $RangeName -and $ws.names.where({$_.name[0] -match '[a-z]'})) {
if (-not $RangeName -and $ws.names.where({ $_.name[0] -match '[a-z]' })) {
$theRange = $ws.names.where({
($_.Name[0] -match '[a-z]' ) -and
($_.Start.Row -eq $StartRow) -and
($_.Start.Column -eq $StartColumn) -and
($_.End.Row -eq $ws.Dimension.End.Row) -and
($_.End.Column -eq $ws.Dimension.End.column) } , 'First', 1)
if ($theRange) {$rangename = $theRange.name}
($_.Name[0] -match '[a-z]' ) -and
($_.Start.Row -eq $StartRow) -and
($_.Start.Column -eq $StartColumn) -and
($_.End.Row -eq $ws.Dimension.End.Row) -and
($_.End.Column -eq $ws.Dimension.End.column) } , 'First', 1)
if ($theRange) { $rangename = $theRange.name }
}
#if we did not get a table name but there is a table which covers the active part of the sheet, set table name to that, and don't do anything with autofilter
$existingTable = $ws.Tables.Where({$_.address.address -eq $ws.dimension.address},'First', 1)
$existingTable = $ws.Tables.Where({ $_.address.address -eq $ws.dimension.address }, 'First', 1)
if ($null -eq $TableName -and $existingTable) {
$TableName = $existingTable.Name
$TableStyle = $existingTable.StyleName -replace "^TableStyle",""
$TableName = $existingTable.Name
$TableStyle = $existingTable.StyleName -replace "^TableStyle", ""
$AutoFilter = $false
}
#if we did not get $autofilter but a filter range is set and it covers the right area, set autofilter to true
elseif (-not $AutoFilter -and $ws.Names['_xlnm._FilterDatabase']) {
if ( ($ws.Names['_xlnm._FilterDatabase'].Start.Row -eq $StartRow) -and
if ( ($ws.Names['_xlnm._FilterDatabase'].Start.Row -eq $StartRow) -and
($ws.Names['_xlnm._FilterDatabase'].Start.Column -eq $StartColumn) -and
($ws.Names['_xlnm._FilterDatabase'].End.Row -eq $ws.Dimension.End.Row) -and
($ws.Names['_xlnm._FilterDatabase'].End.Column -eq $ws.Dimension.End.Column) ) {$AutoFilter = $true}
($ws.Names['_xlnm._FilterDatabase'].End.Row -eq $ws.Dimension.End.Row) -and
($ws.Names['_xlnm._FilterDatabase'].End.Column -eq $ws.Dimension.End.Column) ) { $AutoFilter = $true }
}
$row = $ws.Dimension.End.Row
Write-Debug -Message ("Appending: headers are " + ($script:Header -join ", ") + " Start row is $row")
if ($Title) {Write-Warning -Message "-Title Parameter is ignored when appending."}
if ($Title) { Write-Warning -Message "-Title Parameter is ignored when appending." }
}
elseif ($Title) {
#Can only add a title if not appending!
@@ -180,41 +182,41 @@
$ws.Cells[$row, $StartColumn].Value = $Title
$ws.Cells[$row, $StartColumn].Style.Font.Size = $TitleSize
if ($PSBoundParameters.ContainsKey("TitleBold")) {
if ($PSBoundParameters.ContainsKey("TitleBold")) {
#Set title to Bold face font if -TitleBold was specified.
#Otherwise the default will be unbolded.
$ws.Cells[$row, $StartColumn].Style.Font.Bold = [boolean]$TitleBold
}
if ($TitleBackgroundColor ) {
if ($TitleBackgroundColor -is [string]) {$TitleBackgroundColor = [System.Drawing.Color]::$TitleBackgroundColor }
if ($TitleBackgroundColor -is [string]) { $TitleBackgroundColor = [System.Drawing.Color]::$TitleBackgroundColor }
$ws.Cells[$row, $StartColumn].Style.Fill.PatternType = $TitleFillPattern
$ws.Cells[$row, $StartColumn].Style.Fill.BackgroundColor.SetColor($TitleBackgroundColor)
}
$row ++ ; $startRow ++
}
else { $row = $StartRow }
else { $row = $StartRow }
$ColumnIndex = $StartColumn
$Numberformat = Expand-NumberFormat -NumberFormat $Numberformat
if ((-not $ws.Dimension) -and ($Numberformat -ne $ws.Cells.Style.Numberformat.Format)) {
$ws.Cells.Style.Numberformat.Format = $Numberformat
$setNumformat = $false
$ws.Cells.Style.Numberformat.Format = $Numberformat
$setNumformat = $false
}
else { $setNumformat = ($Numberformat -ne $ws.Cells.Style.Numberformat.Format) }
else { $setNumformat = ($Numberformat -ne $ws.Cells.Style.Numberformat.Format) }
}
catch {throw "Failed preparing to export to worksheet '$WorksheetName' to '$Path': $_"}
catch { throw "Failed preparing to export to worksheet '$WorksheetName' to '$Path': $_" }
#region Special case -inputobject passed a dataTable object
<# If inputObject was passed via the pipeline it won't be visible until the process block, we will only see it here if it was passed as a parameter
if it is a data table don't do foreach on it (slow) - put the whole table in and set dates on date columns,
set things up for the end block, and skip the process block #>
if ($InputObject -is [System.Data.DataTable]) {
if ($InputObject -is [System.Data.DataTable]) {
if ($Append -and $ws.dimension) {
$row ++
$null = $ws.Cells[$row,$StartColumn].LoadFromDataTable($InputObject, $false )
if ($TableName -or $PSBoundParameters.ContainsKey('TableStyle')) {
Add-ExcelTable -Range $ws.Cells[$ws.Dimension] -TableName $TableName -TableStyle $TableStyle
$null = $ws.Cells[$row, $StartColumn].LoadFromDataTable($InputObject, $false )
if ($TableName -or $PSBoundParameters.ContainsKey('TableStyle')) {
Add-ExcelTable -Range $ws.Cells[$ws.Dimension] -TableName $TableName -TableStyle $TableStyle -TableTotalSettings $TableTotalSettings
}
}
else {
else {
#Change TableName if $TableName is non-empty; don't leave caller with a renamed table!
$orginalTableName = $InputObject.TableName
if ($PSBoundParameters.ContainsKey("TableName")) {
@@ -226,157 +228,165 @@
}
#Insert as a table, if Tablestyle didn't arrive as a default, or $TableName non-null - even if empty
if ($null -ne $TableName -or $PSBoundParameters.ContainsKey("TableStyle")) {
$null = $ws.Cells[$row,$StartColumn].LoadFromDataTable($InputObject, (-not $noHeader),$TableStyle )
$null = $ws.Cells[$row, $StartColumn].LoadFromDataTable($InputObject, (-not $noHeader), $TableStyle )
# Workaround for EPPlus not marking the empty row on an empty table as dummy row.
if ($InputObject.Rows.Count -eq 0) {
($ws.Tables | Select-Object -Last 1).TableXml.table.SetAttribute('insertRow', 1)
}
}
else {
$null = $ws.Cells[$row,$StartColumn].LoadFromDataTable($InputObject, (-not $noHeader) )
$null = $ws.Cells[$row, $StartColumn].LoadFromDataTable($InputObject, (-not $noHeader) )
}
$InputObject.TableName = $orginalTableName
}
foreach ($c in $InputObject.Columns.where({$_.datatype -eq [datetime]})) {
foreach ($c in $InputObject.Columns.where({ $_.datatype -eq [datetime] })) {
Set-ExcelColumn -Worksheet $ws -Column ($c.Ordinal + $StartColumn) -NumberFormat 'Date-Time'
}
foreach ($c in $InputObject.Columns.where({$_.datatype -eq [timespan]})) {
foreach ($c in $InputObject.Columns.where({ $_.datatype -eq [timespan] })) {
Set-ExcelColumn -Worksheet $ws -Column ($c.Ordinal + $StartColumn) -NumberFormat '[h]:mm:ss'
}
$ColumnIndex += $InputObject.Columns.Count - 1
if ($noHeader) {$row += $InputObject.Rows.Count -1 }
else {$row += $InputObject.Rows.Count }
$ColumnIndex += $InputObject.Columns.Count - 1
if ($noHeader) { $row += $InputObject.Rows.Count - 1 }
else { $row += $InputObject.Rows.Count }
$null = $PSBoundParameters.Remove('InputObject')
$firstTimeThru = $false
}
#endregion
else {$firstTimeThru = $true}
else { $firstTimeThru = $true }
}
process { if ($PSBoundParameters.ContainsKey("InputObject")) {
try {
if ($null -eq $InputObject) {$row += 1}
foreach ($TargetData in $InputObject) {
if ($firstTimeThru) {
$firstTimeThru = $false
$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 ) {
$script:Header = @(".") # dummy value to make sure we go through the "for each name in $header"
if (-not $Append) {$row -= 1} # By default row will be 1, it is incremented before inserting values (so it ends pointing at final row.); si first data row is 2 - move back up 1 if there is no header .
process {
if ($PSBoundParameters.ContainsKey("InputObject")) {
try {
if ($null -eq $InputObject) { $row += 1 }
foreach ($TargetData in $InputObject) {
if ($firstTimeThru) {
$firstTimeThru = $false
$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 ) {
$script:Header = @(".") # dummy value to make sure we go through the "for each name in $header"
if (-not $Append) { $row -= 1 } # By default row will be 1, it is incremented before inserting values (so it ends pointing at final row.); si first data row is 2 - move back up 1 if there is no header .
}
if ($null -ne $TargetData) { Write-Debug "DataTypeName is '$($TargetData.GetType().name)' isDataTypeValueType '$isDataTypeValueType'" }
}
if ($null -ne $TargetData) {Write-Debug "DataTypeName is '$($TargetData.GetType().name)' isDataTypeValueType '$isDataTypeValueType'" }
}
#region Add headers - if we are appending, or we have been through here once already we will have the headers
if (-not $script:Header) {
if ($DisplayPropertySet -and $TargetData.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames) {
$script:Header = $TargetData.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames.Where( {$_ -notin $ExcludeProperty})
}
else {
if ($NoAliasOrScriptPropeties) {$propType = "Property"} else {$propType = "*"}
$script:Header = $TargetData.PSObject.Properties.where( {$_.MemberType -like $propType}).Name
}
foreach ($exclusion in $ExcludeProperty) {$script:Header = $script:Header -notlike $exclusion}
if ($NoHeader) {
# Don't push the headers to the spreadsheet
$row -= 1
}
else {
$ColumnIndex = $StartColumn
foreach ($Name in $script:Header) {
$ws.Cells[$row, $ColumnIndex].Value = $Name
Write-Verbose "Cell '$row`:$ColumnIndex' add header '$Name'"
$ColumnIndex += 1
#region Add headers - if we are appending, or we have been through here once already we will have the headers
if (-not $script:Header) {
if ($DisplayPropertySet -and $TargetData.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames) {
$script:Header = $TargetData.psStandardmembers.DefaultDisplayPropertySet.ReferencedPropertyNames.Where( { $_ -notin $ExcludeProperty })
}
else {
if ($NoAliasOrScriptPropeties) { $propType = "Property" } else { $propType = "*" }
$script:Header = $TargetData.PSObject.Properties.where( { $_.MemberType -like $propType }).Name
}
foreach ($exclusion in $ExcludeProperty) { $script:Header = $script:Header -notlike $exclusion }
if ($NoHeader) {
# Don't push the headers to the spreadsheet
$row -= 1
}
else {
$ColumnIndex = $StartColumn
foreach ($Name in $script:Header) {
$ws.Cells[$row, $ColumnIndex].Value = $Name
Write-Verbose "Cell '$row`:$ColumnIndex' add header '$Name'"
$ColumnIndex += 1
}
}
}
}
#endregion
#region Add non header values
$row += 1
$ColumnIndex = $StartColumn
<#
#endregion
#region Add non header values
$row += 1
$ColumnIndex = $StartColumn
<#
For each item in the header OR for the Data item if this is a simple Type or data table :
If it is a date insert with one of Excel's built in formats - recognized as "Date and time to be localized"
if it is a timespan insert with a built in format for elapsed hours, minutes and seconds
if its any other numeric insert as is , setting format if need be.
Preserve URI, Insert a data table, convert non string objects to string.
For strings, check for fomula, URI or Number, before inserting as a string (ignore nulls) #>
foreach ($Name in $script:Header) {
if ($isDataTypeValueType) {$v = $TargetData}
else {$v = $TargetData.$Name}
try {
if ($v -is [DateTime]) {
$ws.Cells[$row, $ColumnIndex].Value = $v
$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = 'm/d/yy h:mm' # This is not a custom format, but a preset recognized as date and localized.
}
elseif ($v -is [TimeSpan]) {
$ws.Cells[$row, $ColumnIndex].Value = $v
$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = '[h]:mm:ss'
}
elseif ($v -is [System.ValueType]) {
$ws.Cells[$row, $ColumnIndex].Value = $v
if ($setNumformat) {$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
}
elseif ($v -is [uri] ) {
$ws.Cells[$row, $ColumnIndex].HyperLink = $v
$ws.Cells[$row, $ColumnIndex].Style.Font.Color.SetColor([System.Drawing.Color]::Blue)
$ws.Cells[$row, $ColumnIndex].Style.Font.UnderLine = $true
}
elseif ($v -isnot [String] ) { #Other objects or null.
if ($null -ne $v) { $ws.Cells[$row, $ColumnIndex].Value = $v.toString()}
}
elseif ($v[0] -eq '=') {
$ws.Cells[$row, $ColumnIndex].Formula = ($v -replace '^=','')
if ($setNumformat) {$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
}
elseif ( [System.Uri]::IsWellFormedUriString($v , [System.UriKind]::Absolute) ) {
if ($v -match "^xl://internal/") {
$referenceAddress = $v -replace "^xl://internal/" , ""
$display = $referenceAddress -replace "!A1$" , ""
$h = New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList $referenceAddress , $display
$ws.Cells[$row, $ColumnIndex].HyperLink = $h
foreach ($Name in $script:Header) {
if ($isDataTypeValueType) { $v = $TargetData }
else { $v = $TargetData.$Name }
try {
if ($v -is [DateTime]) {
$ws.Cells[$row, $ColumnIndex].Value = $v
$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = 'm/d/yy h:mm' # This is not a custom format, but a preset recognized as date and localized.
}
else {$ws.Cells[$row, $ColumnIndex].HyperLink = $v } #$ws.Cells[$row, $ColumnIndex].Value = $v.AbsoluteUri
$ws.Cells[$row, $ColumnIndex].Style.Font.Color.SetColor([System.Drawing.Color]::Blue)
$ws.Cells[$row, $ColumnIndex].Style.Font.UnderLine = $true
}
else {
$number = $null
if ( $numberRegex.IsMatch($v) -and # if it contains digit(s) - this syntax is quicker than -match for many items and cuts out slow checks for non numbers
$NoNumberConversion -ne '*' -and # and NoNumberConversion isn't specified
$NoNumberConversion -notcontains $Name -and
[Double]::TryParse($v, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number)
) {
$ws.Cells[$row, $ColumnIndex].Value = $number
if ($setNumformat) {$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
elseif ($v -is [TimeSpan]) {
$ws.Cells[$row, $ColumnIndex].Value = $v
$ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = '[h]:mm:ss'
}
elseif ($v -is [System.ValueType]) {
$ws.Cells[$row, $ColumnIndex].Value = $v
if ($setNumformat) { $ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
}
elseif ($v -is [uri] -and
$NoHyperLinkConversion -ne '*' -and
$NoHyperLinkConversion -notcontains $Name ) {
$ws.Cells[$row, $ColumnIndex].HyperLink = $v
$ws.Cells[$row, $ColumnIndex].Style.Font.Color.SetColor([System.Drawing.Color]::Blue)
$ws.Cells[$row, $ColumnIndex].Style.Font.UnderLine = $true
}
elseif ($v -isnot [String] ) {
#Other objects or null.
if ($null -ne $v) { $ws.Cells[$row, $ColumnIndex].Value = $v.toString() }
}
elseif ($v[0] -eq '=') {
$ws.Cells[$row, $ColumnIndex].Formula = ($v -replace '^=', '')
if ($setNumformat) { $ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
}
elseif ( $NoHyperLinkConversion -ne '*' -and # Put the check for 'NoHyperLinkConversion is null' first to skip checking for wellformedstring
$NoHyperLinkConversion -notcontains $Name -and
[System.Uri]::IsWellFormedUriString($v , [System.UriKind]::Absolute)
) {
if ($v -match "^xl://internal/") {
$referenceAddress = $v -replace "^xl://internal/" , ""
$display = $referenceAddress -replace "!A1$" , ""
$h = New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList $referenceAddress , $display
$ws.Cells[$row, $ColumnIndex].HyperLink = $h
}
else { $ws.Cells[$row, $ColumnIndex].HyperLink = $v } #$ws.Cells[$row, $ColumnIndex].Value = $v.AbsoluteUri
$ws.Cells[$row, $ColumnIndex].Style.Font.Color.SetColor([System.Drawing.Color]::Blue)
$ws.Cells[$row, $ColumnIndex].Style.Font.UnderLine = $true
}
else {
$ws.Cells[$row, $ColumnIndex].Value = $v
$number = $null
if ( $NoNumberConversion -ne '*' -and # Check if NoNumberConversion isn't specified. Put this first as it's going to stop the if clause. Quicker than putting regex check first
$numberRegex.IsMatch($v) -and # and if it contains digit(s) - this syntax is quicker than -match for many items and cuts out slow checks for non numbers
$NoNumberConversion -notcontains $Name -and
[Double]::TryParse($v, [System.Globalization.NumberStyles]::Any, [System.Globalization.NumberFormatInfo]::CurrentInfo, [Ref]$number)
) {
$ws.Cells[$row, $ColumnIndex].Value = $number
if ($setNumformat) { $ws.Cells[$row, $ColumnIndex].Style.Numberformat.Format = $Numberformat }
}
else {
$ws.Cells[$row, $ColumnIndex].Value = $v
}
}
}
catch { Write-Warning -Message "Could not insert the '$Name' property at Row $row, Column $ColumnIndex" }
$ColumnIndex += 1
}
catch {Write-Warning -Message "Could not insert the '$Name' property at Row $row, Column $ColumnIndex"}
$ColumnIndex += 1
$ColumnIndex -= 1 # column index will be the last column whether isDataTypeValueType was true or false
#endregion
}
$ColumnIndex -= 1 # column index will be the last column whether isDataTypeValueType was true or false
#endregion
}
catch { throw "Failed exporting data to worksheet '$WorksheetName' to '$Path': $_" }
}
catch {throw "Failed exporting data to worksheet '$WorksheetName' to '$Path': $_" }
}}
}
end {
if ($firstTimeThru -and $ws.Dimension) {
$LastRow = $ws.Dimension.End.Row
$LastCol = $ws.Dimension.End.Column
$endAddress = $ws.Dimension.End.Address
$LastRow = $ws.Dimension.End.Row
$LastCol = $ws.Dimension.End.Column
$endAddress = $ws.Dimension.End.Address
}
else {
$LastRow = $row
$LastCol = $ColumnIndex
$endAddress = [OfficeOpenXml.ExcelAddress]::GetAddress($LastRow , $LastCol)
$LastRow = $row
$LastCol = $ColumnIndex
$endAddress = [OfficeOpenXml.ExcelAddress]::GetAddress($LastRow , $LastCol)
}
$startAddress = [OfficeOpenXml.ExcelAddress]::GetAddress($StartRow, $StartColumn)
$dataRange = "{0}:{1}" -f $startAddress, $endAddress
$startAddress = [OfficeOpenXml.ExcelAddress]::GetAddress($StartRow, $StartColumn)
$dataRange = "{0}:{1}" -f $startAddress, $endAddress
Write-Debug "Data Range '$dataRange'"
if ($AutoNameRange) {
@@ -385,13 +395,14 @@
# if there aren't any headers, use the the first row of data to name the ranges: this is the last point that headers will be used.
$headerRange = $ws.Dimension.Address -replace "\d+$", $StartRow
#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 += $_ }
if ($PSBoundParameters.ContainsKey($TargetData)) { #if Export was called with data that writes no header start the range at $startRow ($startRow is data)
$targetRow = $StartRow
$ws.Cells[$headerRange].Value | ForEach-Object -Begin { $Script:header = @() } -Process { $Script:header += $_ }
if ($PSBoundParameters.ContainsKey($TargetData)) {
#if Export was called with data that writes no header start the range at $startRow ($startRow is data)
$targetRow = $StartRow
}
else { $targetRow = $StartRow + 1 } #if Export was called without data to add names (assume $startRow is a header) or...
} # ... called with data that writes a header, then start the range at $startRow + 1
else { $targetRow = $StartRow + 1 }
else { $targetRow = $StartRow + 1 }
#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.
@@ -400,7 +411,8 @@
foreach ($c in 0..($LastCol - $StartColumn)) {
$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 )]
try {#this test can throw with some names, surpress any error
try {
#this test can throw with some names, surpress any error
if ([OfficeOpenXml.FormulaParsing.ExcelUtilities.ExcelAddressUtil]::IsValidAddress(($targetRangeName -replace '\W' , '_' ))) {
Write-Warning -Message "AutoNameRange: Property name '$targetRangeName' is also a valid Excel address and may cause issues. Consider renaming the property."
}
@@ -410,16 +422,16 @@
}
}
}
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 }
#Allow table to be inserted by specifying Name, or Style or both; only process autoFilter if there is no table (they clash).
if ($null -ne $TableName -or $PSBoundParameters.ContainsKey('TableStyle')) {
if ($null -ne $TableName -or $PSBoundParameters.ContainsKey('TableStyle')) {
#Already inserted Excel table if input was a DataTable
if ($InputObject -isnot [System.Data.DataTable]) {
Add-ExcelTable -Range $ws.Cells[$dataRange] -TableName $TableName -TableStyle $TableStyle
Add-ExcelTable -Range $ws.Cells[$dataRange] -TableName $TableName -TableStyle $TableStyle -TableTotalSettings $TableTotalSettings
}
}
elseif ($AutoFilter) {
@@ -427,19 +439,19 @@
$ws.Cells[$dataRange].AutoFilter = $true
Write-Verbose -Message "Enabled autofilter. "
}
catch {Write-Warning -Message "Failed adding autofilter to worksheet '$WorksheetName': $_"}
catch { Write-Warning -Message "Failed adding autofilter to worksheet '$WorksheetName': $_" }
}
if ($PivotTableDefinition) {
foreach ($item in $PivotTableDefinition.GetEnumerator()) {
$params = $item.value
if ($Activate) {$params.Activate = $true }
if ($Activate) { $params.Activate = $true }
if ($params.keys -notcontains 'SourceRange' -and
($params.Keys -notcontains 'SourceWorksheet' -or $params.SourceWorksheet -eq $WorksheetName)) {$params.SourceRange = $dataRange}
if ($params.Keys -notcontains 'SourceWorksheet') {$params.SourceWorksheet = $ws }
if ($params.Keys -notcontains 'NoTotalsInPivot' -and $NoTotalsInPivot ) {$params.PivotTotals = 'None'}
if ($params.Keys -notcontains 'PivotTotals' -and $PivotTotals ) {$params.PivotTotals = $PivotTotals}
if ($params.Keys -notcontains 'PivotDataToColumn' -and $PivotDataToColumn) {$params.PivotDataToColumn = $true}
($params.Keys -notcontains 'SourceWorksheet' -or $params.SourceWorksheet -eq $WorksheetName)) { $params.SourceRange = $dataRange }
if ($params.Keys -notcontains 'SourceWorksheet') { $params.SourceWorksheet = $ws }
if ($params.Keys -notcontains 'NoTotalsInPivot' -and $NoTotalsInPivot ) { $params.PivotTotals = 'None' }
if ($params.Keys -notcontains 'PivotTotals' -and $PivotTotals ) { $params.PivotTotals = $PivotTotals }
if ($params.Keys -notcontains 'PivotDataToColumn' -and $PivotDataToColumn) { $params.PivotDataToColumn = $true }
Add-PivotTable -ExcelPackage $pkg -PivotTableName $item.key @Params
}
@@ -453,23 +465,23 @@
$PivotTableName += 'Pivot'
}
if ($PivotTableName) {$params.PivotTableName = $PivotTableName}
else {$params.PivotTableName = $WorksheetName + 'PivotTable'}
if ($Activate) {$params.Activate = $true }
if ($PivotFilter) {$params.PivotFilter = $PivotFilter}
if ($PivotRows) {$params.PivotRows = $PivotRows}
if ($PivotColumns) {$Params.PivotColumns = $PivotColumns}
if ($PivotData) {$Params.PivotData = $PivotData}
if ($NoTotalsInPivot) {$params.PivotTotals = "None" }
Elseif ($PivotTotals) {$params.PivotTotals = $PivotTotals}
if ($PivotDataToColumn) {$params.PivotDataToColumn = $true}
if ($PivotTableName) { $params.PivotTableName = $PivotTableName }
else { $params.PivotTableName = $WorksheetName + 'PivotTable' }
if ($Activate) { $params.Activate = $true }
if ($PivotFilter) { $params.PivotFilter = $PivotFilter }
if ($PivotRows) { $params.PivotRows = $PivotRows }
if ($PivotColumns) { $Params.PivotColumns = $PivotColumns }
if ($PivotData) { $Params.PivotData = $PivotData }
if ($NoTotalsInPivot) { $params.PivotTotals = "None" }
Elseif ($PivotTotals) { $params.PivotTotals = $PivotTotals }
if ($PivotDataToColumn) { $params.PivotDataToColumn = $true }
if ($IncludePivotChart -or
$PSBoundParameters.ContainsKey('PivotChartType')) {
$params.IncludePivotChart = $true
$Params.ChartType = $PivotChartType
if ($ShowCategory) {$params.ShowCategory = $true}
if ($ShowPercent) {$params.ShowPercent = $true}
if ($NoLegend) {$params.NoLegend = $true}
$params.IncludePivotChart = $true
$Params.ChartType = $PivotChartType
if ($ShowCategory) { $params.ShowCategory = $true }
if ($ShowPercent) { $params.ShowPercent = $true }
if ($NoLegend) { $params.NoLegend = $true }
}
Add-PivotTable -ExcelPackage $pkg -SourceWorksheet $ws @params
}
@@ -488,7 +500,7 @@
}
elseif ($FreezeTopRow) {
if ($Title) {
$ws.View.FreezePanes(2, 1)
$ws.View.FreezePanes(3, 1)
Write-Verbose -Message "Froze title and header rows"
}
else {
@@ -513,9 +525,10 @@
}
}
}
catch {Write-Warning -Message "Failed adding Freezing the panes in worksheet '$WorksheetName': $_"}
catch { Write-Warning -Message "Failed adding Freezing the panes in worksheet '$WorksheetName': $_" }
if ($PSBoundParameters.ContainsKey("BoldTopRow")) { #it sets bold as far as there are populated cells: for whole row could do $ws.row($x).style.font.bold = $true
if ($PSBoundParameters.ContainsKey("BoldTopRow")) {
#it sets bold as far as there are populated cells: for whole row could do $ws.row($x).style.font.bold = $true
try {
if ($Title) {
$range = $ws.Dimension.Address -replace '\d+', ($StartRow + 1)
@@ -526,41 +539,41 @@
$ws.Cells[$range].Style.Font.Bold = [boolean]$BoldTopRow
Write-Verbose -Message "Set $range font style to bold."
}
catch {Write-Warning -Message "Failed setting the top row to bold in worksheet '$WorksheetName': $_"}
catch { Write-Warning -Message "Failed setting the top row to bold in worksheet '$WorksheetName': $_" }
}
if ($AutoSize -and -not $env:NoAutoSize) {
try {
#Don't fit the all the columns in the sheet; if we are adding cells beside things with hidden columns, that unhides them
if ($MaxAutoSizeRows -and $MaxAutoSizeRows -lt $LastRow ) {
$AutosizeRange = [OfficeOpenXml.ExcelAddress]::GetAddress($startRow,$StartColumn, $MaxAutoSizeRows , $LastCol)
$AutosizeRange = [OfficeOpenXml.ExcelAddress]::GetAddress($startRow, $StartColumn, $MaxAutoSizeRows , $LastCol)
$ws.Cells[$AutosizeRange].AutoFitColumns()
}
else {$ws.Cells[$dataRange].AutoFitColumns() }
else { $ws.Cells[$dataRange].AutoFitColumns() }
Write-Verbose -Message "Auto-sized columns"
}
catch { Write-Warning -Message "Failed autosizing columns of worksheet '$WorksheetName': $_"}
catch { Write-Warning -Message "Failed autosizing columns of worksheet '$WorksheetName': $_" }
}
elseif ($AutoSize) {Write-Warning -Message "Auto-fitting columns is not available with this OS configuration." }
elseif ($AutoSize) { Write-Warning -Message "Auto-fitting columns is not available with this OS configuration." }
foreach ($Sheet in $HideSheet) {
try {
$pkg.Workbook.Worksheets.Where({$_.Name -like $sheet}) | ForEach-Object {
$pkg.Workbook.Worksheets.Where({ $_.Name -like $sheet }) | ForEach-Object {
$_.Hidden = 'Hidden'
Write-verbose -Message "Sheet '$($_.Name)' Hidden."
}
}
catch {Write-Warning -Message "Failed hiding worksheet '$sheet': $_"}
catch { Write-Warning -Message "Failed hiding worksheet '$sheet': $_" }
}
foreach ($Sheet in $UnHideSheet) {
try {
$pkg.Workbook.Worksheets.Where({$_.Name -like $sheet}) | ForEach-Object {
$pkg.Workbook.Worksheets.Where({ $_.Name -like $sheet }) | ForEach-Object {
$_.Hidden = 'Visible'
Write-verbose -Message "Sheet '$($_.Name)' shown"
}
}
catch {Write-Warning -Message "Failed showing worksheet '$sheet': $_"}
catch { Write-Warning -Message "Failed showing worksheet '$sheet': $_" }
}
if (-not $pkg.Workbook.Worksheets.Where({$_.Hidden -eq 'visible'})) {
if (-not $pkg.Workbook.Worksheets.Where({ $_.Hidden -eq 'visible' })) {
Write-Verbose -Message "No Sheets were left visible, making $WorksheetName visible"
$ws.Hidden = 'Visible'
}
@@ -568,46 +581,46 @@
foreach ($chartDef in $ExcelChartDefinition) {
if ($chartDef -is [System.Management.Automation.PSCustomObject]) {
$params = @{}
$chartDef.PSObject.Properties | ForEach-Object {if ( $null -ne $_.value) {$params[$_.name] = $_.value}}
$chartDef.PSObject.Properties | ForEach-Object { if ( $null -ne $_.value) { $params[$_.name] = $_.value } }
Add-ExcelChart -Worksheet $ws @params
}
elseif ($chartDef -is [hashtable] -or $chartDef -is[System.Collections.Specialized.OrderedDictionary]) {
elseif ($chartDef -is [hashtable] -or $chartDef -is [System.Collections.Specialized.OrderedDictionary]) {
Add-ExcelChart -Worksheet $ws @chartDef
}
}
if ($Calculate) {
try { [OfficeOpenXml.CalculationExtension]::Calculate($ws) }
catch { Write-Warning "One or more errors occured while calculating, save will continue, but there may be errors in the workbook. $_"}
try { [OfficeOpenXml.CalculationExtension]::Calculate($ws) }
catch { Write-Warning "One or more errors occured while calculating, save will continue, but there may be errors in the workbook. $_" }
}
if ($Barchart -or $PieChart -or $LineChart -or $ColumnChart) {
if ($NoHeader) {$FirstDataRow = $startRow}
else {$FirstDataRow = $startRow + 1 }
if ($NoHeader) { $FirstDataRow = $startRow }
else { $FirstDataRow = $startRow + 1 }
$range = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $startColumn, $FirstDataRow, $lastCol )
$xCol = $ws.cells[$range] | Where-Object {$_.value -is [string] } | ForEach-Object {$_.start.column} | Sort-Object | Select-Object -first 1
$xCol = $ws.cells[$range] | Where-Object { $_.value -is [string] } | ForEach-Object { $_.start.column } | Sort-Object | Select-Object -first 1
if (-not $xcol) {
$xcol = $StartColumn
$range = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, ($startColumn +1), $FirstDataRow, $lastCol )
$xcol = $StartColumn
$range = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, ($startColumn + 1), $FirstDataRow, $lastCol )
}
$yCol = $ws.cells[$range] | Where-Object {$_.value -is [valueType] -or $_.Formula } | ForEach-Object {$_.start.column} | Sort-Object | Select-Object -first 1
if (-not ($xCol -and $ycol)) { Write-Warning -Message "Can't identify a string column and a number column to use as chart labels and data. "}
$yCol = $ws.cells[$range] | Where-Object { $_.value -is [valueType] -or $_.Formula } | ForEach-Object { $_.start.column } | Sort-Object | Select-Object -first 1
if (-not ($xCol -and $ycol)) { Write-Warning -Message "Can't identify a string column and a number column to use as chart labels and data. " }
else {
$params = @{
XRange = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $xcol , $lastrow, $xcol)
YRange = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $ycol , $lastrow, $ycol)
Title = ''
Column = ($lastCol +1)
Width = 800
XRange = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $xcol , $lastrow, $xcol)
YRange = [OfficeOpenXml.ExcelAddress]::GetAddress($FirstDataRow, $ycol , $lastrow, $ycol)
Title = ''
Column = ($lastCol + 1)
Width = 800
}
if ($ShowPercent) {$params["ShowPercent"] = $true}
if ($ShowCategory) {$params["ShowCategory"] = $true}
if ($NoLegend) {$params["NoLegend"] = $true}
if (-not $NoHeader) {$params["SeriesHeader"] = $ws.Cells[$startRow, $YCol].Value}
if ($ColumnChart) {$Params["chartType"] = "ColumnStacked" }
elseif ($Barchart) {$Params["chartType"] = "BarStacked" }
elseif ($PieChart) {$Params["chartType"] = "PieExploded3D" }
elseif ($LineChart) {$Params["chartType"] = "Line" }
if ($ShowPercent) { $params["ShowPercent"] = $true }
if ($ShowCategory) { $params["ShowCategory"] = $true }
if ($NoLegend) { $params["NoLegend"] = $true }
if (-not $NoHeader) { $params["SeriesHeader"] = $ws.Cells[$startRow, $YCol].Value }
if ($ColumnChart) { $Params["chartType"] = "ColumnStacked" }
elseif ($Barchart) { $Params["chartType"] = "BarStacked" }
elseif ($PieChart) { $Params["chartType"] = "PieExploded3D" }
elseif ($LineChart) { $Params["chartType"] = "Line" }
Add-ExcelChart -Worksheet $ws @params
}
@@ -615,35 +628,36 @@
# It now doesn't matter if the conditional formating rules are passed in $conditionalText or $conditional format.
# Just one with an alias for compatiblity it will break things for people who are using both at once
foreach ($c in (@() + $ConditionalText + $ConditionalFormat) ) {
foreach ($c in (@() + $ConditionalText + $ConditionalFormat) ) {
try {
#we can take an object with a .ConditionalType property made by New-ConditionalText or with a .Formatter Property made by New-ConditionalFormattingIconSet or a hash table
if ($c.ConditionalType) {
$cfParams = @{RuleType = $c.ConditionalType; ConditionValue = $c.Text ;
BackgroundColor = $c.BackgroundColor; BackgroundPattern = $c.PatternType ;
ForeGroundColor = $c.ConditionalTextColor}
if ($c.Range) {$cfParams.Range = $c.Range}
else {$cfParams.Range = $ws.Dimension.Address }
$cfParams = @{RuleType = $c.ConditionalType; ConditionValue = $c.Text ;
BackgroundColor = $c.BackgroundColor; BackgroundPattern = $c.PatternType ;
ForeGroundColor = $c.ConditionalTextColor
}
if ($c.Range) { $cfParams.Range = $c.Range }
else { $cfParams.Range = $ws.Dimension.Address }
Add-ConditionalFormatting -Worksheet $ws @cfParams
Write-Verbose -Message "Added conditional formatting to range $($c.range)"
}
elseif ($c.formatter) {
elseif ($c.formatter) {
switch ($c.formatter) {
"ThreeIconSet" {Add-ConditionalFormatting -Worksheet $ws -ThreeIconsSet $c.IconType -range $c.range -reverse:$c.reverse }
"FourIconSet" {Add-ConditionalFormatting -Worksheet $ws -FourIconsSet $c.IconType -range $c.range -reverse:$c.reverse }
"FiveIconSet" {Add-ConditionalFormatting -Worksheet $ws -FiveIconsSet $c.IconType -range $c.range -reverse:$c.reverse }
"ThreeIconSet" { Add-ConditionalFormatting -Worksheet $ws -ThreeIconsSet $c.IconType -range $c.range -reverse:$c.reverse -ShowIconOnly:$c.ShowIconOnly}
"FourIconSet" { Add-ConditionalFormatting -Worksheet $ws -FourIconsSet $c.IconType -range $c.range -reverse:$c.reverse -ShowIconOnly:$c.ShowIconOnly}
"FiveIconSet" { Add-ConditionalFormatting -Worksheet $ws -FiveIconsSet $c.IconType -range $c.range -reverse:$c.reverse -ShowIconOnly:$c.ShowIconOnly}
}
Write-Verbose -Message "Added conditional formatting to range $($c.range)"
}
elseif ($c -is [hashtable] -or $c -is[System.Collections.Specialized.OrderedDictionary]) {
if (-not $c.Range -or $c.Address) {$c.Address = $ws.Dimension.Address }
elseif ($c -is [hashtable] -or $c -is [System.Collections.Specialized.OrderedDictionary]) {
if (-not $c.Range -or $c.Address) { $c.Address = $ws.Dimension.Address }
Add-ConditionalFormatting -Worksheet $ws @c
}
}
catch {throw "Error applying conditional formatting to worksheet $_"}
catch { throw "Error applying conditional formatting to worksheet $_" }
}
foreach ($s in $Style) {
if (-not $s.Range) {$s["Range"] = $ws.Dimension.Address }
if (-not $s.Range) { $s["Range"] = $ws.Dimension.Address }
Set-ExcelRange -Worksheet $ws @s
}
if ($CellStyleSB) {
@@ -652,7 +666,7 @@
$LastColumn = $ws.Dimension.Address -replace "^.*:(\w*)\d+$" , '$1'
& $CellStyleSB $ws $TotalRows $LastColumn
}
catch {Write-Warning -Message "Failed processing CellStyleSB in worksheet '$WorksheetName': $_"}
catch { Write-Warning -Message "Failed processing CellStyleSB in worksheet '$WorksheetName': $_" }
}
#Can only add password, may want to support -password $Null removing password.
@@ -661,32 +675,18 @@
$ws.Protection.SetPassword($Password)
Write-Verbose -Message 'Set password on workbook'
}
catch {throw "Failed setting password for worksheet '$WorksheetName': $_"}
catch { throw "Failed setting password for worksheet '$WorksheetName': $_" }
}
if ($PassThru) { $pkg }
if ($PassThru) { $pkg }
else {
if ($ReturnRange) {$dataRange }
if ($ReturnRange) { $dataRange }
if ($Password) { $pkg.Save($Password) }
else { $pkg.Save() }
if ($Password) { $pkg.Save($Password) }
else { $pkg.Save() }
Write-Verbose -Message "Saved workbook $($pkg.File)"
if ($ReZip) {
Write-Verbose -Message "Re-Zipping $($pkg.file) using .NET ZIP library"
try {
Add-Type -AssemblyName 'System.IO.Compression.Filesystem' -ErrorAction stop
}
catch {
Write-Error "The -ReZip parameter requires .NET Framework 4.5 or later to be installed. Recommend to install Powershell v4+"
continue
}
try {
$TempZipPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath ([System.IO.Path]::GetRandomFileName())
$null = [io.compression.zipfile]::ExtractToDirectory($pkg.File, $TempZipPath)
Remove-Item $pkg.File -Force
$null = [io.compression.zipfile]::CreateFromDirectory($TempZipPath, $pkg.File)
}
catch {throw "Error resizipping $path : $_"}
Invoke-ExcelReZipFile -ExcelPackage $pkg
}
$pkg.Dispose()

View File

@@ -16,6 +16,7 @@ function Get-ExcelFileSummary {
[PSCustomObject][Ordered]@{
ExcelFile = Split-Path -Leaf $Path
WorksheetName = $workSheet.Name
Visible = $workSheet.Hidden -eq 'Visible'
Rows = $workSheet.Dimension.Rows
Columns = $workSheet.Dimension.Columns
Address = $workSheet.Dimension.Address

View File

@@ -0,0 +1,15 @@
function Get-ExcelSheetDimensionAddress {
<#
.SYNOPSIS
Get the Excel address of the dimension of a sheet
.EXAMPLE
Get-ExcelSheetDimensionAddress $excel.Sheet1
#>
param(
[Parameter(Mandatory)]
[OfficeOpenXml.ExcelWorksheet]$Worksheet
)
$Worksheet.Dimension.Address
}

View File

@@ -9,36 +9,75 @@ function Get-HtmlTable {
[int]$FirstDataRow=0,
[Switch]$UseDefaultCredentials
)
if ($PSVersionTable.PSVersion.Major -gt 5 -and -not (Get-Command ConvertFrom-Html -ErrorAction SilentlyContinue)) {
# Invoke-WebRequest on .NET core doesn't have ParsedHtml so we need HtmlAgilityPack or similiar Justin Grote's PowerHTML wraps that nicely
throw "This version of PowerShell needs the PowerHTML module to process HTML Tables."
}
$r = Invoke-WebRequest $Url -UseDefaultCredentials: $UseDefaultCredentials
$propertyNames = $Header
$table = $r.ParsedHtml.getElementsByTagName("table")[$TableIndex]
$propertyNames=$Header
$totalRows=@($table.rows).count
if ($PSVersionTable.PSVersion.Major -le 5) {
$table = $r.ParsedHtml.getElementsByTagName("table")[$TableIndex]
$totalRows=@($table.rows).count
for ($idx = $FirstDataRow; $idx -lt $totalRows; $idx++) {
for ($idx = $FirstDataRow; $idx -lt $totalRows; $idx++) {
$row = $table.rows[$idx]
$cells = @($row.cells)
$row = $table.rows[$idx]
$cells = @($row.cells)
if(!$propertyNames) {
if($cells[0].tagName -eq 'th') {
$propertyNames = @($cells | ForEach-Object {$_.innertext -replace ' ',''})
} else {
$propertyNames = @(1..($cells.Count + 2) | Foreach-Object { "P$_" })
if(!$propertyNames) {
if($cells[0].tagName -eq 'th') {
$propertyNames = @($cells | ForEach-Object {$_.innertext -replace ' ',''})
} else {
$propertyNames = @(1..($cells.Count + 2) | Foreach-Object { "P$_" })
}
continue
}
continue
$result = [ordered]@{}
for($counter = 0; $counter -lt $cells.Count; $counter++) {
$propertyName = $propertyNames[$counter]
if(!$propertyName) { $propertyName= '[missing]'}
$result.$propertyName= $cells[$counter].InnerText
}
[PSCustomObject]$result
}
$result = [ordered]@{}
for($counter = 0; $counter -lt $cells.Count; $counter++) {
$propertyName = $propertyNames[$counter]
if(!$propertyName) { $propertyName= '[missing]'}
$result.$propertyName= $cells[$counter].InnerText
}
else {
$h = ConvertFrom-Html -Content $r.Content
if ($TableIndex -is [valuetype]) { $TableIndex += 1}
$rows = $h.SelectNodes("//table[$TableIndex]//tr")
if (-not $rows) {Write-Warning "Could not find rows for `"//table[$TableIndex]`" in $Url ."}
if ( -not $propertyNames) {
if ( $tableHeaders = $rows[$FirstDataRow].SelectNodes("th")) {
$propertyNames = $tableHeaders.foreach({[System.Web.HttpUtility]::HtmlDecode( $_.innerText ) -replace '\W+','_' -replace '(\w)_+$','$1' })
$FirstDataRow += 1
}
else {
$c = 0
$propertyNames = $rows[$FirstDataRow].SelectNodes("td") | Foreach-Object { "P$c" ; $c ++ }
}
}
Write-Verbose ("Property names: " + ($propertyNames -join ","))
foreach ($n in $FirstDataRow..($rows.Count-1)) {
$r = $rows[$n].SelectNodes("td|th")
if ($r -and $r.innerText -ne "" -and $r.count -gt $rows[$n].SelectNodes("th").count ) {
$c = 0
$newObj = [ordered]@{}
foreach ($p in $propertyNames) {
$n = $null
#Join descentandts for cases where the text in the cell is split (e.g with a <BR> ). We also want to remove HTML codes, trim and convert unicode minus sign to "-"
$cellText = $r[$c].Descendants().where({$_.NodeType -eq "Text"}).foreach({[System.Web.HttpUtility]::HtmlDecode( $_.innerText ).Trim()}) -Join " " -replace "\u2212","-"
if ([double]::TryParse($cellText, [ref]$n)) {$newObj[$p] = $n }
else {$newObj[$p] = $cellText }
$c ++
}
[pscustomObject]$newObj
}
}
[PSCustomObject]$result
}
}

View File

@@ -15,7 +15,7 @@
[Alias('Sheet')]
[Parameter(Position = 1)]
[ValidateNotNullOrEmpty()]
[String]$WorksheetName,
[String[]]$WorksheetName,
[Parameter(ParameterSetName = 'PathB' , Mandatory)]
[Parameter(ParameterSetName = 'PackageB', Mandatory)]
[String[]]$HeaderName ,
@@ -23,7 +23,7 @@
[Parameter(ParameterSetName = 'PackageC', Mandatory)]
[Switch]$NoHeader ,
[Alias('HeaderRow', 'TopRow')]
[ValidateRange(1, 9999)]
[ValidateRange(1, 1048576)]
[Int]$StartRow = 1,
[Alias('StopRow', 'BottomRow')]
[Int]$EndRow ,
@@ -35,7 +35,10 @@
[string[]]$AsText,
[string[]]$AsDate,
[ValidateNotNullOrEmpty()]
[String]$Password
[String]$Password,
[Int[]]$ImportColumns,
[Switch]$Raw,
[Switch]$UseSpectre
)
end {
$sw = [System.Diagnostics.Stopwatch]::StartNew()
@@ -62,6 +65,16 @@
)
try {
if ($ImportColumns) {
$end = $sheet.Dimension.End.Column
# Check $ImportColumns
if ($ImportColumns[0] -le 0) { throw "The first entry in ImportColumns must be equal or greater 1" ; return }
# Check $StartColumn and $EndColumn
if (($StartColumn -ne 1) -or ($EndColumn -ne $end)) { Write-Warning -Message "If ImportColumns is set, then individual StartColumn and EndColumn will be ignored." }
# Replace $Columns with $ImportColumns
$Columns = $ImportColumns
}
if ($HeaderName) {
$i = 0
foreach ($H in $HeaderName) {
@@ -84,7 +97,7 @@
foreach ($C in $Columns) {
#allow "False" or "0" to be column headings
$Worksheet.Cells[$StartRow, $C] | Where-Object {-not [string]::IsNullOrEmpty($_.Value) } | Select-Object @{N = 'Column'; E = { $C } }, Value
$sheet.Cells[$StartRow, $C] | Where-Object { -not [string]::IsNullOrEmpty($_.Value) } | Select-Object @{N = 'Column'; E = { $C } }, Value
}
}
}
@@ -114,108 +127,141 @@
}
try {
#Select worksheet
if (-not $WorksheetName) { $Worksheet = $ExcelPackage.Workbook.Worksheets[1] }
if ($WorksheetName -eq '*') { $Worksheet = $ExcelPackage.Workbook.Worksheets }
elseif (-not $WorksheetName) { $Worksheet = $ExcelPackage.Workbook.Worksheets[1] }
elseif (-not ($Worksheet = $ExcelPackage.Workbook.Worksheets[$WorksheetName])) {
throw "Worksheet '$WorksheetName' not found, the workbook only contains the worksheets '$($ExcelPackage.Workbook.Worksheets)'. If you only wish to select the first worksheet, please remove the '-WorksheetName' parameter." ; return
}
#region Get rows and columns
#If we are doing dataonly it is quicker to work out which rows to ignore before processing the cells.
if (-not $EndRow ) { $EndRow = $Worksheet.Dimension.End.Row }
if (-not $EndColumn) { $EndColumn = $Worksheet.Dimension.End.Column }
$endAddress = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[$EndRow]C[$EndColumn]", 0, 0)
if ($DataOnly) {
#If we are using headers startrow will be the header-row so examine data from startRow + 1,
if ($NoHeader) { $range = "A" + ($StartRow ) + ":" + $endAddress }
else { $range = "A" + ($StartRow + 1 ) + ":" + $endAddress }
#We're going to look at every cell and build 2 hash tables holding rows & columns which contain data.
#Want to Avoid 'select unique' operations & large Sorts, becuse time time taken increases with square
#of number of items (PS uses heapsort at large size). Instead keep a list of what we have seen,
#using Hash tables: "we've seen it" is all we need, no need to worry about "seen it before" / "Seen it many times".
$colHash = @{ }
$rowHash = @{ }
foreach ($cell in $Worksheet.Cells[$range]) {
if ($null -ne $cell.Value ) { $colHash[$cell.Start.Column] = 1; $rowHash[$cell.Start.row] = 1 }
}
$rows = ( $StartRow..$EndRow ).Where( { $rowHash[$_] })
$columns = ($StartColumn..$EndColumn).Where( { $colHash[$_] })
}
else {
$Columns = $StartColumn .. $EndColumn ; if ($StartColumn -gt $EndColumn) { Write-Warning -Message "Selecting columns $StartColumn to $EndColumn might give odd results." }
if ($NoHeader) { $rows = $StartRow..$EndRow ; if ($StartRow -gt $EndRow) { Write-Warning -Message "Selecting rows $StartRow to $EndRow might give odd results." } }
elseif ($HeaderName) { $rows = $StartRow..$EndRow }
else {
$rows = (1 + $StartRow)..$EndRow
if ($StartRow -eq 1 -and $EndRow -eq 1) {
$rows = 0
}
$xlBook = [Ordered]@{}
foreach ($sheet in $Worksheet) {
if ($Worksheet.Count -gt 1 -or $Paths.Count -gt 1) {
<#
Needed under these conditions to handle sheets of different number of Row/Col
- When reading more than one xlsx file
- When reading more than one worksheet in the same file
#>
$EndRow = $null
$EndColumn = $null
}
# ; if ($StartRow -ge $EndRow) { Write-Warning -Message "Selecting $StartRow as the header with data in $(1+$StartRow) to $EndRow might give odd results." } }
}
#endregion
#region Create property names
if ((-not $Columns) -or (-not ($PropertyNames = Get-PropertyNames -Columns $Columns -StartRow $StartRow))) {
throw "No column headers found on top row '$StartRow'. If column headers in the worksheet are not a requirement then please use the '-NoHeader' or '-HeaderName' parameter."; return
}
if ($Duplicates = $PropertyNames | Group-Object Value | Where-Object Count -GE 2) {
throw "Duplicate column headers found on row '$StartRow' in columns '$($Duplicates.Group.Column)'. Column headers must be unique, if this is not a requirement please use the '-NoHeader' or '-HeaderName' parameter."; return
}
#endregion
if (-not $rows) {
Write-Warning "Worksheet '$WorksheetName' in workbook '$Path' contains no data in the rows after top row '$StartRow'"
}
else {
#region Create one object per row
if ($AsText -or $AsDate) {
<#join items in AsText together with ~~~ . Escape any regex special characters...
$targetSheetname = $sheet.Name
$xlBook["$targetSheetname"] = @()
#region Get rows and columns
#If we are doing dataonly it is quicker to work out which rows to ignore before processing the cells.
if (-not $EndRow ) { $EndRow = $sheet.Dimension.End.Row }
if (-not $EndColumn) { $EndColumn = $sheet.Dimension.End.Column }
$endAddress = [OfficeOpenXml.ExcelAddress]::TranslateFromR1C1("R[$EndRow]C[$EndColumn]", 0, 0)
if ($DataOnly) {
#If we are using headers startrow will be the header-row so examine data from startRow + 1,
if ($NoHeader) { $range = "A" + ($StartRow ) + ":" + $endAddress }
else { $range = "A" + ($StartRow + 1 ) + ":" + $endAddress }
#We're going to look at every cell and build 2 hash tables holding rows & columns which contain data.
#Want to Avoid 'select unique' operations & large Sorts, becuse time time taken increases with square
#of number of items (PS uses heapsort at large size). Instead keep a list of what we have seen,
#using Hash tables: "we've seen it" is all we need, no need to worry about "seen it before" / "Seen it many times".
$colHash = @{ }
$rowHash = @{ }
foreach ($cell in $sheet.Cells[$range]) {
if ($null -ne $cell.Value ) { $colHash[$cell.Start.Column] = 1; $rowHash[$cell.Start.row] = 1 }
}
$rows = ( $StartRow..$EndRow ).Where( { $rowHash[$_] })
$columns = ($StartColumn..$EndColumn).Where( { $colHash[$_] })
}
else {
$Columns = $StartColumn .. $EndColumn ; if ($StartColumn -gt $EndColumn) { Write-Warning -Message "Selecting columns $StartColumn to $EndColumn might give odd results." }
if ($NoHeader) { $rows = $StartRow..$EndRow ; if ($StartRow -gt $EndRow) { Write-Warning -Message "Selecting rows $StartRow to $EndRow might give odd results." } }
elseif ($HeaderName) { $rows = $StartRow..$EndRow }
else {
$rows = (1 + $StartRow)..$EndRow
if ($StartRow -eq 1 -and $EndRow -eq 1) {
$rows = 0
}
}
# ; if ($StartRow -ge $EndRow) { Write-Warning -Message "Selecting $StartRow as the header with data in $(1+$StartRow) to $EndRow might give odd results." } }
}
#endregion
#region Create property names
if ((-not $Columns) -or (-not ($PropertyNames = Get-PropertyNames -Columns $Columns -StartRow $StartRow))) {
throw "No column headers found on top row '$StartRow'. If column headers in the worksheet are not a requirement then please use the '-NoHeader' or '-HeaderName' parameter."; return
}
if ($Duplicates = $PropertyNames | Group-Object Value | Where-Object Count -GE 2) {
throw "Duplicate column headers found on row '$StartRow' in columns '$($Duplicates.Group.Column)'. Column headers must be unique, if this is not a requirement please use the '-NoHeader' or '-HeaderName' parameter."; return
}
#endregion
if (-not $rows) {
Write-Warning "Worksheet '$WorksheetName' in workbook '$Path' contains no data in the rows after top row '$StartRow'"
}
else {
#region Create one object per row
if ($AsText -or $AsDate) {
<#join items in AsText together with ~~~ . Escape any regex special characters...
# which turns "*" into "\*" make it ".*". Convert ~~~ to $|^ and top and tail with ^%;
So if we get "Week", "[Time]" and "*date*" ; make the expression ^week$|^\[Time\]$|^.*Date.*$
$make a regex for this which is case insensitive (option 1) and compiled (option 8)
#>
$TextColExpression = ''
if ($AsText) {
$TextColExpression += '(?<astext>^' + [regex]::Escape($AsText -join '~~~').replace('\*', '.*').replace('~~~', '$|^') + '$)'
}
if ($AsText -and $AsDate) {
$TextColExpression += "|"
}
if ($AsDate) {
$TextColExpression += '(?<asDate>^' + [regex]::Escape($AsDate -join '~~~').replace('\*', '.*').replace('~~~', '$|^') + '$)'
}
$TextColRegEx = New-Object -TypeName regex -ArgumentList $TextColExpression , 9
}
else {$TextColRegEx = $null}
foreach ($R in $rows) {
#Disabled write-verbose for speed
# Write-Verbose "Import row '$R'"
$NewRow = [Ordered]@{ }
if ($TextColRegEx) {
foreach ($P in $PropertyNames) {
$MatchTest = $TextColRegEx.Match($P.value)
if ($MatchTest.groups.name -eq "astext") {
$NewRow[$P.Value] = $Worksheet.Cells[$R, $P.Column].Text
}
elseif ($MatchTest.groups.name -eq "asdate" -and $Worksheet.Cells[$R, $P.Column].Value -is [System.ValueType]) {
$NewRow[$P.Value] = [datetime]::FromOADate(($Worksheet.Cells[$R, $P.Column].Value))
}
else { $NewRow[$P.Value] = $Worksheet.Cells[$R, $P.Column].Value }
$TextColExpression = ''
if ($AsText) {
$TextColExpression += '(?<astext>^' + [regex]::Escape($AsText -join '~~~').replace('\*', '.*').replace('~~~', '$|^') + '$)'
}
}
else {
foreach ($P in $PropertyNames) {
$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)'."
if ($AsText -and $AsDate) {
$TextColExpression += "|"
}
if ($AsDate) {
$TextColExpression += '(?<asDate>^' + [regex]::Escape($AsDate -join '~~~').replace('\*', '.*').replace('~~~', '$|^') + '$)'
}
$TextColRegEx = New-Object -TypeName regex -ArgumentList $TextColExpression , 9
}
[PSCustomObject]$NewRow
else { $TextColRegEx = $null }
foreach ($R in $rows) {
#Disabled write-verbose for speed
# Write-Verbose "Import row '$R'"
$NewRow = [Ordered]@{ }
if ($TextColRegEx) {
foreach ($P in $PropertyNames) {
$MatchTest = $TextColRegEx.Match($P.value)
if ($MatchTest.groups.name -eq "astext") {
$NewRow[$P.Value] = $sheet.Cells[$R, $P.Column].Text
}
elseif ($MatchTest.groups.name -eq "asdate" -and $sheet.Cells[$R, $P.Column].Value -is [System.ValueType]) {
$NewRow[$P.Value] = [datetime]::FromOADate(($sheet.Cells[$R, $P.Column].Value))
}
else { $NewRow[$P.Value] = $sheet.Cells[$R, $P.Column].Value }
}
}
else {
foreach ($P in $PropertyNames) {
$NewRow[$P.Value] = $sheet.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)'."
}
}
$xlBook["$targetSheetname"] += [PSCustomObject]$NewRow
}
#endregion
}
#endregion
}
}
catch { throw "Failed importing the Excel workbook '$Path' with worksheet '$WorksheetName': $_"; return }
finally {
# $EndRow = 0
# $EndColumn = 0
if ($Path) { $stream.close(); $ExcelPackage.Dispose() }
if ($Raw) {
foreach ($entry in $xlbook.GetEnumerator()) {
$entry.Value
}
}
elseif ($UseSpectre) {
$xlBook | Format-SpectreTable
}
elseif ($Worksheet.Count -eq 1) {
$xlBook["$targetSheetname"]
}
else {
$xlBook
}
}
}
}

View File

@@ -3,13 +3,13 @@ function Import-Html {
[CmdletBinding()]
param(
$Url,
$Index,
[int]$Index = 0,
$Header,
[int]$FirstDataRow=0,
[int]$FirstDataRow = 0,
[Switch]$UseDefaultCredentials
)
$xlFile = [System.IO.Path]::GetTempFileName() -replace "tmp","xlsx"
$xlFile = [System.IO.Path]::GetTempFileName() -replace "tmp", "xlsx"
Remove-Item $xlFile -ErrorAction Ignore
Write-Verbose "Exporting to Excel file $($xlFile)"

View File

@@ -0,0 +1,63 @@
#Requires -Version 5
function Invoke-ExcelQuery {
<#
.SYNOPSIS
Helper method for executing Read-OleDbData with some basic defaults.
For additional help, see documentation for Read-OleDbData cmdlet.
.DESCRIPTION
Uses Read-OleDbData to execute a sql statement against a xlsx file. For finer grained control over the interaction, you may use that cmdlet. This cmdlet assumes a file path will be passed in and the connection string will be built with no headers and treating all results as text.
Running this command is equivalent to running the following:
$FullName = (Get-ChildItem $Path).FullName
Read-OleDbData `
-ConnectionString "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=$FullName;Extended Properties='Excel 12.0 Xml;HDR=NO;IMEX=1;'" `
-SqlStatement $Query
Note that this command uses the MICROSOFT.ACE.OLEDB provider and will not work without it.
If needed, please download the appropriate package from https://www.microsoft.com/en-us/download/details.aspx?id=54920.
.EXAMPLE
Invoke-ExcelQuery .\test.xlsx 'select ROUND(F1) as [A1] from [sheet3$A1:A1]'
.EXAMPLE
$Path = (Get-ChildItem 'test.xlsx').FullName
$Query = "select ROUND(F1) as [A] from [sheet1$A1:A1]"
Read-XlsxUsingOleDb -Path $Path -Query $Query
.EXAMPLE
$ReadDataArgs = @{
Path = .\test.xlsx
Query = Get-Content query.sql -Raw
}
$Results = Invoke-ExcelQuery @ReadDataArgs
#>
param(
#The path to the file to open.
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String] $Path, # var name consistent with Import-Excel
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String] $Query # var name consistent with Invoke-Sqlcmd
)
try {
if ((New-Object system.data.oledb.oledbenumerator).GetElements().SOURCES_NAME -notcontains "Microsoft.ACE.OLEDB.12.0") {
Write-Error "Microsoft.ACE.OLEDB.12.0 provider is missing! Please install from https://www.microsoft.com/en-us/download/details.aspx?id=54920"
return
}
}
catch {
Write-Error "System.Data.OleDb is not working or you are on an unsupported platform."
return
}
$FullName = (Get-ChildItem $Path).FullName
Read-OleDbData `
-ConnectionString "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=$FullName;Extended Properties='Excel 12.0 Xml;HDR=NO;IMEX=1;'" `
-SqlStatement $Query
}

View File

@@ -1,11 +1,12 @@
function New-ConditionalFormattingIconSet {
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '',Justification='Does not change system State')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Does not change system State')]
param(
[Parameter(Mandatory=$true)]
[Parameter(Mandatory = $true)]
$Range,
[ValidateSet("ThreeIconSet","FourIconSet","FiveIconSet")]
[ValidateSet("ThreeIconSet", "FourIconSet", "FiveIconSet")]
$ConditionalFormat,
[Switch]$Reverse
[Switch]$Reverse,
[Switch]$ShowIconOnly
)
DynamicParam {
@@ -40,13 +41,14 @@ function New-ConditionalFormattingIconSet {
End {
$bp = @{}+$PSBoundParameters
$bp = @{} + $PSBoundParameters
$obj = [PSCustomObject]@{
Range = $Range
Formatter = $ConditionalFormat
IconType = $bp.IconType
Reverse = $Reverse
Range = $Range
Formatter = $ConditionalFormat
IconType = $bp.IconType
Reverse = $Reverse
ShowIconOnly = $ShowIconOnly
}
$obj.pstypenames.Clear()

View File

@@ -16,8 +16,10 @@ function New-PivotTableDefinition {
[String]$PivotTotals = "Both",
[Switch]$NoTotalsInPivot,
[String]$GroupDateRow,
[String]$GroupDateColumn,
[OfficeOpenXml.Table.PivotTable.eDateGroupBy[]]$GroupDatePart,
[String]$GroupNumericRow,
[String]$GroupNumericColumn,
[double]$GroupNumericMin = 0 ,
[double]$GroupNumericMax = [Double]::MaxValue ,
[double]$GroupNumericInterval = 100 ,

View File

@@ -1,10 +1,10 @@
function Open-ExcelPackage {
function Open-ExcelPackage {
[CmdLetBinding()]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword","")]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "")]
[OutputType([OfficeOpenXml.ExcelPackage])]
param(
#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.
[switch]$KillExcel,
#The password for a protected worksheet, as a [normal] string (not a secure string).
@@ -13,7 +13,7 @@
[switch]$Create
)
if($KillExcel) {
if ($KillExcel) {
Get-Process -Name "excel" -ErrorAction Ignore | Stop-Process
while (Get-Process -Name "excel" -ErrorAction Ignore) {}
}
@@ -24,21 +24,26 @@
#Create the directory if required.
$targetPath = Split-Path -Parent -Path $Path
if (!(Test-Path -Path $targetPath)) {
Write-Debug "Base path $($targetPath) does not exist, creating"
$null = New-item -ItemType Directory -Path $targetPath -ErrorAction Ignore
Write-Debug "Base path $($targetPath) does not exist, creating"
$null = New-item -ItemType Directory -Path $targetPath -ErrorAction Ignore
}
New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path
}
elseif (Test-Path -Path $path) {
if ($Password) {$pkgobj = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path , $Password }
else {$pkgobj = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path }
if ($Password) { $pkgobj = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path , $Password }
else { $pkgobj = New-Object -TypeName OfficeOpenXml.ExcelPackage -ArgumentList $Path }
if ($pkgobj) {
foreach ($w in $pkgobj.Workbook.Worksheets) {
$sb = [scriptblock]::Create(('$this.workbook.Worksheets["{0}"]' -f $w.name))
Add-Member -InputObject $pkgobj -MemberType ScriptProperty -Name $w.name -Value $sb
try {
Add-Member -InputObject $pkgobj -MemberType ScriptProperty -Name $w.name -Value $sb -ErrorAction Stop
}
catch {
Write-Warning "Could not add sheet $($w.name) as 'short cut', you need to access it via `$wb.Worksheets['$($w.name)'] "
}
}
return $pkgobj
}
}
else {Write-Warning "Could not find $path" }
}
else { Write-Warning "Could not find $path" }
}

85
Public/Read-Clipboard.ps1 Normal file
View File

@@ -0,0 +1,85 @@
#Requires -Version 5
function Read-Clipboard {
<#
.SYNOPSIS
Read text from clipboard and pass to either ConvertFrom-Csv or ConvertFrom-Json.
Check out the how to video - https://youtu.be/dv2GOH5sbpA
.DESCRIPTION
Read text from clipboard. It can read CSV or JSON. Plus, you can specify the delimiter and headers.
.EXAMPLE
Read-Clipboard # Detects if the clipboard contains CSV, JSON, or Tab delimited data.
.EXAMPLE
Read-Clipboard -Delimiter '|' # Converts data using a pipe delimiter
.EXAMPLE
Read-Clipboard -Header 'P1', 'P2', 'P3' # Specify the header columns to be used
#>
param(
$Delimiter,
$Header
)
if ($IsLinux -or $IsMacOS) {
Write-Error "Read-Clipboard only runs on Windows"
return
}
$cvtParams = @{
Data = Get-Clipboard -Raw
}
if ($Delimiter) {
$cvtParams.Delimiter = $Delimiter
}
if ($Header) {
$cvtParams.Header = $Header
}
ReadClipboardImpl @cvtParams
}
function ReadClipboardImpl {
param(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String] $data,
$Delimiter,
$Header
)
if (!$PSBoundParameters.ContainsKey('Delimiter') -and !$PSBoundParameters.ContainsKey('Header')) {
try {
ConvertFrom-Json $data
}
catch {
$dataLines = @($data -split "`r`n?" | Select-Object -First 1)
if ($dataLines[0].indexOf(',') -gt -1) {
ConvertFrom-Csv $data
}
else {
ConvertFrom-Csv $data -Delimiter "`t"
}
}
}
else {
$cvtParams = @{
InputObject = $data
}
if ($Delimiter) {
$cvtParams.Delimiter = $Delimiter
}
if ($Header) {
$cvtParams.Header = $Header
}
ConvertFrom-Csv @cvtParams
}
}

54
Public/Read-OleDbData.ps1 Normal file
View File

@@ -0,0 +1,54 @@
#Requires -Version 5
function Read-OleDbData {
<#
.SYNOPSIS
Read data from an OleDb source using dotnet classes. This allows for OleDb queries against excel spreadsheets. Examples will only be for querying xlsx files.
For additional documentation, see Microsoft's documentation on the System.Data OleDb namespace here:
https://docs.microsoft.com/en-us/dotnet/api/system.data.oledb
.DESCRIPTION
Read data from an OleDb source using dotnet classes. This allows for OleDb queries against excel spreadsheets. Examples will only be for querying xlsx files using ACE.
.EXAMPLE
Read-OleDbData `
-ConnectionString "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=file.xlsx;Extended Properties='Excel 12.0 Xml;HDR=NO;IMEX=1;'" `
-SqlStatement "select ROUND(F1) as [A] from [sheet1$A1:A1]"
.EXAMPLE
$ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=file.xlsx;Extended Properties='Excel 12.0 Xml;HDR=NO;IMEX=1;'"
$SqlStatement = "select ROUND(F1) as [A] from [sheet1$A1:A1]"
Read-OleDbData -ConnectionString $ConnectionString -SqlStatement $SqlStatement
.EXAMPLE
$ReadDataArgs = @{
SqlStatement = Get-Content query.sql -Raw
ConnectionString = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=file.xlsx;Extended Properties='Excel 12.0 Xml;HDR=NO;IMEX=1;'"
}
$Results = Read-OleDbData @ReadDataArgs
#>
param(
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String] $ConnectionString,
[Parameter(Mandatory)]
[ValidateNotNullOrEmpty()]
[String] $SqlStatement
)
try {
if ((New-Object system.data.oledb.oledbenumerator).GetElements().SOURCES_NAME -notcontains "Microsoft.ACE.OLEDB.12.0") {
Write-Warning "Microsoft.ACE.OLEDB.12.0 provider is missing! You will not be able to query Excel files without it. Please install from https://www.microsoft.com/en-us/download/details.aspx?id=54920"
}
}
catch {
Write-Error "System.Data.OleDb is not working or you are on an unsupported platform."
return
}
$DataTable = new-object System.Data.DataTable
$DataAdapter = new-object System.Data.OleDb.OleDbDataAdapter $SqlStatement, $ConnectionString
$null = $DataAdapter.Fill($DataTable)
$null = $DataAdapter.Dispose()
$DataTable.Rows | Select-Object $DataTable.Columns.ColumnName
}

View File

@@ -0,0 +1,70 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Scope='Function', Target='Set*', Justification='Does not change system state')]
param()
function Set-CellComment {
[CmdletBinding(DefaultParameterSetName = "Range")]
param(
[Parameter(Mandatory = $True, ParameterSetName = "ColumnLetter")]
[Parameter(Mandatory = $True, ParameterSetName = "ColumnNumber")]
[Parameter(Mandatory = $False, ParameterSetName = "Range")]
[OfficeOpenXml.ExcelWorkSheet]$Worksheet,
[Parameter(Mandatory = $True, ParameterSetName = "Range", ValueFromPipeline = $true,Position=0)]
[Alias("Address")]
$Range,
[Parameter(Mandatory = $True, ParameterSetName = "ColumnLetter")]
[Parameter(Mandatory = $True, ParameterSetName = "ColumnNumber")]
[Int]$Row,
[Parameter(Mandatory = $True, ParameterSetName = "ColumnLetter")]
[String]$ColumnLetter,
[Parameter(Mandatory = $True, ParameterSetName = "ColumnNumber")]
[Int]$ColumnNumber,
[Parameter(Mandatory = $True)]
[String]$Text
)
If ($PSCmdlet.ParameterSetName -eq "Range") {
Write-Verbose "Using 'Range' Parameter Set"
if ($Range -is [Array]) {
$null = $PSBoundParameters.Remove("Range")
$Range | Set-CellComment @PSBoundParameters
}
else {
#We should accept, a worksheet and a name of a range or a cell address; a table; the address of a table; a named range; a row, a column or .Cells[ ]
if ($Range -is [OfficeOpenXml.Table.ExcelTable]) {$Range = $Range.Address}
elseif ($Worksheet -and $Range -is [string]) {
# Convert range as string to OfficeOpenXml.ExcelAddress
$Range = [OfficeOpenXml.ExcelAddress]::new($Range)
}
elseif ($Range -is [string]) {Write-Warning -Message "The range parameter you have specified also needs a worksheet parameter." ;return}
#else we assume $Range is a OfficeOpenXml.ExcelAddress
}
}
ElseIf ($PSCmdlet.ParameterSetName -eq "ColumnNumber") {
$Range = [OfficeOpenXml.ExcelAddress]::new($Row, $ColumnNumber, $Row, $ColumnNumber)
}
ElseIf ($PSCmdlet.ParameterSetName -eq "ColumnLetter") {
$Range = [OfficeOpenXml.ExcelAddress]::new(("{0}{1}" -f $ColumnLetter,$Row))
}
If ($Range -isnot [Array]) {
Foreach ($c in $Worksheet.Cells[$Range]) {
write-verbose $c.address
Try {
If ($Null -eq $c.comment) {
[Void]$c.AddComment($Text, "ImportExcel")
}
Else {
$c.Comment.Text = $Text
$c.Comment.Author = "ImportExcel"
}
$c.Comment.AutoFit = $True
}
Catch { "Could not add comment to cell {0}: {1}" -f $c.Address, $_.ToString() }
}
}
}

View File

@@ -110,7 +110,7 @@
#region Apply formatting
$params = @{}
foreach ($p in @('Underline','Bold','Italic','StrikeThru', 'FontName', 'FontSize','FontShift','NumberFormat','TextRotation',
foreach ($p in @('Underline','UnderLineType','Bold','Italic','StrikeThru', 'FontName', 'FontSize','FontShift','NumberFormat','TextRotation',
'WrapText', 'HorizontalAlignment','VerticalAlignment', 'Autosize', 'Width', 'FontColor'
'BorderAround', 'BackgroundColor', 'BackgroundPattern', 'PatternColor')) {
if ($PSBoundParameters.ContainsKey($p)) {$params[$p] = $PSBoundParameters[$p]}

View File

@@ -58,7 +58,7 @@
elseif ($Worksheet -and ($Range -is [string] -or $Range -is [OfficeOpenXml.ExcelAddress])) {
$Range = $Worksheet.Cells[$Range]
}
elseif ($Range -is [string]) {Write-Warning -Message "The range pararameter you have specified also needs a worksheet parameter." ;return}
elseif ($Range -is [string]) {Write-Warning -Message "The range parameter you have specified also needs a worksheet parameter." ;return}
#else we assume $Range is a range.
if ($ClearAll) {
$Range.Clear()

6
PublishToGallery.ps1 Normal file
View File

@@ -0,0 +1,6 @@
$p = @{
Name = "ImportExcel"
NuGetApiKey = $NuGetApiKey
}
Publish-Module @p

1353
README.md

File diff suppressed because it is too large Load Diff

1253
README.original.md Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
#Requires -Modules Pester
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments','',Justification='False Positives')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable','',Justification='Only executes on versions without the automatic variable')]
#Requires -Modules @{ ModuleName="Pester"; ModuleVersion="4.0.0" }
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable', '', Justification = 'Only executes on versions without the automatic variable')]
param()
Describe ExportExcel -Tag "ExportExcel" {
BeforeAll {
@@ -8,7 +8,7 @@ Describe ExportExcel -Tag "ExportExcel" {
$WarningAction = "SilentlyContinue"
. "$PSScriptRoot\Samples\Samples.ps1"
if (-not (Get-command Get-Service -ErrorAction SilentlyContinue)) {
Function Get-Service {Import-Clixml $PSScriptRoot\Mockservices.xml}
Function Get-Service { Import-Clixml $PSScriptRoot\Mockservices.xml }
}
if (Get-process -Name Excel, xlim -ErrorAction SilentlyContinue) {
It "Excel is open" {
@@ -205,7 +205,7 @@ Describe ExportExcel -Tag "ExportExcel" {
else { $OtherCurrencySymbol = "£" }
$path = "TestDrive:\test.xlsx"
$warnVar = $null
#Test correct export of different data types and number formats; test hyperlinks, test -NoNumberConversion test object is converted to a string with no warnings, test calcuation of formula
#Test correct export of different data types and number formats; test hyperlinks, test -NoNumberConversion and -NoHyperLinkConversion test object is converted to a string with no warnings, test calcuation of formula
Remove-item -Path $path -ErrorAction SilentlyContinue
[PSCustOmobject][Ordered]@{
Date = Get-Date
@@ -233,9 +233,10 @@ Describe ExportExcel -Tag "ExportExcel" {
Link3 = "xl://internal/sheet1!A1"
Link4 = "xl://internal/sheet1!C5"
Link5 = (New-Object -TypeName OfficeOpenXml.ExcelHyperLink -ArgumentList "Sheet1!E2" , "Display Text")
Link6 = "xl://internal/sheet1!C5"
Process = (Get-Process -Id $PID)
TimeSpan = [datetime]::Now.Subtract([datetime]::Today)
} | Export-Excel -NoNumberConversion IPAddress, StrLeadZero, StrAltPhone2 -Path $path -Calculate -WarningVariable $warnVar
} | Export-Excel -NoNumberConversion IPAddress, StrLeadZero, StrAltPhone2 -NoHyperLinkConversion Link6 -Path $path -Calculate -WarningVariable $warnVar
}
BeforeEach {
@@ -253,7 +254,7 @@ Describe ExportExcel -Tag "ExportExcel" {
}
it "Created the worksheet with the expected name, number of rows and number of columns " {
$ws.Name | Should -Be "sheet1"
$ws.Dimension.Columns | Should -Be 27
$ws.Dimension.Columns | Should -Be 28
$ws.Dimension.Rows | Should -Be 2
}
it "Set a date in Cell A2 " {
@@ -292,6 +293,9 @@ Describe ExportExcel -Tag "ExportExcel" {
$ws.Cells[2, 25].Hyperlink.ReferenceAddress | Should -Be "sheet1!E2"
$ws.Cells[2, 25].Hyperlink.Display | Should -Be "Display Text"
}
it "Create no link in cell Z2 (no hyperlink conversion) " {
$ws.Cells[2, 26].Hyperlink | Should -BeNullOrEmpty
}
it "Processed thousands according to local settings (Cells H2 and I2) " {
if ((Get-Culture).NumberFormat.NumberGroupSeparator -EQ ",") {
($ws.Cells[2, 8].Value -is [valuetype] ) | Should -Be $true
@@ -314,13 +318,13 @@ Describe ExportExcel -Tag "ExportExcel" {
($ws.Cells[2, 19].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) " {
$ws.Cells[2, 26].Value | Should -Match '^System\.Diagnostics\.Process\s+\(.*\)$'
it "Converted a nested object to a string (AA2) " {
$ws.Cells[2, 27].Value | Should -Match '^System\.Diagnostics\.Process\s+\(.*\)$'
}
it "Processed a timespan object (Z2) " {
$ws.cells[2, 27].Value.ToOADate() | Should -BeGreaterThan 0
$ws.cells[2, 27].Value.ToOADate() | Should -BeLessThan 1
$ws.cells[2, 27].Style.Numberformat.Format | Should -Be '[h]:mm:ss'
it "Processed a timespan object (AB2) " {
$ws.cells[2, 28].Value.ToOADate() | Should -BeGreaterThan 0
$ws.cells[2, 28].Value.ToOADate() | Should -BeLessThan 1
$ws.cells[2, 28].Style.Numberformat.Format | Should -Be '[h]:mm:ss'
}
}
@@ -344,8 +348,9 @@ Describe ExportExcel -Tag "ExportExcel" {
PhoneNr1 = '+32 44'
PhoneNr2 = '+32 4 4444 444'
PhoneNr3 = '+3244444444'
Link = [uri]"https://github.com/dfinke/ImportExcel"
} | Export-Excel -NoNumberConversion IPAddress, Number1 -Path $path -NoHeader
Link1 = [uri]"https://github.com/dfinke/ImportExcel"
Link2 = [uri]"https://github.com/dfinke/ImportExcel"
} | Export-Excel -NoHyperLinkConversion Link2 -NoNumberConversion IPAddress, Number1 -Path $path -NoHeader
}
BeforeEach {
@@ -363,7 +368,7 @@ Describe ExportExcel -Tag "ExportExcel" {
it "Created the worksheet with the expected name, number of rows and number of columns " {
$ws.Name | Should -Be "sheet1"
$ws.Dimension.Columns | Should -Be 14
$ws.Dimension.Columns | Should -Be 15
$ws.Dimension.Rows | Should -Be 1
}
@@ -387,9 +392,13 @@ Describe ExportExcel -Tag "ExportExcel" {
it "Set a hyperlink in Cell N1 " {
$ws.Cells[1, 14].Hyperlink | Should -Be "https://github.com/dfinke/ImportExcel"
}
it "Does not set a hyperlink in Cell O1 " {
$ws.Cells[1, 15].Hyperlink | Should -BeNullOrEmpty
}
}
Context "#Example 5 # Adding a single conditional format "{
Context "#Example 5 # Adding a single conditional format " {
BeforeEach {
#Test New-ConditionalText builds correctly
$ct = New-ConditionalText -ConditionalType GreaterThan 525 -ConditionalTextColor ([System.Drawing.Color]::DarkRed) -BackgroundColor ([System.Drawing.Color]::LightPink)
@@ -491,7 +500,7 @@ Describe ExportExcel -Tag "ExportExcel" {
}
}
Context "#Examples 8 & 9 # Adding Pivot tables and charts from parameters" {
Context "#Examples 8 & 9 # Adding Pivot tables and charts from parameters" {
BeforeAll {
$path = "TestDrive:\test.xlsx"
#Test -passthru and -worksheetName creating a new, named, sheet in an existing file.
@@ -544,7 +553,7 @@ Describe ExportExcel -Tag "ExportExcel" {
#Test appending data extends pivot chart (with a warning) .
$warnVar = $null
Get-Process | Select-Object -Last 20 -Property Name, cpu, pm, handles, company |
Export-Excel $path -WorkSheetname Processes -Append -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -WarningAction SilentlyContinue -WarningVariable warnvar
Export-Excel $path -WorkSheetname Processes -Append -IncludePivotTable -PivotRows Company -PivotData PM -IncludePivotChart -ChartType PieExploded3D -WarningAction SilentlyContinue -WarningVariable warnvar
$Excel = Open-ExcelPackage $path
$pt = $Excel.Workbook.Worksheets["ProcessesPivotTable"].PivotTables[0]
@@ -557,12 +566,12 @@ Describe ExportExcel -Tag "ExportExcel" {
}
}
Context " # Add-Worksheet inserted sheets, moved them correctly, and copied a sheet" {
Context " # Add-Worksheet inserted sheets, moved them correctly, and copied a sheet" {
BeforeAll {
$path = "TestDrive:\test.xlsx"
#Test the -CopySource and -Movexxxx parameters for Add-Worksheet
$Excel = Get-Process | Select-Object -first 20 -Property Name, cpu, pm, handles, company |
Export-Excel $path -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -NoTotalsInPivot -PivotDataToColumn -Activate
Export-Excel $path -WorkSheetname Processes -IncludePivotTable -PivotRows Company -PivotData PM -NoTotalsInPivot -PivotDataToColumn -Activate
$Excel = Open-ExcelPackage $path
#At this point Sheets Should be in the order Sheet1, Processes, ProcessesPivotTable
@@ -683,6 +692,72 @@ Describe ExportExcel -Tag "ExportExcel" {
}
}
Context "#Example 10 # Creates a file with a table with a 'totals' row".PadRight(87) {
BeforeEach {
$path = "TestDrive:\test.xlsx"
Remove-item -Path $path -ErrorAction SilentlyContinue
#Test with a maximum of 50 processes for speed; export limited set of properties.
$processes = Get-Process | Where-Object { $_.StartTime } | Select-Object -First 50
# Export as table with a totals row with a set of possibilities
$TableTotalSettings = @{
Id = "COUNT"
WS = "SUM"
Handles = "AVERAGE"
CPU = '=COUNTIF([CPU];"<1")'
NPM = @{
Function = '=SUMIF([Name];"=Chrome";[NPM])'
Comment = "Sum of Non-Paged Memory (NPM) for all chrome processes"
}
}
$Processes | Export-Excel $path -TableName "processes" -TableTotalSettings $TableTotalSettings
$TotalRows = $Processes.count + 2 # Column header + Data (50 processes) + Totals row
$Excel = Open-ExcelPackage -Path $path
$ws = $Excel.Workbook.Worksheets[1]
}
it "Totals row was created".PadRight(87) {
$ws.Tables[0].Address.Rows | Should -Be $TotalRows
$ws.tables[0].ShowTotal | Should -Be $True
}
it "Added four calculations in the totals row".PadRight(87) {
$IDcolumn = $ws.Tables[0].Columns | Where-Object { $_.Name -eq "id" }
$WScolumn = $ws.Tables[0].Columns | Where-Object { $_.Name -eq "WS" }
$HandlesColumn = $ws.Tables[0].Columns | Where-Object { $_.Name -eq "Handles" }
$CPUColumn = $ws.Tables[0].Columns | Where-Object { $_.Name -eq "CPU" }
$NPMColumn = $ws.Tables[0].Columns | Where-Object { $_.Name -eq "NPM" }
# Testing column properties
$IDcolumn | Select-Object -ExpandProperty TotalsRowFunction | Should -Be "Count"
$WScolumn | Select-Object -ExpandProperty TotalsRowFunction | Should -Be "Sum"
$HandlesColumn | Select-Object -ExpandProperty TotalsRowFunction | Should -Be "Average"
$CPUColumn | Select-Object -ExpandProperty TotalsRowFunction | Should -Be "Custom"
$CPUColumn | Select-Object -ExpandProperty TotalsRowFormula | Should -Be 'COUNTIF([CPU],"<1")'
$NPMColumn | Select-Object -ExpandProperty TotalsRowFunction | Should -Be "Custom"
$NPMColumn | Select-Object -ExpandProperty TotalsRowFormula | Should -Be 'SUMIF([Name],"=Chrome",[NPM])'
# Testing actual cell properties
$CountAddress = "{0}{1}" -f (Get-ExcelColumnName -ColumnNumber $IDcolumn.Id).ColumnName, $TotalRows
$SumAddress = "{0}{1}" -f (Get-ExcelColumnName -ColumnNumber $WScolumn.Id).ColumnName, $TotalRows
$AverageAddress = "{0}{1}" -f (Get-ExcelColumnName -ColumnNumber $HandlesColumn.Id).ColumnName, $TotalRows
$CustomAddress = "{0}{1}" -f (Get-ExcelColumnName -ColumnNumber $CPUColumn.Id).ColumnName, $TotalRows
$CustomCommentAddress = "{0}{1}" -f (Get-ExcelColumnName -ColumnNumber $NPMColumn.Id).ColumnName, $TotalRows
$ws.Cells[$CountAddress].Formula | Should -Be "SUBTOTAL(103,processes[Id])"
$ws.Cells[$SumAddress].Formula | Should -Be "SUBTOTAL(109,processes[Ws])"
$ws.Cells[$AverageAddress].Formula | Should -Be "SUBTOTAL(101,processes[Handles])"
$ws.Cells[$CustomAddress].Formula | Should -Be 'COUNTIF([CPU],"<1")'
$ws.Cells[$CustomCommentAddress].Formula | Should -Be 'SUMIF([Name],"=Chrome",[NPM])'
$ws.Cells[$CustomCommentAddress].Comment.Text | Should -Not -BeNullOrEmpty
}
AfterEach {
Close-ExcelPackage -ExcelPackage $Excel
}
}
# Context "#Example 11 # Create and append with title, inc ranges and Pivot table" {
# $path = "TestDrive:\test.xlsx"
# #Test New-PivotTableDefinition builds definition using -Pivotfilter and -PivotTotals options.
@@ -695,7 +770,13 @@ Describe ExportExcel -Tag "ExportExcel" {
$path = "TestDrive:\test.xlsx"
Remove-Item $path -ErrorAction SilentlyContinue
#Test freezing top row/first column, adding formats and a pivot table - from Add-Pivot table not a specification variable - after the export
$excel = Get-Process | Select-Object -Property Name, Company, Handles, CPU, PM, NPM, WS | Export-Excel -Path $path -ClearSheet -WorkSheetname "Processes" -FreezeTopRowFirstColumn -PassThru
$Ex13Data = Get-Process | Select-Object -Property Name, Company, Handles, CPU, PM, NPM, WS
$excel = $Ex13Data | Export-Excel -Path $path -ClearSheet -WorkSheetname "Processes" -FreezeTopRowFirstColumn -PassThru
# Add extra worksheets for testing 'Freeze Top Row' and 'Freeze First Column' with or without title
$excel = Export-Excel -InputObject $Ex13Data -ExcelPackage $excel -WorksheetName "FreezeTopRow" -FreezeTopRow -Passthru
$excel = Export-Excel -InputObject $Ex13Data -ExcelPackage $excel -WorksheetName "FreezeFirstColumn" -FreezeFirstColumn -Passthru
$excel = Export-Excel -InputObject $Ex13Data -Title "Freeze Top Row" -ExcelPackage $excel -WorksheetName "FreezeTopRowTitle" -FreezeTopRow -Passthru
$excel = Export-Excel -InputObject $Ex13Data -Title "Freeze Top Row First Column" -ExcelPackage $excel -WorksheetName "FreezeTRFCTitle" -FreezeTopRowFirstColumn -Passthru
$sheet = $excel.Workbook.Worksheets["Processes"]
if ($isWindows) { $sheet.Column(1) | Set-ExcelRange -Bold -AutoFit }
else { $sheet.Column(1) | Set-ExcelRange -Bold }
@@ -715,6 +796,10 @@ Describe ExportExcel -Tag "ExportExcel" {
$excel = Open-ExcelPackage $path
$sheet = $excel.Workbook.Worksheets["Processes"]
$sheetftr = $excel.Workbook.Worksheets["FreezeTopRow"]
$sheetffc = $excel.Workbook.Worksheets["FreezeFirstColumn"]
$sheetftrt = $excel.Workbook.Worksheets["FreezeTopRowTitle"]
$sheetftrfct = $excel.Workbook.Worksheets["FreezeTRFCTitle"]
}
it "Returned the rule when calling Add-ConditionalFormatting -passthru " {
$rule | Should -Not -BeNullOrEmpty
@@ -761,7 +846,27 @@ Describe ExportExcel -Tag "ExportExcel" {
$sheet.Names[6].Name | Should -Be $sheet.Cells['G1'].Value
}
it "Froze the panes " {
$sheet.view.Panes.Count | Should -Be 3
$sheetPaneInfo = $sheet.worksheetxml.worksheet.sheetViews.sheetView.pane
$sheetftrPaneInfo = $sheetftr.worksheetxml.worksheet.sheetViews.sheetView.pane
$sheetffcPaneInfo = $sheetffc.worksheetxml.worksheet.sheetViews.sheetView.pane
$sheetftrtPaneInfo = $sheetftrt.worksheetxml.worksheet.sheetViews.sheetView.pane
$sheetftrfctPaneInfo = $sheetftrfct.worksheetxml.worksheet.sheetViews.sheetView.pane
$sheet.view.Panes.Count | Should -Be 3 # Don't know if this actually checks anything
$sheetPaneInfo.xSplit | Should -Be 1
$sheetPaneInfo.ySplit | Should -Be 1
$sheetPaneInfo.topLeftCell | Should -Be "B2"
$sheetftrPaneInfo.xSplit | Should -BeNullOrEmpty
$sheetftrPaneInfo.ySplit | Should -Be 1
$sheetftrPaneInfo.topLeftCell | Should -Be "A2"
$sheetffcPaneInfo.xSplit | Should -Be 1
$sheetffcPaneInfo.ySplit | Should -BeNullOrEmpty
$sheetffcPaneInfo.topLeftCell | Should -Be "B1"
$sheetftrtPaneInfo.xSplit | Should -BeNullOrEmpty
$sheetftrtPaneInfo.ySplit | Should -Be 2
$sheetftrtPaneInfo.topLeftCell | Should -Be "A3"
$sheetftrfctPaneInfo.xSplit | Should -Be 1
$sheetftrfctPaneInfo.ySplit | Should -Be 2
$sheetftrfctPaneInfo.topLeftCell | Should -Be "B3"
}
it "Created the pivot table " {
@@ -1081,4 +1186,171 @@ Describe ExportExcel -Tag "ExportExcel" {
}
}
}
}
Context " # Check UnderLineType" -Tag CheckUnderLineType {
BeforeAll {
$Path = Join-Path (Resolve-Path 'TestDrive:').ProviderPath "testUnderLineType.xlsx"
Remove-Item -Path $Path -ErrorAction SilentlyContinue
$data = "
Set-ExcelRange,Set-ExcelColumn
Should be double underlined,Should be double underlined
Should be double underlined,Should be double underlined
" | ConvertFrom-Csv
$data | Export-Excel $Path -AutoSize
$excel = Open-ExcelPackage $Path
$ws = $excel.Workbook.Worksheets["sheet1"]
Set-ExcelRange -Range $ws.Cells["A2:A3"] -Underline -UnderLineType "Double"
Set-ExcelColumn -Worksheet $ws -Column 2 -StartRow 2 -Underline -UnderLineType "Double"
Close-ExcelPackage $excel
}
AfterAll {
Remove-Item -Path $Path -ErrorAction SilentlyContinue
}
it "Check Cell Style Font via Set-ExcelColumn".PadRight(87) {
$excel = Open-ExcelPackage $Path
$cell = $excel.Sheet1.Cells["B2"]
$actual = $cell.Style.Font
$actual.Underline | Should -BeTrue
$actual.UnderlineType | Should -Be "Double"
Close-ExcelPackage $excel -NoSave
}
it "Check Cell Style Font via Set-ExcelRange".PadRight(87) {
$excel = Open-ExcelPackage $Path
$cell = $excel.Sheet1.Cells["A2"]
$actual = $cell.Style.Font
$actual.Underline | Should -BeTrue
$actual.UnderlineType | Should -Be "Double"
Close-ExcelPackage $excel -NoSave
}
}
It "Should have hyperlink created" -Tag hyperlink {
$path = "TestDrive:\testHyperLink.xlsx"
$license = "cognc:MCOMEETADV_GOV,cognc:M365_G3_GOV,cognc:ENTERPRISEPACK_GOV,cognc:RIGHTSMANAGEMENT_ADHOC"
$ms365 = [PSCustomObject]@{
DisplayName = "Test Subject"
UserPrincipalName = "test@contoso.com"
licenses = $license
}
$ms365 | Export-Excel $path
$excel = Open-ExcelPackage $Path
$ws = $excel.Sheet1
$ws.Dimension.Rows | Should -Be 2
$ws.Dimension.Columns | Should -Be 3
$ws.Cells["C2"].Hyperlink | Should -BeExactly $license
Close-ExcelPackage $excel
Remove-Item $path
}
It "Should have no hyperlink created" -Tag hyperlink {
$path = "TestDrive:\testHyperLink.xlsx"
$license = "cognc:MCOMEETADV_GOV,cognc:M365_G3_GOV,cognc:ENTERPRISEPACK_GOV,cognc:RIGHTSMANAGEMENT_ADHOC"
$ms365 = [PSCustomObject]@{
DisplayName = "Test Subject"
UserPrincipalName = "test@contoso.com"
licenses = $license
}
$ms365 | Export-Excel $path -NoHyperLinkConversion licenses
$excel = Open-ExcelPackage $Path
$ws = $excel.Sheet1
$ws.Dimension.Rows | Should -Be 2
$ws.Dimension.Columns | Should -Be 3
$ws.Cells["C2"].Hyperlink | Should -BeNullOrEmpty
Close-ExcelPackage $excel
Remove-Item $path
}
It "Should have no hyperlink created using wild card" -Tag hyperlink {
$path = "TestDrive:\testHyperLink.xlsx"
$license = "cognc:MCOMEETADV_GOV,cognc:M365_G3_GOV,cognc:ENTERPRISEPACK_GOV,cognc:RIGHTSMANAGEMENT_ADHOC"
$ms365 = [PSCustomObject]@{
DisplayName = "Test Subject"
UserPrincipalName = "test@contoso.com"
licenses = $license
}
$ms365 | Export-Excel $path -NoHyperLinkConversion *
$excel = Open-ExcelPackage $Path
$ws = $excel.Sheet1
$ws.Dimension.Rows | Should -Be 2
$ws.Dimension.Columns | Should -Be 3
$ws.Cells["A2"].Value | Should -BeExactly "Test Subject"
$ws.Cells["B2"].Value | Should -BeExactly "test@contoso.com"
$ws.Cells["C2"].Hyperlink | Should -BeNullOrEmpty
Close-ExcelPackage $excel
Remove-Item $path
}
It "Should freeze the correct rows" -tag Freeze {
<#
Export-Excel -InputObject $Data -Path $OutputFile -TableName $SheetName.Replace(' ', '_') -WorksheetName $SheetName -AutoSize -FreezeTopRow -TableStyle $TableStyle -Title $SheetName -TitleBold -TitleSize 18
#>
$path = "TestDrive:\testFreeze.xlsx"
$data = ConvertFrom-Csv @"
Region,State,Units,Price
West,Texas,927,923.71
North,Tennessee,466,770.67
East,Florida,520,458.68
East,Maine,828,661.24
West,Virginia,465,053.58
North,Missouri,436,235.67
South,Kansas,214,992.47
North,North Dakota,789,640.72
South,Delaware,712,508.55
"@
Export-Excel -InputObject $data -Path $path -TableName 'TestTable' -WorksheetName 'TestSheet' -AutoSize -TableStyle Medium2 -Title 'Test Title' -TitleBold -TitleSize 18 -FreezeTopRow
$excel = Open-ExcelPackage -Path $path
$ws = $excel.TestSheet
$r = $ws.worksheetxml.worksheet.sheetViews.sheetView.pane
$r | Should -Not -BeNullOrEmpty
$r.ySplit | Should -Be 2
$r.topLeftCell | Should -BeExactly 'A3'
$r.state | Should -BeExactly 'frozen'
$r.activePane | Should -BeExactly 'bottomLeft'
Close-ExcelPackage $excel
Remove-Item $path
}
}

View File

@@ -140,4 +140,72 @@ Describe "Creating small named ranges with hyperlinks" {
$pt.RowFields[1].Grouping.Interval | Should -Be 3
}
}
Context "Adding group date column" -Tag GroupColumnTests {
it "Tests adding a group date column" {
$xlFile = "TestDrive:\Results.xlsx"
Remove-Item $xlFile -ErrorAction Ignore
$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Points `
-PivotRows Driver -PivotColumns Date -PivotData @{Points = "SUM" } -GroupDateColumn Date -GroupDatePart Years, Months
$excel = Import-Csv "$PSScriptRoot\First10Races.csv" |
Select-Object Race, @{n = "Date"; e = { [datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture)) } }, FinishPosition, Driver, GridPosition, Team, Points |
Export-Excel $xlFile -AutoSize -PivotTableDefinition $PivotTableDefinition -PassThru
$excel.Workbook.Worksheets.Count | Should -Be 2
$excel.Workbook.Worksheets[1].Name | Should -BeExactly 'Sheet1'
$excel.Workbook.Worksheets[2].Name | Should -BeExactly 'Points'
$excel.Points.PivotTables.Count | Should -Be 1
$pt = $excel.Points.PivotTables[0]
$pt.RowFields.Count | Should -Be 1
$pt.RowFields[0].name | Should -Be "Driver"
$pt.ColumnFields.Count | Should -Be 2
$pt.ColumnFields[0].name | Should -Be "Years"
$pt.ColumnFields[0].Grouping | Should -Not -BeNullOrEmpty
$pt.ColumnFields[0].Grouping.GroupBy | Should -Be "Years"
$pt.ColumnFields[1].name | Should -Be "Date"
$pt.ColumnFields[1].Grouping | Should -Not -BeNullOrEmpty
$pt.ColumnFields[1].Grouping.GroupBy | Should -Be "Months"
Close-ExcelPackage $excel
Remove-Item $xlFile -ErrorAction Ignore
}
}
Context "Adding group numeric column" -Tag GroupColumnTests {
it "Tests adding numeric group column" {
$xlFile = "TestDrive:\Results.xlsx"
Remove-Item $xlFile -ErrorAction Ignore
$PivotTableDefinition = New-PivotTableDefinition -Activate -PivotTableName Places `
-PivotRows Driver -PivotColumns FinishPosition -PivotData @{Date = "Count" } -GroupNumericColumn FinishPosition -GroupNumericMin 1 -GroupNumericMax 25 -GroupNumericInterval 3
$excel = Import-Csv "$PSScriptRoot\First10Races.csv" |
Select-Object Race, @{n = "Date"; e = { [datetime]::ParseExact($_.date, "dd/MM/yyyy", (Get-Culture)) } }, FinishPosition, Driver, GridPosition, Team, Points |
Export-Excel $xlFile -AutoSize -PivotTableDefinition $PivotTableDefinition -PassThru
$excel.Workbook.Worksheets.Count | Should -Be 2
$excel.Workbook.Worksheets[1].Name | Should -BeExactly 'Sheet1'
$excel.Workbook.Worksheets[2].Name | Should -BeExactly 'Places'
$excel.Places.PivotTables.Count | Should -Be 1
$pt = $excel.Places.PivotTables[0]
$pt.RowFields.Count | Should -Be 1
$pt.RowFields[0].name | Should -Be "Driver"
$pt.ColumnFields.Count | Should -Be 1
$pt.ColumnFields[0].name | Should -Be "FinishPosition"
$pt.ColumnFields[0].Grouping | Should -Not -BeNullOrEmpty
$pt.ColumnFields[0].Grouping.Start | Should -Be 1
$pt.ColumnFields[0].Grouping.End | Should -Be 25
$pt.ColumnFields[0].Grouping.Interval | Should -Be 3
Close-ExcelPackage $excel
Remove-Item $xlFile -ErrorAction Ignore
}
}
}

View File

@@ -3,9 +3,7 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidAssignmentToAutomaticVariable', '', Justification = 'Only executes on versions without the automatic variable')]
param()
if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) {
Import-Module $PSScriptRoot\..\ImportExcel.psd1
}
Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force
Describe 'All tests for Get-ExcelFileSummary' -Tag "Get-ExcelFileSummary" {
Context "Test Get-ExcelFileSummary" {
@@ -14,6 +12,7 @@ Describe 'All tests for Get-ExcelFileSummary' -Tag "Get-ExcelFileSummary" {
$actual.ExcelFile | Should -BeExactly 'TestData1.xlsx'
$actual.WorksheetName | Should -BeExactly 'Sheet1'
$actual.Visible | Should -BeTrue
$actual.Rows | Should -Be 3
$actual.Columns | Should -Be 2
$actual.Address | Should -BeExactly 'A1:B3'
@@ -26,6 +25,7 @@ Describe 'All tests for Get-ExcelFileSummary' -Tag "Get-ExcelFileSummary" {
$actual[0].ExcelFile | Should -BeExactly 'MultipleSheets.xlsx'
$actual[0].WorksheetName | Should -BeExactly 'Sheet1'
$actual[0].Visible | Should -BeTrue
$actual[0].Rows | Should -Be 1
$actual[0].Columns | Should -Be 4
$actual[0].Address | Should -BeExactly 'A1:D1'
@@ -33,11 +33,20 @@ Describe 'All tests for Get-ExcelFileSummary' -Tag "Get-ExcelFileSummary" {
$actual[1].ExcelFile | Should -BeExactly 'MultipleSheets.xlsx'
$actual[1].WorksheetName | Should -BeExactly 'Sheet2'
$actual[1].Visible | Should -BeTrue
$actual[1].Rows | Should -Be 2
$actual[1].Columns | Should -Be 2
$actual[1].Address | Should -BeExactly 'A1:B2'
$actual[1].Path | Should -Not -BeNullOrEmpty
}
It "Tests if sheet is hidden or not" {
$actual = Get-ExcelFileSummary "$PSScriptRoot\ImportExcelTests\SheetVisibleTesting.xlsx"
$actual[0].Visible | Should -BeTrue
$actual[1].Visible | Should -BeFalse
$actual[2].Visible | Should -BeTrue
$actual[3].Visible | Should -BeFalse
}
}
}

View File

@@ -1,33 +1,70 @@
#Requires -Modules Pester
if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) {
Import-Module $PSScriptRoot\..\ImportExcel.psd1
}
Describe "Import-Excel on a sheet with no headings" {
BeforeAll {
$xlfile = "TestDrive:\testImportExcel.xlsx"
$xlfileHeaderOnly = "TestDrive:\testImportExcelHeaderOnly.xlsx"
$xl = "" | Export-excel $xlfile -PassThru
$xlfile = "$PSScriptRoot\testImportExcel.xlsx"
$xlfileHeaderOnly = "$PSScriptRoot\testImportExcelHeaderOnly.xlsx"
$xlfileImportColumns = "$PSScriptRoot\testImportExcelImportColumns.xlsx"
Set-ExcelRange -Worksheet $xl.Sheet1 -Range A1 -Value 'A'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range B1 -Value 'B'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range C1 -Value 'C'
# Create $xlfile if it does not exist
if (!(Test-Path -Path $xlfile)) {
$xl = "" | Export-excel $xlfile -PassThru
Set-ExcelRange -Worksheet $xl.Sheet1 -Range A2 -Value 'D'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range B2 -Value 'E'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range C2 -Value 'F'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range A1 -Value 'A'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range B1 -Value 'B'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range C1 -Value 'C'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range A2 -Value 'D'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range B2 -Value 'E'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range C2 -Value 'F'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range A3 -Value 'G'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range B3 -Value 'H'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range C3 -Value 'I'
Close-ExcelPackage $xl
}
Set-ExcelRange -Worksheet $xl.Sheet1 -Range A3 -Value 'G'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range B3 -Value 'H'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range C3 -Value 'I'
# Create $xlfileHeaderOnly if it does not exist
if (!(Test-Path -Path $xlfileHeaderOnly)) {
$xl = "" | Export-excel $xlfileHeaderOnly -PassThru
Close-ExcelPackage $xl
Set-ExcelRange -Worksheet $xl.Sheet1 -Range A1 -Value 'A'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range B1 -Value 'B'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range C1 -Value 'C'
# crate $xlfileHeaderOnly
$xl = "" | Export-excel $xlfileHeaderOnly -PassThru
Close-ExcelPackage $xl
}
Set-ExcelRange -Worksheet $xl.Sheet1 -Range A1 -Value 'A'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range B1 -Value 'B'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range C1 -Value 'C'
# Create $xlfileImportColumns if it does not exist
if (!(Test-Path -Path $xlfileImportColumns)) {
$xl = "" | Export-Excel $xlfileImportColumns -PassThru
Close-ExcelPackage $xl
Set-ExcelRange -Worksheet $xl.Sheet1 -Range A1 -Value 'A'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range B1 -Value 'B'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range C1 -Value 'C'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range D1 -Value 'D'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range E1 -Value 'E'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range F1 -Value 'F'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range A2 -Value '1'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range B2 -Value '2'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range C2 -Value '3'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range D2 -Value '4'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range E2 -Value '5'
Set-ExcelRange -Worksheet $xl.Sheet1 -Range F2 -Value '6'
Close-ExcelPackage $xl
}
}
AfterAll {
Remove-Item $PSScriptRoot\testImportExcelSparse.xlsx -ErrorAction SilentlyContinue
}
It "Import-Excel should have this shape" {
@@ -167,7 +204,7 @@ Describe "Import-Excel on a sheet with no headings" {
}
It "Should" {
$xlfile = "TestDrive:\testImportExcelSparse.xlsx"
$xlfile = "$PSScriptRoot\testImportExcelSparse.xlsx"
$xl = "" | Export-excel $xlfile -PassThru
Set-ExcelRange -Worksheet $xl.Sheet1 -Range A1 -Value 'Chuck'
@@ -197,6 +234,7 @@ Describe "Import-Excel on a sheet with no headings" {
$actual.Count | Should -Be 1
Remove-Item $xlfile
# Looks like -DataOnly does not handle empty columns
# $actual[0].FirstName | Should -BeExactly 'Jean-Claude'
# $actual[0].SecondName | Should -BeExactly 'Vandamme'
@@ -224,4 +262,139 @@ Describe "Import-Excel on a sheet with no headings" {
$actual[0].P2 | Should -Be 'B'
$actual[0].P3 | Should -Be 'C'
}
It "Should import correct data if -ImportColumns is used with the first column" {
$actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(1,2,4,5))
$actualNames = $actual[0].psobject.properties.Name
$actualNames.Count | Should -Be 4
$actualNames[0] | Should -Be 'A'
$actualNames[2] | Should -Be 'D'
$actual.Count | Should -Be 1
$actual[0].A | Should -Be 1
$actual[0].B | Should -Be 2
$actual[0].D | Should -Be 4
$actual[0].E | Should -Be 5
}
It "Should import correct data if -ImportColumns is used with the first column" {
$actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(1,3,4,5))
$actualNames = $actual[0].psobject.properties.Name
$actualNames.Count | Should -Be 4
$actualNames[0] | Should -Be 'A'
$actualNames[2] | Should -Be 'D'
$actual.Count | Should -Be 1
$actual[0].A | Should -Be 1
$actual[0].C | Should -Be 3
$actual[0].D | Should -Be 4
$actual[0].E | Should -Be 5
}
It "Should import correct data if -ImportColumns is used without the first column" {
$actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(2,3,6))
$actualNames = $actual[0].psobject.properties.Name
$actualNames.Count | Should -Be 3
$actualNames[0] | Should -Be 'B'
$actualNames[2] | Should -Be 'F'
$actual.Count | Should -Be 1
$actual[0].B | Should -Be 2
$actual[0].C | Should -Be 3
$actual[0].F | Should -Be 6
}
It "Should import correct data if -ImportColumns is used without the first column" {
$actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(2,5,6))
$actualNames = $actual[0].psobject.properties.Name
$actualNames.Count | Should -Be 3
$actualNames[0] | Should -Be 'B'
$actualNames[2] | Should -Be 'F'
$actual.Count | Should -Be 1
$actual[0].B | Should -Be 2
$actual[0].E | Should -Be 5
$actual[0].F | Should -Be 6
}
It "Should import correct data if -ImportColumns is used with only 1 column" {
$actual = @(Import-Excel $xlfile -ImportColumns @(2))
$actualNames = $actual[0].psobject.properties.Name
$actualNames.Count | Should -Be 1
$actualNames[0] | Should -Be 'B'
$actual.Count | Should -Be 2
$actual[0].B | Should -Be 'E'
}
It "Should import correct data if -ImportColumns is used with only 1 column which is also the last" {
$actual = @(Import-Excel $xlfile -ImportColumns @(3))
$actualNames = $actual[0].psobject.properties.Name
$actualNames.Count | Should -Be 1
$actualNames[0] | Should -Be 'C'
$actual.Count | Should -Be 2
$actual[1].C | Should -Be 'I'
}
It "Should import correct data if -ImportColumns contains all columns" {
$actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(1,2,3,4,5,6))
$actualNames = $actual[0].psobject.properties.Name
$actualNames.Count | Should -Be 6
$actualNames[0] | Should -Be 'A'
$actualNames[2] | Should -Be 'C'
$actual.Count | Should -Be 1
$actual[0].A | Should -Be 1
$actual[0].B | Should -Be 2
$actual[0].C | Should -Be 3
$actual[0].D | Should -Be 4
$actual[0].E | Should -Be 5
$actual[0].F | Should -Be 6
}
It "Should ignore -StartColumn and -EndColumn if -ImportColumns is set aswell" {
$actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(5) -StartColumn 2 -EndColumn 7)
$actualNames = $actual[0].psobject.properties.Name
$actualNames.Count | Should -Be 1
$actualNames[0] | Should -Be 'E'
$actual[0].E | Should -Be '5'
}
It "Should arrange the columns if -ImportColumns is not in order" {
$actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(5,1,4))
$actualNames = $actual[0].psobject.properties.Name
$actualNames.Count | Should -Be 3
$actualNames[0] | Should -Be 'E'
$actualNames[1] | Should -Be 'A'
$actualNames[2] | Should -Be 'D'
$actual[0].E | Should -Be '5'
$actual[0].A | Should -Be '1'
$actual[0].D | Should -Be '4'
}
It "Should arrange the columns if -ImportColumns is not in order and -NoHeader is used" {
$actual = @(Import-Excel $xlfileImportColumns -ImportColumns @(5,1,4) -NoHeader -StartRow 2)
$actualNames = $actual[0].psobject.properties.Name
$actualNames.Count | Should -Be 3
$actualNames[0] | Should -Be 'P1'
$actualNames[1] | Should -Be 'P2'
$actualNames[2] | Should -Be 'P3'
$actual[0].P1 | Should -Be '5'
$actual[0].P2 | Should -Be '1'
$actual[0].P3 | Should -Be '4'
}
}

Binary file not shown.

View File

@@ -0,0 +1,57 @@
Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force
Describe 'Test' -Tag ImportExcelEndRowAndCols {
BeforeAll {
$script:xlFilename = "$PSScriptRoot\DataInDiffRowCol.xlsx"
}
Context 'Test reading a partial sheet' {
It 'Should read 2 rows and first 3 columns' {
$actual = Import-Excel $xlFilename -StartRow 5 -EndRow 7 -StartColumn 3 -EndColumn 5
# $actual | out-host
$actual.Count | Should -Be 2
$colNames = $actual[0].psobject.properties.Name
$colNames.Count | Should -Be 3
$colNames[0] | Should -Be 'Region'
$colNames[1] | Should -Be 'State'
$colNames[2] | Should -Be 'Units'
}
It 'Should read second 2 rows and last 2 columns' {
$actual = Import-Excel $xlFilename -StartRow 8 -EndRow 9 -StartColumn 5 -EndColumn 6 -HeaderName 'Units', 'Price'
# $actual | out-host
$actual.Count | Should -Be 2
$colNames = $actual[0].psobject.properties.Name
$colNames.Count | Should -Be 2
$colNames[0] | Should -Be 'Units'
$colNames[1] | Should -Be 'Price'
}
It 'Should read any row up to maximum allowed row' {
$xlMaxRows = "$PSScriptRoot\MaxRows.xlsx"
$actual = Import-Excel $xlMaxRows -StartRow 1048576 -EndRow 1048576 -NoHeader
$actual.P1 | Should -Be 1048576
}
}
Context 'Test reading multiple sheets with data in differnt rows and columns' {
It 'Should read 2 sheets same StartRow different dimensions' {
$xlFilename = "$PSScriptRoot\DataInDiffRowColMultipleSheets.xlsx"
$actual = Import-Excel $xlFilename -StartRow 5 -WorksheetName *
$actual.Keys.Count | Should -Be 2
$actual.Contains('Sheet1') | Should -BeTrue
$actual.Contains('Sheet2') | Should -BeTrue
$actual['Sheet1'].Count | Should -Be 9
$actual['Sheet2'].Count | Should -Be 12
}
}
}

View File

@@ -0,0 +1,82 @@
#Requires -Modules Pester
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')]
param()
Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force
Describe 'Different ways to import sheets' -Tag ImportExcelReadSheets {
BeforeAll {
$xlFilename = "$PSScriptRoot\yearlySales.xlsx"
}
Context 'Test reading sheets' {
It 'Should read one sheet' {
$actual = Import-Excel $xlFilename
$actual.Count | Should -Be 100
$actual[0].Month | Should -BeExactly "April"
$actual[99].Month | Should -BeExactly "April"
}
It 'Should read two sheets' {
$actual = Import-Excel $xlFilename march, june
$actual.keys.Count | Should -Be 2
$actual["March"].Count | Should -Be 100
$actual["June"].Count | Should -Be 100
}
It 'Should read all the sheets' {
$actual = Import-Excel $xlFilename *
$actual.keys.Count | Should -Be 12
$actual["January"].Count | Should -Be 100
$actual["February"].Count | Should -Be 100
$actual["March"].Count | Should -Be 100
$actual["April"].Count | Should -Be 100
$actual["May"].Count | Should -Be 100
$actual["June"].Count | Should -Be 100
$actual["July"].Count | Should -Be 100
$actual["August"].Count | Should -Be 100
$actual["September"].Count | Should -Be 100
$actual["October"].Count | Should -Be 100
$actual["November"].Count | Should -Be 100
$actual["December"].Count | Should -Be 100
}
It 'Should throw if it cannot find the sheet' {
{ Import-Excel $xlFilename april, june, notthere } | Should -Throw
}
It 'Should return an array not a dictionary' {
$actual = Import-Excel $xlFilename april, june -Raw
$actual.Count | Should -Be 200
$group = $actual | Group-Object month -NoElement
$group.Count | Should -Be 2
$group[0].Name | Should -BeExactly 'April'
$group[1].Name | Should -BeExactly 'June'
}
It "Should read multiple sheets with diff number of rows correctly" {
$xlFilename = "$PSScriptRoot\construction.xlsx"
$actual = Import-Excel $xlFilename 2015, 2016
$actual.keys.Count | Should -Be 2
$actual["2015"].Count | Should -Be 12
$actual["2016"].Count | Should -Be 1
}
It "Should read multiple sheets with diff number of rows correctly and flatten it" {
$xlFilename = "$PSScriptRoot\construction.xlsx"
$actual = Import-Excel $xlFilename 2015, 2016 -Raw
$actual.Count | Should -Be 13
}
}
}

Binary file not shown.

View File

@@ -0,0 +1,57 @@
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')]
Param()
Import-Module $PSScriptRoot\..\..\ImportExcel.psd1 -Force
Describe "Test reading multiple XLSX files of different row count" -Tag ReadMultipleXLSX {
It "Should find these xlsx files" {
Test-Path -Path $PSScriptRoot\rows05.xlsx | Should -BeTrue
Test-Path -Path $PSScriptRoot\rows10.xlsx | Should -BeTrue
}
It "Should find two xlsx files" {
(Get-ChildItem $PSScriptRoot\row*xlsx).Count | Should -Be 2
}
It "Should get 5 rows" {
(Import-Excel $PSScriptRoot\rows05.xlsx).Count | Should -Be 5
}
It "Should get 10 rows" {
(Import-Excel $PSScriptRoot\rows10.xlsx).Count | Should -Be 10
}
It "Should get 15 rows" {
$actual = Get-ChildItem $PSScriptRoot\row*xlsx | Import-Excel
$actual.Count | Should -Be 15
}
It "Should get 4 property names" {
$actual = Get-ChildItem $PSScriptRoot\row*xlsx | Import-Excel
$names = $actual[0].psobject.properties.name
$names.Count | Should -Be 4
$names[0] | Should -BeExactly "Region"
$names[1] | Should -BeExactly "State"
$names[2] | Should -BeExactly "Units"
$names[3] | Should -BeExactly "Price"
}
It "Should have the correct data" {
$actual = Get-ChildItem $PSScriptRoot\row*xlsx | Import-Excel
# rows05.xlsx
$actual[0].Region | Should -BeExactly "South"
$actual[0].Price | Should -Be 181.52
$actual[4].Region | Should -BeExactly "West"
$actual[4].Price | Should -Be 216.56
# rows10.xlsx
$actual[5].Region | Should -BeExactly "South"
$actual[5].Price | Should -Be 199.85
$actual[14].Region | Should -BeExactly "East"
$actual[14].Price | Should -Be 965.25
}
}

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,66 @@
if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) {
Import-Module $PSScriptRoot\..\ImportExcel.psd1
}
Describe "Test New Conditional Formatting IconSet" -Tag ConditionalFormattingIconSet {
BeforeEach {
$xlFilename = "TestDrive:\ConditionalFormattingIconSet.xlsx"
Remove-Item $xlFilename -ErrorAction SilentlyContinue
$data = ConvertFrom-Csv @"
Region,State,Other,Units,Price,InStock
West,Texas,1,927,923.71,1
North,Tennessee,3,466,770.67,0
East,Florida,0,1520,458.68,1
East,Maine,1,1828,661.24,0
West,Virginia,1,465,053.58,1
North,Missouri,1,436,235.67,1
South,Kansas,0,214,992.47,1
North,North Dakota,1,789,640.72,0
South,Delaware,-1,712,508.55,1
"@
}
It "Should set ThreeIconSet" {
# $cfi1 = New-ConditionalFormattingIconSet -Range C:C -ConditionalFormat ThreeIconSet -IconType Symbols -ShowIconOnly
$cfi1 = New-ConditionalFormattingIconSet -Range C:C -ConditionalFormat ThreeIconSet -IconType Symbols
$data | Export-Excel $xlFilename -ConditionalFormat $cfi1
$actual = Import-Excel $xlFilename
$actual.count | Should -Be 9
$xl = Open-ExcelPackage $xlFilename
$xl.Workbook.Worksheets.Count | Should -Be 1
$targetSheet = $xl.Workbook.Worksheets[1]
$targetSheet.Name | Should -Be "Sheet1"
$targetSheet.ConditionalFormatting.Count | Should -Be 1
$targetSheet.ConditionalFormatting[0].Type | Should -Be "ThreeIconSet"
$targetSheet.ConditionalFormatting[0].IconSet | Should -Be "Symbols"
$targetSheet.ConditionalFormatting[0].Reverse | Should -BeFalse
$targetSheet.ConditionalFormatting[0].ShowValue | Should -BeTrue
Close-ExcelPackage $xl -NoSave
}
It "Should set ThreeIconSet with ShowOnlyIcon" {
$cfi1 = New-ConditionalFormattingIconSet -Range C:C -ConditionalFormat ThreeIconSet -IconType Symbols -ShowIconOnly
$data | Export-Excel $xlFilename -ConditionalFormat $cfi1
$actual = Import-Excel $xlFilename
$actual.count | Should -Be 9
$xl = Open-ExcelPackage $xlFilename
$xl.Workbook.Worksheets.Count | Should -Be 1
$targetSheet = $xl.Workbook.Worksheets[1]
$targetSheet.Name | Should -Be "Sheet1"
$targetSheet.ConditionalFormatting.Count | Should -Be 1
$targetSheet.ConditionalFormatting[0].Type | Should -Be "ThreeIconSet"
$targetSheet.ConditionalFormatting[0].IconSet | Should -Be "Symbols"
$targetSheet.ConditionalFormatting[0].Reverse | Should -BeFalse
$targetSheet.ConditionalFormatting[0].ShowValue | Should -BeFalse
Close-ExcelPackage $xl -NoSave
}
}

View File

@@ -0,0 +1,39 @@
#Requires -Modules Pester
if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) {
Import-Module $PSScriptRoot\..\ImportExcel.psd1
}
<#
Methods
-------
Dispose
Equals
GetAsByteArray
GetHashCode
GetType
Load
Save
SaveAs
ToString
Properties
----------
Compatibility
Compression
DoAdjustDrawings
Encryption
File
Package
Stream
Workbook
#>
Describe "Test Open Excel Package" -Tag Open-ExcelPackage {
It "Should handle opening a workbook with Worksheet Names that will cause errors" {
$xlFilename = "$PSScriptRoot\UnsupportedWorkSheetNames.xlsx"
{ Open-ExcelPackage -Path $xlFilename -ErrorAction Stop } | Should -Not -Throw
}
}

View File

@@ -1,11 +1,12 @@
Describe "Test reading relative paths" {
BeforeAll {
$script:xlfileName = "TestR.xlsx"
@{data = 1 } | Export-Excel (Join-Path $PWD "TestR.xlsx")
If ([String]::IsNullOrEmpty($PWD)) { $PWD = $PSScriptRoot }
@{data = 1 } | Export-Excel (Join-Path $PWD "TestR.xlsx")
}
AfterAll {
Remove-Item (Join-Path $PWD "$($script:xlfileName)")
Remove-Item (Join-Path $PWD "$($script:xlfileName)")
}
It "Should read local file".PadRight(90) {

View File

@@ -1,22 +1,22 @@
#Requires -Modules Pester
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments','',Justification='False Positives')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingCmdletAliases','',Justification='Testing for presence of alias')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'False Positives')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingCmdletAliases', '', Justification = 'Testing for presence of alias')]
param()
describe "Consistent passing of ranges." {
BeforeAll {
$path = "TestDrive:\test.xlsx"
if (-not (Get-command Get-Service -ErrorAction SilentlyContinue)) {
Function Get-Service {Import-Clixml $PSScriptRoot\Mockservices.xml}
}
$path = "TestDrive:\test.xlsx"
# if (-not (Get-command Get-Service -ErrorAction SilentlyContinue)) {
Function Get-Service { Import-Clixml $PSScriptRoot\Mockservices.xml }
# }
}
Context "Conditional Formatting" {
Context "Conditional Formatting" {
it "accepts named ranges, cells['name'], worksheet + Name, worksheet + column " {
Remove-Item -path $path -ErrorAction SilentlyContinue
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -AutoNameRange -Title "Services on $Env:COMPUTERNAME"
{Add-ConditionalFormatting $excel.Services.Names["Status"] -StrikeThru -RuleType ContainsText -ConditionValue "Stopped" } | Should -Not -Throw
{ Add-ConditionalFormatting $excel.Services.Names["Status"] -StrikeThru -RuleType ContainsText -ConditionValue "Stopped" } | Should -Not -Throw
$excel.Services.ConditionalFormatting.Count | Should -Be 1
{Add-ConditionalFormatting $excel.Services.Cells["Name"] -Italic -RuleType ContainsText -ConditionValue "SVC" } | Should -Not -Throw
{ Add-ConditionalFormatting $excel.Services.Cells["Name"] -Italic -RuleType ContainsText -ConditionValue "SVC" } | Should -Not -Throw
$excel.Services.ConditionalFormatting.Count | Should -Be 2
$warnvar = $null
Add-ConditionalFormatting $excel.Services.Column(3) `
@@ -25,25 +25,25 @@ describe "Consistent passing of ranges." {
$excel.Services.ConditionalFormatting.Count | Should -Be 2
$warnvar = $null
Add-ConditionalFormatting $excel.Services.Column(3) -Worksheet $excel.Services`
-underline -RuleType ContainsText -ConditionValue "Windows" -WarningVariable warnvar -WarningAction SilentlyContinue
-underline -RuleType ContainsText -ConditionValue "Windows" -WarningVariable warnvar -WarningAction SilentlyContinue
$warnvar | Should -BeNullOrEmpty
$excel.Services.ConditionalFormatting.Count | Should -Be 3
{Add-ConditionalFormatting "Status" -Worksheet $excel.Services `
-ForeGroundColor ([System.Drawing.Color]::Green) -RuleType ContainsText -ConditionValue "Running"} | Should -Not -Throw
{ Add-ConditionalFormatting "Status" -Worksheet $excel.Services `
-ForeGroundColor ([System.Drawing.Color]::Green) -RuleType ContainsText -ConditionValue "Running" } | Should -Not -Throw
$excel.Services.ConditionalFormatting.Count | Should -Be 4
Close-ExcelPackage -NoSave $excel
}
it "accepts table, table.Address and worksheet + 'C:C' " {
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME"
{Add-ConditionalFormatting $excel.Services.Tables[0] `
-Italic -RuleType ContainsText -ConditionValue "Svc" } | Should -Not -Throw
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME"
{ Add-ConditionalFormatting $excel.Services.Tables[0] `
-Italic -RuleType ContainsText -ConditionValue "Svc" } | Should -Not -Throw
$excel.Services.ConditionalFormatting.Count | Should -Be 1
{Add-ConditionalFormatting $excel.Services.Tables["ServiceTable"].Address `
-Bold -RuleType ContainsText -ConditionValue "windows" } | Should -Not -Throw
{ Add-ConditionalFormatting $excel.Services.Tables["ServiceTable"].Address `
-Bold -RuleType ContainsText -ConditionValue "windows" } | Should -Not -Throw
$excel.Services.ConditionalFormatting.Count | Should -Be 2
{Add-ConditionalFormatting -Worksheet $excel.Services -Address "a:a" `
-RuleType ContainsText -ConditionValue "stopped" -ForeGroundColor ([System.Drawing.Color]::Red) } | Should -Not -Throw
{ Add-ConditionalFormatting -Worksheet $excel.Services -Address "a:a" `
-RuleType ContainsText -ConditionValue "stopped" -ForeGroundColor ([System.Drawing.Color]::Red) } | Should -Not -Throw
$excel.Services.ConditionalFormatting.Count | Should -Be 3
Close-ExcelPackage -NoSave $excel
}
@@ -52,29 +52,29 @@ describe "Consistent passing of ranges." {
Context "Formating (Set-ExcelRange or its alias Set-Format) " {
it "accepts Named Range, cells['Name'], cells['A1:Z9'], row, Worksheet + 'A1:Z9'" {
$excel = Get-Service | Export-Excel -Path test2.xlsx -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -RangeName servicerange -Title "Services on $Env:COMPUTERNAME"
{Set-format $excel.Services.Names["serviceRange"] -Bold } | Should -Not -Throw
{ Set-format $excel.Services.Names["serviceRange"] -Bold } | Should -Not -Throw
$excel.Services.cells["B2"].Style.Font.Bold | Should -Be $true
{Set-ExcelRange -Range $excel.Services.Cells["serviceRange"] -italic:$true } | Should -Not -Throw
{ Set-ExcelRange -Range $excel.Services.Cells["serviceRange"] -italic:$true } | Should -Not -Throw
$excel.Services.cells["C3"].Style.Font.Italic | Should -Be $true
{Set-format $excel.Services.Row(4) -underline -Bold:$false } | Should -Not -Throw
{ Set-format $excel.Services.Row(4) -underline -Bold:$false } | Should -Not -Throw
$excel.Services.cells["A4"].Style.Font.UnderLine | Should -Be $true
$excel.Services.cells["A4"].Style.Font.Bold | Should -Not -Be $true
{Set-ExcelRange $excel.Services.Cells["A3:B3"] -StrikeThru } | Should -Not -Throw
{ Set-ExcelRange $excel.Services.Cells["A3:B3"] -StrikeThru } | Should -Not -Throw
$excel.Services.cells["B3"].Style.Font.Strike | Should -Be $true
{Set-ExcelRange -Worksheet $excel.Services -Range "A5:B6" -FontSize 8 } | Should -Not -Throw
{ Set-ExcelRange -Worksheet $excel.Services -Range "A5:B6" -FontSize 8 } | Should -Not -Throw
$excel.Services.cells["A5"].Style.Font.Size | Should -Be 8
Close-ExcelPackage -NoSave $excel
}
it "Accepts Table, Table.Address , worksheet + Name, Column," {
$excel = Get-Service | Export-Excel -Path test2.xlsx -WorksheetName Services -PassThru -AutoNameRange -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME"
{Set-ExcelRange $excel.Services.Tables[0] -Italic } | Should -Not -Throw
{ Set-ExcelRange $excel.Services.Tables[0] -Italic } | Should -Not -Throw
$excel.Services.cells["C3"].Style.Font.Italic | Should -Be $true
{Set-format $excel.Services.Tables["ServiceTable"].Address -Underline } | Should -Not -Throw
{ Set-format $excel.Services.Tables["ServiceTable"].Address -Underline } | Should -Not -Throw
$excel.Services.cells["C3"].Style.Font.UnderLine | Should -Be $true
{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.Column(3) | Set-ExcelRange -FontColor ([System.Drawing.Color]::Red) } | Should -Not -Throw
{ $excel.Services.Column(3) | Set-ExcelRange -FontColor ([System.Drawing.Color]::Red) } | Should -Not -Throw
$excel.Services.cells["C4"].Style.Font.Color.Rgb | Should -Be "FFFF0000"
Close-ExcelPackage -NoSave $excel
}
@@ -82,41 +82,41 @@ describe "Consistent passing of ranges." {
}
Context "PivotTables" {
it "Accepts Named range, .Cells['Name'], name&Worksheet, cells['A1:Z9'], worksheet&'A1:Z9' "{
it "Accepts Named range, .Cells['Name'], name&Worksheet, cells['A1:Z9'], worksheet&'A1:Z9' " {
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -RangeName servicerange -Title "Services on $Env:COMPUTERNAME"
$ws = $excel.Workbook.Worksheets[1] #can get a worksheet by name or index - starting at 1
$end = $ws.Dimension.End.Address
$ws = $excel.Workbook.Worksheets[1] #can get a worksheet by name or index - starting at 1
$end = $ws.Dimension.End.Address
#can get a named ranged by name or index - starting at zero
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt0 -SourceRange $ws.Names[0]`
-PivotRows Status -PivotData Name } | Should -Not -Throw
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt0 -SourceRange $ws.Names[0]`
-PivotRows Status -PivotData Name } | Should -Not -Throw
$excel.Workbook.Worksheets["pt0"] | Should -Not -BeNullOrEmpty
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt1 -SourceRange $ws.Names["servicerange"]`
-PivotRows Status -PivotData Name } | Should -Not -Throw
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt1 -SourceRange $ws.Names["servicerange"]`
-PivotRows Status -PivotData Name } | Should -Not -Throw
$excel.Workbook.Worksheets["pt1"] | Should -Not -BeNullOrEmpty
#Can specify the range for a pivot as NamedRange or Table or TableAddress or Worksheet + "A1:Z10" or worksheet + RangeName, or worksheet.cells["A1:Z10"] or worksheet.cells["RangeName"]
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt2 -SourceRange "servicerange" -SourceWorkSheet $ws `
-PivotRows Status -PivotData Name } | Should -Not -Throw
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt2 -SourceRange "servicerange" -SourceWorkSheet $ws `
-PivotRows Status -PivotData Name } | Should -Not -Throw
$excel.Workbook.Worksheets["pt2"] | Should -Not -BeNullOrEmpty
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt3 -SourceRange $ws.cells["servicerange"]`
-PivotRows Status -PivotData Name } | Should -Not -Throw
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt3 -SourceRange $ws.cells["servicerange"]`
-PivotRows Status -PivotData Name } | Should -Not -Throw
$excel.Workbook.Worksheets["pt3"] | Should -Not -BeNullOrEmpty
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt4 -SourceRange $ws.cells["A2:$end"]`
-PivotRows Status -PivotData Name } | Should -Not -Throw
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt4 -SourceRange $ws.cells["A2:$end"]`
-PivotRows Status -PivotData Name } | Should -Not -Throw
$excel.Workbook.Worksheets["pt4"] | Should -Not -BeNullOrEmpty
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt5 -SourceRange "A2:$end" -SourceWorkSheet $ws `
-PivotRows Status -PivotData Name } | Should -Not -Throw
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt5 -SourceRange "A2:$end" -SourceWorkSheet $ws `
-PivotRows Status -PivotData Name } | Should -Not -Throw
$excel.Workbook.Worksheets["pt5"] | Should -Not -BeNullOrEmpty
Close-ExcelPackage -NoSave $excel
Close-ExcelPackage -NoSave $excel
}
it "Accepts Table, Table.Addres " {
$excel = Get-Service | Export-Excel -Path $path -WorksheetName Services -PassThru -AutoSize -DisplayPropertySet -TableName servicetable -Title "Services on $Env:COMPUTERNAME"
$ws = $excel.Workbook.Worksheets["Services"] #can get a worksheet by name or index - starting at 1
$ws = $excel.Workbook.Worksheets["Services"] #can get a worksheet by name or index - starting at 1
#Can get a table by name or -stating at zero. Can specify the range for a pivot as or Table or TableAddress
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt1 -SourceRange $ws.tables["servicetable"]`
-PivotRows Status -PivotData Name } | Should -Not -Throw
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt1 -SourceRange $ws.tables["servicetable"]`
-PivotRows Status -PivotData Name } | Should -Not -Throw
$excel.Workbook.Worksheets["pt1"] | Should -Not -BeNullOrEmpty
{Add-PivotTable -ExcelPackage $excel -PivotTableName pt2 -SourceRange $ws.tables[0].Address `
-PivotRows Status -PivotData Name } | Should -Not -Throw
{ Add-PivotTable -ExcelPackage $excel -PivotTableName pt2 -SourceRange $ws.tables[0].Address `
-PivotRows Status -PivotData Name } | Should -Not -Throw
$excel.Workbook.Worksheets["pt2"] | Should -Not -BeNullOrEmpty
Close-ExcelPackage -NoSave $excel
}

View File

@@ -0,0 +1,90 @@
#Requires -Modules Pester
# if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) {
Import-Module $PSScriptRoot\..\ImportExcel.psd1 -Force
# }
Describe "Read Clipboard" -Tag "Read-Clipboard" {
It 'Should return $null if it cannot detect data format on the clipboard' {
$testData = 'abc'
$actual = ReadClipboardImpl $testData
$actual.Count | Should -Be 0
$actual | Should -BeNullOrEmpty
}
It 'Should return converted csv data' {
$testData = @"
Region,State,Units,Price
West,Texas,927,923.71
North,Tennessee,466,770.67
East,Florida,520,458.68
"@
$actual = ReadClipboardImpl $testData
$actual.count | Should -Be 3
}
It 'Should return converted tab delimited data' {
$testData = @"
YEAR PRESIDENT FIRST LADY VICE PRESIDENT
2021- Joseph R. Biden Jill Biden Kamala Harris
2017-2021 Donald J. Trump Melania Trump Mike Pence
2009-2017 Barack Obama Michelle Obama Joseph R. Biden
"@
$actual = ReadClipboardImpl $testData
$actual.count | Should -Be 3
}
It 'Should return converted json data' {
$testData = @"
[
{
"YEAR": "2021-",
"PRESIDENT": "Joseph R. Biden",
"FIRST LADY": "Jill Biden",
"VICE PRESIDENT": "Kamala Harris"
},
{
"YEAR": "2017-2021",
"PRESIDENT": "Donald J. Trump",
"FIRST LADY": "Melania Trump",
"VICE PRESIDENT": "Mike Pence"
},
{
"YEAR": "2009-2017",
"PRESIDENT": "Barack Obama",
"FIRST LADY": "Michelle Obama",
"VICE PRESIDENT": "Joseph R. Biden"
}
]
"@
$actual = ReadClipboardImpl $testData
$actual.count | Should -Be 3
}
It 'Should return converted "|" delimited data' {
$testData = @"
Region|State|Units|Price
West|Texas|927|923.71
North|Tennessee|466|770.67
East|Florida|520|458.68
"@
$actual = ReadClipboardImpl $testData -Delimiter '|'
$actual.count | Should -Be 3
}
It 'Should return converted data with headers' {
$testData = @"
West,Texas,927,923.71
North,Tennessee,466,770.67
East,Florida,520,458.68
"@
$actual = ReadClipboardImpl $testData -Header 'P1', 'P2', 'p3', 'P4'
$actual.count | Should -Be 3
$propertyNames = $actual[0].psobject.Properties.Name
$propertyNames[0] | Should -BeExactly 'P1'
$propertyNames[1] | Should -BeExactly 'P2'
$propertyNames[2] | Should -BeExactly 'p3'
$propertyNames[3] | Should -BeExactly 'P4'
}
}

View File

@@ -0,0 +1,46 @@
#Requires -Modules Pester
if (-not (Get-command Import-Excel -ErrorAction SilentlyContinue)) {
Import-Module $PSScriptRoot\..\ImportExcel.psd1
}
$skip = $false
if ($IsLinux -or $IsMacOS) {
$skip = $true
Write-Warning "Invoke-ExcelQuery: Linux and MacOs are not supported. Skipping tests."
}else{
try {
if ((New-Object system.data.oledb.oledbenumerator).GetElements().SOURCES_NAME -notcontains "Microsoft.ACE.OLEDB.12.0") {
$skip = $true
Write-Warning "Invoke-ExcelQuery: Microsoft.ACE.OLEDB.12.0 provider not found. Skipping tests."
}
}
catch {
$skip = $true
Write-Warning "Invoke-ExcelQuery: Calls to System.Data.OleDb failed. Skipping tests."
}
}
Describe "Invoke-ExcelQuery" -Tag "Invoke-ExcelQuery" {
$PSDefaultParameterValues = @{ 'It:Skip' = $skip }
BeforeAll {
$tfp = "$PSScriptRoot\Read-OleDbData.xlsx"
}
Context "Basic Checks" {
It "Should have a valid Test file" {
Test-Path $tfp | Should -Be $true
}
It "Should have the Read-OleDbData command loaded" {
(Get-Command Read-OleDbData -ErrorAction SilentlyContinue) -ne $null | Should -Be $true
}
It "Should have the Invoke-ExcelQuery command loaded" {
(Get-Command Invoke-ExcelQuery -ErrorAction SilentlyContinue) -ne $null | Should -Be $true
}
}
Context "Sheet1`$A1" {
It "Should return 1 result with a value of 1" {
$Results = Invoke-ExcelQuery $tfp "select ROUND(F1) as [A1] from [sheet1`$A1:A1]"
@($Results).length + $Results.A1 | Should -Be 2
}
}
}

View File

@@ -0,0 +1,4 @@
select
ROUND(F1) as [A1]
from
[sheet3$A1:A1]

View File

@@ -0,0 +1,7 @@
select ROUND(F1) as [A1] from [sheet1$A1:A1]
union all select ROUND(F1) as [A1] from [sheet2$A1:A1]
union all select ROUND(F1) as [A1] from [sheet3$A1:A1]
union all select ROUND(F1) as [A1] from [sheet4$A1:A1]
union all select ROUND(F1) as [A1] from [sheet5$A1:A1]
union all select ROUND(F1) as [A1] from [sheet6$A1:A1]
union all select ROUND(F1) as [A1] from [sheet7$A1:A1]

View File

@@ -0,0 +1,4 @@
select
*
from
[sheet1$A1:E10]

View File

@@ -0,0 +1,10 @@
select top 1
'All A1s' as [A1],
F1 as [Sheet1],
(select F1 FROM [sheet2$a1:a1]) as [Sheet2],
(select F1 FROM [sheet3$a1:a1]) as [Sheet3],
(select F1 FROM [sheet4$a1:a1]) as [Sheet4],
(select F1 FROM [sheet5$a1:a1]) as [Sheet5],
(select F1 FROM [sheet6$a1:a1]) as [Sheet6],
(select F1 FROM [sheet7$a1:a1]) as [Sheet7]
FROM [sheet1$a1:a1]

Some files were not shown because too many files have changed in this diff Show More