Customize header of Table of Content - apache-poi

Good morning
I try to add a Table of Content to my doc generated with apache-poi.
I followed this solution
Code url
and it works great.
I have only a problem. By default the header of the TOC is "Table of Content" as you can see from the following image
TOC HEADER IMAGE
I would like to change it with another text. Is it possible?
Thanks
Regards

Good morning
Thanks to Axel Richter advice this is the correct code that generate index without the automatic title Table of Content.
I rewrote the code with custom title of TOC
public class App {
public static void main(String[] args) throws Exception {
XWPFDocument doc= new XWPFDocument();
addCustomHeadingStyle(doc, "heading 1", 1);
addCustomHeadingStyle(doc, "heading 2", 2);
// the body content
XWPFParagraph paragraph = doc.createParagraph();
XWPFRun run=paragraph.createRun();
// set custom title of TOC
run.setBold(true);
run.setFontSize(30);
run.setText("INDEX"); //or whatever other text
CTP ctP = paragraph.getCTP();
CTSimpleField toc = ctP.addNewFldSimple();
toc.setInstr("TOC \\h");
toc.setDirty(STOnOff.TRUE);
run.setText("The Body:");
paragraph = doc.createParagraph();
run=paragraph.createRun();
run.setText("Lorem ipsum");
paragraph.setStyle("heading 1");
paragraph = doc.createParagraph();
run=paragraph.createRun();
run.addBreak(BreakType.PAGE);
run.setText("Lorem ipsum");
paragraph.setStyle("heading 2");
paragraph = doc.createParagraph();
run=paragraph.createRun();
run.addBreak(BreakType.PAGE);
run.setText("Lorem ipsum");
FileOutputStream fos = new FileOutputStream("D:\\toc.docx");
doc.write(fos);
}
private static void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) {
CTStyle ctStyle = CTStyle.Factory.newInstance();
ctStyle.setStyleId(strStyleId);
CTString styleName = CTString.Factory.newInstance();
styleName.setVal(strStyleId);
ctStyle.setName(styleName);
CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
indentNumber.setVal(BigInteger.valueOf(headingLevel));
// lower number > style is more prominent in the formats bar
ctStyle.setUiPriority(indentNumber);
CTOnOff onoffnull = CTOnOff.Factory.newInstance();
ctStyle.setUnhideWhenUsed(onoffnull);
// style shows up in the formats bar
ctStyle.setQFormat(onoffnull);
// style defines a heading of the given level
CTPPr ppr = CTPPr.Factory.newInstance();
ppr.setOutlineLvl(indentNumber);
ctStyle.setPPr(ppr);
XWPFStyle style = new XWPFStyle(ctStyle);
// is a null op if already defined
XWPFStyles styles = docxDocument.createStyles();
style.setType(STStyleType.PARAGRAPH);
styles.addStyle(style);
}
}

Related

How add to a picture to previously created word document with poi

In my project, I'm creating word document (.docx) with apache poi. When the document created, project sending it to approvers via e-mail. I want to add a approver's signature picture to specific place to previously created word document, when the approver is approved the document. But I couldn't figure it out how to do it on previously created word document.
Can I add a picture to previously created word document or do i have to rebuilt it?
UPDATE
I tried this code part
FileInputStream docxFile=new FileInputStream(System.getProperty("jboss.server.data.dir")+"/corrolog/TestWS/"+strSO+" Test Workscope "+revision+".docx");
FileInputStream approverFile=new FileInputStream(approvers);
XWPFDocument doc = new XWPFDocument(docxFile);
List<XWPFParagraph> xwpfParagraphList = doc.getParagraphs();
for (XWPFParagraph xwpfParagraph : xwpfParagraphList) {
for (XWPFRun xwpfRun : xwpfParagraph.getRuns()) {
String text = xwpfRun.getText(0);
System.out.println(text);
if (text == "approved signature" && text.equals("approved signature")) {
text.replace("approved signature", "");
xwpfRun.setText(text);
xwpfRun.addPicture(approverFile, XWPFDocument.PICTURE_TYPE_PNG, "approved", Units.toEMU(130), Units.toEMU(55));
}
}
}
FileOutputStream out = new FileOutputStream(System.getProperty("jboss.server.data.dir")+"/corrolog/TestWS/"+strSO+" Test Workscope "+revision+" Approved.docx");
doc.write(out);
out.close();
But it doesn't add picture to XWPFRun.
SOLUTION
String approvers=v2500Service.getApproverSignatures(approver).get(0).getImagePath();
FileInputStream approverFile=new FileInputStream(approvers);)
XWPFDocument doc = new XWPFDocument(Files.newInputStream(Paths.get(System.getProperty("jboss.server.data.dir")+"/corrolog/TestWS/EV13077-04 Test Workscope Rev0.docx")));
Iterator<IBodyElement> iter = doc.getBodyElementsIterator();
while (iter.hasNext()) {
IBodyElement elem = iter.next();
if (elem instanceof XWPFTable) {
for(XWPFTableRow rows:((XWPFTable) elem).getRows())
{
for(XWPFTableCell cell:rows.getTableCells())
{
text=cell.getText();
System.out.println(text);
if(text.equals("approved signature"))
{
text.replace("approved signature", "");
cell.getParagraphArray(0).removeRun(0);
cell.getParagraphArray(0).createRun();
cell.getParagraphArray(0).getRuns().get(0).addPicture(approverFile, XWPFDocument.PICTURE_TYPE_PNG, "approved", Units.toEMU(130), Units.toEMU(55));
}
}
}
System.out.println(((XWPFTable) elem).getRow(0).getCell(0).getText());
}
}
It was about XWPFParagraph, it has to be iterate XWPFTable.

