Link to home
Start Free TrialLog in
Avatar of smegghead
smeggheadFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Print HTML from c#

Hi,

I want to be able to print a letter from my c# application. Each client has a different letter, and at the moment, I've hard-coded a standard format (this is NOT good)

What I'd like is for the users to be able to change the format themselves, maybe by editing an html file, or maybe an xml file with appropriate tags. The letter also contains various things like date of appointment, the client's name etc...

I'm reluctant to use crystal to do this, as it means that our clients have to know how to use it, and there is probably a licensing issue with it.

The best solution I can think of is to have the users create their letter in word, and add things like {dateapp} for the date of appointment, then, save it as HTML.. then, when it comes to printing it, I replace it with the relevant value. So.. I've now got an html file, which has all the replaced values.. how can I print this ? ok, I can fire up iexpore.exe, and pass the filename as a parameter, but some PC's have removed the users' ability to open IE...

Maybe I'm barking up the wrong tree.. I've also done this in the past using word merge etc.. but remember it as not being very tidy.

I'm considering writing my own xml parser which writes a format similar to HTML to a graphics object.. this would be a nice solution.. but does it exist already ???

Anyway, I'm just really looking for ideas on this one... any advice anyone ??

Chrs
Smg.
Avatar of sachiek
sachiek
Flag of Singapore image

Check in this page. There are many ways you can obtain it.
There are soo many articles listed in this below url to explain about different ways to acheive it.

http://www.c-sharpcorner.com/Printing.asp


Sachi
Avatar of smegghead

ASKER

Hi Sachi,

I've looked at most of the links on that page, but none of them allow me to do what I want. All these links do is explain how to print, there is nothing in there about printing an HTML document from c# !!!

I know how to print, and I've written many reports for my users, but I want them to be able to define the format...

Smg.
ASKER CERTIFIED SOLUTION
Avatar of gregoryyoung
gregoryyoung
Flag of Canada image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Interesting article. I wasn't sure about how easy it would be to use IE.. although I do know that some of our clients restrict their users' ability to run IE..

