views:

1253

answers:

4

How do you generate paper-prints from a web application?

Specifically I am thinking about more complex paper documents like diplomas, invoices and contracts. Variable number of pages with frames, tables, logos and headers/footers.

Today I use custom forms and CSS for certain things and iTextSharp for others (I work with asp.net and MS-SQL), but I think both approaches are time-consuming and hard to make consistent across different documents.

Is there a better way to go about it?

+3  A: 

IMHO for fixed format printing PDF if the answer

aivarsak
A: 

Even though you've stated you've tried a CSS-based approach, the best way forward is to take a look at the @print media type (http://www.w3.org/TR/CSS2/media.html). Basically allows you to use a different stylesheet for printing, than for screen, or any of the other (many) media types.

Then, if you want to launch a print event automatically, you want to use something like this (JavaScript):

window.print();

Of course, you'll have to check the browser actually supports printing via JavaScript, and act accordingly:

function doPrint() {
    if(!window.print())
    {
        alert("Your browser does not support direct printing, please select 'Print' from the 'File' menu.");
    }
}

If, however, you're adamant that CSS won't meet your needs, then you're probably going to need to go towards a PDF-based solution. Though, I have no experience of producing web printouts 'via' PDF.

James Burgess
A: 

If you are using SQL Server, you could create a report using reporting services. The user can then either print this directly or export it themselves to a number of different formats (you can control which formats are available to the user).

I have used this approach in the past and I have found that it gives me a lot more control over the look of the document when it is printed or exported.

KevB
+3  A: 

Creating documents from scratch with iTextSharp can be very time consuming. As an alternative, you can create (or reuse) PDF "template" documents by adding form fields to them (if necessary). The easiest way to do this is with a full version of Adobe Acrobat, but you can also add fillable form fields using nothing but iTextSharp.

For example, for an award or diploma, you find, create, or modify a PDF containing all of the text, graphics, fancy borders and fonts for the document, then add a form field for the recipient's name. You might add other fields for dates, signature lines, type of award, etc.

Then it's very easy to use iTextSharp from your web application to fill in the form, flatten it, and stream it back to the user.

At the end of this post is a complete ASHX handler code example.

Also remember that iTextSharp (or just iText) is also useful for combining PDF documents or pages from different documents. So, for an annual report that has a fixed design for a cover or explanation page but dynamically generated content, you can open the cover page, open a template page for the report, generate the dynamic content onto a blank area of the template, open the back page "boilerplate", then combine them all into a single document to return to the user.

using System;
using System.Data;
using System.Web;
using System.Collections;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Text;
using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.pdf;

namespace iTextFormFillerDemo
{
    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class DemoForm : IHttpHandler
    {

     public void ProcessRequest(HttpContext context)
     {

      context.Response.ContentType = "application/pdf";
      //This line will force the user to either open or save the 
      //file instead of it appearing on its own page - if you remove it, 
      //the page will appear in the browser in the same window.
      context.Response.AddHeader("Content-Disposition", 
       "attachment; filename=DemoForm_Filled.pdf");

      FillForm(context.Response.OutputStream);

      context.Response.End();
     }

     // Fills the form and pushes it out the output stream.
     private void FillForm(System.IO.Stream outputStream)
     {
      //Need to get the proper directory (dynamic path) for this file. 
      //This is a filesystem reference, not a web/URL reference...
      //The PDF reader reads in the fillable form
      PdfReader reader = new PdfReader("C:/DemoForm_Fillable.pdf");

      //The PDF stamper creates an editable working copy of the form from the reader 
      //and associates it with the response output stream
      PdfStamper stamper = new PdfStamper(reader, outputStream);

      //The PDF has a single "form" consisting of AcroFields
      //Note that this is shorthand for writing out 
      //stamper.AcroFields.SetField(...) for each set
      AcroFields form = stamper.AcroFields;

      //Set each of the text fields this way: SetField(name, value)
      form.SetField("txtFieldName", "Field Value");
      form.SetField("txtAnotherFieldName", "AnotherField Value");

      //Set the radio button fields using the names and string values:
      form.SetField("rbRadioButtons", "Yes"); //or "No"

      //Form flattening makes the form non-editable and saveable with the 
      //form data filled in
      stamper.FormFlattening = true;

      //Closing the stamper flushes it out the output stream
      stamper.Close();

      //We're done reading the file
      reader.Close();
     }

     public bool IsReusable
     {
      get
      {
       return false;
      }
     }
    }
}
CMPalmer
Thanks for the input! Being able to use iTextSharp to "complete" a pdf template where all the tricky layout has been done in an appropriate application sounds perfect. If you do have some sample code or a link to a resource that covers this approach I would very much appreciate it.
Console