Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Print HTML from c#

Posted on 2005-04-21
23
Medium Priority
?
8,092 Views
Last Modified: 2008-01-09
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.
0
Comment
Question by:smegghead
  • 12
  • 10
23 Comments
 
LVL 11

Expert Comment

by:sachiek
ID: 13839831
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
0
 
LVL 10

Author Comment

by:smegghead
ID: 13849297
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.
0
 
LVL 37

Accepted Solution

by:
gregoryyoung earned 2000 total points
ID: 13850622
I woud use the axbrowser object as illustrated here http://ryanfarley.com/blog/archive/2004/12/23/1330.aspx

btw: why not just use an xslt transformation to transform the data :) would be alot more flexible and would allow you to do alot of future reports in the same manner.

Greg

0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 10

Author Comment

by:smegghead
ID: 13851082
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.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 13851214
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
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 13851221
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
0
 
LVL 10

Author Comment

by:smegghead
ID: 13851239
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.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 13851240
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
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 13851242
the axbrowser can display/print the html generated by the xslt transformation.
0
 
LVL 10

Author Comment

by:smegghead
ID: 13851256
I'm off out in a minute.. so no rush.. later tomorrow would be cool though.. cheers

Smg.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 13851292
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
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 13854163
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
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 13941481
did this solve your problem?

Greg
0
 
LVL 10

Author Comment

by:smegghead
ID: 13943586
Hi Gregory, will come back to this asap.. I've hod lots of other deadlines in the past few week.
0
 
LVL 10

Author Comment

by:smegghead
ID: 13988762
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.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 13988878
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
0
 
LVL 10

Author Comment

by:smegghead
ID: 13989142
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.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 13989288
Cool I recommended this same course of action for a project I am working on, could save me some time :)
0
 
LVL 10

Author Comment

by:smegghead
ID: 14014966
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.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 14015213
send me your release that you sent them : this name at this web site.

Greg
0
 
LVL 10

Author Comment

by:smegghead
ID: 14015231
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.
0
 
LVL 37

Expert Comment

by:gregoryyoung
ID: 14015480
is this the interop .dll that is generated by VS ?
0
 
LVL 10

Author Comment

by:smegghead
ID: 14016996
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.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The article shows the basic steps of integrating an HTML theme template into an ASP.NET MVC project
Hello there! As a developer I have modified and refactored the unit tests which was written by fellow developers in the past. On the course, I have gone through various misconceptions and technical challenges when it comes to implementation. I would…
Loops Section Overview
The Relationships Diagram is a good way to get an overall view of what a database is keeping track of. It is also where relationships are defined. A relationship specifies how two tables connect to each other. As you build tables in Microsoft Ac…
Suggested Courses

571 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question