How to: Print a Report Without Displaying a Preview

This example demonstrates how to implement the PrintContacts Action, which prints the "Contacts Report" report without displaying its preview. Note that this Action is not designed for reports with end-user-specified parameters (i.e., reports that use ReportParametersObjectBase parameters or native XtraReport parameters).

You can also use the code from this example to access an XtraReport object and then export or email the report content as illustrated in the tutorials listed in the Exporting Reports document.

Note

Mobile applications do not support the report printing mechanism, so the approach described in this topic cannot be implemented in the Mobile platform.

It is recommended that you review the following XtraReport help topics and examples before proceeding.

Tip

A complete sample project is available in the DevExpress Code Examples database at http://www.devexpress.com/example=E5146.

In this topic, it is assumed that you have an XAF application that uses the Reports V2 Module, and you have created one or more reports (see Reports V2 Module Overview).

Create the PrintContacts Action in the Abstract Platform-Agnostic Controller

In the platform-agnostic module, implement the following abstract Controller class.

using DevExpress.ExpressApp;
using DevExpress.ExpressApp.Actions;
using DevExpress.ExpressApp.ReportsV2;
using DevExpress.Persistent.Base;
// ...
public abstract class PrintContactsController : ObjectViewController<ListView, Contact> {
    public PrintContactsController() {
        SimpleAction printAction = new SimpleAction(this, "PrintContacts", PredefinedCategory.Reports);
        printAction.ImageName = "Action_Printing_Print";
        printAction.Execute += delegate(object sender, SimpleActionExecuteEventArgs e) {
            IObjectSpace objectSpace = ReportDataProvider.ReportObjectSpaceProvider.CreateObjectSpace(typeof(ReportDataV2));
            IReportDataV2 reportData = objectSpace.FindObject<ReportDataV2>(
                new BinaryOperator("DisplayName","Contacts Report"));
            if (reportData == null) {
                throw new UserFriendlyException("Cannot find the 'Contacts Report' report.");
            }
            else {
                PrintReport(reportData);
            }
        };
    }
    protected abstract void PrintReport(IReportDataV2 reportData);
}

As you can see, the PrintContactsController targets Contact objects, so it will be activated when a user selects Contact in the navigation. The Controller introduces the PrintContacts SimpleAction. The abstract PrintReport method is called when the Action is executed (see SimpleAction.Execute). The ReportDataV2 object that has the ReportDataV2.DisplayName set to "Contacts Report" is obtained from the database and passed to the PrintReport method (here, it is assumed that such a report is already created). The next two sections will explain how to provide implementations of the PrintReport method for WinForms and ASP.NET.

Implement Report Printing for WinForms

In the WinForms module project, inherit the PrintContactsController and implement the PrintReport method in the following manner.

using DevExpress.ExpressApp.ReportsV2;
using DevExpress.XtraReports.UI;
// ...
public class WinPrintContactsController : PrintContactsController{
    protected override void PrintReport(IReportDataV2 reportData) {
        XtraReport report = ReportDataProvider.ReportsStorage.LoadReport(reportData);
        ReportsModuleV2 reportsModule = ReportsModuleV2.FindReportsModule(Application.Modules);
        if (reportsModule != null && reportsModule.ReportsDataSourceHelper != null) {
            reportsModule.ReportsDataSourceHelper.SetupBeforePrint(report);
            report.PrintDialog();
        }
    }
}

Here, the ReportsStorage.LoadReport method is used to load the XtraReport object from the passed IReportDataV2 persistent object. The ReportsStorage instance is accessed using the static ReportDataProvider.ReportsStorage property. Then, the report is prepared for printing using the ReportDataSourceHelper.SetupBeforePrint method. The ReportDataSourceHelper instance is accessed usin the ReportsModuleV2.ReportsDataSourceHelper property. The print dialog where an end-user can specify a printer and other print options before printing the document is invoked using the XtraReport's PrintDialog extension method.

Important

Ensure that the DevExpress.XtraPrinting.v18.1.dll is referenced. The PrintDialog extension method is implemented in this assembly.

The result is demonstrated in the image below.

InstantPrintReport_Win

Implement Report Printing for ASP.NET

In the ASP.NET module project, inherit the PrintContactsController and implement the PrintReport method in the following manner.