I've never used xslt, is that the xml file which formats xml data ?? so, could you pass a dataset's xml representation into an xslt stream/file and have it output to somewhere ?? where does it output to ?? I take it not a graphics device :-(

Smg.
umm the control uses a com component of IE ...

as for xslt ... it defines an xml transformation ... you could output it to a memory stream and then just use the same code as in the article to just push the html into the embedded browser ... I believe all windows machines already have the control as things such as the control panel use it.

Greg
just to be clear it defines how to transform the xml to html ... its kind of a beefed up way of doing what you are talking about (replacement) it also will handle loopings, conditionals, etc.

Greg
so, you're suggesting using the xslt transformation, rather than replacing Dear {title}. {surname} with 'Dear Mr. Head' - I thought there might have been some 'magic' way to output the results of the transformation to a Graphics object... shame the Graphics object hasn't got a ParseHtml(stream HtmlStream) method.. maybe I'll write one, and just create my own xml format, which has tags like 'font' / 'colour' etc.. as I don't think the reports will be using much else.

Smg.
p.s. I am building a little thing right now which illustrates it. I have to run out on errands with my girlfriend but can probably send you an example this evening.

Greg
the axbrowser can display/print the html generated by the xslt transformation.
I'm off out in a minute.. so no rush.. later tomorrow would be cool though.. cheers

Smg.
btw: writing your own display for html seems like a rather daunting task which would likely lead to immense failures esp with trying to keep up with standards, aside from that the axbrowser already has full support for css, dhtml, and javascript which are rather familiar tools for users to be able to work with.

There are also purchasble xslt visual designers (and components for design) which would work incredibly for less technically adept users you just need to give your app the ability to dump out an xsd for them to model their xslts (which can be done via dataset.getschema for datasets and you should already have an xsd for xmlserliaztion if you are dealing with class structures)

Cheers,

Greg
simple quick code ...

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;

namespace AxBrowserExample
{
      /// <summary>
      /// Summary description for Form1.
      /// </summary>
      public class Form1 : System.Windows.Forms.Form
      {
            private System.Windows.Forms.Panel panel1;
            private System.Windows.Forms.Button button1;
            private System.Windows.Forms.Button button2;
            private System.Windows.Forms.Button button3;
            private System.Windows.Forms.Button button4;
            private System.Windows.Forms.Button button5;
            private AxSHDocVw.AxWebBrowser axWebBrowser1;
            /// <summary>
            /// Required designer variable.
            /// </summary>
            private System.ComponentModel.Container components = null;

            public Form1()
            {
                  //
                  // Required for Windows Form Designer support
                  //
                  InitializeComponent();

                  //
                  // TODO: Add any constructor code after InitializeComponent call
                  //
            }

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            protected override void Dispose( bool disposing )
            {
                  if( disposing )
                  {
                        if (components != null)
                        {
                              components.Dispose();
                        }
                  }
                  base.Dispose( disposing );
            }

            #region Windows Form Designer generated code
            /// <summary>
            /// Required method for Designer support - do not modify
            /// the contents of this method with the code editor.
            /// </summary>
            private void InitializeComponent()
            {
                  System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(Form1));
                  this.panel1 = new System.Windows.Forms.Panel();
                  this.button1 = new System.Windows.Forms.Button();
                  this.button2 = new System.Windows.Forms.Button();
                  this.button3 = new System.Windows.Forms.Button();
                  this.button4 = new System.Windows.Forms.Button();
                  this.button5 = new System.Windows.Forms.Button();
                  this.axWebBrowser1 = new AxSHDocVw.AxWebBrowser();
                  this.panel1.SuspendLayout();
                  ((System.ComponentModel.ISupportInitialize)(this.axWebBrowser1)).BeginInit();
                  this.SuspendLayout();
                  //
                  // panel1
                  //
                  this.panel1.Controls.Add(this.button5);
                  this.panel1.Controls.Add(this.button4);
                  this.panel1.Controls.Add(this.button3);
                  this.panel1.Controls.Add(this.button2);
                  this.panel1.Controls.Add(this.button1);
                  this.panel1.Dock = System.Windows.Forms.DockStyle.Bottom;
                  this.panel1.Location = new System.Drawing.Point(0, 341);
                  this.panel1.Name = "panel1";
                  this.panel1.Size = new System.Drawing.Size(512, 40);
                  this.panel1.TabIndex = 0;
                  //
                  // button1
                  //
                  this.button1.Location = new System.Drawing.Point(8, 8);
                  this.button1.Name = "button1";
                  this.button1.TabIndex = 0;
                  this.button1.Text = "Transform";
                  this.button1.Click += new System.EventHandler(this.button1_Click);
                  //
                  // button2
                  //
                  this.button2.Location = new System.Drawing.Point(88, 8);
                  this.button2.Name = "button2";
                  this.button2.TabIndex = 1;
                  this.button2.Text = "Show XML";
                  this.button2.Click += new System.EventHandler(this.button2_Click);
                  //
                  // button3
                  //
                  this.button3.Location = new System.Drawing.Point(168, 8);
                  this.button3.Name = "button3";
                  this.button3.TabIndex = 2;
                  this.button3.Text = "Show XSLT";
                  this.button3.Click += new System.EventHandler(this.button3_Click);
                  //
                  // button4
                  //
                  this.button4.Location = new System.Drawing.Point(248, 8);
                  this.button4.Name = "button4";
                  this.button4.TabIndex = 3;
                  this.button4.Text = "Show HTML";
                  this.button4.Click += new System.EventHandler(this.button4_Click);
                  //
                  // button5
                  //
                  this.button5.Location = new System.Drawing.Point(328, 8);
                  this.button5.Name = "button5";
                  this.button5.TabIndex = 4;
                  this.button5.Text = "Print";
                  this.button5.Click += new System.EventHandler(this.button5_Click);
                  //
                  // axWebBrowser1
                  //
                  this.axWebBrowser1.Dock = System.Windows.Forms.DockStyle.Fill;
                  this.axWebBrowser1.Enabled = true;
                  this.axWebBrowser1.Location = new System.Drawing.Point(0, 0);
                  this.axWebBrowser1.OcxState = ((System.Windows.Forms.AxHost.State)(resources.GetObject("axWebBrowser1.OcxState")));
                  this.axWebBrowser1.Size = new System.Drawing.Size(512, 341);
                  this.axWebBrowser1.TabIndex = 1;
                  //
                  // Form1
                  //
                  this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
                  this.ClientSize = new System.Drawing.Size(512, 381);
                  this.Controls.Add(this.axWebBrowser1);
                  this.Controls.Add(this.panel1);
                  this.Name = "Form1";
                  this.Text = "Form1";
                  this.Load += new System.EventHandler(this.Form1_Load);
                  this.panel1.ResumeLayout(false);
                  ((System.ComponentModel.ISupportInitialize)(this.axWebBrowser1)).EndInit();
                  this.ResumeLayout(false);

            }
            #endregion

            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            [STAThread]
            static void Main()
            {
                  Application.Run(new Form1());
            }

            private string Transform(string _XmlFilename, string _XsltFilename)
            {
                  System.Xml.Xsl.XslTransform xslt = new System.Xml.Xsl.XslTransform();
                  xslt.Load(_XsltFilename);
                  System.Xml.XPath.XPathDocument doc = new
                        System.Xml.XPath.XPathDocument(_XmlFilename);
                  System.IO.Stream str = new System.IO.MemoryStream();
                  xslt.Transform(doc, null, str);
                  str.Flush();
                  str.Position = 0;
                  StreamReader reader = new StreamReader(str);
                  string text = reader.ReadToEnd();
                  reader.Close();
                  return text;
            }

            private void ShowFile(string _Filename)
            {
                  FileStream str = File.Open(_Filename,FileMode.Open);
                  StreamReader reader = new StreamReader(str);
                  string text = reader.ReadToEnd();
                  reader.Close();
                  text = System.Web.HttpUtility.HtmlEncode(text);
                  text=text.Replace("\n","<BR>");
                  mshtml.IHTMLDocument2 doc = axWebBrowser1.Document as mshtml.IHTMLDocument2;
                  doc.clear();
                  doc.writeln(text);

                  doc.close();
            }

            private void button1_Click(object sender, System.EventArgs e)
            {
                  mshtml.IHTMLDocument2 doc = axWebBrowser1.Document as mshtml.IHTMLDocument2;
                  doc.clear();
                  doc.writeln(this.Transform("sample.xml", "sampletransform.xslt"));

                  doc.close();                  
            }

            private void Form1_Load(object sender, System.EventArgs e)
            {
                  object empty = System.Reflection.Missing.Value;
                  axWebBrowser1.Navigate("about:blank", ref empty, ref empty, ref empty, ref empty);
            }

            private void button2_Click(object sender, System.EventArgs e)
            {
                  ShowFile("sample.xml");
            }

            private void button5_Click(object sender, System.EventArgs e)
            {
                  mshtml.IHTMLDocument2 doc = axWebBrowser1.Document as mshtml.IHTMLDocument2;
                  doc.execCommand("Print", true, 0);
            }

            private void button3_Click(object sender, System.EventArgs e)
            {
                  ShowFile("sampletransform.xslt");
            }

            private void button4_Click(object sender, System.EventArgs e)
            {
                  mshtml.IHTMLDocument2 doc = axWebBrowser1.Document as mshtml.IHTMLDocument2;
                  string source = ((mshtml.HTMLDocumentClass)(doc)).documentElement.outerHTML;
                  doc.clear();
                  doc.writeln(System.Web.HttpUtility.HtmlEncode(source));
                  doc.close();
            }
      }
}

