Java Apache POI: place an image in a specific location - java

I need to place an image in a specific location in docx file. I can place an image at any paragraph and even create a new paragraph, but aligning breaks.
I tried to put a placeholder in the document and put my image there. Here is my code:
try (XWPFDocument doc = new XWPFDocument(
Objects.requireNonNull(getClass().getClassLoader().getResourceAsStream(filePath)));
) {
List<XWPFParagraph> xwpfParagraphList = doc.getParagraphs();
for (XWPFParagraph xwpfParagraph : xwpfParagraphList) {
if (Objects.equals(xwpfParagraph.getText().trim(), "QR")) {
InputStream is = new ByteArrayInputStream(qr);
XWPFRun qrRun = xwpfParagraph.createRun();
qrRun.addPicture(is, XWPFDocument.PICTURE_TYPE_JPEG, "qr", Units.toEMU(100), Units.toEMU(120));
is.close();
}
...
and the output docx looks like this:
enter image description here
How to place an image at the place, where the QR placeholder is located?

Related

Generate Inter-Document Hyperlink with Apache POI in Java

I'm generating an XWPFDocument with Apache POI (never used it before this) and I'd like to link one paragraph to another paragraph inside the same .docx document. Is this possible using POI's native functionality or do I need to deep-dive into XML Bean wrapper classes (i.e. CTP) to hand-jam this or am I out of luck? Every instance of a question regarding hyperlinks and POI that I have seen references creating either an external-type hyperlink or a link between Excel workbook sheets. I am as of now only able to generate a 'hyperlink' in the sense of ctrl-clicking the paragraph inside the finished document and it appears to simply do a text search starting from the top of the document. Here's the code I am currently using to achieve this. Thanks in advance!
public static void addInternalHyperlink(XWPFParagraph origin, String text, XWPFParagraph target) {
if (target != null) {
// Create the hyperlink itself
CTHyperlink link = origin.getCTP().addNewHyperlink();
link.setAnchor(target.getText());
// Create hyperlink text
CTText linkText = CTText.Factory.newInstance();
linkText.setStringValue(text);
CTR ctr = CTR.Factory.newInstance();
ctr.setTArray(new CTText[] {linkText});
// Format hyperlink text
CTFonts fonts = CTFonts.Factory.newInstance();
fonts.setAscii("Times New Roman");
CTRPr rpr = ctr.addNewRPr();
CTColor color = CTColor.Factory.newInstance();
color.setVal("0000FF");
rpr.setColor(color);
CTRPr rpr1 = ctr.addNewRPr();
rpr1.addNewU().setVal(STUnderline.SINGLE);
// Insert formatted text into link
link.setRArray(new CTR[] {ctr});
}
}
Please note that I'd like to use the 'origin' argument as the paragraph containing the actual link, the 'text' argument as the link text, and the 'target' argument as the actual link destination.
UPDATE: Here's an XML snippet containing a sample paragraph which I have linked to a section heading via the Word GUI.
<w:p w14:paraId="5B1C3A0C" w14:textId="659E388D" w:rsidR="00A4419C" w:rsidRDefault="00A4419C" w:rsidP="00A4419C"><w:hyperlink w:anchor="_Another_Heading" w:history="1"><w:r w:rsidRPr="00A4419C"><w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr><w:t>Here is some stuff that could b</w:t></w:r><w:r w:rsidRPr="00A4419C"><w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr><w:t>e</w:t></w:r><w:r w:rsidRPr="00A4419C"><w:rPr><w:rStyle w:val="Hyperlink"/></w:rPr><w:t xml:space="preserve"> the link</w:t></w:r></w:hyperlink></w:p><w:p w14:paraId="19996B78" w14:textId="5C39B081" w:rsidR="00A4419C" w:rsidRPr="00A4419C" w:rsidRDefault="00A4419C" w:rsidP="00A4419C"><w:pPr><w:pStyle w:val="Heading1"/></w:pPr><w:bookmarkStart w:id="0" w:name="_Another_Heading"/><w:bookmarkEnd w:id="0"/><w:r><w:t>Another Heading</w:t></w:r><w:bookmarkStart w:id="1" w:name="_GoBack"/><w:bookmarkEnd w:id="1"/></w:p>
The solution falls into two parts.
First we need a XWPFHyperlinkRun whose target is an anchor in the document.
Second we need that target anchor, which can be a bookmark in the document for example. So we need creating such bookmark in the document.
Unfortunately both is not supported using only high level classes of apache poi until now. So we need the low level classes form ooxml-schemas too.
The following code works using apache poi 4.0.0 together with ooxml-schemas-1.4.
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTBookmark;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTHyperlink;
import java.math.BigInteger;
public class CreateWordHyperlinkBookmark {
static XWPFHyperlinkRun createHyperlinkRunToAnchor(XWPFParagraph paragraph, String anchor) throws Exception {
CTHyperlink cthyperLink=paragraph.getCTP().addNewHyperlink();
cthyperLink.setAnchor(anchor);
cthyperLink.addNewR();
return new XWPFHyperlinkRun(
cthyperLink,
cthyperLink.getRArray(0),
paragraph
);
}
static XWPFParagraph createBookmarkedParagraph(XWPFDocument document, String anchor, int bookmarkId) {
XWPFParagraph paragraph = document.createParagraph();
CTBookmark bookmark = paragraph.getCTP().addNewBookmarkStart();
bookmark.setName(anchor);
bookmark.setId(BigInteger.valueOf(bookmarkId));
XWPFRun run = paragraph.createRun();
paragraph.getCTP().addNewBookmarkEnd().setId(BigInteger.valueOf(bookmarkId));
return paragraph;
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument();
String anchor = "hyperlink_target";
int bookmarkId = 0;
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("This is a text paragraph having ");
//create hyperlink run
XWPFHyperlinkRun hyperlinkrun = createHyperlinkRunToAnchor(paragraph, anchor);
hyperlinkrun.setText("a link to an bookmark anchor");
hyperlinkrun.setColor("0000FF");
hyperlinkrun.setUnderline(UnderlinePatterns.SINGLE);
run = paragraph.createRun();
run.setText(" in it.");
//some empty paragraphs
for (int i = 0; i < 10; i++) {
paragraph = document.createParagraph();
}
//create bookmarked paragraph as the hyperlink target
paragraph = createBookmarkedParagraph(document, anchor, bookmarkId++);
run = paragraph.getRuns().get(0);
run.setText("This is the target.");
FileOutputStream out = new FileOutputStream("CreateWordHyperlinkBookmark.docx");
document.write(out);
out.close();
document.close();
}
}

For Text, Appending is not happening in word doc (.docx) in Java Code

I have tried using below code to append the content present in word doc:
XWPFDocument doc=new XWPFDocument();
XWPFParagraph para=doc.createParagraph();
XWPFRun run=para.createRun();
File f=new File("Text.docx");
FileOutputStream fos=new FileOutputStream(f, true);
run.setText("Append The value please");
doc.write(fos);
But, after completion of program, when I try to open the file, it says "We're sorry. We can't open the file. We found a problem with its content" .
I am using below jars:
1. Poi 3.12
2. Poi -ooxml-3.10.1
3. Poi-scratchpad-3.15
4. Ooxml-schemas-1.1
5. Xmlbeans-2.3.0
6. Dom4j-1.1
what is the reason of this & what could be the solution to avoid this?
It is because, you are not opening the file using Apache POI.
Use XWPFDocument to open the word document to append data. Pfb the code.
XWPFDocument doc = new XWPFDocument(OPCPackage.open(fileLocationPath + "Document.doc"));
List<XWPFParagraph> paragraphs = doc.getParagraphs();
XWPFParagraph paragraph = paragraphs.get(paragraphs.size() - 1);
XWPFRun runText = paragraph.createRun();
//if you want to add text
runText.setText("appending here");
//if you want to add image
runText.addPicture(java.io.InputStream pictureData, int pictureType, java.lang.String filename, int width, int height)
try (FileOutputStream out = new FileOutputStream(fileLocationPath + "Document.doc")) {
doc.write(out);
} catch (IOException e) {
e.printStackTrace();
}
if you want to add image - use addPicture Method of XWPFRun - refer here - Apache POI XWPFRun Add Picture

Add an image to an XWPFDocument using Apache POI

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.

Java - How to add a JLabel that contains an image to a pdf file in iText

I want to add an image which is retrieved from the mysql db and print it on a pdf file in iText java. The image retrieved from the db is stored in the lblimg. How do I achieve that in java ?
Here's my partial code:
String filename = null;
int s = 0;
byte[] person_img = null;
uploadbtn = new JButton("Upload a Photo");
uploadbtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
chooser.showOpenDialog(null);
File f = chooser.getSelectedFile();
String filename = f.getAbsolutePath();
try{
File img = new File(filename);
FileInputStream fis = new FileInputStream(img);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
for(int readNum; (readNum = fis.read(buf)) != -1;){
bos.write(buf, 0, readNum);
}
person_img = bos.toByteArray();
fis.close();
}catch(Exception e1){
e1.printStackTrace();
}
}
});
// Partial code for adding image to db
stt.setBytes(8, person_img);
// Partial codes for retrieving image from db
byte[] imageData = rs.getBytes("Image");
format = new ImageIcon(imageData);
lblimg.setIcon(format);
//Creating the document and adding the lblimg (which contains the image retrieved from the db). PLEASE HELP HERE. I CANNOT ADD THE IMAGE TO PDF document.
Document doc = new Document();
PdfWriter.getInstance(doc, new FileOutputStream("Report.pdf"));
doc.open();
doc.add(new Paragraph( // img to be added here ));
Update 1 by Bruno Lowagie
Snippet taken from the full code:
try {
Image i = Image.getInstance((PdfTemplate) lblimg.getIcon());
Document doc = new Document();
PdfWriter.getInstance(doc, new FileOutputStream("Report.pdf"));
doc.open();
Image img = Image.getInstance("ja.png");
doc.add(img);
doc.add(i);
doc.add(new Paragraph("Employee Information", FontFactory.getFont(FontFactory.TIMES_BOLD,18, Font.BOLD, BaseColor.RED)));
doc.add(new Paragraph("______________________________________________________________________________"));
doc.add(new Paragraph("Employee ID is " + val1));
doc.add(new Paragraph("First Name is " + val2 + "\t\t" + " Last Name is " + val3));
doc.add(new Paragraph("Job Position " + val4));
doc.add(new Paragraph("Allowances allowed " + val5));
doc.add(new Paragraph("Salary " + val10));
JOptionPane.showMessageDialog(null, "Report Saved");
doc.close();
} catch(Exception e1) {
e1.printStackTrace();
}
As getIcon returns a javax.swing class and as PdfTemplate is an iText class extending the PdfContentByte class that contains a ByteBuffer of PDF syntax, a ClassCastException is thrown here: (PdfTemplate) lblimg.getIcon()
Update 2 by Bruno Lowagie
The actual question was posted as a comment: How do I retrieve an image which is in a JLabel and add it on a PDF? This question is answered in update 3 of my answer.
Assuming that this contains an image:
byte[] imageData = rs.getBytes("Image");
In other words: assuming that imageData is a valid JPEG, JPEG2000, GIF, PNG, BMP, WMF, TIFF or JBIG2 image, then you can create a com.itextpdf.text.Image object like this:
Image img = Image.getInstance(imageData);
Once you have this img instance, you can add it to the document like this:
document.add(img);
I don't understand why you'd create an ImageIcon instance. Nor is it clear why you refer to a Paragraph object.
Update 1:
Now that I see your full code, I see a very strange line:
Image i = Image.getInstance((PdfTemplate) lblimg.getIcon());
You are casting a javax.swing object to an iText object. This can never work. You should get a ClassCastException at this point in your code.
I also see that you know how to add an image from a file:
Image img = Image.getInstance("ja.png");
doc.add(img);
When you don't have a path to a file, the fastest way you'll find alternative getInstance() methods, is by consulting the Javadoc API documentation: http://api.itextpdf.com/itext/com/itextpdf/text/Image.html#getInstance(byte[])
Update 2:
I have updated the question so that it contains the relevant code. As explained in my answer (that unfortunately wasn't accepted), the following line throws a ClassCastException:
Image i = Image.getInstance((PdfTemplate) lblimg.getIcon());
This exception is caught like this:
} catch(Exception e1) {
e1.printStackTrace();
}
Hence all the code starting with the following line is skipped:
Document doc = new Document();
As a result, no document is created. This is not an iText problem. This is a case of bad exception handling.
Update 3:
Finally, the real question is asked in a comment: In simple words: How to I retrieve an image which is in a JLabel and add it on a PDF?
Again it turns out that I have already answered that question. I referred to the Javadoc API documentation for the Image class. We find the following getInstance() method: http://api.itextpdf.com/itext/com/itextpdf/text/Image.html#getInstance(java.awt.Image, java.awt.Color)
In other words, we can create an iText Image object using a Java Image object. You have the following line in your code:
ImageIcon format = new ImageIcon(imageData);
Or, in your case, you could try something like:
ImageIcon format = (ImageIcon)lblimg.getIcon();
You can get a java.awt.Image object from this ImageIcon like this:
java.awt.Image awtImage = format.getImage();
As per the iText API documentation, you can create an iText image like this:
Image img = Image.getInstance(awtImage, null);

Insert .pdf doc or .png image content into a .docx file using java

How can I insert pdf or png content into a docx file using java?
I've tried using Apache POI API in the following way, but it is not working (it generates some junk doc file):
XWPFDocument doc = new XWPFDocument();
String pdf = "D://capture1.pdf";
PdfReader reader = new PdfReader(pdf);
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
TextExtractionStrategy strategy = parser.processContent(i,new SimpleTextExtractionStrategy());
String text = strategy.getResultantText();
XWPFParagraph p = doc.createParagraph();
XWPFRun run = p.createRun();
run.setText(text);
run.addBreak(BreakType.PAGE);
}
FileOutputStream out1 = new FileOutputStream("D://javadomain1.docx");
doc.write(out1);
out1.close();
reader.close();
System.out.println("Document converted successfully");
You should be able to do it with POI, and you can certainly do it using docx4j.
Here's sample code for inserting an image using docx4j.
Note that to "insert a PDF", you need to OLE embed it. That's more difficult, since you need to convert the PDF to a suitable binary OLE object. In docx4j, helper code for doing this is part of the commercial Enterprise edition.

Categories