Library code snippets

How to create PDF files from ASP.NET pages

Visual Studio .NET comes with a useful version of Crystal Reports which allows you to create Crystal Reports (.rpt files) and then bind them to your database to produce PDF files on a web page, all from within the Visual Studio .NET GUI without ever even getting into the code. As easy as this is, you can have a lot more control over the process if you do it yourself.

This code shows you how to create and bind a DataSet and a Crystal Report file (.rpt) without even using Visual Studio at all (I used Web Matrix). It is assumed, however, that you have access to the Crystal Reports .dlls which came with Visual Studio .NET and that you have the ability to create .rpt files (I used Crystal Reports 9.0).

Here are the steps:

  1. Copy the file "EmployeeReport" into an ASP.NET web folder.
  2. Important: Make SURE that that folder is a WEB folder and not just a sub-directory of another ASP.NET web folder. This is necessary for the \bin directory to function.
  3. Create a \bin directory and copy the two .dll files "CrystalDecisions.CrystalReports.Engine.dll" and "CrystalDecisions.Shared.dll" to your bin directory (I found the .dlls here: C:\Program Files\Common Files\Crystal Decisions\1.1\Managed)
  4. Point your browser to your .aspx file, e.g. http://localhost/... This will create your schema file (Employees.xsd).
  5. In Crystal Reports, create a report from a ADO.NET XML data source. When you are asked for an XML file, point it to your .XSD file. Create the report just as you would any other report from the fields in the table provided.
  6. Important: click on FILE and turn OFF the option "Save Report with Data". This will allow your .rpt file to use information coming from a DataSet at run-time, otherwise it will ignore the DataSet and always be empty.
  7. Save your report as "Employees.rpt" in your web folder.
  8. Now in your .aspx file, change the action variable to "CreatePdf" and reload the page in your browser. You should see a link to "Employees.pdf". Click on it and you will see your PDF file which was created by combining your DataSet with your RPT file. Note that the line "dt.TableName = "Table";" is very important. If you change this name, then you table won't get through to your report. I believe you can rename your table but it has to have the same name when you create the schema as when you run the report.

 

 

<%@ Page Language="C#" Debug="true" %>
<%@ import Namespace="CrystalDecisions.CrystalReports.Engine" %>
<%@ import Namespace="CrystalDecisions.Shared" %>
<%@ import Namespace="System.Data" %>
<%@ import Namespace="System.IO" %>
<%@ import Namespace="System.Xml" %>
<%@ import Namespace="System.Text" %>
<script runat="server">
    public void Page_Load(Object sender, EventArgs E) {
        //*** INSTRUCTIONS:
        //define action for this program
        //1. set action to "CreateSchemaFile"
        //2. run program which creates your .xsd schema file
        //3. create crystal report based on that file
        //4. then set action permanently to "CreatePdf"
        //the command
        string action = "CreatePdf";
        //variables
        string tableName = "fin";
        string rptFile = "fin.rpt";
        string xsdFile = "fin.xml";
        string pdfFile = "fin.pdf";
        //either create the schema (first time only) or the pdf file
        if(action.ToUpper() == "CREATESCHEMAFILE") {
            DataTable dt = new DataTable();
            dt = DummyTable();
            DataSet ds = new DataSet();
            ds.Tables.Add(dt);
            CreateSchemaFile(xsdFile,ds);
            Response.Write("Your schema file has been created:<br/><br/> <b>" + Server.MapPath(xsdFile) + "</b><br/><br/>");
            Response.Write("Use it to create your Crystal Reports report file named:<br/><br/> <b>" + Server.MapPath(pdfFile) + "</b>");
        } else {
            //create the report document
            ReportDocument doc = new ReportDocument();
            string fileName = Server.MapPath(rptFile);
            doc.Load(fileName);
            DataTable dt = DummyTable();
            dt.TableName = tableName;
            DataSet ds = new DataSet();
            dt.TableName    = "Table";
            ds.Tables.Add(dt);
            doc.SetDataSource(ds);
            ExportOptions exportOpts = doc.ExportOptions;
            exportOpts.ExportFormatType = ExportFormatType.PortableDocFormat;
            exportOpts.ExportDestinationType = ExportDestinationType.DiskFile;
            exportOpts.DestinationOptions = new DiskFileDestinationOptions();
            // Set the disk file options.
            DiskFileDestinationOptions diskOpts = new DiskFileDestinationOptions();
            ( ( DiskFileDestinationOptions )doc.ExportOptions.DestinationOptions ).DiskFileName = Server.MapPath("fin.pdf");
            doc.Export();
            Response.Write(dt.Rows.Count);
            Response.Write("<a href=\"" + pdfFile + "\">" + pdfFile + "</a>");
        }

    }
    private void CreateSchemaFile(string fileName, DataSet ds) {
        string absoluteFileName = HttpContext.Current.Server.MapPath(fileName);
        FileStream myFileStream = new FileStream (absoluteFileName, FileMode.Create);
        XmlTextWriter myXmlWriter = new XmlTextWriter(myFileStream, Encoding.Unicode);
        ds.WriteXml( myXmlWriter,XmlWriteMode.WriteSchema );
        myXmlWriter.Close();
    }
    private DataTable GetTheData() {
        //get datatable
        DataTable dt = qs.GetDataTable("SELECT * FROM fin");
        DataTable d2 = dt.Copy();
        return d2;
    }
    private DataTable DummyTable()    {
        //create table
        DataTable dt = new DataTable("Employees");
        dt.Columns.Add("id",Type.GetType("System.Int32"));
        dt.Columns.Add("FirstName",Type.GetType("System.String"));
        dt.Columns.Add("LastName",Type.GetType("System.String"));
        dt.Columns.Add("HireDate",Type.GetType("System.DateTime"));
        //fill rows
        DataRow dr;
        for(int x=1;x<=10;x++) {
            dr = dt.NewRow();
            dr["id"] = x;
            dr["FirstName"] = "Joe" + x;
            dr["LastName"] = "Smith" + x;
            dr["HireDate"] = DateTime.Now;
            dt.Rows.Add(dr);
        }
        return dt;
    }
