From 463944ae2d5040f2aebb35a180474889a84cb542 Mon Sep 17 00:00:00 2001 From: jhoneill Date: Wed, 30 Oct 2019 10:59:45 +0000 Subject: [PATCH] Added support for Send-SQLData -force --- Send-SQLDataToExcel.ps1 | 65 ++++++++++++++++++++++++++--------------- 1 file changed, 41 insertions(+), 24 deletions(-) diff --git a/Send-SQLDataToExcel.ps1 b/Send-SQLDataToExcel.ps1 index 874ee87..280f82f 100644 --- a/Send-SQLDataToExcel.ps1 +++ b/Send-SQLDataToExcel.ps1 @@ -29,6 +29,8 @@ A System.Data.DataTable object containing the data to be inserted into the spreadsheet without running a query. This remains supported to avoid breaking older scripts, but if you have a DataTable object you can pass the it into Export-Excel using -InputObject. + .PARAMETER Force + If specified Export-Excel will be called with parameters specified, even if there is no data to send .EXAMPLE C:\> Send-SQLDataToExcel -MsSQLserver -Connection localhost -SQL "select name,type,type_desc from [master].[sys].[all_objects]" -Path .\temp.xlsx -WorkSheetname master -AutoSize -FreezeTopRow -AutoFilter -BoldTopRow @@ -108,7 +110,8 @@ [string]$SQL, [int]$QueryTimeout, [Parameter(ParameterSetName="Pre-FetchedData", Mandatory=$true)] - [System.Data.DataTable]$DataTable + [System.Data.DataTable]$DataTable, + [switch]$Force ) #Import the parameters from Export-Excel, we will pass InputObject, and we have the common parameters so exclude those, #and re-write the [Parmameter] attribute on each one to avoid parameterSetName here competing with the settings in Export excel. @@ -135,38 +138,52 @@ $null = $PSBoundParameters.Remove('AutoFilter') } #We were either given a session object or a connection string (with, optionally a MSSQLServer parameter) - #If we got -MSSQLServer, create a SQL connection, if we didn't but we got -Connection create an ODBC connection - if ($MsSQLserver -and $Connection) { + try { + #If we got -MSSQLServer, create a SQL connection, if we didn't but we got -Connection create an ODBC connection + if ($MsSQLserver -and $Connection) { if ($Connection -notmatch '=') {$Connection = "server=$Connection;trusted_connection=true;timeout=60"} $Session = New-Object -TypeName System.Data.SqlClient.SqlConnection -ArgumentList $Connection if ($Session.State -ne 'Open') {$Session.Open()} if ($DataBase) {$Session.ChangeDatabase($DataBase) } - } - elseif ($Connection) { + } + elseif ($Connection) { $Session = New-Object -TypeName System.Data.Odbc.OdbcConnection -ArgumentList $Connection ; $Session.ConnectionTimeout = 30 + } } - if ($Session) { - #A session was either passed in or just created. If it's a SQL one make a SQL DataAdapter, otherwise make an ODBC one - if ($Session -is [String] -and $Global:DbSessions[$Session]) {$Session = $Global:DbSessions[$Session]} - if ($Session.GetType().name -match "SqlConnection") { - $dataAdapter = New-Object -TypeName System.Data.SqlClient.SqlDataAdapter -ArgumentList ( - New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList $SQL, $Session) - } - else { - $dataAdapter = New-Object -TypeName System.Data.Odbc.OdbcDataAdapter -ArgumentList ( - New-Object -TypeName System.Data.Odbc.OdbcCommand -ArgumentList $SQL, $Session ) - } - if ($QueryTimeout) {$dataAdapter.SelectCommand.CommandTimeout = $QueryTimeout} + catch { + Write-Warning "An Error occured trying to connect to $Connection, the error was $([Environment]::NewLine + $_.Exception.InnerException))" + } + if ($Session -is [String] -and $Global:DbSessions[$Session]) {$Session = $Global:DbSessions[$Session]} - #Both adapter types output the same kind of table, create one and fill it from the adapter - $DataTable = New-Object -TypeName System.Data.DataTable - $rowCount = $dataAdapter.fill($dataTable) - Write-Verbose -Message "Query returned $rowCount row(s)" + if ($Session) { + try { + #A session was either passed in or just created. If it's a SQL one make a SQL DataAdapter, otherwise make an ODBC one + if ($Session.GetType().name -match "SqlConnection") { + $dataAdapter = New-Object -TypeName System.Data.SqlClient.SqlDataAdapter -ArgumentList ( + New-Object -TypeName System.Data.SqlClient.SqlCommand -ArgumentList $SQL, $Session) + } + else { + $dataAdapter = New-Object -TypeName System.Data.Odbc.OdbcDataAdapter -ArgumentList ( + New-Object -TypeName System.Data.Odbc.OdbcCommand -ArgumentList $SQL, $Session ) + } + if ($QueryTimeout) {$dataAdapter.SelectCommand.CommandTimeout = $QueryTimeout} + + #Both adapter types output the same kind of table, create one and fill it from the adapter + $DataTable = New-Object -TypeName System.Data.DataTable + $rowCount = $dataAdapter.fill($dataTable) + Write-Verbose -Message "Query returned $rowCount row(s)" + } + catch { + Write-Warning "An Error occured trying to run the query, the error was $([Environment]::NewLine + $_.Exception.InnerException))" + } } - if ($DataTable.Rows.Count) { + #if force was specified export even if there are no rows. If there are no columns, the query failed and export "null" if forced + if ($Force -or $DataTable.Rows.Count) { #Call export-excel removing parameters which relate to the SQL query, and keeping the rest. - 'Connection' , 'Database' , 'Session' , 'MsSQLserver' , 'SQL' , 'DataTable' , 'QueryTimeout' | ForEach-Object {$null = $PSBoundParameters.Remove($_) } - Export-Excel @PSBoundParameters -InputObject $DataTable + 'Connection' , 'Database' , 'Session' , 'MsSQLserver' , 'SQL' , 'DataTable' , 'QueryTimeout' | + ForEach-Object {$null = $PSBoundParameters.Remove($_) } + if ($DataTable.Columns.Count) { Export-Excel @PSBoundParameters -InputObject $DataTable } + else { Export-Excel @PSBoundParameters -InputObject $null } } else {Write-Warning -Message ' No Data to insert.' } #If we were passed a connection and opened a session, close that session.