Skip to content

Commit 5b4857d

Browse files
author
James O'Neill
committed
New subtotals, tweak module stats example
1 parent 0f301ff commit 5b4857d

File tree

2 files changed

+141
-7
lines changed

2 files changed

+141
-7
lines changed

Add-Subtotals.ps1

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
Function Add-Subtotals {
2+
param(
3+
[Parameter(Mandatory=$true, Position=0)]
4+
$ChangeColumnName , # = "Location"
5+
6+
[Parameter(Mandatory=$true, Position=1)]
7+
[hashtable]$AggregateColumn , #= @{"Sales" = "SUM" }
8+
9+
[Parameter(Position=2)]
10+
$ExcelPath = ([System.IO.Path]::GetTempFileName() -replace "\.tmp", ".xlsx") ,
11+
12+
[Parameter(Position=3)]
13+
$WorksheetName = "Sheet1",
14+
15+
[Parameter(ValueFromPipeline=$true)]
16+
$InputObject, #$DataToPivot | Sort location, product
17+
18+
[switch]$HideSingleRows,
19+
[switch]$NoSort,
20+
[switch]$NoOutLine,
21+
[switch]$Show
22+
23+
)
24+
begin {
25+
if (-not $PSBoundParameters.ContainsKey('ExcelPath')) {$Show = $true}
26+
$data = @()
27+
$aggFunctions = [ordered]@{
28+
"AVERAGE" = 1; "COUNT" = 2; "COUNTA" = 3 #(non empty cells) f
29+
"MAX" = 4; "MIN" = 5; "PRODUCT" = 6; "STDEV" = 7 # (sample)
30+
"STDEVP" = 8 # (whole population);
31+
"SUM" = 9; "VAR" = 10 # (Variance sample)
32+
"VARP" = 11 # (whole population) #add 100 to ignore hidden cells
33+
}
34+
}
35+
process {
36+
$data += $InputObject
37+
}
38+
end {
39+
if (-not $NoSort) {$data = $data | Sort-Object $changeColumnName}
40+
$Header = $data[0].PSObject.Properties.Name
41+
#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
42+
$aggFormulas = @{}
43+
foreach ($k in $AggregateColumn.Keys) {
44+
$columnNo = 0 ;
45+
while ($columnNo -lt $header.count -and $header[$columnNo] -ne $k) {$columnNo ++}
46+
if ($columnNo -eq $header.count) {
47+
throw "'$k' isn't a property of the first row of data."; return
48+
}
49+
if ($AggregateColumn[$k] -is [string]) {
50+
$aggfn = $aggFunctions[$AggregateColumn[$k]]
51+
if (-not $aggfn) {
52+
throw "$($AggregateColumn[$k]) is not a valid aggregation function - these are $($aggFunctions.keys -join ', ')" ; return
53+
}
54+
}
55+
else {$aggfn = $AggregateColumn[$k]}
56+
$aggFormulas[$k] = "=SUBTOTAL({0},{1}{{0}}:{1}{{1}})" -f $aggfn , (Get-ExcelColumnName ($columnNo+1) ).ColumnName
57+
}
58+
if ($aggformulas.count -lt 1) {throw "We didn't get any aggregation formulas"}
59+
$aggFormulas | out-string -Stream | Write-Verbose -Verbose
60+
#endregion
61+
$insertedRows = @()
62+
$singleRows = @()
63+
$previousValue = $data[0].$changeColumnName
64+
$currentRow = $lastChangeRow = 2
65+
#region insert subtotals and send to excel:
66+
#each time there is a change in the column we're intetersted in.
67+
#either Add a row with the value and subtotal(s) function(s) if there is more than one row to total
68+
#or note the row if there was only one row with that value (we may hide it later.)
69+
$excel = $data |
70+
ForEach-Object -process {
71+
if ($_.$changeColumnName -ne $previousValue) {
72+
if ($lastChangeRow -lt ($currentrow - 1)) {
73+
$NewObj = @{$changeColumnName = $previousValue}
74+
foreach ($k in $aggFormulas.Keys) {
75+
$newobj[$k] = $aggformulas[$k] -f $lastChangeRow, ($currentRow - 1)
76+
}
77+
$insertedRows += $currentRow
78+
[pscustomobject]$newobj
79+
$currentRow += 1
80+
}
81+
else {$singleRows += $currentRow }
82+
$lastChangeRow = $currentRow
83+
$previousValue = $_.$changeColumnName
84+
}
85+
$_
86+
$currentRow += 1
87+
} -end { # the process block won't output the last row
88+
if ($lastChangeRow -lt ($currentrow - 1)) {
89+
$NewObj = @{$changeColumnName = $previousValue}
90+
foreach ($k in $aggFormulas.Keys) {
91+
$newobj[$k] = $aggformulas[$k] -f $lastChangeRow, ($currentRow - 1)
92+
}
93+
$insertedRows += $currentRow
94+
[pscustomobject]$newobj
95+
}
96+
else {$singleRows += $currentRow }
97+
} | Export-Excel -Path $ExcelPath -PassThru -AutoSize -AutoFilter -AutoNameRange -BoldTopRow -WorksheetName $WorksheetName -Activate -ClearSheet #-MaxAutoSizeRows 10000
98+
#endregion
99+
#Put the subtotal rows in bold optionally hide rows where only one has the value of interest.
100+
$ws = $excel.$WorksheetName
101+
#We kept lists of the total rows Since 1 rows won't get expand/collapse we can hide them.
102+
foreach ($r in $insertedrows) {$ws.Row($r).style.font.bold = $true }
103+
if ($HideSingleRows) {
104+
foreach ($r in $hideRows) { $ws.Row($r).hidden = $true}
105+
}
106+
$range = $ws.Dimension.Address
107+
$ExcelPath = $excel.File.FullName
108+
$SheetIndex = $ws.index
109+
if ($NoOutline) {
110+
Close-ExcelPackage $excel -show:$Show
111+
return
112+
}
113+
else {
114+
Close-ExcelPackage $excel
115+
116+
try { $excelApp = New-Object -ComObject "Excel.Application" }
117+
catch { Write-Warning "Could not start Excel application - which usually means it is not installed." ; return }
118+
119+
try { $excelWorkBook = $excelApp.Workbooks.Open($ExcelPath) }
120+
catch { Write-Warning -Message "Could not Open $ExcelPath." ; return }
121+
$ws = $excelWorkBook.Worksheets.item($SheetIndex)
122+
$null = $ws.Range($range).Select()
123+
$null = $excelapp.ActiveCell.AutoOutline()
124+
$null = $ws.Outline.ShowLevels(1,$null)
125+
$excelWorkBook.Save()
126+
if ($show) {$excelApp.Visible = $true}
127+
else {
128+
[void]$excelWorkBook.close()
129+
$excelapp.Quit()
130+
}
131+
}
132+
}
133+
}

