C#/Java Dynamic Generation of Electronic Invoice

Posted by pillarofautumn on Fri, 23 Aug 2019 06:45:49 +0200

Electronic invoice is the product of e-commerce era. PDF invoice is one of the most common electronic invoices. In this article, I will share a free C # solution for dynamically generating PDF electronic invoices, and attach a Java solution at the end of the article.

Typical invoices contain the names and addresses of customers and suppliers, invoice numbers, descriptions of purchases, payment amounts, etc. To generate invoices dynamically, I used MS Word to create a template in which I designed most of the content and document style I wanted to present, then replaced the text with code and inserted new content, and finally saved it as a PDF document. Using code to manipulate parts of a Word document requires the use of Free version of Spire. Doc for. NET 7.1.

Creating Templates
As shown in Figure 1, the invoice template consists of two tables. Table 1 is used to display information of buyers and sellers and order information, and Table 2 is used to display a list of products or services provided by sellers to buyers. What we need to do is replace the text in Table 1 that begins with # and fill the customer's shopping list into the second table.

In order to automatically calculate the total amount, formula fields need to be added to some cells. For example, cell E2 contains a formula "= C2*D2", which calculates the total price of the goods in cell B2. When a buyer purchases more than one item, we need to add more rows to the table and update the formulas of some cells dynamically.

Figure 1 Invoice template

How to Replace Text
Spire.Doc has an IBodyRegion. Replace (string given, string replaced, bool case Sensitive, bool wholeWord) method that can be used to replace the specified string in the document. For example, by replacing "orderNum" with "2516595027", we can directly use the following code, in which doc is a Document object.

doc.Replace("#orderNum", "2516595027", true, true);

How to update Table 2

Now let's see how to add rows to existing tables, how to populate data into tables, and how to update formulas dynamically. To make the logic clearer, I created three methods and produced Figure 2 to show their specific meanings and their invocation relationships.

Figure 2 The meaning and invocation relationship of the custom method

Next, take a look at the code snippets of these three methods:

1. AddRows()

This method actually duplicates the second row of the existing table and adds the duplicate rows to the bottom of the second row in turn. The new line inherits the cell format, font style and formula of the second line. Therefore, we need to update the formulas in the new rows in turn, and the following formulas as the number of rows increases.

private static void AddRows(Table table, int rowNum)
{
 
    for (int i = 0; i < rowNum; i++)
    {
        //Add the second row of the specified number of replicated rows to the bottom of the second row in turn
        table.Rows.Insert(2 + i, table.Rows[1].Clone());
 
        //Update the formula of the cell corresponding to the "amount"
        foreach (var item in table.Rows[2 + i].Cells[4].Paragraphs[0].ChildObjects)
        {
            if (item is Field)
            {
                Field field = item as Field;
                field.Code = string.Format("=C{0}*D{0}\\# \"0.00\"", 3 + i);
            }
            break;
        }
 
    }
 
    //Update the formula of the cell corresponding to the "discount amount"
    foreach (var item in table.Rows[4 + rowNum].Cells[4].Paragraphs[0].ChildObjects)
    {
        if (item is Field)
        {
            Field field = item as Field;
            field.Code = string.Format("=E{0}*0.05\\# \"0.00\"", 3 + rowNum);
        }
        break;
    }
 
    //Update the formula for the cell corresponding to the "total"
    foreach (var item in table.Rows[5 + rowNum].Cells[4].Paragraphs[0].ChildObjects)
    {
        if (item is Field)
        {
            Field field = item as Field;
            field.Code = string.Format("=E{0}-E{1}\\# \"¥#,##0.00\"", 3 + rowNum, 5 + rowNum);
        }
        break;
    }
 
}

 

 2. FillTableWithData()

This method is only used to write sting [][] type data from the second row of the table.

private static void FillTableWithData(Table table, string[][] data)
 {
     for (int r = 0; r < data.Length; r++)
     {
         for (int c = 0; c < data[r].Length; c++)
         {
             //Write data to the table from the second row of the table
             table.Rows[r + 1].Cells[c].Paragraphs[0].Text = data[r][c];
         }
     }
 }

 

