Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Printing Problem

Status
Not open for further replies.

kettch

Programmer
Mar 5, 2001
110
US
I need to be able to print a report from report server on my own terms, so I have written some code to retrieve the report rendered as EMF and preview it, and then print it. The problem is that the PrintPage event of the printdocument fires too many times and causes an exception in the collection I am using to store the streams that each page is in.

When I use an if-conditional to keep the code from executing, I only get the second and third pages and not the first. If I do some fiddling in the debugger I can get it to print the first page if I remove the second and third page from the collection and only let it hit the first. (Does that make sense?)

Maybe somebody can take a look at my code and tell me if anything is wrong. Thanks

Code:
    Dim WithEvents reportDoc As Printing.PrintDocument
    Dim printView As PrintPreviewDialog
    Dim reportStreams As Generic.List(Of IO.MemoryStream)
    Dim currentPage As Integer = 0
    Dim streamIDs As String()


    Private Sub RetrieveReport()
        reportStreams = New Generic.List(Of IO.MemoryStream)

        Dim devInfo As String

        devInfo = _
          "<DeviceInfo>" & _
          "  <OutputFormat>EMF</OutputFormat>" & _
          "  <StartPage>0</StartPage>" & _
          "  <PageWidth>8.5in</PageWidth>" & _
          "  <PageHeight>11in</PageHeight>" & _
          "  <MarginTop>0.5in</MarginTop>" & _
          "  <MarginLeft>0.5in</MarginLeft>" & _
          "  <MarginRight>0.5in</MarginRight>" & _
          "  <MarginBottom>0.5in</MarginBottom>" & _
          "</DeviceInfo>"

        'render the report so that I know how many pages
        RV1.ServerReport.Render("Image", devInfo, "", "", "", streamIDs, Nothing)

        Dim bt As Byte()
        Dim pageCount As Integer = streamIDs.Length + 1

        Dim count As Integer
        For count = 1 To pageCount Step 1
            devInfo = _
              "<DeviceInfo>" & _
              "  <OutputFormat>EMF</OutputFormat>" & _
              "  <StartPage>" & count & "</StartPage>" & _
              "  <PageWidth>8.5in</PageWidth>" & _
              "  <PageHeight>11in</PageHeight>" & _
              "  <MarginTop>0.5in</MarginTop>" & _
              "  <MarginLeft>0.5in</MarginLeft>" & _
              "  <MarginRight>0.5in</MarginRight>" & _
              "  <MarginBottom>0.5in</MarginBottom>" & _
              "</DeviceInfo>"
            reportStreams.Add(New IO.MemoryStream(RV1.ServerReport.Render("Image", devInfo, "", "", "", Nothing, Nothing)))
        Next

        For Each stream As IO.MemoryStream In reportStreams
            stream.Position = 0
        Next

        reportDoc = New Printing.PrintDocument
        AddHandler reportDoc.PrintPage, AddressOf reportDoc_PrintPage
        Dim reportpreview As PrintPreviewDialog = New PrintPreviewDialog
        Dim settings As New Printing.PrinterSettings
        settings.MaximumPage = pageCount
        settings.MinimumPage = 1
        settings.FromPage = 1
        settings.ToPage = pageCount
        settings.PrintRange = Printing.PrintRange.SomePages
        reportDoc.PrinterSettings = settings
        reportDoc.OriginAtMargins = False
        reportpreview.Document = reportDoc
        reportpreview.UseAntiAlias = True
        reportpreview.ShowDialog(Me)
    End Sub

    Private Sub reportDoc_PrintPage(ByVal sender As Object, ByVal e As Printing.PrintPageEventArgs) Handles reportDoc.PrintPage
        Dim pageImage As New System.Drawing.Imaging.Metafile(reportStreams(currentPage))
        e.Graphics.DrawImage(pageImage, e.PageBounds)

        currentPage += 1
        e.HasMorePages = (currentPage < reportStreams.Count)
    End Sub

this is the gist, let me know if you need more.

Thanks, again
 
I notice in the first call the StartPage is 0, but in the For...Next loop you go from 1 to PageCount.

What do the different values of StartPage in the DeviceInfo object do?

What if in the ForNext loop, you went from 0 to PageCount?
 
The start page just tells it what pages to render. The documentation I can find indicates that you are supposed to render first with all to get the page count and then pull down each page individually to actually get the EMF data. But, the documentation is pretty sparse for what I want to do.
 
So StartPage of 0 means that it's supposed to render all?

Where are you placing the if conditional, and what is the if conditional?
 
well, the documentation I saw said to count the number of streamid's that the render method returned and use that to determine how many pages to render. The problem was that the code for the printing only assumes as many pages as there were stream ids and breaks if the preview control tries to render too many pages.

so I did something like this:

Code:
    Private Sub reportDoc_PrintPage(ByVal sender As Object, ByVal e As Printing.PrintPageEventArgs) Handles reportDoc.PrintPage
If currentpage < reportstreams.Count then
        Dim pageImage As New System.Drawing.Imaging.Metafile(reportStreams(currentPage))
        e.Graphics.DrawImage(pageImage, e.PageBounds)

        currentPage += 1
        e.HasMorePages = (currentPage < reportStreams.Count)
end if
    End Sub

but for some reason, that doesn't end up printing all of the pages.
 
What kind of fiddling do you do in the debugger that gets the first page to print (without the last 2 pages)?

Also how many times does the For...Next render loop run?
 
oh, you know, just hit a break point and then use the immediate window to manually run reportstream.removeat(1) until only the first item remains.

OK, I juse changed how I was rendering each page so that I wasn't passing it a specific StreamID to retrieve and it now returns 4 pages:

Code:
            reportStreams.Add(New IO.MemoryStream(RV1.ServerReport.Render("Image", devInfo, "", "", "", Nothing, Nothing)))

but now it only prints page 2 and page 4

if I do this:

Code:
            Dim page As Byte() = RV1.ServerReport.Render("Image", devInfo, "", "", "", Nothing, Nothing)
            My.Computer.FileSystem.WriteAllBytes("c:\temp\test" & count.ToString & ".emf", page, False)

Then it saves 4 *.emf files to the disk and each has the proper page inside.

So the problem appears to be how the PrintPage event is running from the previewdialog. It runs 4 times and one would assume that would mean that it is printing 4 pages, but maybe there is something that I am missing. It would appear that the problem is not in how I am using reports but how I am printing. Does anybody know a good way to print EMF files?
 
Ok, so we've exhausted the more obvious means for defeating this problem - looks like we'll have to move to the less than obvious. Unfortunately I have run out of ideas. Good luck kettch.

Anyone wanna pick up where I left off?
 
Thanks for your help. I guess it just boils down to a question of how does one print EMF files? What techniques are there, is the one that I am using the best way?
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top