Gravy

In a Win Forms app, is it possible to print a report without using the ReportViewer control I want to provide a print button on a Form (like Outlook does) and then use an embedded Report to print the data so I don't really need the ReportViewer.

I would want to display the PrinterDialog though and use the settings from here to control the printed Report. Is this possible too

Regards

Graham



Re: Visual Studio Report Controls Printing without the ReportViewer

Gravy

Well, I'm so close yet so far.

I have found the GetPrintDocument method  on the Viewer and I thought I could do something like:

All in code...
1. Create a ReportView Control.
2. Set the LocalReport properties for the report datasource and resource
3. Create a PrintDialog control.
4. Set the printDialog.Document property to reportView.GetPrintDocument()
5. Show the PrintDialog
6. Call printDialog.Document.Print()

the problem I have is the following exception when I call GetPrintDocument():

TEMPORARY RESTRICTION: Must be in print preview mode in local mode with rendering complete

Can anyone tell me when or if the restriction will be lifted

Graham




Re: Visual Studio Report Controls Printing without the ReportViewer

Rajeev Karunakaran

In the final product you'll be able to print using the code below. Notice that ReportViewer object is not required. (This code will not work in Beta 2 unfortunately.)

using System;
using System.IO;
using System.Data;
using System.Text;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.Collections.Generic;
using Microsoft.Reporting.WinForms;

public class Demo : IDisposable
{
    private int m_currentPageIndex;
    private IList<Stream> m_streams;
    private DataTable LoadSalesData()
    {
        DataSet dataSet = new DataSet();
        dataSet.ReadXml("data.xml");
        return dataSet.Tables[0];
    }
    private Stream CreateStream(string name, string fileNameExtension, Encoding encoding,
                              string mimeType, bool willSeek)
    {
        Stream stream = new FileStream(name + "." + fileNameExtension, FileMode.Create);
        m_streams.Add(stream);
        return stream;
    }
    private void Export(LocalReport report)
    {
        string deviceInfo =
          "<DeviceInfo>" +
          "  <OutputFormat>EMF</OutputFormat>" +
          "  <PageWidth>8.5in</PageWidth>" +
          "  <PageHeight>11in</PageHeight>" +
          "  <MarginTop>0.25in</MarginTop>" +
          "  <MarginLeft>0.25in</MarginLeft>" +
          "  <MarginRight>0.25in</MarginRight>" +
          "  <MarginBottom>0.25in</MarginBottom>" +
          "</DeviceInfo>";
        Warning[] warnings;
        m_streams = new List<Stream>();
        report.Render("Image", deviceInfo, CreateStream, out warnings);
        foreach (Stream stream in m_streams)
            stream.Position = 0;
    }
    private void PrintPage(object sender, PrintPageEventArgs ev)
    {
        Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
        ev.Graphics.DrawImage(pageImage, 0, 0);
        m_currentPageIndex++;
        ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
    }
    private void Print()
    {
        const string printerName = "Microsoft Office Document Image Writer";
        if (m_streams == null || m_streams.Count == 0)
            return;
        PrintDocument printDoc = new PrintDocument(); 
        printDoc.PrinterSettings.PrinterName = printerName;
        if (!printDoc.PrinterSettings.IsValid)
        {
            string msg = String.Format("Can't find printer \"{0}\".", printerName);
            Console.WriteLine(msg);
            return;
        }
        printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
        printDoc.Print();
    }
    private void Run()
    {
        LocalReport report = new LocalReport();
        report.ReportPath = "Report.rdlc";
        report.DataSources.Add(new ReportDataSource("Sales", LoadSalesData()));
        Export(report);
        m_currentPageIndex = 0;
        Print();
    }
    public void Dispose()
    {
        if (m_streams != null)
        {
            foreach (Stream stream in m_streams)
                stream.Close();
        }
    }
    public static void Main(string[] args) 
    {
        using (Demo demo = new Demo())
        {
            demo.Run();
        }

    }
}

 





Re: Visual Studio Report Controls Printing without the ReportViewer

Gravy

Wow, thanks Rajeev. It does look quite complicated but it does seem to fit in to the printing framework quiet well.

Graham





Re: Visual Studio Report Controls Printing without the ReportViewer

Bob Lafleur