sampletransform.xslt
*************************************************************************************************************
<?xml version="1.0" ?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

  <xsl:template match="/">
     <html><head><title>Sorting example</title></head><body>

     <xsl:apply-templates select="famous-persons/persons">
       <xsl:sort select="@category" />
     </xsl:apply-templates>

     </body></html>
  </xsl:template>

  <xsl:template match="persons">

    <h2><xsl:value-of select="@category" /></h2>
    <ul>

       <xsl:apply-templates select="person">
         <xsl:sort select="name"      />
         <xsl:sort select="firstname" />
       </xsl:apply-templates>

    </ul>

  </xsl:template>

  <xsl:template match="person">

        <xsl:text disable-output-escaping="yes">
            &lt;li&gt;
        </xsl:text>

        <b><font color="red"><xsl:value-of select="name"      /></font></b>
           <xsl:value-of select="firstname" />

  </xsl:template>

</xsl:stylesheet>

sample.xml
**********************************************************************************************************************
<?xml version="1.0" ?>

<famous-persons>

<persons category="medicine">
  <person>
    <firstname> Edward   </firstname>
    <name>      Jenner   </name>
  </person>

  <person>
    <firstname> Gertrude </firstname>
    <name>      Elion    </name>
  </person>
</persons>

<persons category="computer science">
  <person>
    <firstname> Charles  </firstname>
    <name>      Babbage  </name>
  </person>

  <person>
    <firstname> Alan     </firstname>
    <name>      Touring  </name>
  </person>

  <person>
    <firstname> Ada      </firstname>
    <name>      Byron    </name>
  </person>
