This works for me - but I don't have column headers in my word template, so be careful they might break this functionality.
Just fill the HashMap correctly and it should work out of the box if you have everything setup right ;)
These are the 3 functions I use for replacement:
private void replaceTable(String[] placeholders, List<Map<String, String>> textToAdd, WordprocessingMLPackage template) throws Docx4JException, JAXBException {
List<Object> tables = doc.getAllElementFromObject(template.getMainDocumentPart(), Tbl.class);
Tbl tempTable = getTemplateTable(tables, placeholders[0]);
List<Object> rows = doc.getAllElementFromObject(tempTable, Tr.class);
if (rows.size() == 1) { //careful only tables with 1 row are considered here
Tr templateRow = (Tr) rows.get(0);
for (Map<String, String> replacements : textToAdd) {
addRowToTable(tempTable, templateRow, replacements);
}
assert tempTable != null;
tempTable.getContent().remove(templateRow);
}
}
private void addRowToTable(Tbl reviewTable, Tr templateRow, Map<String, String> replacements) {
Tr workingRow = (Tr) XmlUtils.deepCopy(templateRow);
List<?> textElements = doc.getAllElementFromObject(workingRow, Text.class);
for (Object object : textElements) {
Text text = (Text) object;
String replacementValue = (String) replacements.get(text.getValue());
if (replacementValue != null)
text.setValue(replacementValue);
}
reviewTable.getContent().add(workingRow);
}
private Tbl getTemplateTable(List<Object> tables, String templateKey) throws Docx4JException, JAXBException {
for (Object tbl : tables) {
List<?> textElements = doc.getAllElementFromObject(tbl, Text.class);
for (Object text : textElements) {
Text textElement = (Text) text;
if (textElement.getValue() != null && textElement.getValue().equals(templateKey))
return (Tbl) tbl;
}
}
return null;
}
And here's roughly how to use it for your example:
ArrayList<Map<String, String>> list = new ArrayList<>();
//Create a loop here through all entries
Map<String, String> entry = new HashMap<>();
entry.put("${nrCrt}", "1");
list.add(entry);
//...
entry.put("${tva}", "55");
list.add(entry);
entry.put("${nrCrt}", "2");
list.add(entry);
//...
replaceTable(new String[]{"${nrCrt}"}, list, template);
I forgot to mention:
doc
is just a helper class, this is the implementation of getAllElementFromObject
:
public List<Object> getAllElementFromObject(Object obj, Class<?> toSearch) {
List<Object> result = new ArrayList<Object>();
if (obj instanceof JAXBElement) obj = ((JAXBElement<?>) obj).getValue();
if (obj.getClass().equals(toSearch))
result.add(obj);
else if (obj instanceof ContentAccessor) {
List<?> children = ((ContentAccessor) obj).getContent();
for (Object child : children) {
result.addAll(getAllElementFromObject(child, toSearch));
}
}
return result;
}