Skip to main content Skip to footer

Creating Simple Invoices with .docx Report Templates in C#

Throughout various business vertical markets, a common scenario or need is creating invoices. Invoices can be simple; purchase of a single item, or more complex, purchasing multiple components to make up a single item. Either way, it's important to have a consistent format so customers can read, recognize and reconcile their purchases easily. This makes an Invoice document a perfect candidate for document automation using the Document Solutions for Word (DsWord, previously GcWord) API Report Templates.

This feature lets you generate Word Reports by defining Report Templates using template tags, bound to a data source to replace the tags with appropriate data and generate the document. Refer to documentation, demos, and the featured blog for detailed insight on this feature.

This blog post focuses on the steps required to create an Invoice Template and generate an Invoice by processing the template.

Configure .NET Application

  1. Create a new C# .NET Core Console Application
  2. Install DS.Documents.Word package using NuGet package manager in the application.
    .NET C# Word API NuGet Package - Document Solutions for Word
  3. Add a reference to GrapeCity.Documents.Word namespace in Program.cs file, using the following code:
    using Grapecity.Documents.Word;
    Note: Document Solutions was previously named GrapeCity Documents, the previous name is still seen in areas of the API.

Create Invoice Template

DsWord API supports a set of template tags divided into Value Tags and Range Tags, used to create the Report Template. Refer to the documentation for a detailed understanding of template tags.

The Invoice template shown below was created using MS Word, following the steps below:

  1. Design the Report Template by creating a new Word document.
  2. Add labels and paragraphs as required to display static text.
  3. Add the required structural elements, which is a Table displaying the list of ordered products. After adding the static text and structural elements, we must add tags using the Mustache syntax "{{" and "}}" which serves as placeholders for data when processing the template to generate the Invoice.

The table below describes the different tags used to design the Invoice template:

Tag Tag Type Description