using DevExpress.ExpressApp.ReportsV2;
using DevExpress.ExpressApp.Web;
// ...
public class WebPrintContactsController : PrintContactsController {
    protected override void PrintReport(IReportDataV2 reportData) {
        string reportContainerHandle = ReportDataProvider.ReportsStorage.GetReportContainerHandle(reportData);
        ((WebWindow)WebApplication.Instance.MainWindow).RegisterStartupScript(
            "InstantPrintReport", GetPrintingScript(reportContainerHandle), overwrite: true);
    }
    private string GetPrintingScript(string reportContainerHandle) {
        return string.Format(@"
        if(!ASPx.Browser.Edge) {{
            var iframe = document.getElementById('reportout');
            if (iframe != null) {{
                document.body.removeChild(iframe);
            }}
            iframe = document.createElement('iframe');
            iframe.setAttribute('id', 'reportout');
            iframe.style.width = 0;
            iframe.style.height = 0;
            iframe.style.border = 0;
            document.body.appendChild(iframe);
            document.getElementById('reportout').contentWindow.location = 
'InstantPrintReport.aspx?reportContainerHandle={0}';
            }} else {{
                window.open('InstantPrintReport.aspx?reportContainerHandle={0}', '_blank');
        }}
        ", reportContainerHandle);
    }
}

Here, the ReportsStorage.GetReportContainerHandle method is used to get the report handle from the passed IReportDataV2 persistent object. The ReportsStorage instance is accessed using the static ReportDataProvider.ReportsStorage property. The printing script is registered using the WebWindow.RegisterStartupScript method.

Note

In the Edge browser, it is impossible to trigger a print in an iframe embedded in a html page, so you can open the generated report PDF-file in a new window and print this file using the standard PDF-viewer functions.

The script above creates the iframe element and passes the report's handle to the InstantPrintReport.aspx page intended for report printing. So, create the InstantPrintReport.aspx page in the ASP.NET application project (Add | New Item... | Web Form).

Open the created InstantPrintReport.aspx.cs (InstantPrintReport.aspx.vb) file and modify the Page_Load method as follows.

using System.IO;
using DevExpress.XtraPrinting;
using DevExpress.XtraReports.UI;
using DevExpress.ExpressApp.ReportsV2;
// ...
public partial class InstantPrintReport : System.Web.UI.Page {
    protected void Page_Load(object sender, EventArgs e) {
        string reportDataHandle = Request.QueryString["reportContainerHandle"];
        ReportsModuleV2 module = ReportsModuleV2.FindReportsModule(
            ApplicationReportObjectSpaceProvider.ContextApplication.Modules);
        if(!String.IsNullOrEmpty(reportDataHandle) && module != null) {
            XtraReport report = null;
            try {
                report = ReportDataProvider.ReportsStorage.GetReportContainerByHandle(reportDataHandle).Report;
                module.ReportsDataSourceHelper.SetupBeforePrint(report, null, null, false, null, false);
                using(MemoryStream ms = new MemoryStream()) {
                    report.CreateDocument();
                    PdfExportOptions options = new PdfExportOptions();
                    options.ShowPrintDialogOnOpen = true;
                    report.ExportToPdf(ms, options);
                    ms.Seek(0, SeekOrigin.Begin);
                    byte[] reportContent = ms.ToArray();
                    Response.ContentType = "application/pdf";
                    Response.Clear();
                    Response.OutputStream.Write(reportContent, 0, reportContent.Length);
                    Response.End();
                }
            }
            finally {
                if (report != null) report.Dispose();
            }
        }
    }
}

Here, the ReportsStorage.GetReportContainerByHandle method and IReportContainer.Report property are is used to load the XtraReport object from the report handle passed using the HTTP query string. Then, the report is prepared for further printing using the ReportDataSourceHelper.SetupBeforePrint method. The ReportDataSourceHelper instance is accessed using the ReportsModuleV2.ReportsDataSourceHelper property. The report is then printed using the Adobe PDF web browser plug-in, as illustrated in the How to print a report without displaying it in a web application code example.

The PrintContacts Action should be executed on postback, because a postback is required to transmit a file to the client. So, open the Model Editor in the ASP.NET module project and set the IModelActionWeb.IsPostBackRequired property of the ActionDesign | Actions | PrintContacts node to true.

InstantPrintReport_ME

The result is demonstrated in the image below.

InstantPrintReport_Web

See Also