Search the Site

Sponsors

bottom corner

Use Java to generate Word document from XML template

This note shows how we can use simple Java code to generate Word documents based on a template.

This page is filed under keyword(s): java.

To accomplish this, we first need a template. I already created a template for the purpose of this sample, which resembles a very simple invoice; please download word_template.xml file should you wish to follow along. In this file, you will see that there are many fields enclosed by "##" markers. For example:

...
<w:r>
<w:t>Invoice Number: ##INVOICENUMBER##</w:t>
</w:r>
...

The "##" markers signify places where the program will substitute in values we will provide when we call the Java program. The Java program code is below, with the main() method being an example we can run. The example shown by main() sets values for each required key in a hashtable, as well as setting up the location and file name of the template and output XML files. When we wish to run this example, place the template file in C:\ and let it go! The output file should look like the content of word_output.xml.

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.Hashtable;

/**
 * This code takes in a hashtable containing key fields required to populate
 * values into a Word template (XML) and output a Word document (also XML).
 * Template should contain ##KEY## fields for each hashtable key with same
 * name (without the ##s); the ##KEY## will be replaced by the value.
 * The main() method is written as an example.
 * Modified from code found at http://dinoch.dyndns.org:7070/WordML/AboutWordML.jsp
 * @author C. Peter Chen of http://dev-notes.com
 * @date 20080327
 */

public class msWordUtils {
	
	/**
	 * This main() method is used for demonstration purposes only.
	 * @param args
	 * @author C. Peter Chen of http://dev-notes.com
	 * @date 20080327
	 */
	public static void main(String[] args) {
		String templatePathFilename = "c:\\word_template.xml";
		String outputPathFilename = "c:\\word_output.xml";

		Hashtable ht = new Hashtable();
		ht.put("INVOICENUMBER","384123");
		ht.put("CUSTOMERNAME","Some Company, LLC.");
		ht.put("ITEMNAME1","Coffee");
		ht.put("UNITPRICE1","1.50");
		ht.put("QTY1","1");
		ht.put("LINETOTAL1","1.50");
		ht.put("ITEMNAME2","Donut");
		ht.put("UNITPRICE2","1.00");
		ht.put("QTY2","2");
		ht.put("LINETOTAL2","2.00");
		ht.put("INVOICETOTAL","3.50");
		ht.put("DUEDATE","4/1/2008");
		
		generateWordDoc(ht, templatePathFilename, outputPathFilename);
	}
	
	/**
	 * 
	 * @param ht
	 * @param templatePathFileName
	 * @param outputPathFileName
	 * @author C. Peter Chen of http://dev-notes.com
	 * @date 20080327
	 */
	public static void generateWordDoc(Hashtable ht, String templatePathFilename, String outputPathFilename) {	
		try {
			BufferedReader reader = new BufferedReader(new FileReader(templatePathFilename));
			
			File destination = new File(outputPathFilename);
			BufferedWriter writer = new BufferedWriter(new FileWriter(destination));
			
			String thisLine;
			int i = 0;
			
			while ((thisLine = reader.readLine()) != null) {
				System.out.println(i);
				
				for (java.util.Enumeration e = ht.keys(); e.hasMoreElements();) {
					String name = (String) e.nextElement();
					String value = ht.get(name).toString();
					// Use this if we need to XML-encode the string in hashtable value...
					thisLine = thisLine.replaceAll("##" + name.toUpperCase() + "##", XmlEncode(value));
					// ... or this if we do not need to do XML-encode.
					//thisLine= thisLine.replaceAll("##" + name.toUpperCase() + "##", value);
			    }
				writer.write(thisLine);
				writer.newLine();
				i++;
			}
			writer.close();
			System.out.println("done");
		}
		catch (Exception e) {
			System.out.println("exception!=" + e);
		}
	}

	/**
	 * Encodes regular text to XML.
	 * @param text
	 * @return string
	 * @author http://dinoch.dyndns.org:7070/WordML/AboutWordML.jsp
	 * @date 20050328
	 */
	private static String XmlEncode(String text) {
		int[] charsRequiringEncoding = {38, 60, 62, 34, 61, 39};
		for(int i = 0; i < charsRequiringEncoding.length - 1; i++) {
			text = text.replaceAll(String.valueOf((char)charsRequiringEncoding[i]),"&#"+charsRequiringEncoding[i]+";");
		}
		return text; 
	}
	
}

As noted in the JavaDoc, much of the basis for this code came from http://dinoch.dyndns.org:7070/WordML/AboutWordML.jsp. Much thanks to the unnamed author!

Did you find this page useful? Please consider browsing other articles or subscribing to the RSS feed to keep up with latest.

This page is filed under keyword(s): java.
Author: C. Peter Chen
Last updated: 27 Mar 2008

bottom corner