Skip to main content Skip to footer

Introducing Report Templates to Generate Data-Bound Word Documents in C#

As the digital age expands, safely documenting all types of content becomes more important. Digital expansion brings with it a need for simplification. It should be easy to store and create documents that follow regulations and keep private information secure.

In the past, creating these documents involved a template, filled out by hand, or manually on a computer. Files were then saved, or scanned to a digital format for storage. This is not necessarily a bad option for smaller organizations, but it does not scale well.

For enterprise companies such as large ebanks, insurance companies, or investment firms this type of work is time consuming and error prone. It makes more sense to create a structured document with all the fields in place. Then populate it with the actual data and generate the required document automatically by combining a template and data from a database . This structured document is generally referred to as a template and the process of attaching data to it is known as document automation.

As document automation becomes the norm, Developers need to choose a document automation system. The Word API from GrapeCity (GcWord) is an ideal system. With familiar syntax and robust tools, GcWord API for .NET makes implementing document automation quick and easy.

GcWord supports templates in Word. Documents are stored in a central location, then retrieved and populated on-demand. Using the GcWord API, generating data bound Word documents in a .NET application maximizes the effort used to design the layout of the document template. GcWord API for .NET is ideal for businesses that need hundreds or thousands of documents created at once.

This article details the document automation process using GcWord API for .NET. First we create templates in Word. Then we use an application to create and store important files with document automation.

Use Cases for Report Templates

A large regional travel agency needs your help automating the creation of customer itineraries. Although each of the agency’s customers has different information in their itinerary, the document format should remain consistent.

Customers love the accuracy and consistent layout of their itineraries. However, the agency’s business has increased significantly. As business increases the agency can’t keep up. They make errors translating travel plans from orders to itineraries. This causes confusion and angers customers.

Each itinerary must include customer information, flight and hotel booking details, and any activities planned for the vacation. What varies in each document is the customer data but the document structure remains the same. Help the company implement a process that creates accurate, consistent documents quickly. First, design a template with tags. Then process the document using external data, and save the document to the appropriate repository.

Follow the steps below to set up, code, and use this sample application:

Configure .NET Application

  1. Create a new C# .NET Core Console Application
  2. Install GrapeCity.Documents.Word package using Nuget package manager in the application
  3. Add a reference to GrapeCity.Documents.Word namespace in Program.cs file
  4. Get the sample itinerary template or create one from scratch based on the below image using GrapeCity.Documents.Word;

Template Design

Create the template using Word. Add the required structural elements such as list, tables, and tags using the Mustache syntax {{ and }}/ for the places that need filled with data.

Create the itinerary template by adding text labels, tables, and appropriate tags corresponding to each text label and in each table cell. Here is a snapshot of the Itinerary template created using Word:

Sample template GcWord

Template Processing in .NET

