How to create a Crystal Reports invoice and export it as PDF

In this article we are going to show how to create a Crystal Reports report in Visual Studio 2008, bind data to it and export it as a PDF document.

As an example we shall create invoice report. For example a customer has purchased a product on your website and you want to generate an invoice for the customer.

We will create the report in the following steps

  1. Create a report template
  2. Create a dataset
  3. Add dataset as data source to the report template
  4. Design the report template
  5. Fill data in the dataset and bind it to the report template
  6. Export the report as a PDF document
  7. Example
Create VS project

First create a new project in Visual Studio 2008. The purpose of the project is to create reports. Call the project something like <Company Name>.Reports. Since the library is independent of technology we don't need a Web or Windows in the namespace name.

Create report template

Add a folder to your project and name it e.g. Templates. This folder will contain the report templates. Add a Crystal Report to you template. Since we are going to create an invoice you should call it something with Invoice. In the Crystal Reports dialog select blank report.

Create a dataset

Add a new folder to your project: Datasets. This will ensure that you get a new sub namespace and have order in your files. Add a dataset to the folder. Call it e.g. Invoice Data. In design mode add two data tables to your dataset. Call them e.g. Invoice and Invoice Line. The data tables correspond to the tables in your database, but we don't need a one-to-one correspondence since we probably don't need all the fields in the tables. Add columns to your data tables in the dataset. The columns should be fields that you wish to add to your report.

Add dataset as data source to the report template

Open your report in Crystal Reports. Browse the field explorer. Right click Database fields and select Database expert. Under the Data tab, expand the Project Data folder and expand ADO.NET Datasets folder. Select the dataset you created and add it to data sources.

Design the report template

Now that you have added the dataset to the report you can drag fields from the data tables onto you reports. To make your report scalable select no printer under printer setup. You can eventually set your margin under page setup. As you notice a Crystal Report is divided into sections. Since we can have more than one invoice line in our data table we place the fields from invoice line in the detail section. This ensures that all rows get shown.

Fill data in the dataset and bind it to the report template

Add a new folder to your project. Call it e.g. Report Binding. Add a new class to the folder. The purpose of the class is to make the binding of data in the database to data tables of the dataset and to bind the dataset to the report template.

The class looks like this:

