5

I am working on WPF C# 4.0 project in which I am trying to print a RDLC report which is basically an invoice directly without displaying the ReportViewer. I refered code from the following MSDN link and modified it for my purpose.

Following is the modified code which I am using.

using System;
using System.IO;
using System.Data;
using System.Text;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.Collections.Generic;
using System.Windows.Forms;
using Microsoft.Reporting.WinForms;
using System.Xml;
using System.Resources;
using System.Drawing;
using System.Reflection;

namespace POS.Classes
{
    public class DirectReportPrint : IDisposable
    {
        private double[] PageBounds = { 0,0,0,0,0,0};
        private int m_currentPageIndex;
        private IList<Stream> m_streams;

        private DataTable _table = new DataTable();
        /// <summary>
        /// Must set this to get the report data
        /// </summary>
        public DataTable ReportTable
        {
            get { return _table; }
            set { _table = value; }
        }

        // Routine to provide to the report renderer, in order to
        //    save an image for each page of the report.
        private Stream CreateStream(string name,
          string fileNameExtension, Encoding encoding,
          string mimeType, bool willSeek)
        {
            //Stream stream = new FileStream(@"..\..\" + name +
            //   "." + fileNameExtension, FileMode.Create);
            Stream stream = new FileStream(Path.GetTempPath() + "\\" + name +
               "." + fileNameExtension, FileMode.Create);
            m_streams.Add(stream);
            return stream;
        }

        private string ReadEmbeddedResource(string ResourceName)
        {
            var assembly = Assembly.GetExecutingAssembly();
            using (Stream stream = assembly.GetManifestResourceStream(ResourceName))
            using (StreamReader reader = new StreamReader(stream))
            {
                string result = reader.ReadToEnd();
                string temp = result.Replace('\r',' ');
                return temp;
            }
        }

        private string ReadReportXML(string ReportName)
        {
            try
            {
                string s = " ", temp = "", t = "";
                int x, y, z;
                string result = ReadEmbeddedResource(ReportName);
                if (result.Contains("<PageHeight>") && result.Contains("</PageHeight>"))
                {
                    x = result.IndexOf("<PageHeight>");
                    y = result.IndexOf("</PageHeight>");
                    temp = result.Substring(x, y - x);
                    s += temp + "</PageHeight>  ";
                    z = temp.IndexOf('>') + 1;
                    t = temp.Substring(z, temp.Length - z);
                    PageBounds[0] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
                }
                if (result.Contains("<PageWidth>") && result.Contains("</PageWidth>"))
                {
                    x = result.IndexOf("<PageWidth>");
                    y = result.IndexOf("</PageWidth>");
                    temp = result.Substring(x, y - x);
                    s += temp + "</PageWidth>  ";
                    z = temp.IndexOf('>') + 1;
                    t = temp.Substring(z, temp.Length - z);
                    PageBounds[1] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
                }
                if (result.Contains("<LeftMargin>") && result.Contains("</LeftMargin>"))
                {
                    x = result.IndexOf("<LeftMargin>");
                    y = result.IndexOf("</LeftMargin>");
                    temp = result.Substring(x, y - x);
                    s += temp + "</LeftMargin>  ";
                    z = temp.IndexOf('>') + 1;
                    t = temp.Substring(z, temp.Length - z);
                    PageBounds[2] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
                }
                if (result.Contains("<RightMargin>") && result.Contains("</RightMargin>"))
                {
                    x = result.IndexOf("<RightMargin>");
                    y = result.IndexOf("</RightMargin>");
                    temp = result.Substring(x, y - x);
                    s += temp + "</RightMargin>  ";
                    z = temp.IndexOf('>') + 1;
                    t = temp.Substring(z, temp.Length - z);
                    PageBounds[3] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
                }
                if (result.Contains("<TopMargin>") && result.Contains("</TopMargin>"))
                {
                    x = result.IndexOf("<TopMargin>");
                    y = result.IndexOf("</TopMargin>");
                    temp = result.Substring(x, y - x);
                    s += temp + "</TopMargin>  ";
                    z = temp.IndexOf('>') + 1;
                    t = temp.Substring(z, temp.Length - z);
                    PageBounds[4] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
                }
                if (result.Contains("<BottomMargin>") && result.Contains("</BottomMargin>"))
                {
                    x = result.IndexOf("<BottomMargin>");
                    y = result.IndexOf("</BottomMargin>");
                    temp = result.Substring(x, y - x);
                    s += temp + "</BottomMargin>  ";
                    z = temp.IndexOf('>') + 1;
                    t = temp.Substring(z, temp.Length - z);
                    PageBounds[5] = Math.Round(Convert.ToDouble(t.Substring(0, t.Length - 2)), 2);
                }
                return s;
            }
            catch (Exception ex)
            {
                return null;
            }
        }        