Examples/Extra/Get-ModuleStats.ps1

+8-7
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,16 @@
66
#>
77

88
param(
9-
[Parameter(Mandatory=$true)]
10-
$moduleName,
9+
$moduleName = "ImportExcel",
1110
[ValidateSet('Column','Bar','Line','Pie')]
1211
$chartType="Line"
1312
)
1413

15-
$galleryUrl = "https://www.powershellgallery.com/packages/$moduleName"
16-
$nolegend = '-nolegend'
17-
if($chartType -eq 'pie') {$nolegend = $null}
18-
$code = "$($chartType)Chart (Get-HtmlTable $galleryUrl -FirstDataRow 1 | sort lastupdated -desc) -title 'Download stats for $moduleName' $nolegend"
14+
$download = Get-HtmlTable "https://www.powershellgallery.com/packages/$moduleName" -FirstDataRow 1 |
15+
Select-Object @{n="Version";e={$v = $Null ; if ($_.version -is [valuetype]) {[string][version]($_.version.tostring("0.0")) }
16+
elseif ($_.version -is [string] -and [version]::TryParse($_.version.trim(),[ref]$v)) {$v}
17+
else {$_.Version.trim() -replace "\s+"," " } }},
18+
Downloads, @{n="LastUpdated";e={[datetime]$_.last_updated}} |
19+
Sort-Object lastupdated -Descending
1920

20-
$code | Invoke-Expression
21+
& "$($chartType)Chart" $download "Download stats for $moduleName" -nolegend:($chartype -ne 'pie')

0 commit comments

Comments
 (0)