Will this printing method work in the June CTP of Visual Studio 2005

Thanks.

   - Bob





Re: Visual Studio Report Controls Printing without the ReportViewer

Ramazan Binarbasi

I tried sample in beta2, it didn't compile because function doesn't match delegate. Only added last parameter as below..

private
Stream CreateStream( string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek, Microsoft.ReportingServices.Interfaces.StreamOper oper )

It's working fine.

Thx for sample, it was only sample I could find Smile






Re: Visual Studio Report Controls Printing without the ReportViewer

orbit

'For those who want it in VB

Option Strict On

Option Explicit On

Imports System

Imports System.IO

Imports System.Data

Imports System.Text

Imports System.Drawing.Imaging

Imports System.Drawing.Printing

Imports System.Collections.Generic

Imports Microsoft.Reporting.WinForms

Public Class Demo_DirectPrinting

Implements IDisposable

#Region " IDisposable "

Private disposedValue As Boolean = False ' To detect redundant calls

' IDisposable

Protected Overridable Sub Dispose(ByVal disposing As Boolean)

If Not Me.disposedValue Then

If disposing Then

' TODO: free unmanaged resources when explicitly called

If Not (m_streams Is Nothing) Then

Dim stream As Stream

For Each stream In m_streams

stream.Close()

Next stream

End If

End If

' TODO: free shared unmanaged resources

End If

Me.disposedValue = True

End Sub

' This code added by Visual Basic to correctly implement the disposable pattern.

Public Sub Dispose() Implements IDisposable.Dispose

' Do not change this code. Put cleanup code in Dispose(ByVal disposing As Boolean) above.

Dispose(True)

GC.SuppressFinalize(Me)

End Sub

#End Region

Private m_currentPageIndex As Integer

Private m_streams As IList(Of Stream)

Private Function LoadSalesData() As DataTable

Dim dataSet As New DataSet()

dataSet.ReadXml("data.xml")

Return dataSet.Tables(0)

End Function

'Private Function CreateStream(ByVal name As String, ByVal fileNameExtension As String, ByVal encoding As Encoding, ByVal mimeType As String, ByVal willSeek As Boolean, ByVal oper As Microsoft.ReportingServices.Interfaces.StreamOper) As Stream

Private Function CreateStream(ByVal name As String, ByVal fileNameExtension As String, ByVal encoding As Encoding, ByVal mimeType As String, ByVal willSeek As Boolean) As Stream

Dim rc As Stream = New FileStream(name + "." + fileNameExtension, FileMode.Create)

m_streams.Add(rc)

Return rc

End Function

Private Sub Export(ByVal report As LocalReport)

Dim deviceInfo As String = _

"<DeviceInfo>" + _

" <OutputFormat>EMF</OutputFormat>" + _

" <PageWidth>8.5in</PageWidth>" + _

" <PageHeight>11in</PageHeight>" + _

" <MarginTop>0.25in</MarginTop>" + _

" <MarginLeft>0.25in</MarginLeft>" + _

" <MarginRight>0.25in</MarginRight>" + _

" <MarginBottom>0.25in</MarginBottom>" + _

"</DeviceInfo>"

Dim warnings() As Warning = Nothing

m_streams = New List(Of Stream)

report.Render("Image", deviceInfo, AddressOf CreateStream, warnings)

Dim stream As Stream

For Each stream In m_streams

stream.Position = 0

Next stream

End Sub

Private Sub PrintPage(ByVal sender As Object, ByVal ev As PrintPageEventArgs)

Dim pageImage As New Metafile(m_streams(m_currentPageIndex))

ev.Graphics.DrawImage(pageImage, 0, 0)

m_currentPageIndex += 1

ev.HasMorePages = m_currentPageIndex < m_streams.Count

End Sub

Private Sub Print()

Const printerName As String = "Microsoft Office Document Image Writer"

If m_streams Is Nothing Or m_streams.Count = 0 Then

Return

End If

Dim printDoc As New PrintDocument()

printDoc.PrinterSettings.PrinterName = printerName

If Not printDoc.PrinterSettings.IsValid Then

Dim msg As String = [String].Format("Can't find printer ""{0}"".", printerName)

Console.WriteLine(msg)

Return

End If

