With R3 2021, we introduced a new functionality in the WordsProcessing library—replace text with other document elements.

This functionality allows you to easily find any text inside the document and replace it with a table, image, paragraph or just other text. All that functionality is encapsulated in a single method that has different overloads for maximum flexibility.

Today I will show how you can use the Replace Text functionality to generate a document representing an online purchase using a predefined template for the static data. Here is the template that we will be using in this post:

Template document to replace contents inside - with '[customer name]' and '[product table]' fields

As you can see, we will need to fill in the customer’s name and the products they purchased. Let’s see how this can be achieved.

Our first task is to import the template into a RadFlowDocument instance. I have it in DOCX format, thus I will use DocxFormatProvider:

RadFlowDocument document;
using (Stream input = File.OpenRead("template.docx"))
    DocxFormatProvider provider = new DocxFormatProvider();
    document = provider.Import(input);

Now it’s time to populate the data. In the following snippet, you can see the class that holds the information we need to populate. Bear in mind that, for the purpose of the example, I will be using static data, but you can populate it from anywhere—server, database, user input, etc.

public class Order
    public long ID { get; set; }
    public string CustomerName { get; set; }
    public List<ProductInfo> Products { get; set; }
    public static Order GetSampleOrder()
        List<ProductInfo> products = new List<ProductInfo>() {
            new ProductInfo() { Name = "Jeans", Price = 33.6M, Quantity = 1, ImagePath = "../../jeans.jpg" },
            new ProductInfo() { Name = "T-shirt", Price = 10.99M, Quantity = 1, ImagePath = "../../t-shirt.png" },
            new ProductInfo() { Name = "Socks", Price = 2.99M, Quantity = 3, ImagePath = "../../socks.jpg" },
            new ProductInfo() { Name = "Dress", Price = 52.99M, Quantity = 1, ImagePath = "../../dress.jpg" }
        Order order = new Order() { ID = 123456, CustomerName = "John", Products = products };
        return order;
public class ProductInfo
    public string Name { get; set; }
    public decimal Price { get; set; }
    public string ImagePath { get; set; }
    public int Quantity { get; set; }

Having the needed data, let’s start filling in our template. The first placeholder in the template is the customer name. It can be replaced in a pretty straightforward way:

Order order = Order.GetSampleOrder();
RadFlowDocumentEditor editor = new RadFlowDocumentEditor(document);
editor.ReplaceText("[customer name]", order.CustomerName);

To generate the table, we will need to iterate the products inside the order, extract their data and populate the table with it.

private Table CreateTable(RadFlowDocument document, Order order)
    Border border = new Border(1, BorderStyle.Single, new ThemableColor(Colors.LightGray));
    Table productsTable = new Table(document);
    productsTable.PreferredWidth = new TableWidthUnit(TableWidthUnitType.Percent, 100);
    productsTable.Borders = new TableBorders(border, border, border, border);
    // Generate the header row
    TableRow firstRow = productsTable.Rows.AddTableRow();
    AddCellWithTextContent(firstRow, "Product", true);
    AddCellWithTextContent(firstRow, "Image", true);
    AddCellWithTextContent(firstRow, "Quantity", true);
    AddCellWithTextContent(firstRow, "Price", true);
    // Generate row for each product
    foreach (var product in order.Products)
        TableRow row = productsTable.Rows.AddTableRow();
        this.AddCellWithTextContent(row, product.Name);
        TableCell cell = row.Cells.AddTableCell();
        cell.Borders = new TableCellBorders(null, border, null, border);
        cell.Padding = new Telerik.Windows.Documents.Primitives.Padding(5);
        ImageInline image = new ImageInline(document);
        image.Image.ImageSource = new ImageSource(File.ReadAllBytes(product.ImagePath), Path.GetExtension(product.ImagePath));
        image.Image.SetHeight(true, 40);
        Paragraph paragraph = cell.Blocks.AddParagraph();
        this.AddCellWithTextContent(row, product.Quantity.ToString());
        this.AddCellWithTextContent(row, product.Price.ToString("C"));
    return productsTable;
private void AddCellWithTextContent(TableRow row, string cellContent, bool isHeaderCell = false)
    TableCell cell = row.Cells.AddTableCell();
    ThemableColor lightGrayColor = new ThemableColor(Colors.LightGray);
    Border border = new Border(1, BorderStyle.Single, lightGrayColor);
    cell.Borders = new TableCellBorders(null, border, null, border);
    Run run = new Run(row.Document);
    run.Text = cellContent;
    if (isHeaderCell)
        run.FontWeight = FontWeights.Bold;
        cell.Shading.BackgroundColor = lightGrayColor;
    Paragraph paragraph = cell.Blocks.AddParagraph();

In addition to each specific product and its details, the total sum is also very important. That is why I decided to add a paragraph after the table to show that information as well. Here is how I generate that paragraph:

private Paragraph CreateParagraphTotal(RadFlowDocument document, Order order)
    decimal total = 0;
    foreach (var product in order.Products)
        total += product.Price * product.Quantity;
    Run run = new Run(document);
    run.FontWeight = FontWeights.Bold;
    run.FontSize = 20;
    run.Text = string.Format("Total: " + total.ToString("C") + "\t\t");
    Paragraph paragraph = new Paragraph(document);
    paragraph.Properties.TextAlignment.LocalValue = Alignment.Right;
    return paragraph;

The only thing left to do is to put the pieces together and replace the placeholder with the generated elements.

Table productsTable = this.CreateTable(document, order);
Paragraph paragraphTotal = this.CreateParagraphTotal(document, order);
List<BlockBase> blocksToInsert = new List<BlockBase>() { productsTable, paragraphTotal };
editor.ReplaceText("[products table]", blocksToInsert);

That’s all. Now the filled document is ready to be exported in one of the supported formats and sent to your customer. In the following picture, you can see what the document looks like:

The replaced content

I hope that you like the new functionality and that you will agree that this feature will make creating the documents your users need much easier.

Share Your Feedback

In case you still haven’t tried Telerik Document Processing, use the button below to obtain a trial version and explore all the features and possibilities of the libraries.

The libraries ship for free with all our web and desktop product bundles as well as with each individual product.

Download a Free Trial

If you are already familiar with the package, don’t forget that we are eager to hear your feedback. Feel free to drop us a comment below sharing your thoughts. Or, visit our Document Processing Libraries Feedback Portal to let us know if you have any suggestions or if you need any particular features.

About the Author

Tanya Dimitrova

Tanya Dimitrova is a Tech Support Engineer in the Telerik XAML Team. In her work her main responsibility is to assist clients to implement different scenarios using the document processing libraries and editors. She is passionate in finding new adventures and in her free time enjoys travelling, reading, swimming, dancing or just spending time with friends.

Related Posts


Comments are disabled in preview mode.