</persons>

<persons category="astronomy">
  <person>
    <firstname> Tycho    </firstname>
    <name>      Brahe    </name>
  </person>

  <person>
    <firstname> Johannes </firstname>
    <name>      Kepler   </name>
  </person>

  <person>
    <firstname> Galileo  </firstname>
    <name>      Galilei  </name>
  </person>
</persons>

</famous-persons>



If you need the actual project let me know thisname _@_ exeprtsexchange and I will email it to you as a zip file.

Cheers,

Greg
did this solve your problem?

Greg
Hi Gregory, will come back to this asap.. I've hod lots of other deadlines in the past few week.
Hi,

Sorry about the delay, I've just got around to doing this.

The link you provided in the first comment provided me with enough to get it working, however, it displays "Page 1 of 2" and the "about:blank" and the date in the footer of the page.. do you know how to prevent this from happening ?? I know I could change the default settings in IE (I assume), but I'd like to control this programatically.

Thanks
Smg.
you have to do custom headers / footers ...

I couldn't in a quick google find a C# example but the is a C++ example. http://support.microsoft.com/default.aspx?scid=kb;EN-US;Q267240

I believe you can also do it with I.E. specific stuff in your document. i.e. PrintTemplates http://www.webreference.com/js/column89/

Greg
Ok, thanks, I'm sure I'll be able to work it out from that..

I'll post my code here when it's done.

Smg.
Cool I recommended this same course of action for a project I am working on, could save me some time :)
Hi,

Just a quick one..

I've released this to a few clients, and they get an error saying file or assembly microsoft.mshtml was not found.. (or something similar).. I've searched the disk and found mshtml.dll, but no microsoft.html.dll... do you know where I can get this from ??

Smg.
send me your release that you sent them : this name at this web site.

Greg
Hi Gregory,

Even if I sent you my release it would take about 2 hours to set up the app to get to the point where you can run the print. It's a large app with database/required data - which would be a pain. anyway...

I've managed to get this working by manually copying microsoft.mshtml.dll to the client machine and running gacutil on it. However, I'd rather be able to tell our clients to download it from the internet somewhere.

I tried creating a setup project, which referenced the output of the project which has the link to mshtml, but that just put the file in the directory and didn't GAC it.

Smg.
is this the interop .dll that is generated by VS ?
No, the interops created by VS are called AxInterop.ShDocVw.dll and Interop.SHDocVw.dll.. these are fine, I just keep these in the application directory.

Smg.