I've got a list of placeholders in my DOCX document I've referenced this way :
private void findPlaceHolders() {
Docx4JPlaceHolderFinder finder = new Docx4JPlaceHolderFinder();
TraversalUtil.visit(document, false, finder);
placeHoldersRegister = new HashMap<>(finder.getFoundPlaceHolders());
}
Docx4JPlaceHolderFinder
is an implementation of CallbackImpl
, finding all ContentAccessor
(mostly R
) instance containing text value of this form : $[placeholder_name].
placeHolderRegister
is an instance of HashMap<String, List<ContentAccessor>>
; it associates lists of ContentAccessor
instances with their corresponding placeholder keyword.
I want to be able to insert picture in those placeholders. Here is the complete source code of my Docx4JImageMailMerger
class :
package org.johndoe.fwk.simplefile.implementation.docxutil;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.docx4j.TraversalUtil;
import org.docx4j.dml.wordprocessingDrawing.Inline;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;
import org.docx4j.openpackaging.parts.Part;
import org.docx4j.openpackaging.parts.WordprocessingML.BinaryPartAbstractImage;
import org.docx4j.wml.ContentAccessor;
import org.docx4j.wml.Drawing;
import org.docx4j.wml.ObjectFactory;
import org.johndoe.fwk.exception.ExceptionFwk;
/**
* Classe dédiée au publipostage d'image dans un document Docx4J.
*/
public class Docx4JImageMailMerger {
private final ObjectFactory factory;
private WordprocessingMLPackage document;
private Map<String, List<ContentAccessor>> placeHoldersRegister;
public Docx4JImageMailMerger(WordprocessingMLPackage document) {
this.factory = new ObjectFactory();
this.document = document;
}
public void setImage(String placeHolderName, File imageFile) {
setImage(placeHolderName, imageFile, null);
}
public void setImage(String placeHolderName, File imageFile, Long width) {
List<ContentAccessor> placeHolders = selectPlaceHolders(placeHolderName);
for (ContentAccessor placeHolder : placeHolders) {
cleanPlaceHolder(placeHolder);
includeImage(placeHolder, imageFile, width);
}
}
private List<ContentAccessor> selectPlaceHolders(String imageName) {
if (placeHoldersRegister == null)
findPlaceHolders();
List<ContentAccessor> selectedPlaceHolders = new ArrayList<>();
selectedPlaceHolders.addAll(placeHoldersRegister.get(imageName));
return selectedPlaceHolders;
}
private void findPlaceHolders() {
Docx4JPlaceHolderFinder finder = new Docx4JPlaceHolderFinder();
TraversalUtil.visit(document, false, finder);
placeHoldersRegister = new HashMap<>(finder.getFoundPlaceHolders());
}
private void cleanPlaceHolder(ContentAccessor placeHolder) {
placeHolder.getContent().clear();
}
private void includeImage(ContentAccessor placeHolder, File imageFile, Long width) {
try {
Part part = getOwningPart(placeHolder);
BinaryPartAbstractImage imagePart = BinaryPartAbstractImage.createImagePart(document, part, imageFile);
Inline inline;
if (width == null)
inline = imagePart.createImageInline(imageFile.getName(), "test", 0, 1, false);
else
inline = imagePart.createImageInline(imageFile.getName(), "test", 0, 1, width, false);
Drawing drawing = factory.createDrawing();
drawing.getAnchorOrInline().add(inline);
placeHolder.getContent().add(drawing);
} catch (Exception e) {
throw new ExceptionFwk("Erreur lors de l'inclusion de l'image", e);
}
}
private Part getOwningPart(ContentAccessor placeHolder) {
// What should I do here ?
}
}
I don't know in which part of my document is the selected placeholder : body, header, footer, etc. The problem is I must determine it for BinaryPartAbstractImage.createImagePart(document, part, imageFile)
.
Is there any way I could get the Part
instance to which my element belongs to ?
Generally speaking, given say a P
object, you can call getParent()
to find its parent object.
But those objects don't know which part they are associated with.
When you first find your place holders using your Docx4JPlaceHolderFinder
, you are going to need to record the part in which they are found. Or change your approach to do the processing part by part.