Is there any way to replace an image on word(docx) file header by name of the image with apache poi? I'am thinking about that:
+--------------------------------+
+HEADER myimage.jpeg-+
+ -----------BODY------------+
+--------------------------------+
replaceImage("myimage.jpeg", newPictureInputStream,
"newPicture_name.jpeg");
Here what I tried:
XWPFParagraph originalParagraph = null;
originalParagraph = getPictureParagraphInHead(lookingPictureName);
ListIterator<XWPFRun> it = originalParagraph.getRuns().listIterator();
XWPFRun replacedRun = null;
while (it.hasNext()) {
XWPFRun run = it.next();
int runIDX = it.nextIndex();
if (run.getEmbeddedPictures().size() > 0) {
XWPFRun newRun = null;
newRun = new XWPFRun(run.getCTR(), (IRunBody) originalParagraph);
originalParagraph.addRun(newRun);
originalParagraph.removeRun(originalParagraph.getRuns().indexOf(run));
break;
}
}
I'm not sure if you can get the "filename" of the image with POI. It's probably in the XML so you might have to make your own method for finding the image.
To get the Header you do:
XWPFHeaderFooterPolicy policy = new XWPFHeaderFooterPolicy(doc); // XWPFDocument
XWPFHeader header = policy.getDefaultHeader();
And to delete the images, get the XWPFRun from your paragraph (cell/row/table..)
CTR ctr = myRun.getCTR(); //
List<CTDrawing> images = ctr.getDrawingList();
for (int i=0; i<images.size(); i++)
{
ctr.removeDrawing(i);
}
Related
In one of my projects I need to read images from a .doc file using Apache POI. For each row there is a cell containing an images(one, two, three, etc. ) which I need to read out along side with text data.
So I tried the following code
FileInputStream fileInputStream = new FileInputStream(file);
POIFSFileSystem poifsFileSystem = new POIFSFileSystem(fileInputStream);
HWPFDocument doc = new HWPFDocument(poifsFileSystem);
Range range = doc.getRange();
PicturesTable pictureTable = doc.getPicturesTable();
PicturesSource pictures = new PicturesSource(doc);
Paragraph tableParagraph = range.getParagraph(0);
Table table = range.getTable(tableParagraph);
TableRow row = table.getRow(0);
TableCell cell1 = row.getCell(0);
for (int j = 0; j < cell1.getParagraph(0).numCharacterRuns(); j++) {
CharacterRun cr = cell1.getParagraph(0).getCharacterRun(j);
if (pictureTable.hasPicture(cr)) {
logger.debug("Has picture If--");
Picture picture = pictures.getFor(cr);
logger.debug("pictures Description--" + picture.getDescription());
}
}
Now I am able to read images of a particular cell, but the problem is I am not able to read all the images of a cell means, I am able to read image before the text and image in between the text, but I am not able to read the image which is followed by the text. Example "image_1---some text---image_2 some text---.image_3". Now in this case I am not able to read image_3 only. What should I do, So I can read image_3 also. I searched a lot but no luck till now. Hope someone knows the way to do this. Thanks in Advance.
With the HWPFDocument, I am having problems, too. If you have a chance to change the Word documents to docx before processing, here's an example that works with XWPFDocuments:
FileInputStream fileInputStream = new FileInputStream(file);
XWPFDocument doc = new XWPFDocument(fileInputStream);
for (XWPFTable tbl : doc.getTables()) {
for (XWPFTableRow row : tbl.getRows()) {
for (XWPFTableCell cell : row.getTableCells()) {
for (XWPFParagraph para : cell.getParagraphs()) {
for (XWPFRun run : para.getRuns()) {
for (XWPFPicture pic : run.getEmbeddedPictures()) {
System.out.println(pic.getPictureData());
}
}
}
}
}
}
I need help by replacing an image with another image in Word using Apache POI or any other library that might do the job. I know how to replace a word using Apache POI but I can't figure a way out to replace an image.
public static void main(String[] args) throws FileNotFoundException {
String c22 = "OTHER WORD";
try {
XWPFDocument doc = new XWPFDocument(OPCPackage.open("imagine.docx"));
for (XWPFParagraph p : doc.getParagraphs()) {
List<XWPFRun> runs = p.getRuns();
if (runs != null) {
for (XWPFRun r : runs) {
String text = r.getText(0);
if (text != null ) {
String imgFile = "imaginedeschis.jpg";
try (FileInputStream is = new FileInputStream(imgFile)) {
r.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, imgFile,
Units.toEMU(200), Units.toEMU(200)); // 200x200 pixels
text = text.replace("1ST WORD", c22);
} // 200x200 pixels
r.setText(text, 0);
}
}
}
}
doc.write(new FileOutputStream("output.docx"));
} catch (InvalidFormatException | IOException m){ }
}
I am using below Java code to replace one image in Word document (*.docx). Please share if anyone have better approach.
public XWPFDocument replaceImage(XWPFDocument document, String imageOldName, String imagePathNew, int newImageWidth, int newImageHeight) throws Exception {
try {
LOG.info("replaceImage: old=" + imageOldName + ", new=" + imagePathNew);
int imageParagraphPos = -1;
XWPFParagraph imageParagraph = null;
List<IBodyElement> documentElements = document.getBodyElements();
for(IBodyElement documentElement : documentElements){
imageParagraphPos ++;
if(documentElement instanceof XWPFParagraph){
imageParagraph = (XWPFParagraph) documentElement;
if(imageParagraph != null && imageParagraph.getCTP() != null && imageParagraph.getCTP().toString().trim().indexOf(imageOldName) != -1) {
break;
}
}
}
if (imageParagraph == null) {
throw new Exception("Unable to replace image data due to the exception:\n"
+ "'" + imageOldName + "' not found in in document.");
}
ParagraphAlignment oldImageAlignment = imageParagraph.getAlignment();
// remove old image
document.removeBodyElement(imageParagraphPos);
// now add new image
// BELOW LINE WILL CREATE AN IMAGE
// PARAGRAPH AT THE END OF THE DOCUMENT.
// REMOVE THIS IMAGE PARAGRAPH AFTER
// SETTING THE NEW IMAGE AT THE OLD IMAGE POSITION
XWPFParagraph newImageParagraph = document.createParagraph();
XWPFRun newImageRun = newImageParagraph.createRun();
//newImageRun.setText(newImageText);
newImageParagraph.setAlignment(oldImageAlignment);
try (FileInputStream is = new FileInputStream(imagePathNew)) {
newImageRun.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, imagePathNew,
Units.toEMU(newImageWidth), Units.toEMU(newImageHeight));
}
// set new image at the old image position
document.setParagraph(newImageParagraph, imageParagraphPos);
// NOW REMOVE REDUNDANT IMAGE FORM THE END OF DOCUMENT
document.removeBodyElement(document.getBodyElements().size() - 1);
return document;
} catch (Exception e) {
throw new Exception("Unable to replace image '" + imageOldName + "' due to the exception:\n" + e);
} finally {
// cleanup code
}
}
Please visit https://bitbucket.org/wishcoder/java-poi-word-document/wiki/Home for more examples like:
Open existing Microsoft Word Document (*.docx)
Clone Table in Word Document and add new data to cloned table
Update existing Table->Cell data in document
Update existing Hyper Link in document
Replace existing Image in document
Save update Microsoft Word Document (*.docx)
I recommend using transparent tables to track images. following code will replace table row 0 col 1 cell's picture.
List<XWPFParagraph> paragraphs = table.getRow(0).getCell(1).getParagraphs();
for (XWPFParagraph para: paragraphs) {
for (XWPFRun r : para.getRuns()) {
CTR ctr = r.getCTR();
List<CTDrawing> drawings = ctr.getDrawingList();
for (int i = 0; i < drawings.size(); i++) {
ctr.removeDrawing(i);
}
}
}
XWPFParagraph paragraph = table.getRow(0).getCell(1).addParagraph();
XWPFRun run = paragraph.createRun();
FileInputStream fis = new FileInputStream('filepath');
run.addPicture(fis, XWPFDocument.PICTURE_TYPE_PNG, "filename", Units.toEMU(200), Units.toEMU(60));
I have code to get paragraphs from a .doc file in Apache POI, but I'd like to get footnotes also. Also, is this the only way to get paragraphs?
Code so far:
InputStream stream = ...
HWPFDocument document = new HWPFDocument(stream);
Range range = document.getRange();
StyleSheet stylesheet = document.getStyleSheet();
for (int i = 0; i < range.numParagraphs(); i++) {
Paragraph paragraph = range.getParagraph(i);
String text = paragraph.text();
}
Any ideas?
You could try this...
WordExtractor extractor = new WordExtractor(document);
paragraphs.addAll(Arrays.asList(extractor.getParagraphText()) );
footnotes.addAll(Arrays.asList(extractor.getFootnoteText()) );
extractor.close();
I have tried adding an image to the header of an XWPFDocument with no success. I am using Apache POI.
Here is what I am currently using as a solution:
Header creation
XWPFDocument document = new XWPFDocument(OPCPackage.open(docxInputStream));
CTP headerCtp = CTP.Factory.newInstance();
CTR headerCtr = headerCtp.addNewR();
XWPFParagraph headerParagraph = new XWPFParagraph(headerCtp, document);
XWPFRun run = headerParagraph.getRun(headerCtr);
InputStream pictureInputStream = new FileInputStream("D:\\logo.jpg");
run.addPicture(pictureInputStream, XWPFDocument.PICTURE_TYPE_JPEG, "logo.jpg", 300, 150);
pictureInputStream.close();
run.addTab();
run.setText(contentName);
setTabStop(headerCtp, STTabJc.Enum.forString("right"), BigInteger.valueOf(9000));
XWPFParagraph[] headerParagraphs = {headerParagraph};
CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
XWPFHeaderFooterPolicy headerFooterPolicy = new XWPFHeaderFooterPolicy(document, sectPr);
headerFooterPolicy.createHeader(STHdrFtr.DEFAULT, headerParagraphs);
setTabStop method
private static void setTabStop(CTP oCTP, STTabJc.Enum oSTTabJc, BigInteger oPos) {
CTPPr oPPr = oCTP.getPPr();
if (oPPr == null) {
oPPr = oCTP.addNewPPr();
}
CTTabs oTabs = oPPr.getTabs();
if (oTabs == null) {
oTabs = oPPr.addNewTabs();
}
CTTabStop oTabStop = oTabs.addNewTab();
oTabStop.setVal(oSTTabJc);
oTabStop.setPos(oPos);
}
The trouble I am having is that the image is loaded in the run, meaning the size of the pictures array is 1, however it isn't getting displayed in the document.
I have tried numerous solutions such as the following ones:
Add image into a word .docx document header using Apache POI XWPF
how to add a picture to a .docx document with Apache POI XWPF in java
Java - POI - Add a picture to the header
How i can add an Image as my header in a word document using Apache POI
Any hints and ideas as to what I may be doing wrong are welcome.
Thanks.
I am using Apace POI to process some documents and I would like to add a header/footer which would consist of multiple paragraphs, but I would like for them to be displayed on the same line.
This is my attempt so far:
XWPFDocument document = new XWPFDocument();
// adding header and footer
CTP ctp = CTP.Factory.newInstance();
CTR ctr = ctp.addNewR();
// create footer components
CTText footerCopyrightText = ctr.addNewT();
footerCopyrightText.setStringValue("\u00A9" + " My Website - " + Calendar.getInstance().get(Calendar.YEAR));
CTText footerPageText = ctr.addNewT();
footerPageText.setStringValue(document.getProperties().getExtendedProperties().getUnderlyingProperties().getPages() + "");
XWPFParagraph footerCopyrightParagraph = new XWPFParagraph( ctp, document );
footerCopyrightParagraph.setAlignment(ParagraphAlignment.CENTER);
XWPFParagraph footerPageParagraph = new XWPFParagraph(ctp, document);
footerPageParagraph.setAlignment(ParagraphAlignment.RIGHT);
XWPFParagraph[] footerParagraphs = {footerCopyrightParagraph, footerPageParagraph};
CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
XWPFHeaderFooterPolicy headerFooterPolicy = new XWPFHeaderFooterPolicy(document, sectPr );
headerFooterPolicy.createFooter(STHdrFtr.DEFAULT, footerParagraphs);
However, the end result so far is that I get a single right-aligned text, which consists of the two XWPFParagraphs, concatenated.
I have also checked some other examples here on Stack Overflow (there was one for a Header, but I didn't manage to get it to work).
A basic idea of what I want to achieve is this: http://imgur.com/jrwVO0F
Any ideas on what I am doing wrong?
Thank you,
Add Tabstops and use them
Here's my draft - printing my Name Left, Center and Right on a A4 Document. I have no clue whatsoever as to how those position elements are calculated though... Code to add tabstops is from Java Apache POI Tab Stop word document
import java.awt.Desktop;
import java.io.*;
import java.math.BigInteger;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
public class POIExample {
public static void main(String[] args) {
try {
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph = document.createParagraph();
XWPFRun tmpRun = paragraph.createRun();
tmpRun.setText("JAN");
tmpRun.addTab();
tmpRun.setText("JAN");
tmpRun.addTab();
tmpRun.setText("JAN");
BigInteger pos1 = BigInteger.valueOf(4500);
setTabStop(paragraph, STTabJc.Enum.forString("center"), pos1);
BigInteger pos2 = BigInteger.valueOf(9000);
setTabStop(paragraph, STTabJc.Enum.forString("right"), pos2);
File f = File.createTempFile("poi", ".docx");
try (FileOutputStream fo = new FileOutputStream(f)) {
document.write(fo);
}
Desktop.getDesktop().open(f);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void setTabStop(XWPFParagraph oParagraph, STTabJc.Enum oSTTabJc, BigInteger oPos) {
CTP oCTP = oParagraph.getCTP();
CTPPr oPPr = oCTP.getPPr();
if (oPPr == null) {
oPPr = oCTP.addNewPPr();
}
CTTabs oTabs = oPPr.getTabs();
if (oTabs == null) {
oTabs = oPPr.addNewTabs();
}
CTTabStop oTabStop = oTabs.addNewTab();
oTabStop.setVal(oSTTabJc);
oTabStop.setPos(oPos);
}
}
So, after some tinkering, I finally have a functioning version. Here's hoping it will prove useful to other users as well.
Creating footer object code
// create footer components
XWPFDocument document = new XWPFDocument();
CTP footerCtp = CTP.Factory.newInstance();
CTR footerCtr = footerCtp.addNewR();
XWPFParagraph footerCopyrightParagraph = new XWPFParagraph(footerCtp, document);
document.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();
XWPFRun run = footerCopyrightParagraph.getRun(footerCtr);
run.setText("My Website.com");
run.addTab();
run.setText("\u00A9" + " My Website - " + Calendar.getInstance().get(Calendar.YEAR));
run.addTab();
run.setText("Right Side Text");
setTabStop(footerCtp, STTabJc.Enum.forString("right"), BigInteger.valueOf(9000));
XWPFParagraph[] footerParagraphs = {footerCopyrightParagraph};
CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();
XWPFHeaderFooterPolicy headerFooterPolicy = new XWPFHeaderFooterPolicy(document, sectPr);
headerFooterPolicy.createFooter(STHdrFtr.DEFAULT, footerParagraphs);
SetTabStop method
private static void setTabStop(CTP oCTP, STTabJc.Enum oSTTabJc, BigInteger oPos) {
CTPPr oPPr = oCTP.getPPr();
if (oPPr == null) {
oPPr = oCTP.addNewPPr();
}
CTTabs oTabs = oPPr.getTabs();
if (oTabs == null) {
oTabs = oPPr.addNewTabs();
}
CTTabStop oTabStop = oTabs.addNewTab();
oTabStop.setVal(oSTTabJc);
oTabStop.setPos(oPos);
}