Category : .Net | Author : Chtiwi Malek | First posted : 10/8/2013 | Updated : 10/9/2013
Tags : sql, reporting, reportviewer, microsoft, reports, data, visual studio, print, solution, hack, trick
Cross-Browser Printing with Asp.Net ReportViewer

Cross-Browser Printing with Asp.Net ReportViewer

Microsoft Reporting Tools (SSRS) is a powerful reporting component freely available for .net developpers using Visual Studio, unfortunatly printing has always been an issue: The .net reportviewer only works on Internet Browser because the print button is an Active-X control, so for users using other browsers like Google Chrome, Firefox, Opera... the print button is hidden and they will have to download the rapport as a pdf, word doc.. and print it from there.

Also exporting a report to HTML format programmatically is not available for LocalReport, it's only available on the SQL Server Reporting Services (SSRS).

So I had to come up with a solution that :

- Enable printing for LocalReports in webforms.
- Works on all other browsers (Chrome, Firefox, Opera...).
- Allow multiple pages printing at once (since Reportviewer only shows the first page)
- Doesn't mess up with the PDF, DOC, Excel, Image export formats and layout.
- Doesn't require the client to install any plugin or software.

The Solution :

This little javascript code I wrote will have to be added to the report page and when called, it will read from the reportviewer the generated report html and the required css style, then will inject that into a new popup and launch printing.
// Print function (require the reportviewer client ID)
function printReport(report_ID) {
    var rv1 = $('#' + report_ID);
    var iDoc = rv1.parents('html');

    // Reading the report styles
    var styles = iDoc.find("head style[id$='ReportControl_styles']").html();
    if ((styles == undefined) || (styles == '')) {
        iDoc.find('head script').each(function () {
            var cnt = $(this).html();
            var p1 = cnt.indexOf('ReportStyles":"');
            if (p1 > 0) {
                p1 += 15;
                var p2 = cnt.indexOf('"', p1);
                styles = cnt.substr(p1, p2 - p1);
            }
        });
    }
    if (styles == '') { alert("Cannot generate styles, Displaying without styles.."); }
    styles = '<style type="text/css">' + styles + "</style>";

    // Reading the report html
    var table = rv1.find("div[id$='_oReportDiv']");
    if (table == undefined) {
        alert("Report source not found.");
        return;
    }

    // Generating a copy of the report in a new window
    var docType = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/loose.dtd">';
    var docCnt = styles + table.parent().html();
    var docHead = '<head><title>Printing ...</title><style>body{margin:5;padding:0;}</style></head>';
    var winAttr = "location=yes, statusbar=no, directories=no, menubar=no, titlebar=no, toolbar=no, dependent=no, width=720, height=600, resizable=yes, screenX=200, screenY=200, personalbar=no, scrollbars=yes";;
    var newWin = window.open("", "_blank", winAttr);
    writeDoc = newWin.document;
    writeDoc.open();
    writeDoc.write(docType + '<html>' + docHead + '<body onload="window.print();">' + docCnt + '</body></html>');
    writeDoc.close();

    // The print event will fire as soon as the window loads
    newWin.focus();
    // uncomment to autoclose the preview window when printing is confirmed or canceled.
    // newWin.close();
};
then simply bind the previous print function to a print button :
// Linking the print function to the print button
$('#printreport').click(function () {
    printReport('rv1');
});
Now, this will only print the first page, because the following pages (if there is any) have not been generated by the reportviewer.

The workaround I came up with for that is to use the Rectangle element in your report designer, and place all the report content into the rectangle. Then check the property "Keep contents together on a single page, if possible". This will show all the data in one page in the reportviewer, and the cool thing is that the PDF, DOC, EXCEL exported files will still have their multipage preview and printing.



This solution has been tested on Visual Studio 2012 with Microsoft report viewer 2012 (v11), and should work with other versions as well.

You can download the sample website below to test this, and please feel free to comment if you have any question or improvement.
About the author :
Malek Chtiwi is the man behind Codicode.com
34 years old full stack developer.
Loves technology; but also likes design, photography and composing music.
Comments & Opinions :
Iframe instead of open window
Thanks a lot for you useful post.
I used iframe to prevent from opening a new windows. I think this way is user friendly.
 
var strFrameName = ("printer-" + (new Date()).getTime());
var jFrame = $("<iframe name='" + strFrameName + "'>");
jFrame
.css("width""1px")
.css("height""1px")
.css("left""-2000px")
.css("position""absolute")
.appendTo($("body:first"));
var objFrame = window.frames[strFrameName];
var objDoc = objFrame.document;
var jStyleDiv = $("<div>").append($("style").clone());
var styles = '<style type="text/css">' + jStyleDiv.html() + "</style>";
var docType = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">';
var docCnt = styles + $("#VisibleReportContentctl00_cphMain_rvReportMain_ctl09").html();
var docHead = '<head><title>...</title><style>body{margin:5;padding:0;}</style></head>';
objDoc.open();
objDoc.write(docType + '<html>' + docHead + '<body onload="window.print();">' + docCnt + '</body></html>');
objDoc.close();

and I used js code to adding print icon in report viewer control instead of a new print button:

