Reputation: 1
I am trying to generate pdf from word document templates using Apache POI - XWPF. There is an image on the header of the docx template that needs to be replaced with a new image. The new image should be exactly at the same position as the old image. The generated pdf would have the new image. I am able to see the new image on the generated pdf but could not be sure if it is placed at the position where it should be. I would appreciate if you can help me on this issue. Thanks
Upvotes: 0
Views: 1382
Reputation: 61852
In Office Open XML documents (*.xlsx
, *.docx
, *.pptx
, ...) picture shapes are linked to picture data in media directory of the Office Open XML ZIP archive. The shape is anchored on the sheet, the document, the slide, ... Additionally the anchor determines the size. But the picture data contains the bytes of the picture which shall be shown. So if position and size shall stay but only the shown picture shall change, then only replacing the picture data is needed.
Following code shows this for XWPF
. It replaces all picture data of JPEG-type pictures in all headers with given stackoverflowLogo.jpg
. Then it saves the resulting *.docx
file. Then it converts to PDF using XDocReport.
import org.apache.poi.xwpf.usermodel.*;
import org.apache.poi.util.IOUtils;
import java.io.*;
import fr.opensagres.xdocreport.converter.Options;
import fr.opensagres.xdocreport.converter.IConverter;
import fr.opensagres.xdocreport.converter.ConverterRegistry;
import fr.opensagres.xdocreport.converter.ConverterTypeTo;
import fr.opensagres.xdocreport.core.document.DocumentKind;
class WordReplacePictures {
static void replacePictureData(XWPFPictureData source, byte[] data) {
try ( ByteArrayInputStream in = new ByteArrayInputStream(data);
OutputStream out = source.getPackagePart().getOutputStream();
) {
byte[] buffer = new byte[2048];
int length;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void main(String[] args) throws Exception {
String docPathTemplate = "./WordHavingPictureTemplateInHeader.docx";
String docPathAfterReplacing = "./WordResult.docx";
String pdfPath = "./WordDocument.pdf";
// replacde picture dara in headers
try (XWPFDocument document = new XWPFDocument(new FileInputStream(docPathTemplate));
FileOutputStream out = new FileOutputStream(docPathAfterReplacing);
) {
for (XWPFHeader header : document.getHeaderList()) {
for (XWPFPictureData pictureData : header.getAllPictures()) {
String fileName = pictureData.getFileName();
System.out.println(fileName);
if (pictureData.getPictureType() == Document.PICTURE_TYPE_JPEG) {
FileInputStream is = new FileInputStream("./stackoverflowLogo.jpg");
byte[] bytes = IOUtils.toByteArray(is);
replacePictureData(pictureData, bytes);
System.out.println(fileName + " replaced by stackoverflowLogo.jpg");
}
}
}
document.write(out);
} catch (Exception ex) {
ex.printStackTrace();
}
//convert to PDF
try (InputStream in = new FileInputStream(new File(docPathAfterReplacing));
OutputStream out = new FileOutputStream(new File(pdfPath));
) {
Options options = Options.getFrom(DocumentKind.DOCX).to(ConverterTypeTo.PDF);
IConverter converter = ConverterRegistry.getRegistry().getConverter(options);
converter.convert(in, out, options);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
This code is tested and works using apache poi 4.1.2
in combination with XDocReport
version 2.0.2
. It also is tested and works using apache poi 5.2.2
in combination with XDocReport
version 2.0.3
.
See how to replace an image with another image in excel using POI for the same using XSSF
(Excel).
Upvotes: 2