AddHandler printDoc.PrintPage, AddressOf PrintPage

printDoc.Print()

End Sub

Private Sub Run()

Dim report As New LocalReport()

report.ReportPath = "Report.rdlc"

report.DataSources.Add(New ReportDataSource("Sales", LoadSalesData()))

Export(report)

m_currentPageIndex = 0

Print()

End Sub

'Entry point which delegates to C-style main Private Function

Public Overloads Shared Sub Main()

Main(System.Environment.GetCommandLineArgs())

End Sub

Public Overloads Shared Sub Main(ByVal args() As String)

Dim demo As New Demo_DirectPrinting()

Try

demo.Run()

Finally

demo.Dispose()

End Try

End Sub

End Class

 





Re: Visual Studio Report Controls Printing without the ReportViewer

SMILEMan

Besides changing the pagewidth and pageheight in the DeviceInfo section, what else needs to be done to print Landscape.



Re: Visual Studio Report Controls Printing without the ReportViewer

aownbey

I am able to print; however, the report is being cut off on the right of the page. If I change the page width in the DeviceInfo section to be smaller then 8.5" it will display the cut off section on a second page. A width greater then 8.5" will cut off an inch or more as the width is made larger. A width of 8.5" also removes the right margin and I do not get a second page with the missing section of the report. This report was converted from an rdl to rdlc and would print correctly using the print control on the toolbar. Has anyone else experienced this issue

Thanks





Re: Visual Studio Report Controls Printing without the ReportViewer

cobramatt

I run in to the following error, "An error occurred during local report processing."

The only changes that I made to the code sample given above was the Run method. I'm passing in an existing datatable and I'm setting the report as shown below. The try/catch is where the error is raised. In particular it's on the following line of code in the "Export(LocalReport report) method:

report.Render("Image", deviceInfo, CreateStream, out warnings);

public void Run(DataTable dt)

{

LocalReport report = new LocalReport();

report.DataSources.Add(new ReportDataSource("MyReport", dt));

report.ReportEmbeddedResource = "WindowsApplication5.Reports.ChangedFilesReport.rdlc";

try

{

Export(report);

}

catch (Exception exc)

{

System.Windows.Forms.MessageBox.Show(exc.Message);

}

m_currentPageIndex = 0;

Print();

}

Any ideas as to how to resolve this

Thanks all in advance.





Re: Visual Studio Report Controls Printing without the ReportViewer

Jesse Arnold

Has anyone noticed that when rendering using EMF manually the print quality is horrible   It appears to me that the internal report rendering used in the ReportViewer produces nice vector based EMF, whereas when using the referenced method to render without the ReportViewer control, the EMF output is very jagged like a raster image!






Re: Visual Studio Report Controls Printing without the ReportViewer

Jesse Arnold

I figured out the print quality issue. The sample code in this post uses the drawimage improperly. The code sample on the MSDN docs shows the correct usage:

http://msdn2.microsoft.com/en-us/library/ms252091.aspx

the PrintPage method should call DrawImage with the PrintPageEventArgs PageBounds property like this:

ev.Graphics.DrawImage(pageImage, ev.PageBounds);

The code sample in this post uses

ev.Graphics.DrawImage(pageImage, 0, 0);

which seems to cause the renderer to produce a rasterized EMF output.

Another cool trick is to avoid writing out the .emf files like all the samples do, and juse use a MemoryStream instead.

swap out the CreateStrem function with this:

private Stream CreateStream(string name, string fileNameExtension, Encoding encoding, string mimeType, bool willSeek)
{
Stream stream = new MemoryStream();
m_streams.Add(stream);
return stream;
}







Re: Visual Studio Report Controls Printing without the ReportViewer

Waxdoll

Well done! However, when I print the report, it zooms in. Isn't it strange 3x




Re: Visual Studio Report Controls Printing without the ReportViewer

Jesse Arnold

Are you seeing the zoom in the viewer or on the actual hardcopy print




Re: Visual Studio Report Controls Printing without the ReportViewer

Waxdoll

3x for your reply. I don't know what the actual hardcopy print is. The problem I met with is similar to the one raised in the following URL :
http://www.dotnet247.com/247reference/msgs/34/172114.aspx.

My English is poor, so pls refer to the above URL and give me help. 3X!