function addPrintButton(ctl) {
    var innerTbody = '<tbody><tr><td><input type="image" style="border-width: 0px; padding: 2px; height: 16px; width: 16px;" alt="Print" src="/App/Reserved.ReportViewerWebControl.axd?OpType=Resource&Version=10.0.40219.1&Name=Microsoft.Reporting.WebForms.Icons.Print.gif" title="Print"></td></tr></tbody>';
    var innerTable = '<table title="Print" onclick="javascript:PrintFunc(\'' + ctl + '\'); return false;" id="do_print" style="cursor: default;">' + innerTbody + '</table>'
    var outerDiv = '<div style="display: inline-block; font-size: 8pt; height: 30px;" class=" "><table cellspacing="0" cellpadding="0" style="display: inline;"><tbody><tr><td height="28px">' + innerTable + '</td></tr></tbody></table></div>';
    $("#ctl00_cphMain_rvReportMain_ctl05 > div").append(outerDiv);
}
ctl: is the id of report viewer's id.

Thanks again.
- by Alex on 7/26/2015
Figure it out
No I am getting error  Code:
   public partial class ReportForm : System.Web.UI.Page and that is part of all trouble

I have  inserted click event code as follow but not matching  my function can you help:
   protected void Button1_Click(object sender, EventArgs e)
        {

            //$('#printReport').click(function ()) {
            //   printReport('rv1');
            //}};
        }
 
- by Vijay Patel on 8/13/2015
error at $ sign
I am getting  list of error   mentioned below  when rewrite clik evvent codes:

Error    1    Unexpected character '$'    C:\Users\DevAdmin\Documents\Visual Studio 2013\Projects\ReportWeb Site1\Web Base SSRS2\Web Base SSRS2\ReportPage.aspx.cs    50    13    Web Base SSRS2
Error    2    Too many characters in character literal    C:\Users\DevAdmin\Documents\Visual Studio 2013\Projects\ReportWeb Site1\Web Base SSRS2\Web Base SSRS2\ReportPage.aspx.cs    50    15    Web Base SSRS2
Error    3    Too many characters in character literal    C:\Users\DevAdmin\Documents\Visual Studio 2013\Projects\ReportWeb Site1\Web Base SSRS2\Web Base SSRS2\ReportPage.aspx.cs    51    18    Web Base SSRS2
Error    4    Invalid expression term ''    C:\Users\DevAdmin\Documents\Visual Studio 2013\Projects\ReportWeb Site1\Web Base SSRS2\Web Base SSRS2\ReportPage.aspx.cs    50    13    Web Base SSRS2
Error    5    ) expected    C:\Users\DevAdmin\Documents\Visual Studio 2013\Projects\ReportWeb Site1\Web Base SSRS2\Web Base SSRS2\ReportPage.aspx.cs    50    50    Web Base SSRS2
Error    6    Invalid expression term ')'    C:\Users\DevAdmin\Documents\Visual Studio 2013\Projects\ReportWeb Site1\Web Base SSRS2\Web Base SSRS2\ReportPage.aspx.cs    52    2    Web Base SSRS2


line 50            $('# printReport').click(function () {
line 51     printReport('rv1');
Line 52 });


Please help
- by Vijay Patel on 8/17/2015
I read some articles on this site and I think your blog is really interesting and has great information. Thank you for your sharing.
fb login
- by fb login on 7/3/2017
Barcode Nor showing
Thanks.. Good Code and works well, but barcode is not showing on report, please tell me about Bar code in this code..
- by Aqeel on 3/11/2016
Stlying not applied
a big thanks to you for this awesome technique, but i am having issue with styling, because it is not showing me any styling, like colors, border and etc, please help me
- by Adam on 5/5/2017
Sayed
It is not working with Masterpage.
- by Sayed on 10/22/2018
Thanks!
It works fine with IE/Edge. not with Chrome/FF
- by nand on 6/14/2019
This works with Chrome/FF
function printReport() {  //works with IE/Edge, not with Chrome/FF
//alert("print");
var rv1 = $('#' + 'ReportViewer2');
var iDoc = rv1.parents('html');
 
// Reading the report styles
var styles = iDoc.find("head style[id$='ReportControl_styles']").html();
if ((styles == undefined) || (styles == '')) {
iDoc.find('head script').each(function () {
var cnt = $(this).html();
var p1 = cnt.indexOf('ReportStyles":"');
if (p1 > 0) {
p1 += 15;
var p2 = cnt.indexOf('"', p1);
styles = cnt.substr(p1, p2 - p1);
}
});
}
if (styles == '') { alert("Cannot generate styles, Displaying without styles.."); }
styles = '<style type="text/css">' + styles + "</style>";
 
// Reading the report html
var table = rv1.find("div[id$='_oReportDiv']");
if (table == undefined) {
alert("Report source not found.");
return;
}
 
// Generating a copy of the report in a new window 
var docType = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/loose.dtd">';
var docCnt = styles + table.parent().html();
var docHead = '<head><title></title><style>body{margin:5;padding:0;}</style></head>';
var winAttr = "location=yes, statusbar=no, directories=no, menubar=no, titlebar=no, toolbar=no, dependent=no, width=720, height=600, resizable=yes, screenX=200, screenY=200, personalbar=no, scrollbars=yes";;
var newWin = window.open("", "_blank", winAttr);
writeDoc = newWin.document;
writeDoc.open();
writeDoc.write(docType + '<html>' + docHead + '<body onload="window.print();">' + docCnt + '</body></html>');
writeDoc.close();
 
// The print event will fire as soon as the window loads
newWin.focus();
//newWin.close();
setTimeout(function () {
newWin.close();
document.location.reload(true);
}, 2500);
};
- by nand on 6/19/2019
multipage not printed only one page print when clicl on print icon
hello guys,
i have one problem when i click on print icon then print single page not yet multipale pages i use firefox
kind clints requierments ..
please help us it's urgently .
- by Jemin on 4/11/2020
Leave a Comment:
Name :
Email : * will not be shown
Title :
Comment :