-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathExport-Excel.ps1
executable file
·198 lines (167 loc) · 6.75 KB
/
Export-Excel.ps1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# https://gist.github.com/josheinstein/9898245
#.SYNOPSIS
# Exports objects to an Excel spreadsheet by writing them to a temporary
# CSV file and using Excel automation model to import it into a workbook.
# This allows formatting to be applied to columns which would not otherwise
# be possible in a plain CSV export.
function Export-Excel {
[CmdletBinding()]
param(
# The path to save the Excel spreadsheet to.
[Parameter(Position=1)]
[String]$Path,
# An object or array of objects to write out to an Excel spreadsheet.
# This parameter typically comes from pipeline input.
[Parameter(ValueFromPipeline=$true)]
[Object[]]$InputObject,
# A hashtable that contains column headers as keys and
# valid Excel format strings as values. The formats will
# be applied to the columns after the worksheet is generated.
[Parameter()]
[Hashtable]$Format,
# An array of column names to hide.
# You should probably exclude them from the output by using the
# Select-Object command earlier in the pipeline, but if you want them
# to be in the spreadsheet, but simply hidden, use this parameter.
[Parameter()]
[String[]]$Hide,
# Turns off column wrapping on all cells.
[Parameter()]
[Switch]$NoWrap,
# Quits Excel after the spreadsheet is generated.
# This parameter should be used with caution since Excel may already be
# open prior to the command.
[Parameter()]
[Switch]$Quit
)
begin {
if ($Path) {
# If they supplied an output path, we will actually save the temp file
# to the specified path in the format indicated by the extension. Since
# the path will be given to Excel, we need to resolve the native path
# in case a PowerShell path (like ~\Desktop\blah.xls) was used.
$Path = $PSCmdlet.SessionState.Path.GetUnresolvedProviderPathFromPSPath($Path)
# If the output file already exists, nuke it.
if (Test-Path $Path -PathType Leaf) {
Remove-Item $Path -Force
}
}
# Excel VBA objects
$Excel = $Null
$Workbook = $Null
$Sheet = $Null
# Use a temporary file in the system temp directory to write the
# results to. If it already exists, delete it.
$ScratchName = "Export-Excel.html"
$ScratchPath = "$ENV:TEMP\$ScratchName"
Write-Verbose "Writing output to $ScratchPath"
Remove-Item $ScratchPath -Force -ErrorAction 0
# Create a wrapped pipeline that we can pass each input
# object to as if it were piped directly to ConvertTo-Html.
# We're using ConvertTo-Html because it produces a decent
# table that Excel can open without worrying about newlines
# in a CSV file.
$ScriptBlock = { ConvertTo-Html -As Table -Title "Export-Excel" | Set-Content $ScratchPath -Encoding UTF8 -Force }
$Pipeline = $ScriptBlock.GetSteppablePipeline($MyInvocation.CommandOrigin)
$Pipeline.Begin($PSCmdlet)
# Define some helper functions for modifying the worksheet
# using the named column headers
$Headers = @{}
# Sets the display format string on columns with a given name
function SetColumnFormat($Header, $Format) {
if ($Headers[$Header]) {
$Range = $Sheet.Cells.Item(1, $Headers[$Header]).EntireColumn
try {
$Range.NumberFormat = $Format
}
catch {
Write-Warning "Column $Header has invalid format string: $Format ($_)"
}
}
}
# Hides columns with a given name
function SetColumnHidden($Header) {
if ($Headers[$Header]) {
$Range = $Sheet.Cells.Item(1, $Headers[$Header]).EntireColumn
try {
$Range.Hidden = $True
}
catch {
Write-Warning "Could not hide column $Header ($_)"
}
}
}
}
process {
# Not much to do here except pass the input object to the
# wrapped pipeline which sends it to the output file.
foreach ($o in $InputObject) {
$Pipeline.Process($o)
}
}
end {
$Pipeline.End()
$Pipeline.Dispose()
# Figure out column headings and store them in a hashtable.
# This makes it easier to refer to a column range by name.
$i = 1
foreach ($Match in [Regex]::Matches($(Get-Content $ScratchPath), '(?is)<TH>([^<]+)</TH>')) {
$Headers[$Match.Groups[1].Value] = $i++
}
# Excel Automation
try {
$Excel = [System.Runtime.InteropServices.Marshal]::GetActiveObject('Excel.Application')
}
catch [System.Management.Automation.MethodInvocationException] {
$Excel = New-Object -ComObject 'Excel.Application'
}
$Workbook = $Excel.Workbooks.Open($ScratchPath)
$Sheet = $Workbook.Worksheets.Item(1)
# Turn off cell wrapping
if ($NoWrap) {
$Sheet.UsedRange.WrapText = $False
}
# Set column formats
foreach ($Key in $Format.Keys) {
SetColumnFormat $Key $Format[$Key]
}
# Hide certain columns
foreach ($Key in $Hide) {
SetColumnHidden $Key
}
$Workbook.Activate()
$Excel.ActiveWindow.DisplayGridlines = $true
# Save As?
if ($Path) {
$FileFormat = 51
switch ([IO.Path]::GetExtension($Path)) {
'.xlsb' { $FileFormat = 50 } # Excel 12 Binary
'.xlsx' { $FileFormat = 51 } # Excel 12 XML (No Macro)
'.xlsm' { $FileFormat = 52 } # Excel 12 (With Macro)
'.xls' { $FileFormat = 56 } # Excel Classic
}
$Workbook.SaveAs($Path, $FileFormat)
}
if ($Quit) {
$Excel.Quit()
}
else {
$Excel.Visible = $true
$Excel.ActiveWindow.Activate()
}
$Excel = $null
}
}
# $ExcelArgs = @{
# Verbose = $True
# Path = "~\Desktop\EventLogs.xlsx"
# Format = @{
# InstanceId = '#,##0'
# TimeGenerated = 'm/d/yy h:mm AM/PM'
# TimeWritten = 'm/d/yy h:mm AM/PM'
# }
# Hide = ('Data','ReplacementStrings')
# NoWrap = $True
# Quit = $True
# }
# Get-EventLog Application -Newest 100 | Export-Excel @ExcelArgs