how to add comment to a table of word by apache poi

I want to write a comment to a existing word document programmatically using apache poi. I have successfully added comments to the paragraph by the method mentioned here, but when adding comments to the table, I don't know how to associate it with real comments
BigInteger cId = BigInteger.ZERO;
ctComment = comments.addNewComment();
ctComment.setAuthor("Axel Ríchter");
ctComment.setInitials("AR");
ctComment.setDate(new GregorianCalendar(Locale.US));
ctComment.addNewP().addNewR().addNewT().setStringValue("The first comment.");
ctComment.setId(cId);
paragraph = document.createParagraph();
paragraph.getCTP().addNewCommentRangeStart().setId(cId);
run = paragraph.createRun();
run.setText("Paragraph with the first comment.");
paragraph.getCTP().addNewCommentRangeEnd().setId(cId);
paragraph.getCTP().addNewR().addNewCommentReference().setId(cId);
in paragraph, we can use paragraph.getCTP().addNewR().addNewCommentReference().setId() to link a comment, but there seems no similar method in table. what should i do? I am a beginner to apache poi, any suggestions are greatly appreciated.
The short answer to your question how to comment a whole table is: You get the first paragraph in first cell of that table to set the CommentRangeStart as the first element in that paragraph. Then you get the last paragraph in last cell of that table to set the CommentRangeEnd as the last element in that paragraph.
But if you wants changing a already present Word document, then much more needs to be taken into account. What if there are comment already? My example you are linking is for creating a new Word document from scratch. So there cannot be comments already before. I have provided also How to manipulate content of a comment with Apache POI. But this rely on already present comments. Now we have to use a combination of both. This needs to take into account already present comments as well as a not already present comments document which then needs to be new created.
Additional there is difficulty to to set the CommentRangeStart as the first element in a already present paragraph. There are no methods for this. So we need using very low level XML manipulating to achieve this.
The following example needs a WordDocument.docx having at least one table. This whole table gets commented then.
import java.io.*;
import org.apache.poi.*;
import org.apache.poi.ooxml.*;
import org.apache.poi.openxml4j.opc.*;
import org.apache.xmlbeans.*;
import org.apache.poi.xwpf.usermodel.*;
import static org.apache.poi.ooxml.POIXMLTypeLoader.DEFAULT_XML_OPTIONS;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import javax.xml.namespace.QName;
import java.math.BigInteger;
import java.util.GregorianCalendar;
import java.util.Locale;
public class WordCommentWholeTable {
//a method to get or create the CommentsDocument /word/comments.xml in the *.docx ZIP archive
private static MyXWPFCommentsDocument createCommentsDocument(XWPFDocument document) throws Exception {
MyXWPFCommentsDocument myXWPFCommentsDocument = null;
//trying to get the CommentsDocument
for (POIXMLDocumentPart.RelationPart rpart : document.getRelationParts()) {
String relation = rpart.getRelationship().getRelationshipType();
if (relation.equals(XWPFRelation.COMMENT.getRelation())) {
POIXMLDocumentPart part = rpart.getDocumentPart();
myXWPFCommentsDocument = new MyXWPFCommentsDocument(part.getPackagePart());
String rId = document.getRelationId(part);
document.addRelation(rId, XWPFRelation.COMMENT, myXWPFCommentsDocument);
}
}
//create a new CommentsDocument if there is not one already
if (myXWPFCommentsDocument == null) {
OPCPackage oPCPackage = document.getPackage();
PackagePartName partName = PackagingURIHelper.createPartName("/word/comments.xml");
PackagePart part = oPCPackage.createPart(
partName,
"application/vnd.openxmlformats-officedocument.wordprocessingml.comments+xml");
myXWPFCommentsDocument = new MyXWPFCommentsDocument(part);
document.addRelation(null, XWPFRelation.COMMENT, myXWPFCommentsDocument);
}
return myXWPFCommentsDocument;
}
//a method to get the next comment Id from CTComments
private static BigInteger getCommentId(CTComments comments) {
BigInteger cId = BigInteger.ZERO;
for (CTComment ctComment : comments.getCommentList()) {
if (ctComment.getId().compareTo(cId) == 1) {
cId = ctComment.getId();
}
}
cId = cId.add(BigInteger.ONE);
return cId;
}
//method to set CommentRangeStart as first element in paragraph
private static CTMarkupRange insertCommentRangeStartAsFirstElement(XWPFParagraph paragraph) {
String uri = CTMarkupRange.type.getName().getNamespaceURI();
String localPart = "commentRangeStart";
XmlCursor cursor = paragraph.getCTP().newCursor();
cursor.toFirstChild();
cursor.beginElement(localPart, uri);
cursor.toParent();
CTMarkupRange commentRangeStart = (CTMarkupRange)cursor.getObject();
cursor.dispose();
return commentRangeStart;
}
public static void main(String[] args) throws Exception {
XWPFDocument document = new XWPFDocument(new FileInputStream("WordDocument.docx"));
MyXWPFCommentsDocument myXWPFCommentsDocument = createCommentsDocument(document);
CTComments comments = myXWPFCommentsDocument.getComments();
CTComment ctComment;
XWPFParagraph paragraph;
XWPFRun run;
//comment for the table
BigInteger cId = getCommentId(comments);
ctComment = comments.addNewComment();
ctComment.setAuthor("Axel Ríchter");
ctComment.setInitials("AR");
ctComment.setDate(new GregorianCalendar(Locale.US));
ctComment.addNewP().addNewR().addNewT().setStringValue("This is a comment for whole table.");
ctComment.setId(cId);
//get first paragraph in first table cell to set CommentRangeStart
XWPFTable table = document.getTables().get(0);
XWPFTableRow row = table.getRow(0);
XWPFTableCell cell = row.getCell(0);
paragraph = cell.getParagraphArray(0);
CTMarkupRange commentRangeStart = insertCommentRangeStartAsFirstElement(paragraph);
commentRangeStart.setId(cId);
//get last paragraph in last table cell to set CommentRangeEnd and CommentReference
row = table.getRows().get(table.getRows().size()-1);
cell = row.getTableCells().get(row.getTableCells().size()-1);
paragraph = cell.getParagraphs().get(cell.getParagraphs().size()-1);
paragraph.getCTP().addNewCommentRangeEnd().setId(cId);
paragraph.getCTP().addNewR().addNewCommentReference().setId(cId);
FileOutputStream out = new FileOutputStream("WordDocumentWithComments.docx");
document.write(out);
out.close();
document.close();
}
//a wrapper class for the CommentsDocument /word/comments.xml in the *.docx ZIP archive
private static class MyXWPFCommentsDocument extends POIXMLDocumentPart {
private CTComments comments;
private MyXWPFCommentsDocument(PackagePart part) throws Exception {
super(part);
try {
comments = CommentsDocument.Factory.parse(part.getInputStream(), DEFAULT_XML_OPTIONS).getComments();
} catch (Exception ex) {
// there was no comments yet
}
if (comments == null) comments = CommentsDocument.Factory.newInstance().addNewComments();
}
private CTComments getComments() {
return comments;
}
#Override
protected void commit() throws IOException {
XmlOptions xmlOptions = new XmlOptions(DEFAULT_XML_OPTIONS);
xmlOptions.setSaveSyntheticDocumentElement(new QName(CTComments.type.getName().getNamespaceURI(), "comments"));
PackagePart part = getPackagePart();
OutputStream out = part.getOutputStream();
comments.save(out, xmlOptions);
out.close();
}
}
}