3. WriteDataToDocument()

Since the invoice template already has one line (the second line) for displaying an item, we need to determine whether more lines need to be added. If the customer purchases only one item, the template document can contain the product information and output the results; otherwise, we need to add rows to accommodate more items and update the formula dynamically to get the correct total amount.

private static void WriteDataToDocument(Document doc, string[][] purhcaseData)
{
    //Obtain Word The second table in the template
    Table table = doc.Sections[0].Tables[1] as Table;
 
    //If more than one item is purchased, add purhcaseData.Length - 1 Row
    if (purhcaseData.Length > 1)
    {
        AddRows(table, purhcaseData.Length - 1);
    }
 
    //Fill in the purchase data into the form
    FillTableWithData(table, purhcaseData);
}

One of the parameters of the WriteDataToDocument() method is the sting [][] object, which stores the customer's purchase information. Each element of the object is an array of strings, which can be set as follows:

string[] product = new string[] { "1023", "HUAWEI P30 Pro (8G+128G)A phone fit all kinds of networks", "1", "4288" };

The length of string [][] is the number of items in the commodity. If the length is greater than 1, a new line [length - 1] needs to be added.

Generation of invoices

The following is the code in the Main function for generating PDF invoices.

using Spire.Doc;
using Spire.Doc.Fields;
 
namespace CreatePdfInvoice
{
    class Program
    {
        static void Main(string[] args)
        {
            //Load Word Template document
            Document doc = new Document();
            doc.LoadFromFile("Invoice-Template.docx");
 
            //Replace the document with#Beginning Text
            doc.Replace("#customerName", "Wei Wei", true, true);
            doc.Replace("#contactNum", "13601234567", true, true);
            doc.Replace("#shippingAdd", "Unit 3, Unit 2, Building 1, Happy Community, Haidian District, Beijing", true, true);
            doc.Replace("#orderDate", "2019-05-30", true, true);
            doc.Replace("#orderNum", "2516595027", true, true);
 
            //Define customer purchase data
            string[][] purchaseData = {
 
                                  new string[]{"1023","HUAWEI P30 Pro (8G+128G)A phone fit all kinds of networks","1","4288"},
                                  new string[]{"1429","HUAWEI Watch GT Sports Edition","2","1288"},
                                  new string[]{"1268","Huawei Wireless Headphones FreeBuds 2Pro","2","799"},
                                  new string[]{"1281","HUAWEI MateBook 14 (i5 8G 512G)","1","5999"},
                              };
 
            //Write the purchase data to the second table of the template document
            WriteDataToDocument(doc, purchaseData);
 
            //Update domain
            doc.IsUpdateFields = true;
 
            //Save as PDF Format document
            doc.SaveToFile("Invoice.pdf", FileFormat.PDF);
            System.Diagnostics.Process.Start("Invoice.pdf");
        }
    }
}

The resulting document is as follows:

Figure 3 PDF invoices for more than one item

 

If you enter only one line of purchase data, you will get the result document as shown in Figure 4.

string[][] purchaseData = {new string[]{"1023","HUAWEI P30 Pro (8G+128G)A phone fit all kinds of networks","1","4288"},};

Figure 4 Single item PDF invoice

 

Engineering Download

C# Project (including DLL and template documents) https://pan.baidu.com/s/1jCI1J5J08hGReGIe0ZzOsA  Extraction code: zp6n
Java engineering (including Jar and template documents)  https://pan.baidu.com/s/1bthB3gnd0B0JQYzwZDWmVA   Extraction code: ciey

 




 

 

Note:

The free version of Spire.Doc can load and generate no more than 500 paragraphs or 25 tables of Word documents. Only the first three pages are supported when the Word documents are saved as PDF. Most invoices have only one or two pages, so this scheme is applicable in most cases.


--------
Copyright Statement: This is an original article by CSDN blogger "ssw_jack".
Original link: https://blog.csdn.net/ssw_jack/article/details/91379486

Topics: C# Java