{{o.OrderID}}
Value Used to fetch OrderId from template's datasource.
{{o.OrderDate}:toshortdatestring()} Value Used to fetch Order Date from template's datasource and format it using toshortdatestring date formatter. Refer to Formatters topic for details.
{{o.CompanyName}} Value Used to fetch Company name from template's datasource.
{{o.Name}} Value Used to fetch billing name from template's datasource.
{{o.Address}} Value Used to fetch billing address from template's datasource.
{{o.Email}} Value Used to fetch billing email from template's datasource.
{{o.Name}} Value Used to fetch shipping name from template's datasource.
{{o.Address}} Value Used to fetch shipping address from template's datasource.
{{total}:format(C)} Value Used to fetch sum of the Total Price column, saved in total variable in template's datsource and format it using format value formatter.
{{#ds}}{{ps.ProductName}} Range Used to mark the start of a range block and fetch product's name from template's datasource.
{{ps.Quantity}} Range Used to fetch product's quantity from template's datasource.
{{ps.UnitPrice}:format(C)} Range Used to fetch product's unit price from template's datasource and format it using format value formatter.
{{ps.Total}:format(C)}{/ds}} Range Used to mark the end of a range block and fetch total price of a product from template's datasource. The fetched value is formatted using format value formatter.

Below is a snapshot of the Invoice template created using Word, which can be downloaded here.

Word .docx template

Create Template Datasource

DsWord API lets you bind data to Report Templates from any data source as long as the data can be placed in the following objects in code:

  • DataSet
  • DataTable
  • IEnumerable objects

For this example, the data will be fetched from an XML file GcNWind.xml. Create a new folder named Resources in the project folder, download GcNWind.xml, and add it to the Resources folder.

For generating an Invoice, Shipping Information, Billing Information, and the list of purchased products should be available. All this information is stored in three tables Suppliers, OrdersCustomersEmployees and EmployeesProductOrders. The code below fetches data from all three tables and then fetches the detailed information for a specific order. This fetched order detail is saved in a newly created object in code, which is then returned to bind it to the template's datasource.

//Fetch data from XML to create template datasource
public static object FetchData()
{
   using (var ds = new DataSet())
   {
      // Load the sample database, fetch a random supplier
      // and a random order from that supplier:
      ds.ReadXml(Path.Combine("Resources", "data", "GcNWind.xml"));

      // Database tables used by the invoice:
      var dtSuppliers = ds.Tables["Suppliers"];
      var dtOrders = ds.Tables["OrdersCustomersEmployees"];
      var dtOrdersDetails = ds.Tables["EmployeesProductsOrders"];

      // Collect order data:
      var random = new Random();

      var fetchedIndex = random.Next(dtSuppliers.Select().Count());
      var supplier = dtSuppliers.Select()
                    .Skip(fetchedIndex).Take(1)
                    .Select(it => new
                    {
                        SupplierID = Convert.ToInt32(it["SupplierID"]),
                        CompanyName = it["CompanyName"].ToString(),
                        ContactName = it["ContactName"].ToString(),
                        ContactTitle = it["ContactTitle"].ToString(),
                        Address = it["Address"].ToString(),
                        City = it["City"].ToString(),
                        Region = it["Region"].ToString(),
                        PostalCode = it["PostalCode"].ToString(),
                        Country = it["Country"].ToString(),
                        Phone = it["Phone"].ToString(),
                        Fax = it["Fax"].ToString(),
                        HomePage = it["HomePage"].ToString()
                    }).FirstOrDefault();

       fetchedIndex = random.Next(dtOrders.Select().Count());
       var order = dtOrders.Select()
                   .Skip(fetchedIndex).Take(1)
                   .Select(it => new
                   {
                        // used in template:
                        OrderDate = it["OrderDate"],
                        OrderID = Convert.ToInt32(it["OrderID"]),
                        CompanyName = it["CompanyName"].ToString(),
                        Name = $"{it["FirstName"]} {it["LastName"]}",
                        Address = $"{it["ShipAddress"]},\n{it["ShipCity"]} {it["ShipRegion"]} {it["ShipPostalCode"]} {it["ShipCountry"]}",
                        Email = GetEmail(it["FirstName"].ToString(), it["LastName"].ToString(), it["CompanyName"].ToString())
                   }).FirstOrDefault();

       var orderDetails = dtOrdersDetails.Select()
                    .Select(it => new
                    {
                        OrderID = Convert.ToInt32(it["OrderID"]),
                        ProductName = it["ProductName"].ToString(),
                        UnitPrice = Convert.ToDecimal(it["UnitPrice"]),
                        Quantity = Convert.ToDecimal(it["Quantity"]),
                        Total = Convert.ToDecimal(it["UnitPrice"]) * Convert.ToDecimal(it["Quantity"]),
                    })
                    .Where(it => it.OrderID == order.OrderID)
                    .OrderBy(it => it.ProductName).ToList();

        // Finally, prep the integrated data source for the template:
        var data = new
        {
           o = order,
           ps = orderDetails,
           total = orderDetails.Sum(od_ => od_.Total),
        };
     return data;
   }
}

public static GetEmail(string firstName, string lastName, string companyName)
{
   var x = new string(companyName.ToLower().Where(c_ => char.IsLetterOrDigit(c_)).ToArray());
   return $"{firstName.ToLower()}.{char.ToLower(lastName[0])}@{x}.com";
}

Template Processing in .NET

After generating the template datasource and creating the report template saved in DOCX format using the steps above, follow these steps to process the template and generate the document (using C#):

  1. Instantiate an instance of GcWordDocument and load the InvoiceTemplate.docx into it.
//Initialize GcWordDocument instance
var doc = new GcWordDocument();

//Load the template DOCX
doc.Load(Path.Combine("Resources", "WordDocs", "InvoiceTemplate.docx"));
  1. Fetch the data for the template invoking the method defined above and add it to the template's datasources using the Add method of DsWord API
//Fetch template data
dynamic data = FetchData();

//Add the template data source
doc.DataTemplate.DataSources.Add("ds", data);
  1. Invoke the Process method to replace the tags with data while iterating over all data items.
//Process the template
doc.DataTemplate.Process();
  1. Invoke the Save method to save the processed data-bound document.
//Save the generated invoice document
doc.Save("InvoiceDemo.docx");

This is how the final Invoice document looks:

Generated Word .docx invoice using C# Word API

Be sure to download the sample implementing the Invoice generation scenario using the Report Templates feature of DsWord API or view our online demo!

Download a Free Trial of Document Solutions for Word Today!


comments powered by Disqus