以编程方式在电子邮件正文中发送SSRS报告

时间:2016-06-07 10:56:29

标签: sql-server email reporting-services sql-server-2012 ssrs-2012

我有一个接受参数的SSRS报告,根据此参数,报告应该在电子邮件正文中发送到特定地址。可以有数百个不同的地址可以发送到这些地址。我们使用的是SQL Server标准版。

基于此,以下情况属实:

  • 我们无法使用数据驱动订阅(仅限企业版)
  • 我们无法为每个潜在收件人设置多个订阅(可能有数百个)
  • 我们不希望将报告作为附件发送(需要成为电子邮件正文)

我知道我们可以通过SQL Server或.Net代码调用订阅,但我们无法根据需要更改收件人。我们最好的解决方案是在SSRS之外创建一个具有适当格式的HTML字符串,并将其添加到电子邮件正文中。在这样做时,这意味着如果需要更改任何内容,或者需要创建新报表,开发人员需要随时创建字符串,因此对于不熟悉HTML的人来说,它不是非常灵活。

那么还有其他方法可以在SSRS中创建报告,并根据参数值将其发送到指定电子邮件地址的电子邮件正文中吗?

1 个答案:

答案 0 :(得分:3)

简短的回答是肯定的,但并不简单。这是我为SQL 2008开发的东西。

首先,要使报告显示在电子邮件正文中,您只需使用MHTML渲染器输出报告。这也可以参数化。

接下来,您需要一个带有脚本任务的SSIS包,该脚本任务可以运行报告并生成所需的输出。

以下是SSIS需要的VB脚本片段:

