Skip to content

Commit ace9563

Browse files
authored
export record (#187)
1 parent aadc515 commit ace9563

File tree

2 files changed

+171
-1
lines changed

2 files changed

+171
-1
lines changed
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
<#
2+
.SYNOPSIS
3+
Export table records to a file
4+
5+
.DESCRIPTION
6+
Export table records in csv, xml, xls, xlsx, or pdf format.
7+
You can filter, sort, and choose specific properties to include in the report.
8+
Only basic authentication is supported.
9+
Export configurations, eg. row limit, can be found at System Properties->Import Export.
10+
11+
.PARAMETER Table
12+
Name of the table to be queried, by either table name or class name. Use tab completion for list of known tables.
13+
You can also provide any table name ad hoc.
14+
15+
.PARAMETER Id
16+
Either the record sys_id or number.
17+
If providing just an Id, not with Table, the Id prefix will be looked up to find the table name.
18+
19+
.PARAMETER Property
20+
Return one or more specific fields otherwise all fields will be returned
21+
22+
.PARAMETER Filter
23+
Array or multidimensional array of fields and values to filter on.
24+
Each array should be of the format @(field, comparison operator, value) separated by a join, either 'and', 'or', or 'group'.
25+
For a complete list of comparison operators, see $script:ServiceNowOperator and use Name in your filter.
26+
See the examples.
27+
28+
.PARAMETER Sort
29+
Array or multidimensional array of fields to sort on.
30+
Each array should be of the format @(field, asc/desc).
31+
32+
.PARAMETER Path
33+
Path to output file including the file name.
34+
File extension must be either .csv, .xml, .xls, .xlsx, or .pdf.
35+
36+
.PARAMETER ServiceNowSession
37+
ServiceNow session created by New-ServiceNowSession. Will default to script-level variable $ServiceNowSession.
38+
39+
.EXAMPLE
40+
Export-ServiceNowRecord -Id RITM0010001 -Path .\out.pdf
41+
Export a specific record by number
42+
43+
.EXAMPLE
44+
Export-ServiceNowRecord -Table incident -Filter @('assigned_to.name', '-like', 'greg') -Path .\out.xlsx
45+
Export incident records where the assigned to user's name contains greg
46+
47+
.EXAMPLE
48+
$filter = @('state', '-eq', '1'),
49+
'-and',
50+
@('short_description','-like', 'powershell'),
51+
'-group',
52+
@('state', '-eq', '2')
53+
PS > Export-ServiceNowRecord -Table incident -Filter $filter -Path .\out.pdf
54+
Export incident records where state is New and short description contains the word powershell or state is In Progress.
55+
The first 2 filters are combined and then or'd against the last.
56+
57+
.EXAMPLE
58+
Export-ServiceNowRecord -Table 'Incident' -Filter @('opened_at', '-between', (Get-Date).AddMonths(-24), (get-date).AddMonths(-12)) -Path .\out.pdf
59+
Export incident records that were opened between 1 and 2 years ago
60+
61+
.EXAMPLE
62+
Export-ServiceNowRecord -Table incident -Filter @('state', '-eq', '1') -Sort @('opened_at', 'desc') -Path .\out.pdf
63+
Export incident records where state equals New and sort by the field opened_at descending
64+
65+
.LINK
66+
https://docs.servicenow.com/bundle/rome-platform-user-interface/page/use/navigation/task/navigate-using-url.html
67+
68+
.LINK
69+
https://docs.servicenow.com/bundle/sandiego-platform-administration/page/administer/exporting-data/task/t_ExportDirectlyFromTheURL.html#t_ExportDirectlyFromTheURL
70+
#>
71+
function Export-ServiceNowRecord {
72+
73+
[CmdletBinding(DefaultParameterSetName = 'Id')]
74+
75+
Param (
76+
[Parameter(ParameterSetName = 'Table', Mandatory)]
77+
[Alias('sys_class_name')]
78+
[string] $Table,
79+
80+
[Parameter(ParameterSetName = 'Id', Mandatory, Position = 0)]
81+
[Parameter(ParameterSetName = 'Table')]
82+
[ValidateScript( {
83+
if ($_ -match '^[a-zA-Z0-9]{32}$' -or $_ -match '^([a-zA-Z]+)[0-9]+$') {
84+
$true
85+
} else {
86+
throw 'Id must be either a 32 character alphanumeric, ServiceNow sysid, or prefix/id, ServiceNow number.'
87+
}
88+
})]
89+
[Alias('sys_id', 'number')]
90+
[string] $Id,
91+
92+
[Parameter()]
93+
[Alias('Fields', 'Properties')]
94+
[string[]] $Property,
95+
96+
[Parameter()]
97+
[System.Collections.ArrayList] $Filter,
98+
99+
[parameter()]
100+
[ValidateNotNullOrEmpty()]
101+
[System.Collections.ArrayList] $Sort,
102+
103+
[Parameter(Mandatory)]
104+
[ValidateScript({
105+
$allowedExts = '.csv', '.xml', '.pdf', '.xls', '.xlsx'
106+
if ([System.IO.Path]::GetExtension($_).ToLower() -in $allowedExts ) {
107+
$true
108+
} else {
109+
throw ('File extension must be one of {0}' -f ($allowedExts -join ', '))
110+
}
111+
})]
112+
[string] $Path,
113+
114+
[Parameter()]
115+
[hashtable] $ServiceNowSession = $script:ServiceNowSession
116+
)
117+
118+
process {
119+
120+
$newFilter = $Filter
121+
122+
if ( $Table ) {
123+
$thisTable = $Table
124+
}
125+
126+
if ( $Id ) {
127+
if ( $Id -match '^[a-zA-Z0-9]{32}$' ) {
128+
if ( -not $thisTable ) {
129+
throw 'Providing sys_id for -Id requires a value for -Table. Alternatively, provide an Id with a prefix, eg. INC1234567, and the table will be automatically determined.'
130+
}
131+
132+
$newFilter = @('sys_id', '-eq', $Id)
133+
} else {
134+
if ( -not $thisTable ) {
135+
# get table name from prefix if only Id was provided
136+
$idPrefix = ($Id | Select-String -Pattern '^([a-zA-Z]+)([0-9]+$)').Matches.Groups[1].Value.ToLower()
137+
Write-Debug "Id prefix is $idPrefix"
138+
$thisTable = $script:ServiceNowTable | Where-Object { $_.NumberPrefix -and $idPrefix -eq $_.NumberPrefix } | Select-Object -ExpandProperty Name
139+
if ( -not $thisTable ) {
140+
throw ('The prefix for Id ''{0}'' was not found and the appropriate table cannot be determined. Known prefixes are {1}. Please provide a value for -Table.' -f $Id, ($ServiceNowTable.NumberPrefix.Where( { $_ }) -join ', '))
141+
}
142+
}
143+
$newFilter = @('number', '-eq', $Id)
144+
}
145+
}
146+
147+
$params = Get-ServiceNowAuth -S $ServiceNowSession
148+
$params.Body = @{
149+
'sysparm_query' = (New-ServiceNowQuery -Filter $newFilter -Sort $Sort)
150+
}
151+
152+
if ($Property) {
153+
$params.Body.sysparm_fields = ($Property -join ',').ToLower()
154+
}
155+
156+
$params.OutFile = $Path
157+
158+
# need to tell SN the format, get it from file extension
159+
$format = [System.IO.Path]::GetExtension($Path).Replace('.', '').ToUpper()
160+
161+
# only exception to 'extension is the format' rule
162+
if ( $format -eq 'XLS' ) { $format = 'EXCEL' }
163+
164+
$params.Uri = 'https://{0}/{1}_list.do?{2}' -f $ServiceNowSession.Domain, $thisTable, $format
165+
166+
Write-Verbose ($params | ConvertTo-Json)
167+
Invoke-RestMethod @params
168+
169+
}
170+
}

ServiceNow/ServiceNow.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ FunctionsToExport = 'Get-ServiceNowRecordInterim', 'New-ServiceNowConfigurationI
8181
'New-ServiceNowQuery', 'New-ServiceNowRecord',
8282
'Remove-ServiceNowAttachment', 'Remove-ServiceNowRecord',
8383
'Update-ServiceNowChangeRequest', 'Update-ServiceNowIncident',
84-
'Update-ServiceNowRequestedItem', 'Update-ServiceNowRecord'
84+
'Update-ServiceNowRequestedItem', 'Update-ServiceNowRecord', 'Export-ServiceNowRecord'
8585

8686
# Cmdlets to export from this module, for best performance, do not use wildcards and do not delete the entry, use an empty array if there are no cmdlets to export.
8787
CmdletsToExport = @()

0 commit comments

Comments
 (0)