</script>
<!--#include file="qs.aspx" -->

Comments

  1. 01 May 2007 at 03:26
    where's is the source code?
  2. 24 Jun 2005 at 16:46
    Hi,

    I tried implementing the code you posted and I keep receiving a "File or assembly name CrystalKeyCodeLib, or one of its dependencies, was not found." I'm sure it has something to do with the Crystal Reports registration issue in VS.NET. In a normal deployment you would use the proper merge modules to make it work but I can't seem to accomplish that here.

    Any help would be appreciated!!
    Thanks
  3. 08 Apr 2005 at 10:42

    I will post here a version of Crystal Reports integrated into Visual Studio.NET


    Basically you have to create a Crystal Report using VS.NET (Employees.rpt) and don't worry about "Save report with data Option". This does not exists in VS.NET.
    Another thing is to that line dt.tableName = "Table" because the table name is set at the begining of the code (string tableName = "Employees".


    I will attach the whole code here:


    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Web;
    using System.Web.SessionState;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.HtmlControls;
    using System.IO;
    using System.Xml;
    using System.Text;
    using CrystalDecisions.CrystalReports.Engine;
    using CrystalDecisions.Shared;


    namespace CRep
    {
    /// <summary>
    /// Summary description for WebForm1.
    /// </summary>
    public class WebForm1 : System.Web.UI.Page
    {


    private void Page_Load(object sender, System.EventArgs e)
    {
    // Put user code to initialize the page here
    //* INSTRUCTIONS:
    //define action for this program
    //1. set action to "CreateSchemaFile"
    //2. run program which creates your .xsd schema file
    //3. create crystal report based on that file
    //4. then set action permanently to "CreatePdf"
    //the command
    string action = "CREATEPDF";
    //variables
    string tableName = "Employees";
    string rptFile = "Employees.rpt";
    string xsdFile = "Employees.xsd";
    string pdfFile = "Employees.pdf";
    //either create the schema (first time only) or the pdf file
    if(action.ToUpper() == "CREATESCHEMAFILE")
    {
    DataTable dt = new DataTable();
    dt = DummyTable();
    DataSet ds = new DataSet();
    ds.Tables.Add(dt);
    CreateSchemaFile(xsdFile,ds);
    Response.Write("Your schema file has been created:<br/><br/> <b>" + Server.MapPath(xsdFile) + "</b><br/><br/>");
    Response.Write("Use it to create your Crystal Reports report file named:<br/><br/> <b>" + Server.MapPath(pdfFile) + "</b>");
    }
    else
    {
    //create the report document
    ReportDocument doc = new ReportDocument();
    string fileName = Server.MapPath(rptFile);
    doc.Load(fileName);
    DataTable dt = DummyTable();
    dt.TableName = tableName;
    DataSet ds = new DataSet();
    ds.Tables.Add(dt);
    doc.SetDataSource(ds);
    ExportOptions exportOpts = doc.ExportOptions;
    exportOpts.ExportFormatType = ExportFormatType.PortableDocFormat;
    exportOpts.ExportDestinationType = ExportDestinationType.DiskFile;
    exportOpts.DestinationOptions = new DiskFileDestinationOptions();


    // Set the disk file options.
    DiskFileDestinationOptions diskOpts = new DiskFileDestinationOptions();
    ( ( DiskFileDestinationOptions )doc.ExportOptions.DestinationOptions ).DiskFileName = Server.MapPath("Employees.pdf");
    doc.Export();
    Response.Write("<a href=\"" + pdfFile + "\">" + pdfFile + "</a>");
    }


    }


    region Web Form Designer generated code


    override protected void OnInit(EventArgs e)
    {
    //
    // CODEGEN: This call is required by the ASP.NET Web Form Designer.
    //
    InitializeComponent();
    base.OnInit(e);
    }


    /// <summary>
    /// Required method for Designer support - do not modify
    /// the contents of this method with the code editor.
    /// </summary>
    private void InitializeComponent()
    {    
    this.Load += new System.EventHandler(this.Page_Load);


    }

    endregion



    private void CreateSchemaFile(string fileName, DataSet ds)
    {
    string absoluteFileName = HttpContext.Current.Server.MapPath(fileName);
    FileStream myFileStream = new FileStream (absoluteFileName, FileMode.Create);
    XmlTextWriter myXmlWriter = new XmlTextWriter(myFileStream, Encoding.Unicode);
    ds.WriteXml( myXmlWriter,XmlWriteMode.WriteSchema );
    myXmlWriter.Close();
    }


    private DataTable DummyTable()    
    {
    //create table
    DataTable dt = new DataTable("Employees");
    dt.Columns.Add("id",Type.GetType("System.Int32"));
    dt.Columns.Add("FirstName",Type.GetType("System.String"));
    dt.Columns.Add("LastName",Type.GetType("System.String"));
    dt.Columns.Add("HireDate",Type.GetType("System.DateTime"));
    //fill rows
    DataRow dr;
    for(int x=1;x<=10;x++)
    {
    dr = dt.NewRow();
    dr["id"] = x;
    dr["FirstName"] = "Joe" + x;
    dr["LastName"] = "Smith" + x;
    dr["HireDate"] = DateTime.Now;
    dt.Rows.Add(dr);
    }
    return dt;
    }
    }
    }

  4. 07 Dec 2004 at 10:45

    Very good article, but it doesn't discuss the version of Crystal Reports integrated into Visual Studio.NET. How do I turn OFF the "Save Report with Data" option in that environment? I need to get it working. Please, help!

  5. 02 Mar 2004 at 04:42

    The only code missing that I can see is the functions that retrieved the info from the database - so just replace the line


    DataTable dt = qs.GetDataTable("SELECT * FROM fin");


    in GetTheData() with your own method for retrieving the data.

  6. 16 Feb 2004 at 17:27

    Hi
    Do you have all the source code available so that I can try the example out


    Wayne

  7. 01 Jan 1999 at 00:00

    This thread is for discussions of How to create PDF files from ASP.NET pages.

Leave a comment

Sign in or Join us (it's free).

Edward Tanguay Edward Tanguay updates his personal web site tanguay.info weekly with code, links, quotes and thoughts on web development. Sign up for the free newsletter.
AddThis

Related podcasts

Events coming up

  • Jul 13

    IKT-Forum für Menschen mit Behinderungen

    Linz, Austria

    ICT Forum for People with Disabilities.Deutschsprachige Konferenz mit den Themenschwerpunkten: Unterstützte Kommunikation (Technologien, Symbolsysteme, Gebärdensprache, etc.), Barrierefreies Web- und Softwaredesign, Barrierefreies Dokument- un...

Want to stay in touch with what's going on? Follow us on twitter!