Apache POI - add multiple paragraphs to header/footer on the same line - java

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);
}

Related

Add footer to Java iTextPdf 7 with page number

I am trying to add footer containing username on the left and page number of total pages on the right
I am using iTextPdf 7 on Java but I am not able to find any useful way to do that
please find below my code
The import :
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
small sample of the code :
PdfWriter pdfWriter = new PdfWriter(path);
PdfDocument pdfDocument = new PdfDocument(pdfWriter);
pdfDocument.addNewPage();
Document document = new Document(pdfDocument);
Paragraph dateParagraph = new Paragraph(todayDate.toString());
dateParagraph.setTextAlignment(TextAlignment.RIGHT);
document.add(dateParagraph);
document.close();
footer sample :
this is sample for the needed footer
A very basic example that does the job. There are numerous ways of adding footers with page numbers in iText and depending on your context one way might be more suitable than the others. The sample I provide is a good start:
Document document = new Document(pdfDocument, PageSize.A4, false);
for (int i = 0; i < 10; i++) {
if (i != 0) {
document.add(new AreaBreak());
}
document.add(new Paragraph("Hello"));
}
int totalPages = document.getRenderer().getCurrentArea().getPageNumber();
for (int i = 1; i <= totalPages; i++) {
Paragraph footer = createFooter(totalPages);
footer.setFixedPosition(i, 40, 40, 300);
document.add(footer);
}
document.close();
Note that I am using Paragraph as a footer element but you can use Table or anything else really:
private Paragraph createFooter(int totalPages) {
Paragraph p = new Paragraph();
Text currentPage = new Text("");
currentPage.setNextRenderer(new CurrentPageNumberRenderer(currentPage));
p.add("Page ").add(currentPage).add(" of ").add(new Text(String.valueOf(totalPages)));
return p;
}
Here is our custom renderer that will assign page number dynamically:
private static class CurrentPageNumberRenderer extends TextRenderer {
public CurrentPageNumberRenderer(Text textElement) {
super(textElement);
}
#Override
public LayoutResult layout(LayoutContext layoutContext) {
int currentPageNumber = layoutContext.getArea().getPageNumber();
setText(String.valueOf(currentPageNumber));
return super.layout(layoutContext);
}
#Override
public IRenderer getNextRenderer() {
return new CurrentPageNumberRenderer((Text) modelElement);
}
}
Visual result:

how create TextBox in a cell of table in document .docx using apache poi

I used Javafx and
I created a table using apache poi:
XWPFDocument document = new XWPFDocument();
XWPFParagraph paragraph = document.createParagraph();
XWPFTable table = document.createTable(4, 3);
and created the paragraph like the paragraph below:
XWPFParagraph p1 = table.getRow(0).getCell(2).getParagraphs().get(0);
XWPFRun r1 = p1.createRun();
r1.setText(category_number.getText() + category.toString());
Now, I want create a TextBox in a one cell of a row but don't know how address Cell and Row to a textBox and set text and alignment textBox.
Please Help me ):
A text box in a *.docx is a shape in the document content. Creating shapes is not yet implemented in XWPF. But it can be done using the underlying ooxml-schemas classes.
Example:
import java.io.FileOutputStream;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTPicture;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTxbxContent;
import com.microsoft.schemas.vml.CTGroup;
import com.microsoft.schemas.vml.CTShape;
import org.w3c.dom.Node;
public class CreateWordTextBoxInTable {
public static void main(String[] args) throws Exception {
XWPFDocument document= new XWPFDocument();
XWPFParagraph paragraph = document.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText("The table:");
XWPFTable table = document.createTable(4, 3);
// table header row
for (int c = 0; c < 3; c++ ) {
paragraph = table.getRow(0).getCell(c).getParagraphArray(0);
if (paragraph == null) paragraph = table.getRow(0).getCell(c).addParagraph();
run = paragraph.createRun();
run.setText("Column " + (c+1));
}
// get run in cell for text box
XWPFTableCell cell = table.getRow(1).getCell(1);
paragraph = cell.getParagraphArray(0);
if (paragraph == null) paragraph = cell.addParagraph();
run = paragraph.createRun();
// create inline text box in run
// first crfeate group shape
CTGroup ctGroup = CTGroup.Factory.newInstance();
// now add shape to group shape
CTShape ctShape = ctGroup.addNewShape();
ctShape.setStyle("width:100pt;height:36pt");
// add text box content to shape
CTTxbxContent ctTxbxContent = ctShape.addNewTextbox().addNewTxbxContent();
XWPFParagraph textboxparagraph = new XWPFParagraph(ctTxbxContent.addNewP(), (IBody)cell);
textboxparagraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun textboxrun = textboxparagraph.createRun();
textboxrun.setText("The TextBox content...");
textboxrun.setFontSize(10);
// add group shape as picture to the run
Node ctGroupNode = ctGroup.getDomNode();
CTPicture ctPicture = CTPicture.Factory.parse(ctGroupNode);
CTR cTR = run.getCTR();
cTR.addNewPict();
cTR.setPictArray(0, ctPicture);
FileOutputStream out = new FileOutputStream("test.docx");
document.write(out);
out.close();
}
}
This code was tested using apache poi 4.0.1 and needs the ooxml-schemas-1.4.jar in class path.

Apache poi replace existing picture on header

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);
}

Replace a image with Apache POI

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));

How to create table in ms word doc with rowspan and colspan using apache POI?

I am using APACHE POI to create word doc containing table. The table looks like as follows, I want to create cells with rowspan and colspan(as shown in figure).
Is it possible using APACHE POI ?
Is there any other java library for the same. Any help is appreciated.
You can try this.
public class Word2Doc {
public static void main(String aaa[]){
System.out.println("This is Word To Document Class");
File file = null;
FileOutputStream fos = null;
XWPFDocument document = null;
XWPFParagraph para = null;
XWPFRun run = null;
try {
// Create the first paragraph and set it's text.
document = new XWPFDocument();
para = document.createParagraph();
para.setAlignment(ParagraphAlignment.CENTER);
para.setSpacingAfter(100);
para.setSpacingAfterLines(10);
run = para.createRun();
run.addBreak(); // similar to new line
run.addBreak();
XWPFTable table = document.createTable(4, 3);
table.setRowBandSize(1);
table.setWidth(1);
table.setColBandSize(1);
table.setCellMargins(1, 1, 100, 30);
table.setStyleID("finest");
table.getRow(1).getCell(1).setText("EXAMPLE OF TABLE");
table.getRow(2).getCell(1).setText("fine");
XWPFParagraph p1 = table.getRow(0).getCell(0).getParagraphs().get(0);
p1.setAlignment(ParagraphAlignment.CENTER);
XWPFRun r1 = p1.createRun();
r1.setBold(true);
r1.setText("Test Name");
r1.setItalic(true);
r1.setFontFamily("Courier");
r1.setUnderline(UnderlinePatterns.DOT_DOT_DASH);
r1.setTextPosition(100);
//Locating the cell values
table.getRow(0).getCell(1).setText("Value");
table.getRow(0).getCell(2).setText("Normal Ranges");
table.getRow(2).getCell(2).setText("numeric values");
table.setWidth(120);
file = new File("c:\\nwhpe.docx");
if(file.exists())
file.delete();
FileOutputStream out = new FileOutputStream(file);
document.write(out);
out.close();
} catch(Exception e){e.printStackTrace();}
}
}

Categories