(Trolls原谅我使用VB。这些天我只使用C#)

保存文件的第一种方法。

Protected Sub SaveFile(ByVal url As String, ByVal localpath As String)
    Dim loRequest As System.Net.HttpWebRequest
    Dim loResponse As System.Net.HttpWebResponse
    Dim loResponseStream As System.IO.Stream
    Dim loFileStream As New System.IO.FileStream(localpath, System.IO.FileMode.Create, System.IO.FileAccess.Write)
    Dim laBytes(256) As Byte
    Dim liCount As Integer = 1
    Try

        loRequest = CType(System.Net.WebRequest.Create(url), System.Net.HttpWebRequest)
        loRequest.Credentials = System.Net.CredentialCache.DefaultCredentials
        loRequest.Timeout = 99999 '1 minute
        loRequest.Method = "GET"
        loResponse = CType(loRequest.GetResponse, System.Net.HttpWebResponse)
        loResponseStream = loResponse.GetResponseStream
        Do While liCount > 0
            liCount = loResponseStream.Read(laBytes, 0, 256)
            loFileStream.Write(laBytes, 0, liCount)
        Loop
        loFileStream.Flush()
        loFileStream.Close()
    Catch ex As Exception
    End Try
End Sub

以所需格式调用SSRS报告并使用第一种方法保存的第二种方法。

Public Sub Main()
    Dim url, destination As String
    Dim FileExtension As String
    Dim RenderAs As String

    'default to avoid nulls
    FileExtension = ".NULL" 'http://msdn.microsoft.com/en-gb/library/ms154606.aspx

    RenderAs = Dts.Variables("FileType").Value.ToString

    If RenderAs = "EXCEL" Then
        FileExtension = ".xls"
    ElseIf RenderAs = "WORD" Then
        FileExtension = ".doc"
    ElseIf RenderAs = "PDF" Then
        FileExtension = ".pdf"
    ElseIf RenderAs = "MHTML" Then
        FileExtension = ".mhtml"
    ElseIf RenderAs = "CSV" Then
        FileExtension = ".csv"
    ElseIf RenderAs = "IMAGE" Then
        FileExtension = ".tif"
    End If

    'create ssrs url
    'url = "http://hisrs01/ReportServer/Pages/ReportViewer.aspx?%2fCombined+Reports+-+HIS%2f14-15+SSoTP+Staff+Level+Weekly+Activity&rs:Command=Render&StaffGroup=" + Dts.Variables("varRSParameter1").Value.ToString + "&Provider=" + Dts.Variables("varRSParameter2").Value.ToString + "&rs:Format=Excel"
    url = Dts.Variables("ReportURL").Value.ToString + "&rs:Format=" + Dts.Variables("FileType").Value.ToString

    'create destination
    destination = Dts.Variables("TempFilePath").Value.ToString + "\Reports Created\" + Dts.Variables("FileName").Value.ToString + FileExtension

    'System.Threading.Thread.Sleep(5000)

    'write url out to test file (debugging)
    'strFile = "D:\Test\" + Replace(Dts.Variables("varRSParameter1").Value.ToString, "+", " ") + " - " + Replace(Dts.Variables("varRSParameter2").Value.ToString, "+", " ") + ".txt"
    'File.AppendAllText(strFile, url)

    SaveFile(url, destination)

    Dts.TaskResult = ScriptResults.Success

End Sub

您需要使用SSIS包变量来处理报告的生成方式,格式和方式。

enter image description here

然后我创建了一个存储过程来调用带有所需值的SSIS包。然后,它使用SQL Server数据库邮件收集SSIS生成的文件,附加它,然后关闭由dbmail处理的收件人,而不是来自SSRS订阅的SMTP调用。

这是一个程序。

CREATE PROCEDURE [dbo].[EmailSSRSReport]
    (
    @Event VARCHAR(50) = 'Test',
    @ReportURL NVARCHAR(500),
    @FileType VARCHAR(10) = 'MHTML',
    @FileName VARCHAR(100) = 'Rendered SSRS Report',
    @Debug BIT = 0
    )
AS

BEGIN

    --local variables
    DECLARE @Cmd NVARCHAR(500)
    DECLARE @EmailAddresses NVARCHAR(500)
    DECLARE @PackagePath NVARCHAR(255)
    DECLARE @FullFilePath NVARCHAR(500)
    DECLARE @FinalBodyText VARCHAR(MAX)
    DECLARE @FinalSubject VARCHAR(MAX)
    DECLARE @CmdOutput TABLE
        (
        [Output] NVARCHAR(500) NULL
        )

    --set and get parts for report and email    
    SELECT
        @EmailAddresses = [Notifications].[dbo].[fn_GetEmailAddresses](@Event),
        @PackagePath = [dbo].[fn_GetProperty]('SSISPackageLocation'),
        @FullFilePath = [dbo].[fn_GetProperty]('ReportsOutputFolder') + @FileName + 
            CASE UPPER(@FileType)
                WHEN 'EXCEL' THEN '.xls'
                WHEN 'WORD' THEN '.doc'
                WHEN 'PDF' THEN '.pdf'
                WHEN 'MHTML' THEN '.mhtml'
                WHEN 'CSV' THEN '.csv'
                WHEN 'IMAGE' THEN '.tif'
            END,
        @FinalBodyText = 'Please see attached the requested SSRS report <strong>' + @FileName + '</strong>.<br/><br/>Kind regards<br/><br/>S&SHIS Data Management<br/><a href="mailto:datamanagement@sshis.nhs.uk?subject=SSRS Report Auto Email">DataManagement@sshis.nhs.uk</a>',
        @FinalSubject = 'Auto Alert For ' + @FileName + '. ' + CONVERT(VARCHAR, GETDATE(), 103)

    SET @Cmd = 'dtexec /f "' + @PackagePath + 'Run SSRS Report.dtsx" /set \package.variables[ReportURL].Value;"' + @ReportURL + '" /set \package.variables[FileName].Value;"' + @FileName + '" /set \package.variables[FileType].Value;"' + @FileType + '"'

    --add styling
    SET @FinalBodyText = 
    '
    <html>
    <head>
        <style type="text/css">
            body
                {
                font-family: "calibri";
                font-size: 16px;
                }
        </style>
    </head>
    <body>
    ' + @FinalBodyText +
    '</body>
    </html>'

    --run command to produce SSRS report with params
    INSERT INTO @CmdOutput
    EXEC [master].sys.xp_cmdshell @Cmd

    --check cmd output for errors
    IF EXISTS
        ( 
        SELECT
            *
        FROM
            @CmdOutput
        WHERE
            [Output] LIKE '%error%'
        )
        BEGIN
            RAISERROR('Error executing command, run procedure in debug mode o view output.',16,1)
            RETURN;
        END

    --output details in debug mode
    IF @Debug = 1
        BEGIN
            SELECT @Cmd AS 'Cmd'

            SELECT
                *
            FROM
                @CmdOutput
        END

    --send email
    EXEC msdb.dbo.sp_send_dbmail 
        @recipients = @EmailAddresses,
        @subject = @FinalSubject,
        @body = @FinalBodyText,
        @file_attachments = @FullFilePath,
        @body_format = 'HTML'; 

END
GO

这为您提供了完全灵活的方式来运行任何SSRS报告并将其发送给任何人。但要实现当前不灵活的开箱即用功能的解决方案需要付出很多努力和工程。

最后,我建议使用上述步骤迭代配置表包含电子邮件地址数据等。

当然,如果您愿意,可以使用此方法添加其他定制的报告参数。