In this document we will learn how to read, write, and manage Microsoft Word documents using the DBStudio JavaScript libraries.

1 Introduction

To create an Excel workbook JavaScript object we use the following statement.

Copy
var doc = new Ax.ms.Word("Document1");

The JavaScript object doc is a new instanceof of DBStudio Word object witch is a wrapper of Document POI class. It contains methods to load, write and manipulate an Word Documents.

2 Simple document

Let's see how to generate a simple Word document with a few paragraphs and an external image.

Copy
<script type="js">
    var document = new Ax.ms.Word();
    
    var paragraph1 = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";
    var paragraph2 = "Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of 'de Finibus Bonorum et Malorum' (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, 'Lorem ipsum dolor sit amet..', comes from a line in section 1.10.32.";
    var paragraph3 = "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout. The point of using Lorem Ipsum is that it has a more-or-less normal distribution of letters, as opposed to using 'Content here, content here', making it look like readable English. Many desktop publishing packages and web page editors now use Lorem Ipsum as their default model text, and a search for 'lorem ipsum' will uncover many web sites still in their infancy. Various versions have evolved over the years, sometimes by accident, sometimes on purpose (injected humour and the like).";
    
    var title = document.createParagraph();
    title.setAlignment(Ax.ms.Word.ParagraphAlignment.CENTER);
    var titleRun = title.createRun();
    titleRun.setText("Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...");
    titleRun.setColor("009933");
    titleRun.setBold(true);
    titleRun.setFontFamily("Courier");
    titleRun.setFontSize(20);
    
    var subTitle = document.createParagraph();
    subTitle.setAlignment(Ax.ms.Word.ParagraphAlignment.CENTER);
    var subTitleRun = subTitle.createRun();
    subTitleRun.setText("There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain...");
    subTitleRun.setColor("00CC44");
    subTitleRun.setFontFamily("Courier");
    subTitleRun.setFontSize(16);
    subTitleRun.setTextPosition(20);
    subTitleRun.setUnderline(Ax.ms.Word.UnderlinePatterns.DOT_DOT_DASH);
    
    var image = document.createParagraph();
    image.setAlignment(Ax.ms.Word.ParagraphAlignment.CENTER);
    imageRun = image.createRun();
    imageRun.setTextPosition(20);
    imageRun.addPicture(
       "http://icons.iconarchive.com/icons/iconstoc/ms-office-2013/128/word-icon.png",
       Ax.ms.Word.toEMU(50), 
       Ax.ms.Word.toEMU(50)
     );
    
    var sectionTitle = document.createParagraph();
    var sectionTRun = sectionTitle.createRun();
    sectionTRun.setText("What is Lorem Ipsum?\n");
    sectionTRun.setColor("00CC44");
    sectionTRun.setBold(true);
    sectionTRun.setFontFamily("Courier");
    document.print("");
    
    var para1 = document.createParagraph();
    para1.setAlignment(Ax.ms.Word.ParagraphAlignment.BOTH);
    var para1Run = para1.createRun();
    para1Run.setText(paragraph1);
    document.print("");
    
    var para2 = document.createParagraph();
    para2.setAlignment(Ax.ms.Word.ParagraphAlignment.RIGHT);
    var para2Run = para2.createRun();
    para2Run.setText(paragraph2);
    para2Run.setItalic(true);
    document.print("");
    
    var para3 = document.createParagraph();
    para3.setAlignment(Ax.ms.Word.ParagraphAlignment.LEFT);
    var para3Run = para3.createRun();
    para3Run.setText(paragraph3);
    document.print("");
    
    return document.toBlob();
</script>

3 Working with tables

Let's see how to generate a table using a simple loop.

Copy
<script>
    var document = new Ax.ms.Word("name");
    document.print("This is a document with tables");
    
    var table = document.createTable();
    for (var r = 0; r < 10; r++) {
       var row = table.getRow(r);
       for (var c = 0; c < 6; c++) {
       		row.getCell(c).setText("Cell (r=" + r + ",c="+ c + ")");
       }
    }
    
    return document.toBlob();
</script>

4 Working with database

Now, let's see how to interact with a database. The following example, retrieves data from a system database table to produce a word document.

Copy
<script type='js'>
    var document = new Ax.ms.Word("name");
    
    document.print("This is a document with tables");
    var table = document.createTable(Ax.db.executeQuery(
        "SELECT tabname, tabtype, nrows, created FROM systables WHERE tabid < 10"
    ));
    
    // set row height; units = twentieth of a point, 360 = 0.25"
    table.getRow(0).setHeight(360);
    table.getRow(0).getCell(0).setVertialAlignment("bottom");
    table.getRow(0).getCell(0).setHorizontalAlignment("center");
    table.getRow(0).getCell(0).setFillColor("F44336");
    table.getRow(0).getCell(0).setTextColor("FFFFFF");
    
    return document.toBlob();
</script>

TO DO

This section is incomplete and will be concluded as soon as possible.

5 Reading Word documents

5.1 Reading Complete Text

The class Word has many methods defined to read and extract .docx file contents. getText() can be used to read all the texts in a .docx word document.

Copy
...

6 Read Each Paragraph

Among the many methods defined in XWPFDocument class, we can use getParagraphs() to read a .docx word document paragraph wise.This method returns a list of all the paragraphs(XWPFParagraph) of a word document. Again the XWPFParagraph has many utils method defined to extract information related to any paragraph such as text alignment, style associated with the paragrpahs.

To have more control over the text reading of a word document,each paragraph is again divided into multiple runs. Run defines a region of text with a common set of properties. Following is an example to read paragraphs from a .docx word document.

Copy
...

7 Using templates

You can use a Word document as a template, load it and update it with data from JSON variables. Let's see some examples.

