Docx4j - Replace Text Placeholders with Images in Microsoft Word Documents

Recently, i had been busy looking out for a way to replace text place holders with images. Failed, couldn't find the specific solution, however i found one that replaces Image placeholders in word template with new images through docx4j. 

It was a bad idea, i had as much as 40 images to add in word document on different places. So, if i used this idea of having 40 dummy images in word document, the template was already so ugly. 

I would share the link to this solution once i find it again, or better, i would share that solution dicussed above.

To be able to replace text place holders with binary data, i had to play a trick. I added the Text place holder inside a table with 1 row and 1 column, without borders, they i traveresed the document to get all the tables, and if their 1st row's 1st column contained my text placeholder, i removed the content of that column and added new content which was my image. 

wordMLPackage = getTemplate("C:\\template.docx");

factory = Context.getWmlObjectFactory();

List elemetns = getAllElementFromObject(wordMLPackage.getMainDocumentPart(), Tbl.class);

for(Object obj : elemetns){
   if(obj instanceof Tbl){
      Tbl table = (Tbl) obj;
         List rows = getAllElementFromObject(table, Tr.class);
            for(Object trObj : rows){
        Tr tr = (Tr) trObj;
        List cols = getAllElementFromObject(tr, Tc.class);
        for(Object tcObj : cols){
           Tc tc = (Tc) tcObj;
           List texts = getAllElementFromObject(tc, Text.class);
           for(Object textObj : texts){
             Text text = (Text) textObj;
                     if(text.getValue().equalsIgnoreCase("${MY_PLACE_HOLDER}")){
                        File file = new File("C:\\image.jpeg");
                P paragraphWithImage = addInlineImageToParagraph(createInlineImage(file));
                        tc.getContent().remove(0);
              
                        tc.getContent().add(paragraphWithImage);
             }
                  }
          System.out.println("here");
        }
           }
        System.out.println("here");
    }
}

wordMLPackage.save(new java.io.File("C:\\result.docx"));



Following are the methods for reference. 

private static P addInlineImageToParagraph(Inline inline) {
        // Now add the in-line image to a paragraph
        ObjectFactory factory = new ObjectFactory();
        P paragraph = factory.createP();
        R run = factory.createR();
        paragraph.getContent().add(run);
        Drawing drawing = factory.createDrawing();
        run.getContent().add(drawing);
        drawing.getAnchorOrInline().add(inline);
        return paragraph;
}


 private static Inline createInlineImage(File file) throws Exception {
        byte[] bytes = convertImageToByteArray(file);
 
        BinaryPartAbstractImage imagePart =
            BinaryPartAbstractImage.createImagePart(wordMLPackage, bytes);
 
        int docPrId = 1;
        int cNvPrId = 2;
 
        return imagePart.createImageInline("Filename hint",
                "Alternative text", docPrId, cNvPrId, false);
 }


private static byte[] convertImageToByteArray(File file)
            throws FileNotFoundException, IOException {
     InputStream is = new FileInputStream(file );
     long length = file.length();
     // You cannot create an array using a long, it needs to be an int.
     if (length > Integer.MAX_VALUE) {
            System.out.println("File too large!!");
     }
     byte[] bytes = new byte[(int)length];
     int offset = 0;
     int numRead = 0;
     while (offset= 0) {
            offset += numRead;
     }
     // Ensure all the bytes have been read
     if (offset < bytes.length) {
            System.out.println("Could not completely read file "+file.getName());
     }
     is.close();
     return bytes;
 }


 private static WordprocessingMLPackage getTemplate(String name) 
                        throws Docx4JException, FileNotFoundException {
   WordprocessingMLPackage template = 
           WordprocessingMLPackage.load(new FileInputStream(new File(name)));
    return template;
}

private static List getAllElementFromObject(Object obj, Class toSearch) {
   List result = new ArrayList();
   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;
}

Comments