Link to SSRS report to directly download PDF - reporting-services

Is there a query string parameter I can pass to an SSRS report that will result in a direct download of the report (preferably in PDF) rather than having the browser navigate to the report?

I've done this with a PowerShell script. The key is to pass in &rs:Format=PDF to the URL. Microsoft Reference
#set SSRS variables
$exportPath = 'C:\Temp\';
$ssrsPath = 'http://YourReportServer/ReportServer/Pages/ReportViewer.aspx?%2fYour%20Report%20Folder/Your%20%20Report';
$ssrsFileName = $ssrsPath.split('/')[-1] -replace '%20', ' ';
$ssrsFile = $exportPath + $ssrsFileName + '.pdf';
#remove file if it already exists
if (Test-Path $ssrsFile)
{
Remove-Item $ssrsFile
}
#create pdf of SQL Server Reporting Services (SSRS) report
$ssrsFilePdf = $ssrsPath + '&rs:Format=PDF'
(Invoke-WebRequest -Uri $ssrsFilePdf -OutFile $ssrsFile -UseDefaultCredentials -TimeoutSec 240);

I finally found what I was looking for.
By adding the following query string to the URL, SSRS will deliver the report in PDF format rather than through the usual interface.
&rs:Format=PDF
I'm assuming that all other necessary parameters should be provided in the query string as well.

Related

What is the ItemType for SSRS Catalog Type 14?

SQL Server 2019. I manually uploaded a xlsx file to the server and it was placed in an "Excel Workbooks" group. When I look in the reportserver catalog table I see the Type value is 14. I'm trying to write a powershell script to upload a bunch of xlsx files instead of having to do it manually, one by one. I need to know the ItemType. I can use "Resource" but it doesn't upload it to the "Excel Workbooks" group, it uploads it to the "Resources" group. I did list everything in my report server and see the TypeName for the xlsx I manually uploaded is "ExcelWorkbook", but is not a valid ItemType. Any suggestions? Below is the powershell I'm using (I'm still new to powershell). Thanks!
$WebServiceUrl = "http://xxxx"
$ReportFolder = "PDF_Reports2"
$SourceDirectory = $PSScriptRoot
$Overwrite = $true
$SSRSProxy = New-WebServiceProxy -Uri $WebServiceUrl'/ReportServer/ReportService2010.asmx?WSDL' -UseDefaultCredential
# LIST ITEMS IN SERVER
#$SSRSProxy.ListChildren("/",$true)
$type = $SSRSProxy.GetType().Namespace
$datatype = ($type + '.Property')
$Property =New-Object ($datatype);
$Property.Name = "MimeType"
$Property.Value = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
$SourceDirectory = "c:\tmp\SSRS\"
$ItemType = "Resource" # Resource works, but it gets put in the Resources group, I want it in the Excel Workbooks group.
$ReportFolder = "/PDF_Reports2"
ForEach ($rdlfile in Get-ChildItem $SourceDirectory -Filter "*.xlsx" | Where-Object { $_.Attributes -ne "Directory" } )
{
$byteArray = [System.IO.File]::ReadAllBytes($rdlfile.FullName)
write-host $rdlfile.FullName
$Warnings = #();
$SSRSProxy.CreateCatalogItem($ItemType, $rdlfile, $ReportFolder, $Overwrite, $byteArray, $Property, [ref]$Warnings)
$warnings.Length
}

Changing report name in SSRS email subscription