7.1 Invoice template

The following word template can be used for produce an invoice.

7.1.1 Source from JSON

You can use a JSON object as data source for template processing.

Copy
<script>
    var document = Ax.ms.Word.load("https://bitbucket.org/deister/axional-docs-resources/raw/master/Word/template_invoice1.docx");
    document.setName("Invoice 432");

    var json = {
    	invoice : {
    	"invoiceNumber": "432",
    	"total": 1234.94,
    	"date": "2018-11-24"
    	},
    
    	company : {
        "name": "Fakery Ltd. (Since 1988)",
        "email": "sales@fackery.com",
        "address": "610 5th Ave, New York NY 10020 USA",
        "phone": "212-555-5000"
    	},
    		
    	items = [
        {
            "name": "Monitor cover",
            "price": 59,
            "quantity": 10,
            "cost": 590
        },
        {
            "name": "Laptop bag",
            "price": 12.44,
            "quantity": 1,
            "cost": 12.44
        },
        {
            "name": "Fridge",
            "price": 4219.99,
            "quantity": 1,
            "cost": 4219.99
        },
        {
            "name": "Microwave",
            "price": 99.99,
            "quantity": 5,
            "cost": 499.95
        },
        {
            "name": "Pen",
            "price": 4.15,
            "quantity": 100,
            "cost": 415
        }
    ]
    };
    
    // Update template with JSON
    document.update(json);
    
    return document.toBlob();
</script>

7.1.2 Source from database

Generally, we will have data in a database. How can we take data from database and perform template update as in previous example ? The solution is use ResultSet to JSON tranform. Let's see how to do it.

Create table samples

First, we will create som support tables to emulate the invoice.

Copy
create table if not exists invoice(
   invoiceNumber INTEGER not null,
   invocieDate DATE not null,
   company_id INTEGER not null,
   total DECIMAL(12, 2) not null
);


create table if not exists company(
   company_id INTEGER not null,
   name VARCHAR(40) not null,
   email VARCHAR(40) not null,
   address VARCHAR(40) not null,
   phone VARCHAR(40) not null
);

create table if not exists items(
   invoiceNumber INTEGER,
   seqno INTEGER not null,
   name VARCHAR(40) not null,
   price DECIMAL(12, 2) not null,
   quantity INTEGER not null,
   cost DECIMAL(12, 2) not null
);


delete from invoice;
delete from company;
delete from items;
INSERT INTO invoice VALUES(432, MDY(1,31,2019), 100, 1234.94);
INSERT INTO company VALUES(100, "Fakery Ltd. (Since 1988)", "sales@fackery.com", "610 5th Ave, New York NY 10020 USA", "212-555-5000");
INSERT INTO items   VALUES(432, 1, "Monitor cover",       59,  10,     590);
INSERT INTO items   VALUES(432, 2, "Laptop bag",       12.44,   1,   12.44);
INSERT INTO items   VALUES(432, 3, "Fridge",         4219.99,   1, 4219.99);
INSERT INTO items   VALUES(432, 4, "Microwave",        99.99,   5,  499.95);
INSERT INTO items   VALUES(432, 5, "Pen",               4.15, 100,     415);

Genating JSON

Now, we can create a JSON object from ResultSet data and perform the update in a single operation. (You can also perform a single update for each JSON key).

Notice that database will return columns according it's case implementation. For example, Informix will return lower case while Oracle will return uppercase. As in our template example, invoiceNumber has mixed case it will fail substitution.

Copy
<script>
    var document = Ax.ms.Word.load("https://bitbucket.org/deister/axional-docs-resources/raw/master/Word/template_invoice1.docx");
    document.setName("Invoice 432");

    var number = 432;
    
    var json = {
        invoice : Ax.db.executeQuery("SELECT invoiceNumber, invocieDate as date, total FROM invoice WHERE invoiceNumber = ?", number).toOne(),
        company : Ax.db.executeQuery("SELECT * FROM company where company_id = (SELECT company_id FROM invoice WHERE invoiceNumber = ?)", number).toOne(),
        items   : Ax.db.executeQuery("SELECT * FROM items WHERE invoiceNumber = ? ORDER BY seqno", number).toArray()
    }
    
    // PATCH: fix case sensitive invoiceNumber in JSON
    // json.invoice.invoiceNumber = json.invoice.invoicenumber;
    
    // Show generated JSON in console
    console.log(json);
    
    // Update template with JSON
    document.update(json);
    
    return document.toBlob();
</script>
{
  "invoice": {
    "date": "2019-01-31",
    "total": 1234.94,
    "invoicenumber": 432
  },
  "company": {
    "address": "610 5th Ave, New York NY 10020 USA",
    "company_id": 100,
    "phone": "212-555-5000",
    "name": "Fakery Ltd. (Since 1988)",
    "email": "sales@fackery.com"
  },
  "items": [
    {
      "quantity": 10,
      "cost": 590.00,
      "seqno": 1,
      "price": 59.00,
      "name": "Monitor cover",
      "invoicenumber": 432
    },
    {
      "quantity": 1,
      "cost": 12.44,
      "seqno": 2,
      "price": 12.44,
      "name": "Laptop bag",
      "invoicenumber": 432
    },
    {
      "quantity": 1,
      "cost": 4219.99,
      "seqno": 3,
      "price": 4219.99,
      "name": "Fridge",
      "invoicenumber": 432
    },
    {
      "quantity": 5,
      "cost": 499.95,
      "seqno": 4,
      "price": 99.99,
      "name": "Microwave",
      "invoicenumber": 432
    },
    {
      "quantity": 100,
      "cost": 415.00,
      "seqno": 5,
      "price": 4.15,
      "name": "Pen",
      "invoicenumber": 432
    }
  ]
}

7.2 Generated file