        // Export the given report as an EMF (Enhanced Metafile) file.
        private void Export(LocalReport report, string ReportName)
        {
            try
            {
                string temp = ReadReportXML(ReportName);
                if (temp != null)
                {
                    string deviceInfo =
                      "<DeviceInfo>" +
                      "  <OutputFormat>EMF</OutputFormat>"
                      + temp +
                      "</DeviceInfo>";

                    Warning[] warnings;
                    m_streams = new List<Stream>();
                    report.Render("Image", deviceInfo, CreateStream,
                       out warnings);
                    foreach (Stream stream in m_streams)
                        stream.Position = 0;
                }
                else
                {
                    throw new Exception("Something went wrong. Unable to Print Report");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                MessageBox.Show(ex.InnerException.Message);
            }
        }

        // Handler for PrintPageEvents
        private void PrintPage(object sender, PrintPageEventArgs ev)
        {
            Metafile pageImage = new
            Metafile(m_streams[m_currentPageIndex]);

            // Adjust rectangular area with printer margins.
            Rectangle adjustedRect = new Rectangle(
                ev.PageBounds.Left - (int)ev.PageSettings.HardMarginX,
                ev.PageBounds.Top - (int)ev.PageSettings.HardMarginY,
                ev.PageBounds.Width,
                ev.PageBounds.Height);

            // Draw a white background for the report
            ev.Graphics.FillRectangle(Brushes.White, adjustedRect);

            // Draw the report content
            ev.Graphics.DrawImage(pageImage, adjustedRect);

            // Prepare for the next page. Make sure we haven't hit the end.
            m_currentPageIndex++;
            ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
        }

        private void Print()
        {
            PrinterSettings settings = new PrinterSettings();

            if (m_streams == null || m_streams.Count == 0)
                return;
            PrintDocument printDoc = new PrintDocument();
            printDoc.PrinterSettings.PrinterName = settings.PrinterName;

            PaperSize CustomSize = new PaperSize("Custom", (int)PageBounds[1]*100, (int)PageBounds[0]*100);
            CustomSize.RawKind = (int)PaperKind.Custom;
            printDoc.DefaultPageSettings.PaperSize = CustomSize;


            if (!printDoc.PrinterSettings.IsValid)
            {
                string msg = String.Format(
                   "Can't find printer \"{0}\".", settings.PrinterName);
                MessageBox.Show(msg, "Print Error");
                return;
            }
            printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
            printDoc.Print();
        }

        /// <summary>
        ///  Create a local report for Report.rdlc, load the data,
        ///  export the report to an .emf file, and print it.
        /// Prints the report directly
        /// </summary>
        /// <param name="ReportName">Name of the report</param>
        /// <param name="DS_Name">Dataset name for the report. Provide the name which was used during RDLC file creation</param>
        public void Run(string ReportName, string DS_Name)
        {
            LocalReport report = new LocalReport();
            report.ReportEmbeddedResource = ReportName;
            report.DataSources.Add(new ReportDataSource(DS_Name, ReportTable));
            Export(report, ReportName);
            m_currentPageIndex = 0;
            Print();
            Dispose();
        }

        public void Dispose()
        {
            if (m_streams != null)
            {
                foreach (Stream stream in m_streams)
                    stream.Close();
                m_streams = null;
            }
        }
    }
}

Code which Invokes Run Method

Classes.DirectReportPrint drp = new Classes.DirectReportPrint();
drp.ReportTable = Classes.Class_Sales_Bill.GetBillDetails(this.saleObj.Row_ID);
drp.Run("POS.Reports.Rpt_Anil_Sale_Bill.rdlc", "DataSet1");

This code works well when I am using Visual Studio debugger to execute it. However, it fails if I publish my project, install its setup and then try to run its exe (Weird Behaviour).

If I run exe it works for the first invoice which I try to print. For the subsequent invoices I get the following error.

An error occurred during local report processing. Access to the Path 'c:\Users\Rpt_Anil_Sale_Bill_0.EMF' is denied.

Here Rpt_Anil_Sale_Bill is the name of my RDLC file.

On further digging I identified that the exe code creates an intermediate EMF file in this path C:\Users\Nilesh\AppData\Local\Apps\2.0\BWQ6XD5A.DB0

enter image description here

If I try to open this file I get the following error:

enter image description here

Need help in identifying what's going wrong with the code.

Any help is appreciated. Thanks!!

Nilesh Barai
  • 1,312
  • 8
  • 22
  • 48

1 Answers1

6

I used this code and it works very well for me.

First add this class into your project

Then use the following code to print directly to the default printer:

LocalReport report = new LocalReport();
report.ReportEmbeddedResource = ReportSource;
report.DataSources.Add(myDataSource);
report.PrintToPrinter();
Irshad
  • 3,071
  • 5
  • 30
  • 51
Core
  • 601
  • 2
  • 7
  • 19