public class InvoiceBind : ReportBindBase
{
private int invoiceNo;

private BedstPension.Reports.ReportTemplates.Invoice invoiceReportDocument;

private InvoiceData invoiceData;
private InvoiceBll invoiceBll;
private BedstPension.Data.Bill.Invoice invoice;
private InvoiceLineBll invoiceLineBll;
private IList<InvoiceLine> invoiceLines;

private InvoiceData.InvoiceDataRow invoiceDataRow;
private InvoiceData.InvoiceLineRow invoiceLineRow;
private InvoiceData.CustomerDataRow customerDataRow;

public BedstPension.Reports.ReportTemplates.Invoice InvoiceReportDocument
{
get
{
return this.invoiceReportDocument;
}
}

public InvoiceBind(int invoiceNo) : base()
{
this.invoiceNo = invoiceNo;
this.invoiceData = new InvoiceData();
this.invoiceReportDocument = new BedstPension.Reports.ReportTemplates.Invoice();
}

public void BindData()
{
using (invoiceBll = new InvoiceBll())
{
invoice = invoiceBll.GetByInvoiceNumber(this.invoiceNo);

if (invoice != null)
{
customerId = invoice.CustomerId;

using (customerDataBll = new CustomerDataBll())
{
customerData = customerDataBll.Get(customerId);

customerDataRow = invoiceData.CustomerData.NewCustomerDataRow();

customerDataRow.Id = customerData.Id;
customerDataRow.Forename = customerData.Forename;
customerDataRow.Surname = customerData.Surname;
customerDataRow.Street = customerData.Street;
customerDataRow.Postcode = customerData.Postcode;
customerDataRow.City = customerData.City;

this.invoiceData.CustomerData.AddCustomerDataRow(customerDataRow);
}

invoiceDataRow = this.invoiceData._InvoiceData.NewInvoiceDataRow();

invoiceDataRow.Id = invoice.Id;
invoiceDataRow.InvoiceNumber = invoice.InvoiceNumber;
invoiceDataRow.BillingDate = invoice.BillingDate.Date.ToString(this.DateFormat, this.CultureInfo);
invoiceDataRow.CustomerId = customerId;
invoiceDataRow.Total = invoice.Total;
invoiceDataRow.Vat = invoice.Vat;
invoiceDataRow.OrderId = invoice.OrderId;
invoiceDataRow.TransactionId = invoice.TransactionId;

this.invoiceData._InvoiceData.AddInvoiceDataRow(invoiceDataRow);

using (invoiceLineBll = new InvoiceLineBll())
{
invoiceLines = invoiceLineBll.List(this.invoiceNo);

foreach (InvoiceLine invoiceLine in invoiceLines)
{
invoiceLineRow = this.invoiceData.InvoiceLine.NewInvoiceLineRow();

invoiceLineRow.Id = invoiceLine.Id;
invoiceLineRow.InvoiceNumber = invoiceLine.InvoiceNumber.ToString();
invoiceLineRow.ItemNumber = invoiceLine.ItemNumber.ToString();
invoiceLineRow.ItemsNo = invoiceLine.NumberOfItems;
invoiceLineRow.ItemText = invoiceLine.ItemText;
invoiceLineRow.ItemPrice = invoiceLine.ItemPrice;
invoiceLineRow.ItemVat = invoiceLine.ItemVat;
invoiceLineRow.ProductItemId = invoiceLine.ProductItemId;

this.invoiceData.InvoiceLine.AddInvoiceLineRow(invoiceLineRow);
}
}
}
this.invoiceReportDocument.SetDataSource(this.invoiceData);
}
}

public void Dispose()
{
if (this.invoiceReportDocument != null)
this.invoiceReportDocument.Dispose();

}
}

 

This class is pretty explanatory. The method Bind Data fills data into the dataset and binds the dataset to the report template.

Export the report as a PDF document

Exporting a Crystal Report as PDF is easy. The Export / Export Test method in the class below does the work.

public class BaseReportExport
{
private string diskFileName;
private string physicalPath;
private ReportClass report;

public string PhysicalPath
{
get
{
return this.physicalPath;
}
set
{
this.physicalPath = value;
}
}

public string DiskFileName
{
get
{
return this.diskFileName;
}
}

public ReportClass Report
{
get
{
return this.report;
}
set
{
this.report = value;
}
}

public BaseReportExport(string physicalPath)
{
this.physicalPath = physicalPath;
}

public BaseReportExport(string physicalPath, ReportClass report)
{
this.physicalPath = physicalPath;
this.report = report;
}

public virtual void Export()
{
this.diskFileName = this.physicalPath;
this.report.ExportToDisk(ExportFormatType.PortableDocFormat, this.DiskFileName);
}

public virtual void ExportTest()
{
this.diskFileName = this.physicalPath;
this.diskFileName += "\\" + Guid.NewGuid().ToString().Replace("-", "") + ".pdf";
this.report.ExportToDisk(ExportFormatType.PortableDocFormat, this.DiskFileName);
}

Again this is very self explanatory.

Example

Here we provide an example to show how our reporting system works.

 

InvoiceBind bind = new InvoiceBind(20002);
BaseReportExport export;
bind.BindData();
export = new BaseReportExport(Server.MapPath("~/Reports/Invoices"), bind.InvoiceReportDocument);
export.ExportTest();
bind.Dispose();
string diskFileName = export.DiskFileName;

First we instantiate Invoice Bind object with an invoice number 20002. Then we call the Bind Data method on the object. The method fills the dataset and binds the dataset to the bind.InvoiceReportDocument. Finally we export the report as PDF.

Let us know what you think about the article

SoftPilar | CVR: 31716225 | Studsgaardsgade 9, st. tv. | Copenhagen 2100 | | Contact | Sitemap | Search