10

This is the first time I am working on Apache POI and the question which I am going to ask has been asked already on this site but no clear answer were given for them so I have no choice but to take all your help.

I am trying to write a java program which takes images from one folder and insert that image into a word document. I am using Apache POI for this program. Here I am posting my code.

import java.io.*;
import java.util.*;
import org.apache.poi.util.IOUtils;
import org.apache.poi.xwpf.usermodel.*;

public class ImagesDoc 
{
    public static void main(String[] args) throws IOException 
    {
        XWPFDocument docx = new XWPFDocument();
        XWPFParagraph par = docx.createParagraph();
        XWPFRun run = par.createRun();
        run.setText("Hello, World. This is my first java generated docx-file. Have fun.");
        run.setFontSize(13);
        InputStream pic = new FileInputStream("C:\\Users\\amitabh\\Pictures\\pics\\pool.jpg");
        byte [] picbytes = IOUtils.toByteArray(pic);
        docx.addPicture(picbytes, Document.PICTURE_TYPE_JPEG);

        FileOutputStream out = new FileOutputStream("C:\\Users\\amitabh\\Pictures\\pics\\simple1.docx"); 
        docx.write(out); 
        out.close(); 
        pic.close();
    }
}

I am able to create the word document file and I am able to insert the text as well but docx.addPicture(picbytes, Document.PICTURE_TYPE_JPEG); line is giving me the error as"add cast to docx". I have added all possible jars for this program. For this error I have searched all over the net and found that many people are having similar problem. "addPicture" for XWPFDocument reference is not working. Please help me to resolve this problem.

Viktor Seifert
  • 636
  • 1
  • 7
  • 17
Amitabh Ranjan
  • 1,500
  • 3
  • 23
  • 39
  • Can you post the full error including stacktrace? – Gagravarr Jul 19 '13 at 13:58
  • This is a compilation error. On running, it's giving the error as "Exception in thread "main" java.lang.Error: Unresolved compilation problem: The method addPicture(byte[], int) is undefined for the type XWPFDocument at org.poi.images.ImagesDoc.main(ImagesDoc.java:17)" – Amitabh Ranjan Jul 19 '13 at 14:45
  • Ah, right. Yes, that won't ever work - if you look at the [XWPFJavaDocs](http://poi.apache.org/apidocs/org/apache/poi/xwpf/usermodel/XWPFDocument.html#addPictureData%28byte[],%20int%29) you'll see that the signature is addPictureData! – Gagravarr Jul 19 '13 at 14:55
  • Sorry sir, even that's not working. Its showing the same error. Here I am putting the error I am getting "Exception in thread "main" java.lang.Error: Unresolved compilation problem: The method addPictureData(byte[], int) is undefined for the type XWPFDocument at org.poi.images.ImagesDoc.main(ImagesDoc.java:19) " – Amitabh Ranjan Jul 19 '13 at 15:55
  • Make sure you're using the latest POI jars, sounds like you've both got old jars *and* are following an incorrect tutorial... – Gagravarr Jul 19 '13 at 16:39
  • Sir , according to Apache website the latest stable release is Apache POI 3.9 and I am using the same jar. jar 3.10 version is still in its beta stage. Can you please suggest me a good tutorial for XWPFDocument as I am unable to find one. Thanks – Amitabh Ranjan Jul 19 '13 at 19:03

2 Answers2

15

First, I would like to point out the example provided by apache poi - Link, i.e. the correct way to do it would be

doc.createParagraph().createRun().addPicture(new FileInputStream(imgFile), format, imgFile, Units.toEMU(200), Units.toEMU(200));

However, there is still an existing bug which renders the .docx file unreadable after executing the above statement. It might be resolved soon, in which case the above-mentioned statement will do the work. For the meantime, there is a work-around.

First, generate the docx file without any pictures. Then add this class CustomXWPFDocument to your package.

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;

import java.io.IOException;
import java.io.InputStream;

public class CustomXWPFDocument extends XWPFDocument
{
    public CustomXWPFDocument(InputStream in) throws IOException
    {
        super(in);
    }