We are using SSRS 2012 at my company and we use a plug-in to append a datestamp to about 5% of the emailed report names (along with ZIPping a few of them), as it looks like you can't set up an email subscription and then script the attached report name changes, can only do that when your subscription writes to a file share.
This plug-in is no longer supported and fails quite a bit for no obvious reason. The workaround of writing these reports to a file share then scripting the email process from there is not a practical solution for us.
We will be upgrading to SSRS 2019 this year, can anyone tell me if modifying emailed report names is now an option, I am finding no definitive answer online. Or is there a supported reliable plug-in anyone can recommend, that adds datestamps to email subscription attached report names and can compress those reports?
If you have custom requirements for emailing subscriptions, you can setup a PowerShell script to run on a server under a scheduled task.
Here is an example were I export a Tableau workbook and SSRS report to pdf, zip them and send it as an email.
<#
Description: Powershell Report Subscription
Purpose: To export pdf files from SQL Server Reporting Services and Tableau and then email them as attachments.
References: https://onlinehelp.tableau.com/current/server/en-us/tabcmd_cmd.htm#id7cb8d032-a4ff-43da-9990-15bdfe64bcd0
As Is: Deployed to C:\Temp and running on a schedule with Windows Task Scheduler
#>
Try
{
#set email variables
$smtpServer = 'YourServer.com';
$emailSubject = 'Weekly Report';
$emailFrom = 'Business.Intelligence#yourcompany.com';
$emailError = 'Business.Intelligence#yourcompany.com';
$emailTo = #('John Smith <john.smith#yourcompany.com>', 'Dave Scott <dave.scott#yourcompany.com>');
$emailCc = 'Business.Intelligence#yourcompany.com';
$exportPath = 'C:\Temp\';
$zipFile = $exportPath + 'reports';
#set Tableau variables
$tableauServer = 'TABLEAU_SERVER';
$tableauUsername = 'your_service_account'; #user must have read/write permissions to $exportPath
$tableauPassword = '###################';
$tableauTabCmdPath = 'C:\Program Files\Tableau\Tableau Server\2019.3\extras\Command Line Utility\tabcmd.exe';
$tableauWorkbook = 'YourFolder/YourWorkbook';
$tableauFile = $exportPath + $tableauWorkbook.Substring($tableauWorkbook.IndexOf('/')+1) + '.pdf';
#set SSRS variables
$ssrsPath = 'http://SSRS_SERVER/ReportServer/Pages/ReportViewer.aspx?%2fFinance/Weekly%20Report';
$ssrsFileName = $ssrsPath.split('/')[-1] -replace '%20', ' ';
$ssrsFile = $exportPath + $ssrsFileName + '.pdf';
#remove files if they already exist so we don't send out old reports
if (Test-Path $tableauFile)
{
Remove-Item $tableauFile
}
if (Test-Path $ssrsFile)
{
Remove-Item $ssrsFile
}
#create pdf of SQL Server Reporting Services (SSRS) report
$ssrsFilePdf = $ssrsPath + '&rs:Format=PDF'
(Invoke-WebRequest -Uri $ssrsFilePdf -OutFile $ssrsFile -UseDefaultCredentials -TimeoutSec 240);
#create pdf of Tableau workbook
$tableauServer = $tableauServer;
$tableauWorkbookRefresh = $tableauWorkbook + '?:refresh=yes';
$TabCmd = $tableauTabCmdPath;
& $TabCmd login -s $tableauServer -u $tableauUsername -p $tableauPassword;
& $TabCmd export $tableauWorkbookRefresh -pdf -f $tableauFile;
& $TabCmd logout;
#compress files
Compress-Archive -Path $exportPath -DestinationPath $zipFile
$zipFile = $zipFile + '.zip'
#email attachments to users
Set pathname ="C:\Windows\System32\WindowsPowerShell>";
$emailBody = #"
Hi,
Attached are the weekly reports.
This is a link to the Tableau Workbook Weekly Report
http://$tableauServer/#/views/$tableauWorkbook
This is a link to the Report Manager Weekly Report
$ssrsPath
"#
Send-MailMessage -smtpServer $smtpServer -From $emailFrom -To $emailTo -Cc $emailCc -Subject $emailSubject -Attachments $zipFile -Body $emailBody;
}
Catch
{
$errorType = $_.Exception.GetType().FullName;
$errorMessage = $_.Exception.Message;
$scriptFileName = $MyInvocation.MyCommand.Name;
$scriptFileCode = $MyInvocation.MyCommand.Definition;
Write-Host "Exception:" -ForegroundColor Red;
Write-Host "Exception Type: $($_.Exception.GetType().FullName)" -ForegroundColor Red;
Write-Host "Exception Message: $($_.Exception.Message)" -ForegroundColor Red;
Send-MailMessage -smtpServer $smtpServer -From $emailFrom -To $emailError -Subject "$emailSubject FAILED!" -Body " Host Name: $env:computername `n Error Type: $errorType `n Error Message: $errorMessage. `n`n Script File: $scriptFileName `n Script Code: `n $scriptFileCode";
Break;
}

Azure Runbook Webhook with parameters from httpClient