Apache POI XWPFRun can't get EMF pictures

apache poi 3.17
XWPFDocument document = new XWPFDocument(new FileInputStream("test.docx"));
Iterator<IBodyElement> iterator = document.getBodyElementsIterator();
while (iterator.hasNext()) {
IBodyElement iBodyElement = iterator.next();
switch (iBodyElement.getElementType()) {
case PARAGRAPH:
XWPFParagraph paragraph = (XWPFParagraph) iBodyElement;
for(XWPFRun run :paragraph.getRuns()){
for(XWPFPicture picture : run.getEmbeddedPictures()){
System.out.println(picture.getPictureData().getFileName());
}
}
break;
}
}
output
image3.png
image4.png
image5.png
image6.png
image7.png
image8.png
image9.png
image10.png
image11.png
image12.png
image13.png
image14.png
enter image description here
image1.emf and image2.emf are gone
document.getAllPictures() can get all the pictures, but it's XWPFPictureData
I want to takepicture.GetCTPicture().getSpPr().getXfrm().getExt().getCx();
document.getAllPictures() can get all the pictures.
I found CTObject and I can get the width and the height.
but how can I know which CTObject correspond XWPFPictureData?

Xamarin.Forms Action Bar - Center Aligned Image

Using Xamarin.Forms, how do I get the same effect as the application pictured below, specifically to show a centred image on the Action Bar / page tool bar (the section in a blue box)?
I would like to have a long width image in that section, and the solution must work for Android, iOS, Windows Phone, and Universal Windows (even if it means writing custom renderers or platform specific xamarin code).
I suggest you create your own Xamarin.Forms view and handle the navigation by yourself something similar to this:
public class CustomBackNavigationBar : StackLayout
{
public Image BackIcon;
public Image Icon;
public Label IconTitle;
public StackLayout IconContainer;
public CustomBackNavigationBar(string title, string icon)
{
Padding = new Thickness(15,5);
HeightRequest = 40;
Orientation = StackOrientation.Horizontal;
VerticalOptions = LayoutOptions.Start;
BackgroundColor = StaticData.BlueColor;
Spacing = 15;
BackIcon = new Image
{
Source = StaticData.BackIcon,
HorizontalOptions = LayoutOptions.Start
};
Label Title = new Label
{
Text = title,
TextColor = Color.White,
FontSize = Device.GetNamedSize(NamedSize.Default, typeof(Label)),
FontAttributes = FontAttributes.Bold,
VerticalTextAlignment = TextAlignment.Center
};
Icon = new Image
{
Source = icon
};
IconTitle = new Label
{
Text = StaticData.CallAgent,
TextColor = Color.White,
FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label)),
};
IconContainer = new StackLayout
{
HorizontalOptions = LayoutOptions.EndAndExpand,
Spacing = 2,
Children = { Icon, IconTitle }
};
Children.Add(BackIcon);
Children.Add(Title);
Children.Add(IconContainer);
#region Events
BackIcon.GestureRecognizers.Clear();
BackIcon.GestureRecognizers.Add(new TapGestureRecognizer
{
Command = new Command(PopAsync)
});
#endregion
}
async void PopAsync()
{
await App.AppNavigation.PopAsync();
}
}