    public void createPicture(String blipId,int id, int width, int height)
    {
        final int EMU = 9525;
        width *= EMU;
        height *= EMU;
        //String blipId = getAllPictures().get(id).getPackageRelationship().getId();


        CTInline inline = createParagraph().createRun().getCTR().addNewDrawing().addNewInline();

        String picXml = "" +
                "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
                "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                "         <pic:nvPicPr>" +
                "            <pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>" +
                "            <pic:cNvPicPr/>" +
                "         </pic:nvPicPr>" +
                "         <pic:blipFill>" +
                "            <a:blip r:embed=\"" + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
                "            <a:stretch>" +
                "               <a:fillRect/>" +
                "            </a:stretch>" +
                "         </pic:blipFill>" +
                "         <pic:spPr>" +
                "            <a:xfrm>" +
                "               <a:off x=\"0\" y=\"0\"/>" +
                "               <a:ext cx=\"" + width + "\" cy=\"" + height + "\"/>" +
                "            </a:xfrm>" +
                "            <a:prstGeom prst=\"rect\">" +
                "               <a:avLst/>" +
                "            </a:prstGeom>" +
                "         </pic:spPr>" +
                "      </pic:pic>" +
                "   </a:graphicData>" +
                "</a:graphic>";

        //CTGraphicalObjectData graphicData = inline.addNewGraphic().addNewGraphicData();
        XmlToken xmlToken = null;
        try
        {
            xmlToken = XmlToken.Factory.parse(picXml);
        }
        catch(XmlException xe)
        {
            xe.printStackTrace();
        }
        inline.set(xmlToken);
        //graphicData.set(xmlToken);

        inline.setDistT(0);
        inline.setDistB(0);
        inline.setDistL(0);
        inline.setDistR(0);

        CTPositiveSize2D extent = inline.addNewExtent();
        extent.setCx(width);
        extent.setCy(height);

        CTNonVisualDrawingProps docPr = inline.addNewDocPr();
        docPr.setId(id);
        docPr.setName("Picture " + id);
        docPr.setDescr("Generated");
    }
}

Then, create the updated document by adding your pictures like this :-

CustomXWPFDocument document = new CustomXWPFDocument(new FileInputStream(new File("C:\\Users\\Avarice\\Desktop\\doc1.docx")));
        FileOutputStream fos = new FileOutputStream(new File("C:\\Users\\Avarice\\Desktop\\doc2.docx"));
        String id = document.addPictureData(new FileInputStream(new File("C:\\Users\\Avarice\\Desktop\\thumbnail.jpg")), Document.PICTURE_TYPE_JPEG);
        document.createPicture(id,document.getNextPicNameNumber(Document.PICTURE_TYPE_JPEG), 64, 64);
        document.write(fos);
        fos.flush();
        fos.close();

You should also have the following jars in your build path:-

poi-ooxml-schemas

xmlbeans

dom4j

Avik
  • 1,170
  • 10
  • 25
  • Hi Avik, I tried this code and I have added all the jars you mentioned, but still I am getting the exact same error. When I am using the line "document.getNextPicNameNumber(Document.PICTURE_TYPE_JPEG)" from the code, then it throws an error. When I went for quick fix then it show 5 package import options. I tried all the imports one by one but nothing is working wth this. Can you please segest me some good XWPF tutorials please? I think I am doing some mistake somewhere. – Amitabh Ranjan Jul 22 '13 at 10:17
  • Examples Link - http://svn.apache.org/repos/asf/poi/trunk/src/examples/src/org/apache/poi/ I am sure it's something very simple you are overlooking. Just copy your error stacktrace, paste it on pastebin and give me the link. – Avik Jul 23 '13 at 13:31
  • Hi Thanks to your guidance, now I am able to run the program. The program is working fine but now a new Problem has started. After I run the program I am able to create a new word file. Even I am able to execute addPicture method but When I open the created word file then its showing me the error "the document file can not be opened because there is some problem with the contents." Although I can see the size of the file increasing according to the size of the photo added to it. – Amitabh Ranjan Jul 24 '13 at 10:07
  • Thanks Avik. Finally I am able to add the pictures to the word document and the program is working fine. – Amitabh Ranjan Jul 25 '13 at 05:00
  • Hello Avik, I am trying to run the code you have given. But getting error in the call document.addPictureData(...). It says addPicture is not defined for CustomXWPFDocument type. But document object can identify addPicture(...) i.e document.addPicture(...) call is okay here though its not working after giving call with proper arguments..Can you sense the problem for me?? – amin__ Aug 16 '13 at 12:59
  • Are you sure you are not mixing createPicture and addPictureData? If CustomXWPFDocument has extended XWPFDocument, then any instance of CustomXWPFDocument can call addPictureData. – Avik Aug 17 '13 at 14:40
  • @Avik, No, I dont. Surprisingly here I cant access addPictureData(..) method with customXWPFDocument object. What is more confusing that I have also tried to access the addPictureData(..) with a XWPFDocument object. But this object does not know addPictureData(..) while it knows addPicture(..). Is there any chances of problem with adding jars or jar version?? – amin__ Aug 19 '13 at 04:40
  • @Avik, I have got rid of the problem of finding addPictureData(..) method. But still there are problems here. I got the exception like "parameter id is out of bound". May be I am doing wrong in regenerating the code. It would be very helpful if you would further explain your code for me like what should doc1, doc2 files contain, are they created earlier or created by the running the code?? purpose of those files...thanks – amin__ Aug 19 '13 at 06:50
  • @Avik : Is it possible to add picture in a particular page and line and also with alignment? – softmage99 Jul 09 '14 at 13:10
  • @Magesh : I haven't worked with POI for quite some time. You can ask that question in their mailing list or just tinker with the code. If their high level classes does not support it directly, you can take a look at the wordprocessingDrawing package for alignment. But this is a different question altogether. – Avik Jul 10 '14 at 20:28
  • Hello @AmitabhRanjan I'm also facing the same issue. " the document file can not be opened because there is some problem with the contents" , What is the fix ? – gauti Feb 10 '18 at 14:54
