Templ4docx - Easy way to fill docx templates

A few days ago, I had to prepare Proof-of-Concept connected with filling templates prepared in docx. I took into account two libraries: org.docx4j and apache-poi. After a short play with them, the second library appears to be more suitable in my case. In order to compare these two libraries I’ve prepared two classes that perform the same operations:

  • reading docx file
  • finding all variables in docx file
  • replacing (filling) variables in the template
  • saving filled template
  Docx4j Apache-poi
Operation    
Reading 5599 ms 921,3 ms
Finding variables 205,8 ms 34,51 ms
Filling template 65,46 ms 129,6 ms
Saving template 99,38 ms 267,7 ms

Test docx template

Docx template

Doc4j test classes

Stopwatch stopwatch = Stopwatch.createStarted();
WordprocessingMLPackage wordMLPackage = WordprocessingMLPackage.load(new java.io.File(path));
MainDocumentPart documentPart = wordMLPackage.getMainDocumentPart();
stopwatch.stop();
System.out.println("READ FILE : " + stopwatch);

stopwatch = Stopwatch.createStarted();
List<String> tagValues = getTagValues(documentPart.getXML());
stopwatch.stop();
System.out.println("FIND VARIABLES : " + stopwatch);

stopwatch = Stopwatch.createStarted();
documentPart.variableReplace(mappings);
stopwatch.stop();
System.out.println("REPLACE VARIABLES : " + stopwatch);

stopwatch = Stopwatch.createStarted();
wordMLPackage.save(new java.io.File(outputPath));
stopwatch.stop();
System.out.println("SAVE DOCUMENT : " + stopwatch);

...

private static List<String> getTagValues(final String str) {
	final List<String> tagValues = new ArrayList<String>();
	Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");
	Matcher matcher = pattern.matcher(str);
	while (matcher.find()) {
		tagValues.add(matcher.group());
	}

	return tagValues;
}

Apache-POI test classes

Stopwatch stopwatch = Stopwatch.createStarted();
FileInputStream fis = new FileInputStream(path);
XWPFDocument xdoc = new XWPFDocument(OPCPackage.open(fis));
stopwatch.stop();
System.out.println("READ FILE : " + stopwatch);

XWPFWordExtractor extractor = new XWPFWordExtractor(xdoc);

stopwatch = Stopwatch.createStarted();
List<String> tags = getTagValues(extractor.getText());
stopwatch.stop();
System.out.println("FIND VARIABLES: " + stopwatch);

stopwatch = Stopwatch.createStarted();
replace(xdoc, mappings);
stopwatch.stop();
System.out.println("REPLACE VARIABLES: " + stopwatch);

stopwatch = Stopwatch.createStarted();
xdoc.write(new FileOutputStream(outputPath));
stopwatch.stop();
System.out.println("SAVE DOCUMENT: " + stopwatch);
extractor.close();

...

private List<String> getTagValues(final String str) {
	final List<String> tagValues = new ArrayList<String>();
	Pattern pattern = Pattern.compile("\\$\\{(.*?)\\}");
	Matcher matcher = pattern.matcher(str);
	while (matcher.find()) {
		tagValues.add(matcher.group());
	}

	return tagValues;
}


Templ4docx

Given these results, I’ve chosen apache-poi library. Unfortunately, this library hasn’t any method to find variables in template and replace variables. For this reason I’ve decided to write utility library to work with templates in docx. The heart of the library is Template class which allows you to read docx, find all variables for given pattern, replace variables and save filled template. The example usage of templ4docx is presented below:

Deprecated

The following section concerns the version 1.0.1 The current version is 2.0.0. Read more about this version:

Text Variables
Image Variables
Bullet list Variables
Table Variables



// create new instance of docx template
Docx docx = new Docx("template.docx");

// set the variable pattern. In this example the pattern is as follows: #{variableName}
docx.setVariablePattern(new VariablePattern("#{", "}"));

// read docx content as simple text
String content = docx.readTextContent();

// and display it
System.out.println(content); 

// find all variables satisfying the pattern #{...}
List<String> findVariables = docx.findVariables();

// and display it
for (String var : findVariables) {
        System.out.println("VARIABLE => " + var);
}

// prepare map of variables for template
Variables var = new Variables();
var.addTextVariable(new TextVariable("#{name}", "Lukasz"));

// fill template by given map of variables
docx.fillTemplate(var);

// save filled document
docx.save("output.docx");

How to start ?

The recommended way to get started using templ4docx in your project is a dependency management system – the snippet below can be copied and pasted into your build.

<dependency>
    <groupId>pl.jsolve</groupId>
    <artifactId>templ4docx</artifactId>
    <version>2.0.0</version>
</dependency>


Łukasz Stypka

Java experienced enthusiast, opened for new technologies. Clean code and simple solution fan.

Tomasz Kuryłek

Self-styled and passionate java hipster. Focused on solution that makes user and himself ecstatic..