Java iText Pdf Writer and PrimeFaces Not Refreshing PDF content

Good morning!
I'm using the iText library to create a pdf template and Primefaces to display the content on a web application.
When I ran the first test to see if all the libraries were all set, it was displayed normally. But then I made some changes, and it seems that something is caching my first test in memory and it is the only thing displayed, no matter what changes I make it keeps the same first content. I´ve already cleaned up my netbeans project, closed the IDE and also restarted the computer.
Thats is my tag on the jsf page:
<p:media value="#{atividadeController.pdfContent}" player="pdf" width="100%" height="700px"/>
And here is my method in the managed bean, which is a SessionScoped:
public String preparePdf()
{
try {
ByteArrayOutputStream output = new ByteArrayOutputStream();
Font fontHeader = new Font(Font.FontFamily.HELVETICA, 20, Font.BOLD);
Font fontLine = new Font(Font.FontFamily.TIMES_ROMAN, 14);
Font fontLineBold = new Font(Font.FontFamily.TIMES_ROMAN, 14, Font.BOLD);
Document document = new Document();
PdfWriter.getInstance(document, output);
document.open();
//Writing document
Chunk preface = new Chunk("GERAL", fontHeader);
document.add(preface);
Calendar cal = Calendar.getInstance();
cal.setTime(current.getData());
int year = cal.get(Calendar.YEAR);
int month = 1 + cal.get(Calendar.MONTH);
int day = cal.get(Calendar.DAY_OF_MONTH);
String dateStr = day+"/"+month+"/"+year;
Paragraph dataAndHour = new Paragraph(dateStr, fontLine);
document.add(dataAndHour);
document.close();
pdfContent = new DefaultStreamedContent(new ByteArrayInputStream(output.toByteArray()), "application/pdf");
} catch (Exception e) {
e.printStackTrace();
}
return "/views/view_atividade_pdf";
}
There is no exception on the server log.
I really aprecciate any help. Thanks in advance

Resources