1

我想将我的 SSRS 报告直接发送到打印机。为此,我将报告呈现为字节数组,然后将这些字节数组发送到打印机。

从 SSRS 打印按钮打印报告时,打印的报告大小与报告的大小完全相同。但问题是:当通过我的代码打印时,报告的大小不正确。

生成字节的代码:

    Private Function ExporttoPrinter()
    'Start : Code to Check the Page Count -- Binit
    Dim deviceInfo As String
    Dim format As String = "IMAGE"
    Dim encoding As String = ""
    Dim mimeType As String = ""
    Dim extension As String = ""
    Dim warnings As Warning() = Nothing
    Dim streamids As String() = Nothing
    Dim bytes As Byte() = New Byte(0) {&H0}
    Dim numberOfPages As Integer = 1
    Dim pages As Byte()() = New [Byte](-1)() {}
    Dim currentPageStream As Byte() = New Byte(0) {&H0}

    While currentPageStream.Length > 0
        deviceInfo = String.Format("<DeviceInfo><OutputFormat>EMF</OutputFormat><PrintDpiX>200</PrintDpiX><PrintDpiY>200</PrintDpiY> <StartPage>{0}</StartPage><PageWidth>15in</PageWidth><PageHeight>12in</PageHeight><MarginTop>0.5in</MarginTop><MarginLeft>1in</MarginLeft><MarginRight>0in</MarginRight><MarginBottom>0.5in</MarginBottom></DeviceInfo>", numberOfPages)

        currentPageStream = ReportViewer1.ServerReport.Render(format, deviceInfo, mimeType, encoding, extension, streamids, warnings)

        If currentPageStream.Length = 0 AndAlso numberOfPages = 1 Then
            'renderException = EnumRenderException.ZERO_LENGTH_STREAM;
            Exit While
        End If

        'Add the byte stream of current page in pages[] array so that we can have complete report in pages[][] array
        If currentPageStream.Length > 0 Then
            Array.Resize(pages, pages.Length + 1)
            pages(pages.Length - 1) = currentPageStream
            numberOfPages += 1
        End If
    End While

    numberOfPages = numberOfPages - 1
    ' new Checking End


    Dim objPrint As New clsReportPrinting
    objPrint.PrintReport(pages, "CutePDF Writer")

    Return True

End Function

将字节发送到打印机的代码:

Public Class clsReportPrinting
Private byaPagesToPrint()() As Byte = Nothing, _
        m_oMetafile As Metafile = Nothing, _
        m_iNumberOfPages As Int32 = 0, _
        m_iCurrentPrintingPage As Int32 = 0, _
        m_iLastPrintingPage As Int32 = 0, _
        m_oCurrentPageStream As MemoryStream = Nothing, _
        m_oDelegate As Graphics.EnumerateMetafileProc = Nothing


Public Function PrinterExists(ByVal PrinterName As String) As Boolean

    'Returns TRUE if the named printer is amongst installed printers, FALSE otherwise
    Try

        PrinterName = PrinterName.Trim.ToUpper

        For Each sPrinter As String In PrinterSettings.InstalledPrinters

            'Printers may have UNC names, so we use .EndsWith to deal with \\Server\SharedPrinter
            'if we pass "SharedPrinter" as PrinterName
            If sPrinter.Trim.ToUpper.EndsWith(PrinterName) Then
                Return True
            End If

        Next

        Return False

    Catch oEx As Exception

        Throw (oEx)

        Return False

    End Try

End Function

Public Function MetafileCallback(ByVal oRecType As EmfPlusRecordType, _
                                  ByVal iFlags As Int32, _
                                  ByVal iDataSize As Int32, _
                                  ByVal dpData As IntPtr, _
                                  ByVal oCallbackData As PlayRecordCallback _
                                 ) As Boolean

    Dim byaDataArray() As Byte = Nothing

    If dpData <> IntPtr.Zero Then

        'Copy unmanaged data to managed array for PlayRecord call
        Array.Resize(Of Byte)(byaDataArray, iDataSize)
        Marshal.Copy(dpData, byaDataArray, 0, iDataSize)

    End If

    'Play the record
    m_oMetafile.PlayRecord(oRecType, iFlags, iDataSize, byaDataArray)


    Return True

End Function

Private Function MoveToPage(ByVal lPage As Int32) As Boolean

    'Check current page does exist
    If Me.byaPagesToPrint(m_iCurrentPrintingPage - 1) Is Nothing Then
        Return False
    End If

    'Set current page stream to desired rendered page
    m_oCurrentPageStream = New MemoryStream(Me.byaPagesToPrint(m_iCurrentPrintingPage - 1))
    'Set curernt stream position to its start
    m_oCurrentPageStream.Position = 0

    'Get rid of any former metafile
    If Not m_oMetafile Is Nothing Then
        m_oMetafile.Dispose()
        m_oMetafile = Nothing
    End If

    'Set local metafile to page
    m_oMetafile = New Metafile(m_oCurrentPageStream)

    'Must always return TRUE
    Return True

End Function

Public Sub pd_PrintPage(ByVal oSender As Object, _
                         ByVal oEV As PrintPageEventArgs)

    oEV.HasMorePages = False

    If (m_iCurrentPrintingPage <= m_iLastPrintingPage) And _
       (MoveToPage(m_iCurrentPrintingPage)) Then

        'Draw the page
        DrawPage(oEV.Graphics)

        'Point to next page
        m_iCurrentPrintingPage += 1

        'If there are more pages, flag so.
        oEV.HasMorePages = (m_iCurrentPrintingPage <= m_iLastPrintingPage)

    End If

