11 Oct 2006

Report Viewer Customizing Printing for Local Report

We had a requirement to allow a front page, which was another local report, to be printed before the report within the report viewer was printed.  As both reports were local reports it was easy to create a print button which allowed us to meet the requirements, here is the code that we used:

   1:  if (this.printFrontingSheetCheckbox.Checked)
   2:  {
   3:   LocalReport frontsheet = front.reportViewer1.LocalReport;
   4:   Export(frontsheet, 8.27f, 11.69f, 0f, 0f, 0f, 0f);
   5:   m_currentPageIndex = 0;
   6:   Print(false);
   7:   
   8:   foreach (Stream s in m_streams)
   9:   {
  10:    s.Close();
  11:   }
  12:   front = null;
  13:  }
  14:   
  15:  LocalReport report = reportViewer.LocalReport;
  16:  Export(report, 11.69f, 8.27f, 0f, 0f, 0f, 0f);
  17:  m_currentPageIndex = 0;
  18:   
  19:  Print(true); foreach (Stream s in m_streams)
  20:  {
  21:   s.Close();
  22:  }
  23:   
  24:  private void Print(bool landscape)
  25:  {
  26:   if (m_streams == null || m_streams.Count == 0)
  27:    return;
  28:   PrintDocument printDoc = new PrintDocument();
  29:   PrinterSettings ps = new PrinterSettings();
  30:   ps.PrinterName = printDialog1.PrinterSettings.PrinterName;
  31:   ps.DefaultPageSettings.Landscape = landscape;
  32:      ps.DefaultPageSettings.PrinterSettings.DefaultPageSettings.Landscape = landscape;
  33:   printDoc.PrinterSettings = ps;
  34:   
  35:   if (!printDoc.PrinterSettings.IsValid)
  36:   {
  37:    string msg = String.Format("Can't find printer \"{0}\".", printDialog1.PrinterSettings.PrinterName);
  38:    MessageBox.Show(msg, "Print Error");
  39:    return;
  40:   }
  41:   printDoc.PrintPage += new PrintPageEventHandler(PrintPage);
  42:   printDoc.Print();
  43:  } 
  44:   
  45:  /// <summary>
  46:  /// Export the given report as an EMF (Enhanced Metafile) file.
  47:  /// </summary>
  48:  private void Export(LocalReport report, float PageWidth, float PageHeight, float MarginTop, float MarginLeft, float MarginRight, float MarginBottom)
  49:  {
  50:   StringBuilder deviceInfosb = new StringBuilder();
  51:   deviceInfosb.Append("<DeviceInfo>");
  52:   deviceInfosb.Append("<OutputFormat>EMF</OutputFormat>");
  53:   deviceInfosb.Append(string.Format("<PageWidth>{0}in</PageWidth>", PageWidth)); 
  54:   deviceInfosb.Append(string.Format("<PageHeight>{0}in</PageHeight>", PageHeight));
  55:   deviceInfosb.Append(string.Format("<MarginTop>{0}in</MarginTop>", MarginTop));
  56:   deviceInfosb.Append(string.Format("<MarginLeft>{0}in</MarginLeft>", MarginLeft));
  57:   deviceInfosb.Append(string.Format("<MarginRight>{0}in</MarginRight>", MarginRight));
  58:   deviceInfosb.Append(string.Format("<MarginBottom>{0}in</MarginBottom>", MarginBottom));
  59:   deviceInfosb.Append(string.Format("</DeviceInfo>"));
  60:   string deviceInfo = deviceInfosb.ToString();
  61:   Microsoft.Reporting.WinForms.Warning[] warnings;
  62:   m_streams = new List<Stream>();
  63:   report.Render("Image", deviceInfo, CreateStream, out warnings);
  64:   foreach (Stream stream in m_streams)
  65:   {
  66:    stream.Position = 0;
  67:   }
  68:  }
  69:   
  70:  /// <summary>
  71:  /// Handler for PrintPageEvents
  72:  /// </summary>
  73:  private void PrintPage(object sender, PrintPageEventArgs ev)
  74:  {
  75:   Metafile pageImage = new Metafile(m_streams[m_currentPageIndex]);
  76:   ev.Graphics.DrawImage(pageImage, ev.PageBounds);
  77:   m_currentPageIndex++;
  78:   ev.HasMorePages = (m_currentPageIndex < m_streams.Count);
  79:  } 

Then a new requirement came that we needed to get the report viewer print button to be the same as our print button.  At first I didn’t think it was possible because the button was within the report viewer control, but after looking through all the properties, methods and events we found the print event, which according to the object help, fires after the user prints a report.  This would help because at least we would be able to detect a print event and then print the front page at the end of printing the report.  But a collogue played around with the code and found that the event gets fired first before the printing happens and setting the cancel variable to true stops the report viewer doing the printing then by calling our printing code this allowed us to meet all the requirements.

No comments: