What I am currently trying is doing a multi page mail merge, the problem is that currently i just overwrite the content with my second map.
This are the important code snippets:
public static void main(final String[] args) throws Docx4JException, JAXBException
{
final WordprocessingMLPackage word = Docx4J.load(new File(filePath));
final MainDocumentPart document = word.getMainDocumentPart();
generatePagesFromTemplate(document);
final List<Map<DataFieldName, String>> data = prepareForMailMerge();
for (int i = 0; i < data.size(); i++)
{
MailMerger.performMerge(word, data.get(i), false);
}
// This is a workaround, otherwise the document would have an error
setRandomIdsForDocPr(document);
word.save(new File(outputPath));
createOutputXml(document); // just writes document.getXML() in a file
openFile(outputPath);
}
private static void generatePagesFromTemplate(final MainDocumentPart document, final int nrOfSheets)
{
final List<Object> pageContent = document.getContent();
// This is needed if you don't want a endless loop
final int nrOfElements = pageContent.size();
// Make a copy of the first sheet, to the nr of pages that exist
for (int sheetNr = 1; sheetNr < nrOfSheets; sheetNr++)
{
addPageBreak(document);
for (int i = 0; i < nrOfElements; i++)
{
final Object tmp = pageContent.get(i);
document.addObject(tmp);
System.out.println("Added object: " + tmp.toString());
}
}
}
private static void setRandomIdsForDocPr(final MainDocumentPart document)
throws JAXBException, XPathBinderAssociationIsPartialException
{
final String xpath = "//wp:docPr";
final List<Object> docPr = document.getJAXBNodesViaXPath(xpath, false);
for (int i = 0; i < docPr.size(); i++)
{
final CTNonVisualDrawingProps props = (CTNonVisualDrawingProps) docPr.get(i);
props.setId(setRandomValue());
}
}
private static List<Map<DataFieldName, String>> prepareForMailMerge()
{
final List<Map<DataFieldName, String>> data = new ArrayList<Map<DataFieldName, String>>();
// Instance 1
Map<DataFieldName, String> map = new HashMap<DataFieldName, String>();
map.put(new DataFieldName("Field1"), "Daffy duck");
map.put(new DataFieldName("Field2"), "Plutext");
data.add(map);
// Instance 2
map = new HashMap<DataFieldName, String>();
map.put(new DataFieldName("Field1"), "duck Daffy");
map.put(new DataFieldName("Field2"), "ThisPlutext");
data.add(map);
// Choose how to treat the MERGEFIELD in the output
MailMerger.setMERGEFIELDInOutput(OutputField.KEEP_MERGEFIELD);
return data;
}
Here you can find my document as XML (docPr has different ids in reality, just used this file for a other question)
So I think there are 2 ways to approach this:
- Change the names of the merge fields that every merge field is unique
- Only merge on one page so I don't have to rename every field
I think there must be a way to do handle this for every page or am I wrong?
I also tried out Variable Replace but this doesn't work for textfields, I now try to get into content controls, maybe this will solve my problem.