End Sub

'This draws the current selected stream into a metafile
Public Sub DrawPage(ByVal oGrx As Graphics)

    If m_oCurrentPageStream Is Nothing Or _
       m_oCurrentPageStream.Length = 0 Or _
       m_oMetafile Is Nothing Then

        Return

    End If

    'Critical section follows (no more than one thread a time)
    SyncLock Me

        Dim iWidth As Int32 = m_oMetafile.Width, _
            iHeight As Int32 = m_oMetafile.Height, _
            oDestPoint As Point = Nothing

        'Prepare metafile delegate
        m_oDelegate = New Graphics.EnumerateMetafileProc(AddressOf MetafileCallback)

        'Draw in the rectangle
        oDestPoint = New Point(0, 0)
        oGrx.EnumerateMetafile(m_oMetafile, oDestPoint, m_oDelegate)

        'Clean up
        m_oDelegate = Nothing

    End SyncLock

End Sub

Public Function PrintReport(ByVal byaReport()() As Byte, _
                            ByVal sPrinterName As String _
                           ) As Boolean

    'Report data is an array of pages. Each page in turn is another byte array.



    Me.byaPagesToPrint = byaReport
    m_iNumberOfPages = Me.byaPagesToPrint.Length

    Try

        Dim oPS As PrinterSettings = New PrinterSettings
        oPS.MaximumPage = m_iNumberOfPages
        oPS.MinimumPage = 1
        oPS.PrintRange = PrintRange.SomePages
        oPS.FromPage = 1
        oPS.ToPage = m_iNumberOfPages
        oPS.PrinterName = sPrinterName
        'oPS.DefaultPageSettings.Landscape = False
        'oPS.DefaultPageSettings.Margins.Top = 0.5
        'oPS.DefaultPageSettings.Margins.Bottom = 0.5
        'oPS.DefaultPageSettings.Margins.Left = 0.83
        'oPS.DefaultPageSettings.Margins.Right = 0

        'oPS.DefaultPageSettings.PaperSize.Kind = PaperKind.Custom

        oPS.DefaultPageSettings.PaperSize = New PaperSize("Custom", 1500, 1200)


        'Dim value As Boolean

        'value = oPS.LandscapeAngle
        'oPS.LandscapeAngle = value
        Dim oPD As PrintDocument = New PrintDocument
        m_iCurrentPrintingPage = 1
        m_iLastPrintingPage = m_iNumberOfPages
        oPD.PrinterSettings = oPS


        'Do print the report
        AddHandler oPD.PrintPage, AddressOf Me.pd_PrintPage
        oPD.Print()

        Return True

    Catch oEx As Exception

        Throw (oEx)


    End Try

End Function


'Private Function RenderReport(ByVal reportPath As String, ByVal parameters As ExecutionService.ParameterValue()) As Byte()()
'    ' Private variables for rendering
'    Dim historyId As String = Nothing
'    Dim execHeader As New ExecutionService.ExecutionHeader()

'    Try
'        rs.Timeout = 300000
'        rs.ExecutionHeaderValue = execHeader
'        rs.LoadReport(reportPath, historyId)
'        If (parameters IsNot Nothing) Then
'            rs.SetExecutionParameters(parameters, "en_us")
'        End If


'        Dim pages As Byte()() = New [Byte](-1)() {}
'        Dim format As String = "IMAGE"
'        Dim numberOfPages As Integer = 1
'        Dim currentPageStream As Byte() = New Byte(0) {&H0}
'        ' put a byte to get the loop started
'        Dim extension As String = Nothing
'        Dim encoding As String = Nothing
'        Dim mimeType As String = Nothing
'        Dim streamIDs As String() = Nothing
'        Dim warnings As ExecutionService.Warning() = Nothing

'        While currentPageStream.Length > 0
'            Dim deviceInfo As String = [String].Format("<DeviceInfo><OutputFormat>EMF</OutputFormat><PrintDpiX>200</PrintDpiX><PrintDpiY>200</PrintDpiY>" & "<StartPage>{0}</StartPage></DeviceInfo>", numberOfPages)
'            'rs.Render will render the page defined by deviceInfo's <StartPage>{0}</StartPage> tag
'            currentPageStream = rs.Render(format, deviceInfo, extension, encoding, mimeType, warnings, _
'             streamIDs)

'            If currentPageStream.Length = 0 AndAlso numberOfPages = 1 Then
'                'renderException = EnumRenderException.ZERO_LENGTH_STREAM;
'                Exit While
'            End If

'            'Add the byte stream of current page in pages[] array so that we can have complete report in pages[][] array
'            If currentPageStream.Length > 0 Then
'                Array.Resize(pages, pages.Length + 1)
'                pages(pages.Length - 1) = currentPageStream
'                numberOfPages += 1
'            End If
'        End While

'        numberOfPages = numberOfPages - 1

'        Return pages
'    Catch ex As System.Web.Services.Protocols.SoapException
'        Console.WriteLine(ex.Detail.InnerXml)
'    Catch ex As Exception
'        Console.WriteLine(ex.Message)
'        ' Console.WriteLine("Number of pages: {0}", pages.Length);
'    Finally
'    End Try
'    Return Nothing
'End Function

End Class
4

0 回答 0