looked at a few examples of how to execute a webhook with parameters but can't seem to make the connection on what I am missing. Any advice on what I am doing wrong would be appreciated.
please consider:
my Powershell runbook
[CmdletBinding()]
Param([object]$WebhookData) #this parameter name needs to be called
WebHookData otherwise the webhook does not work as expected.
$VerbosePreference = 'continue'
Write-Output "hello"
"in the inline"
if($WebhookData -ne $null)
{
"using webhookdata"
$WebhookName = $WebhookData.WebhookName
$WebhookBody = $WebhookData.RequestBody
$webhookBodyObject = $WebhookBody | ConvertFrom-JSON
line 15 'The parameter created was ' $webhookBodyObject.strYear
My httpclient post request looks like this (warning..its vb)
dim WebHookData as new StringContent("{'strYear'='2018'}",Encoding.UTF8,"application/json")
Dim resp as Task(Of HttpResponseMessage)
resp = _client.PostAsync(webhook,WebHookData)
status = resp.Result.Content.ReadAsStringAsync().Result
if(status.Contains("JobId"))
status = "Scheduled!"
End If
My Webhook data is being posted to my webhook as this.
{"WebhookName":"myimportjob","RequestBody":"{'strYear'='2018'}","RequestHeader":{"Connection":"Keep-Alive","Expect":"100-continue","Host":"xxx.azure-automation.net","x-ms-request-id":"xxx"}}
I am getting this error
At line:15 char:42
+ 'The parameter created was ' $webhookBodyObject.strYear
+ ~~~~~~~~~~~~~~~~~~ Unexpected token '$webhookBodyObject' in expression or
statement.
I discovered the devil is in the details.
Firstly I had
$webhookBodyObject = $WebhookBody | ConvertFrom-JSON
which is not the same as
$webhookBodyObject = $WebhookBody | ConvertFrom-Json <---this is the correct syntax
The other was that the json I was sending had a single quote like this '{"key":"value"}'
For some reason, even though it passed regular powershell, the runbook didn't like it. It wants it's Json like this {"key":"value"}. I never tested complex objects so I can't speak to that.

Freeze Column Headers in excel after export from ssrs

I have created a report and now I need to freeze tablix header. I tried all the ways related to freeze panes in SSRS, but after export to excel, the freeze pane is not working. Do you know any way to achieve this in SSRS 2016?
Below are the steps that I've tried:
Select the tabix and click on Tablix properties.
In the General tab under Column Headers section you can see "Keep header visible while scrolling" checkbox, check it.
Now the header row will be remain fixed in the report.
OR
In the grouping pane, make sure to turn on advanced mode (click on the small black down arrow on the far right of the grouping pane)
Select the corresponding (Static) item in the row group hierarchy
In the properties grid, set RepeatOnNewPage to true
KeepwithGroup to After
OR
Freeze the header of all columns[ Freezing table header ] : To do select static member of table header row from row groups [ Advanced
Mode ] and set FixedData to true
Freeze the initial 2 columns : To do select static member of columns in column group and set fixedData to true.
There are a two different solutions that I know of to this problem. Each has its pros and cons.
Solution 1
You can follow this guide on mssqltips.com. This solution has you create a text box for each column and place it in the report header. It is a tedious and cumbersome way to get the job done but it works and it is all contained within the report.
Solution 2
The second way to accomplish this is with powershell. This solution only works if you can schedule the distribution of the report instead of having on demand access in the SSRS portal. You have powershell generate the report, modify the output, and distribute. Below is a sample powershell script.
#Set variables
$ReportServerUri = "http://MySsrsServer/ReportServer_MySsrsServer/ReportExecution2005.asmx?WSDL"
$ReportPath = "/MyReportPath"
$ReportOutputType = "EXCEL"
$ReportOutputDirectory = "C:\SsrsOutput\"
$ReportOutputFileName = "MyReport.xlsx"
$ReportOutput = $ReportOutputDirectory + $ReportOutputFileName
#Connect to web service
$ReportServer = New-WebServiceProxy -Class 'ReportServer' -Namespace 'ReportServer' -Uri $ReportServerUri -UseDefaultCredential
$ReportServer.Url = $ReportServerUri
#Load report
$Report = $ReportServer.GetType().GetMethod("LoadReport").Invoke($ReportServer, #($ReportPath, $null))
#Other variables to hold parameters and output values
$parameters = #()
$deviceInfo = "<DeviceInfo><NoHeader>True</NoHeader></DeviceInfo>"
$extension = ""
$mimeType = ""
$encoding = ""
$warnings = $null
$streamIDs = $null
#Render the report
$RenderOutput = $ReportServer.Render($ReportOutputType,
$deviceInfo,
[ref] $extension,
[ref] $mimeType,
[ref] $encoding,
[ref] $warnings,
[ref] $streamIDs
)
#Write file
$Stream = New-Object System.IO.FileStream($ReportOutput), Create, Write
$Stream.Write($RenderOutput, 0, $RenderOutput.Length)
$Stream.Close()
#Open Excel
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false
$excel.DisplayAlerts = $False
#Open File
$workbook = $excel.Workbooks.Open($ReportOutput)
#Disable Split
$excel.ActiveWindow.Split = $false
#Freeze Panes
$excel.Rows.Item("10:10").Select() | Out-Null
$excel.ActiveWindow.FreezePanes = $true
#Save and Close Workbook
$xlFixedFormat = [Microsoft.Office.Interop.Excel.XlFileFormat]::xlWorkbookDefault
$workbook.SaveAs($ReportOutput, $xlFixedFormat)
$workbook.Close($true)
#Close Excel
$excel.Quit()
#Send out email
Send-MailMessage -From "MySsrsReports#MyOrg.com" -To "ReportUsers#MyOrg.com" -Subject "My Report" -SmtpServer "email.myorg.com" -Attachments $ReportOutput

Accessing data retuned by PowerShell Import-CSV

I am trying to write a PowerShell script that uses a CSV file as input that will turn off the clutter feature in Office 365. The CSV file has only 1 column and that has the 2 target email addresses that I am using for testing. When I run this script with a read-host line and enter a valid email address it works with no errors. When I use the CSV file errors follow.
Import-Module MSOnline
$LiveCred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/PowerShell -Credential $LiveCred -Authentication Basic -AllowRedirection
Import-PSSession -allowclobber $Session
Connect-MsolService -Credential $LiveCred
cd c:\scripts
Write-Host "This tool removes the Clutter feature from O365 "
$Clutter = Import-Csv .\Clutteroff.csv
foreach ($user in $Clutter){
Set-Clutter -Identity $User -Enable $false
}
When I run this I get the following error :
Cannot process argument transformation on parameter 'Identity'. Cannot convert value "#{UserID=xxxxx#myCompany.com}" to type "Microsoft.Exchange.Configuration.Tasks.MailboxIdParameter". Error: "Cannot
convert hashtable to an object of the following type: Microsoft.Exchange.Configuration.Tasks.MailboxIdParameter. Hashtable-to-Object conversion is not supported in restricted language mode or a Data
section."
+ CategoryInfo : InvalidData: (:) [Set-Clutter], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Set-Clutter
+ PSComputerName : ps.outlook.com
Any help would be appreciated and explanations will get extra credit :)
CSV file = User, XXXX#MyCompany.com, YYYY#MyCompany.com
Email addresses are valid.
Putting all of the items in one line like that is not going to work well with Import-CSV. Import-CSV is suited to a table structure (columns and rows), whereas you are just using a comma-separated list (one row, with an unknown number of columns). If in fact you do have the items on different lines, then please correct the question and I'll change the answer.
To work with the data from a file formatted like that, I would just split it into an ArrayList, and remove the first item because it is "User" and not not an email address:
[System.Collections.ArrayList]$Clutter = (get-content .\Clutteroff.csv).split(",")
$Clutter.RemoveAt(0)
Then you can iterate through the array:
foreach ($user in $Clutter){
$address = $user.trim()
{Set-Clutter -Identity $address -Enable $false}
}
For the extra credit, $user in your script was returning a row of key/value pairs to represent columns (keys) and the data in the columns (values). Your error message shows #{UserID=xxxxx#myCompany.com}, so to return just the email address you would use $user.UserID to return the value for UserID.
i GOT THIS WORKING TO PULL FROM CSV SO ONLY THOSE USERS ARE MODIFIED!! SORRY FOR THE CAPS BUT I AM A TOTAL NOOB AND I COULDNT BELIEVE I GOT THIS TO WORK!!! I am beyond STOKED!! :)
the csv requires no headers, just the email address of the users you want to modify in one column
$Clutter = (Get-Content "pathofyourcsv.csv")
foreach ($User in $Clutter) {
$address = $User
Get-Mailbox -Identity $User | Set-Clutter -Enable $false}