4
    I have used poi 3.10 to generate word doc and to insert a picture. you need 2 classes.. here is the example

    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Calendar;
    import java.util.List;

    import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
    import org.apache.poi.util.Units;
    import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
    import org.apache.poi.xwpf.usermodel.Document;
    import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
    import org.apache.poi.xwpf.usermodel.UnderlinePatterns;
    import org.apache.poi.xwpf.usermodel.XWPFDocument;
    import org.apache.poi.xwpf.usermodel.XWPFHeader;
    import org.apache.poi.xwpf.usermodel.XWPFParagraph;
    import org.apache.poi.xwpf.usermodel.XWPFRun;
    import org.apache.xmlbeans.XmlException;
    import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;

    public class ImageAttachmentInDocument {
        /**
         * @param args
         * @throws IOException
         */
        public static void main(String[] args) throws IOException {

            DateFormat dateFormat = new SimpleDateFormat("dd-MMM-yyyy");
            Calendar cal = Calendar.getInstance();
            String date = dateFormat.format(cal.getTime());

            // Create a document file
            CustomXWPFDocument document = new CustomXWPFDocument();

            // Adding a file
            try {

                // Working addPicture Code below...
                XWPFParagraph paragraphX = document.createParagraph();
                paragraphX.setAlignment(ParagraphAlignment.CENTER);

                String blipId = paragraphX.getDocument().addPictureData(
                        new FileInputStream(new File("D://c2//WLB.jpg")),
                        Document.PICTURE_TYPE_JPEG);
                System.out.println("4" + blipId);
                System.out.println(document
                        .getNextPicNameNumber(Document.PICTURE_TYPE_JPEG));
                document.createPicture(blipId,
                        document.getNextPicNameNumber(Document.PICTURE_TYPE_JPEG),
                        200, 75);
                System.out.println("5");

            } catch (InvalidFormatException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            // insert doc details
            // Createa a para -1
            XWPFParagraph paragraphOne = document.createParagraph();
            paragraphOne.setAlignment(ParagraphAlignment.CENTER);
            XWPFRun paragraphOneRunOne = paragraphOne.createRun();
            paragraphOneRunOne.setBold(true);
            paragraphOneRunOne.setFontSize(20);
            paragraphOneRunOne.setFontFamily("Verdana");
            paragraphOneRunOne.setColor("000070");
            paragraphOneRunOne.setText("Daily Status Report");

            // Createa a para -2
            XWPFParagraph paragraphTwo = document.createParagraph();
            paragraphTwo.setAlignment(ParagraphAlignment.CENTER);
            XWPFRun paragraphTwoRunOne = paragraphTwo.createRun();
            paragraphTwoRunOne.setFontSize(12);
            paragraphTwoRunOne.setFontFamily("Verdana");
            paragraphTwoRunOne.setColor("000070");
            paragraphTwoRunOne.setText(date);
            paragraphTwoRunOne.addBreak();

            // Createa a para -3
            XWPFParagraph paragraphThree = document.createParagraph();
            paragraphThree.setAlignment(ParagraphAlignment.LEFT);
            XWPFRun paragraphThreeRunOne = paragraphThree.createRun();
            paragraphThreeRunOne.setFontSize(14);
            paragraphThreeRunOne.setFontFamily("Verdana");
            paragraphThreeRunOne.setColor("000070");
            paragraphThreeRunOne.setText("5.30 AM PST");
            paragraphThreeRunOne.addBreak();

            // Createa a para -4
            XWPFParagraph paragraphFour = document.createParagraph();
            paragraphFour.setAlignment(ParagraphAlignment.LEFT);
            XWPFRun paragraphFourRunOne = paragraphFour.createRun();
            paragraphFourRunOne.setBold(true);
            paragraphFourRunOne.setUnderline(UnderlinePatterns.SINGLE);
            paragraphFourRunOne.setFontSize(10);
            paragraphFourRunOne.setFontFamily("Verdana");
            paragraphFourRunOne.setColor("000070");
            paragraphFourRunOne.setText("ABCD");

            // insert doc details end

            XWPFParagraph paragraphFive = document.createParagraph();
            paragraphFive.setAlignment(ParagraphAlignment.RIGHT);
            XWPFRun paragraphFiveRunOne = paragraphFive.createRun();
            paragraphFiveRunOne.addBreak();
            paragraphFourRunOne.setBold(true);
            paragraphFourRunOne.setUnderline(UnderlinePatterns.SINGLE);
            paragraphFourRunOne.setFontSize(10);
            paragraphFourRunOne.setFontFamily("Verdana");
            paragraphFourRunOne.setColor("000070");
            paragraphFourRunOne.setText("ABCD00000000000");

            FileOutputStream outStream = null;
            try {
                double x = Math.random();
                String fileName = "D:\\c2\\" + String.valueOf(x) + ".docx";
                outStream = new FileOutputStream(fileName);
            } catch (FileNotFoundException e) {
                System.out.println("First Catch");
                e.printStackTrace();
            }
            try {
                document.write(outStream);
                outStream.close();
            } catch (FileNotFoundException e) {
                System.out.println("Second Catch");
                e.printStackTrace();
            } catch (IOException e) {
                System.out.println("Third Catch");
                e.printStackTrace();
            }
        }
    }

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlToken;
import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;

import java.io.IOException;
import java.io.InputStream;

public class CustomXWPFDocument extends XWPFDocument
{
    public CustomXWPFDocument()    {
     super();
    }

    public CustomXWPFDocument(InputStream in) throws IOException
    {
        super(in);
    }



    public void createPicture(String blipId,int id, int width, int height)
    {
        final int EMU = 9525;
        width *= EMU;
        height *= EMU;
        //String blipId = getAllPictures().get(id).getPackageRelationship().getId();


        CTInline inline = createParagraph().createRun().getCTR().addNewDrawing().addNewInline();

        String picXml = "" +
                "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" +
                "   <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                "      <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" +
                "         <pic:nvPicPr>" +
                "            <pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>" +
                "            <pic:cNvPicPr/>" +
                "         </pic:nvPicPr>" +
                "         <pic:blipFill>" +
                "            <a:blip r:embed=\"" + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" +
                "            <a:stretch>" +
                "               <a:fillRect/>" +
                "            </a:stretch>" +
                "         </pic:blipFill>" +
                "         <pic:spPr>" +
                "            <a:xfrm>" +
                "               <a:off x=\"0\" y=\"0\"/>" +
                "               <a:ext cx=\"" + width + "\" cy=\"" + height + "\"/>" +
                "            </a:xfrm>" +
                "            <a:prstGeom prst=\"rect\">" +
                "               <a:avLst/>" +
                "            </a:prstGeom>" +
                "         </pic:spPr>" +
                "      </pic:pic>" +
                "   </a:graphicData>" +
                "</a:graphic>";

        //CTGraphicalObjectData graphicData = inline.addNewGraphic().addNewGraphicData();
        XmlToken xmlToken = null;
        try
        {
            xmlToken = XmlToken.Factory.parse(picXml);
        }
        catch(XmlException xe)
        {
            xe.printStackTrace();
        }
        inline.set(xmlToken);
        //graphicData.set(xmlToken);

        inline.setDistT(0);
        inline.setDistB(0);
        inline.setDistL(0);
        inline.setDistR(0);

        CTPositiveSize2D extent = inline.addNewExtent();
        extent.setCx(width);
        extent.setCy(height);

        CTNonVisualDrawingProps docPr = inline.addNewDocPr();
        docPr.setId(id);
        docPr.setName("Picture " + id);
        docPr.setDescr("Generated");
    }
}
Arindam
  • 41
  • 3