Create the template and save it in .docx format. Then follow these steps to process the template and generate the document (using C#):

  1. Initialize GcWordDocument instance and load the Itinerary template into it
GcWordDocument doc = new GcWordDocument();
doc.Load("Resources\\VacationItineraryTemplate.docx");
  1. Define the data source and add it to the template's data sources using the Add method of GcWord API
//Sample data for Itinerary template
var itineraryData = new[]
{
  new {
        clientName = "Mark Louis",
        clientPhoneNumber = "876-123-7546",
        ItineraryStartDate = "01/12/2019",
        ItineraryEndDate = "15/12/2019",
        flightDetails = new {
                              arrivalDate = "01/12/2019",
                              arrivalAirlineName = "British Airways",
                              arrivalTime = "08:00 AM",
                              arrivalTerminal = "T1",
                              departureDate = "15/12/2019",
                              departureAirlineName = "British Airways",
                              departureArrivalTime = "10:00 PM",
                              departureArrivalTerminal = "T2"
                            },
         hotelDetails = new {
                              checkinTime = "12:00 PM",
                              hotelName = "Awasi Patagonia",
                              hotelAddress = "12/13, Block Street",
                              hotelInclusion = "Cab Service",
                              checkOutTime = "11:00 AM"
                           },
         activities = new [] {
                   new { activityDate ="03/12/2019", activityDestination = "Jungle", activity = "Jungle Safari", remarks = "Make sure to carry woolens"},
                   new { activityDate = "07/12/2019", activityDestination = "Spa Room", activity = "Spa Session", remarks = "Morning would be the best time"},
                   new { activityDate = "11/12/2019", activityDestination = "Gym Area", activity = "Yoga Session", remarks = "Wear a comfortable attire"} }
      }
 };

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

The generated document looks like this:

Example of completed template itinerary created automatically by GcWord API for dot NET from GrapeCity

The example above uses an array data source and table structure element in the template. However, GcWord API for .NET supports a variety of data input sources including databases and flat files. Now that we have seen the API in action, let's dig into the details of creating a Word template to use with the GcWord API .

Template Language Syntax

A template document consists of Word structural elements such as paragraphs, lists, tables, and tags. These elements are replaced with actual data to automatically generate data bound documents. An example of one such document is presented in the section above. Creating a Word document template and adding structural elements to it requires elaboration. Let's dig into the details to better understand how defining tags and elements must work in order to successfully create a template for document automation.

The template tags are defined using the Mustache syntax "{{" and "}}" and can be categorized into the following two categories:

Value Tag

Value tags define placeholders for actual data in the template document. They are replaced by actual data from the data source when processing the template. It is possible to define a single value, or a list of values.

Basic syntax is listed below:
{{ds.value_path}[:formatter1(args1):formatter2(args2):..formatterN(argsN)]}

  1. ds: user-defined name of data source when adding the data source to the template using GcWord API
  2. value_path: full dot-delimited path from data source root to the property name
  3. formatterX (optional): one or more formatting options that process the current value of the tag and change the data representation

Range Tag

When performing data binding, the data source is generally a collection of objects. All of these objects must be rendered to create a meaningful document.

Therefore, a value tag added to the template document must be placed multiple times to render each object in the collection. However, this is not the most efficient way to create a template. There are likely times when a list contains more or less items. Best to plan for flexibility.

Range tags provide flexibility. A range tag is basically one or more value tags enclosed in an open tag and a closed tag. It defines the area in the template layout where data is likely to be repeated and renders all objects associated with the section. If the open and closed tags are not incorporated in the template document, it can lead to unexpected results.

  1. {{#ds}} or {{#ds.enumerable_path}}: start of a range block
  2. {{/ds}} or {{/ds.enumerable_path}}: end of a range block

Considering 'ds' is the user-defined name of a data source when adding the data source to the template using GcWord API, enumerable_path is the full dot-delimited path from data source root to the property name.

Short Format Without Datasource

As depicted in the value tag and range tag syntax, when accessing a property or field in the datasource using the dot delimited path, it should begin with the user define datasource name. But this is required only when multiple datasources are associated with the template. When attaching to a single datasource, there is no need to have the datasource name as part of the tag.

For example {{ds.cities.name}} can be referred as {{cities.name}} in short format (but only when other datasources are not present).

For more details refer to the documentation.

The remaining sections of this document make use of these tags to generate different report templates and process them to get the expected documents.

Important Note: Each example below is assuming a single datasource, therefore the short format (as described above) is being used for all template tags.

Features

Batch process multiple rows of data into separate Word (.docx) documents in .NET

For the first example (above), a single customer was processed. However, in the real-world, it is likely there would be multiple customers who needed itinerary's produced. To manage this, the GcWord .NET Word API supports batch processing and generates separate documents for multiple rows of data. This feature is implemented by invoking the BatchProcess method over the report template.

Assuming, we have data for three customers, we can replace the call to Process method with a call to the BatchProcess method and get the desired results of generating three documents one for each customer. Here is the C# sample code:

// produces a document for each root item in the data source collection
int i = 0;
doc.DataTemplate.BatchProcess(() =>
{
   doc.Save($"sample-result-{++i}.docx");
});

Here is quick look at the generated documents:

images depicting the result of batch processing while using the GcWord dotnet Word API from GrapeCity

DataSource Support

The examples up to now have all had static, "in code" data sources. However, the GcWord .NET Word API lets you bind data to Word templates from any data source if the data can be placed in the following objects in code:

  • DataSet
  • DataTable
  • IEnumerable objects Refer to the table below to understand what type of template structure needs to be defined for each type of datasource and what will be the result after processing the template:
Sample Data Template Syntax Word Template Snapshot Data binding results

DataSetData.txt
[Table name].[Column name] word template data set data binding data set
DataTableData.txt [Column name] word template data table data binding data table
ObjectArrayData.txt [Field name] word template object array data binding object array
ObjectListData.txt [Field name] word template object list data binding object list

Help

Lists

Lists are created dynamically by using datasources along with standard Word list types (as noted below). The GcWord .NET Word API has intelligence built in to know, based on the bullet type selected in the template, that it needs to iterate through the datasource referenced in the template to create the list. See the table below to for a visual example of how this works. In other words, there is no need to iterate within code to create separate bullet points in a Word document. The GcWord API along with the template language understands this to be true since the datasource is part of a bulleted list. The different types of lists supported by GcWord templates are:

  • Bullet Lists
  • Numbered Lists
  • Multilevel Lists

Refer to the table below to understand what type of template structure needs to be defined for each type of list and what will be the result after processing the template:

Sample Data Word Template Snapshot Data binding results
BulletListData.txt
  • {{#ds}}{{Category}}{{/ds}}
  • Exotic Liquids
  • Tokyo Traders
  • Specialty Biscuits, Ltd.
NumberedListData.txt
  1. {{#ds}}{{Category}}{{/ds}}
  1. Exotic Liquids
  2. Tokyo Traders
  3. Specialty Biscuits, Ltd.
MultilevelListData.txt
  1. {{#ds}}{{Supplier}} - {{Category}}
    • {{Products.name}}{{/ds}}
  1. Exotic Liquids - Beverages
    • Chai
    • Chang
    • Aniseed Syrup
  2. Tokyo Traders - Meat/Poultry
    • Ikura
    • Mishi Kobe Niku
  3. Specialty Biscuits, Ltd. - Confections
    • Treatime Chocolate Biscuits
    • Sir Rodney's Marmalade
    • Sir Rodney's Scones

The examples above use array data source, you can use datatable or other sources in a similar manner.

Help | Demo

Tables

To use a template for generating a table using data binding create a new Word document, add a table with the required number of columns and two rows (if you want to specify the header row information), or a single row if you don't need headers. Choose an appropriate table style to render the header row and banded rows. If you are rendering the header row, you should specify tags in each cell of the second row to bind each column to specific property or field in the datasource. The template engine is smart enough to understand the datasource object structure and iterate over the collection to generate table with multiple rows.

Here is a quick example of creating a table using an array data source

Sample Data Template Syntax Word Template Snapshot Data binding results
TableData.txt [Field name] word template table data data binding table data

Repeat multiple table rows

Besides the ability to render one row per each source object in the datasource, GcWord .NET Word API can also render multiple table rows for each source object, then repeat this structure for the remaining objects.

Here is an example for rending Order information in two rows, with the first row displaying the Supplier and Category fields, while the second row lists the products supplied from the same source object.

Sample Data Template Syntax Word Template Snapshot Data binding results
RepeatRowData.txt [Field name] word template repeat row data binding repeat row

Help | Demo

Loops and Nesting Data

All the previous examples have been simple by design. However, the GcWord API template engine is much more powerful and can generate complex templated documents, including nested collections of data from a datasoure. For Example, consider generating monthly order summaries for each customer. Each summary would need to elaborate on the orders placed to include data like date of the order, products ordered, and which suppliers were involved in fulfilling the order.

The table below shows an example of the nested datasource and template for generating the report, followed by an example of a data bound report generated for one customer:

Sample Data Word Template Snapshot Data binding results
LoopsNestingData.txt word template loops nesting data binding loops nesting

Help | Demo

Conditionally hide blocks of data

The template document structure containing tags, where datasource objects are populated is call a range, such as a table row or list of items. Each table row or list item generated after repeating the template range and populating the tags with data is referred to as a block. The template engine provides a way to format these blocks to hide them based on specific criteria. The formatting is applied on a tag in the range by passing a parameter to the formatter. The parameter defines the value comparison which the engine uses to decide whether the block is hidden or visible. If the current value of a tag is equal to a value of the parameter, then the engine finds the closest collapsible block and hides it, such as a table row, a list item or an arbitrary section.

Here is a list of all the hide formatters and their short version supported by GcWord .NET Word API template engine, you can use either of these when creating a template.

Hide Formatter Short Version
  • hide-block-if-equals()
  • hide-block-if-greater()
  • hide-block-if-less()
  • hide-block-if-contains()
  • hide-block-if-starts()
  • hide-block-if-ends()
  • hide-block-if-empty()
  • hide-block-if-not-equals()
  • hide-block-if-not-contains()
  • hide-block-if-not-starts()
  • hide-block-if-not-ends()
  • hbi-equals()
  • hbi-greater()
  • hbi-less()
  • hbi-contains()
  • hbi-starts()
  • hbi-ends()
  • hbi-empty()
  • hbi-not-equals()
  • hbi-not-contains()
  • hbi-not-starts()
  • hbi-not-ends()

The table below has examples for hiding each of type of block using a specific hide formatter to help understand the feature better:

  Table Row List Item Arbitrary Section
Sample Data When listing products of different categories in a table, we would like to hide table rows displaying products from a specific category such as Beverages. Here is the sample data: HideRowList.txt When listing products of different categories, we would like to hide list items displaying products from a specific category such as Beverages. Here is the sample data: HideRowList.txt When describing products of different categories in a document using a border less table cell, we would like to hide the section occurrence displaying products from a specific category such as Beverages. Here is the sample data: HideDocSection.txt
Template Snapshot table row template snapshot
  • {{#ds}}{{Category}:hide-block-if-equals{Beverages}} - {{ProductId}} - {{ProductName}} - {{Price}}{{/ds}}
{{#ds}}{{Category}}
{{Products}:hide-block-if-empty()}
ProductId: {{Products.ProductId}}
ProductName: {{Products.ProductName}}
ProductPrice: {{Products.ProductPrice}}
{{/Products}}{{/ds}}
Data binding results table row data binding
  • Condiments - 10000456 - Aniseed Syrup - 30
  • Condiments - 10000321 - Northwoods Cranberry Sauce - 60
  • Seafood - 10000654 - Ikura - 70
  • Seafood - 10000987 - Knobu - 40
  • Condiments - 10000546 - Grandma's Boysenberry Spread - 80
Condiments

Product Id: 10000456
Product Name: Aniseed Syrup
Product Price: 30
Condiments

Product Id: 10000321
Product Name: Northwoods Cranberry Sauce
Product Price: 60
Condiments

Product Id: 10000654
Product Name: Ikura
Product Price: 70
Seafood

Product Id: 10000987
Product Name: Knobu
Product Price: 40
Seafood

Product Id: 10000546
Product Name: Grandma's Boysenberry Spread
Product Price: 80
Condiments

Help

Data Formatters

Within the GcWord .NET Word API, formatting of text and overall document controls are done through what are called "Formatters". These formatters are used to format a tag value when the tag is populated with data. For example, converting a string to upper or lower case, formatting the date to a short string etc.

The tables below list different types of formatters supported by GcWord template engine and portrays an example of each:

Value Formatters String Formatters Date Formatters Array Formatters
  • format()
  • format(val)
  • substring(index)
  • substring(index,length)
  • join(separator)
  • bool(yes,no,maybe)
  • empty(val)
  • length
  • tolower
  • toupper
  • trim
  • gethashcode
  • date
  • day
  • dayofweek
  • dayofyear
  • hour
  • millisecond
  • minute
  • month
  • second
  • ticks
  • timeofday
  • year
  • add
  • subtract
  • length
Time Formatters Image and Link Formatters Collection Formatters
  • gethashcode
  • tolongdatestring
  • tolongtimestring
  • tooadate
  • toshortdatestring
  • toshorttimestring
  • tofiletime
  • tofiletimeutc
  • image(keepratio | fitheight | fitwidth | fitsize | fitsizelim)
  • image(width,height)
  • count

Here are a few examples showcasing the use of above formatters:

Sample Data Template Structure Formatting result
{ CName= "Villy Smith"} {{CName}:substring(6)} Smith
{ cities = new[] {name = "China"}}; {{cities.name}:toupper()} CHINA

For more details on these formatters please refer to the documentation.

Chained formatters

The formatters can be chained and applied to a tag value, where in the result of one formatter might be the input for another formatter. For example, the following chained formatter will hide all records in a list or table, where UnitPrice is less than 30, formatting the included values as currency:

\{{UnitPrice}:hbi-less(30):format(C)} 
or 
\{{UnitPrice}:hide-block-if-less(30):format(C)}

Help | Demo

Word Documents (.docx) you can generate using GcWord templates in .NET

With the template engine in GcWord .NET Word API, the sky is the limit with what can be created. Look at the examples below of documents created by the GcWord templating process:

Lease Agreement

Lease Agreement Template example by GrapeCity

View Demo

Consulting Agreement

Consulting Agreement Template example by GrapeCity

View Demo

Rental Agreement

Rental Agreement template example by GrapeCity

View Demo

Employment Contract

employment Contract Agreement Example by GrapeCity

View Demo

Happy coding, and remember you can use our online demos and documentation or detailed implementation of these scenarios in a .NET application. Feel free to experiment with this new feature and send us your feedback!


Manpreet Kaur - Senior Software Engineer

Manpreet Kaur

Senior Software Engineer
comments powered by Disqus