I need to replace the placeholder with image in the word document using Apache POI. I am able to insert the picture in the word document using Apache poi. But i don't know how to replace the placeholder with image. Can anyone please help in this?
I know it will be easy if we do it through docx4j or some other API, i am allowed to use only the Apache poi.
It can be done but I believe you must insert raw XML to accomplish it currently. This linked question "Insert picture in word document" has the basic idea. You can do it using only the libraries that POI requires, not dom4j. If you look at the source for the method on the XWPFRun that adds a picture it too is trying to add raw XML. But if you use that method it renders your doc unreadable when written back to disk. So you have to add the picture to the document using the XWPFDocument level method, which returns a generated ID for the picture. And then add raw XML to the run with that ID in it, as the example link does.
The way we solved the problem was to instead have our users insert a placeholder image into their Word doc file instead of text. We then: add the replacement image to be inserted at the document level, find the run that contains the placeholder image using the size of the image as criteria, then get and replace the XML for that run with the new image's ID swapped in. As long as the placeholder and the replacement image are the same size this works. If you need to adjust the size of the image after replacing, you could manipulate the XML size values in the same manner. I like our solution better because it is less susceptible to changes in the Word doc XML format then inserting your own full XML for the picture. Cheers
InputStream newImageIS = getImageForCorporation(corporationID);
String relationID = run.getParagraph().getDocument().addPictureData(newImageIS, Document.PICTURE_TYPE_GIF);
replaceRunImageData(run, relationID);
private void replaceRunImageData(XWPFRun run, String relationID) {
CTGraphicalObjectData graph = run.getCTR().getDrawingArray(0).getInlineArray(0).getGraphic()
.getGraphicData();
String currentGraphicXML = graph.toString();
String originalID = RegularExpressionUtil.capture("<a:blip r:embed=\"(\\w+)\"", currentGraphicXML);
String newXML = StringUtils.replace(currentGraphicXML, originalID, relationID);
try {
graph.set(XmlToken.Factory.parse(newXML));
} catch (XmlException e) {
throw new RuntimeException(e);
}
replaced = true;
}
We identified the run of the image to replace by search each run's list of embedded pictures which met the below criteria. We tried using the name of the image as the criteria, but we found that if the placeholder image was copied from one Word doc to another Word doc on a different PC, the name was lost.
private boolean isRunForExistingImage(XWPFPicture pic) {
if (pic == null || pic.getCTPicture() == null || pic.getCTPicture().getSpPr() == null
|| pic.getCTPicture().getSpPr().getXfrm() == null
|| pic.getCTPicture().getSpPr().getXfrm().getExt() == null) {
return false;
}
long x = pic.getCTPicture().getSpPr().getXfrm().getExt().getCx();
long y = pic.getCTPicture().getSpPr().getXfrm().getExt().getCy();
return x == 2066925 && y == 590550;
}