Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.6k views
in Technique[技术] by (71.8m points)

java - Apache POI XWPF adding shapes to header

I'm trying to add some shapes and a logo-file into the header of my word docx document. Adding a picture works for me, but i didn't find any solution how to add a shape. can anyone help me?

String imgFile="logo.png";

XWPFDocument document = new XWPFDocument(new FileInputStream("myfile.docx"));

CTSectPr sectPr = document.getDocument().getBody().addNewSectPr();

XWPFHeaderFooterPolicy headerFooterPolicy = new XWPFHeaderFooterPolicy(document, sectPr);               
XWPFHeader header = headerFooterPolicy.createHeader(XWPFHeaderFooterPolicy.DEFAULT);

XWPFParagraph paragraph = header.getParagraphArray(0);
paragraph.setAlignment(ParagraphAlignment.CENTER);

XWPFRun run = paragraph.createRun();
XWPFPicture picture = run.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, Units.toEMU(195), Units.toEMU(22));

String blipID = "";
for(XWPFPictureData picturedata : header.getAllPackagePictures()) {
  blipID = header.getRelationId(picturedata);
}
picture.getCTPicture().getBlipFill().getBlip().setEmbed(blipID); //now they have a blipID too

At the end the header should look like this

thanks

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Since the apache poi XWPF is really in beta state until now, such things are only possible if one knows exactly how Word will store it's contents into the XML. Then one can work around the inadequacies of apache poi XWPF. You have already used such a workaround which corrects the missed blipID when pictures are added to runs in header or footer.

To discover how Word will store it's contents into the XML is not rocket science. A *.docx file is simply a ZIP file. If one unzip this file using a Zip software, one can simply have a look into the XML files.

As far as I know adding shapes (in this case text boxes) in Word documents is not supported by apache poi directly. For this using the low level underlying objects (in this case CTGroupand CTShape) is needed.

Example: (code should be self explanatory)

import java.io.*;

import org.apache.poi.util.Units;

import org.apache.poi.xwpf.usermodel.*;

import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;

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.openxmlformats.schemas.wordprocessingml.x2006.main.CTTabStop;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTabJc;

import org.w3c.dom.Node;

import java.math.BigInteger;

public class CreateWordHeaderFooterTextBoxPicture {

 public static void main(String[] args) throws Exception {

  XWPFDocument doc= new XWPFDocument();

  // the body content
  XWPFParagraph paragraph = doc.createParagraph();
  XWPFRun run=paragraph.createRun();  
  run.setText("The Body:");

  paragraph = doc.createParagraph();
  run=paragraph.createRun();  
  run.setText("Lorem ipsum....");

  // create header start
  XWPFHeaderFooterPolicy headerFooterPolicy = doc.createHeaderFooterPolicy();
  XWPFHeader header = headerFooterPolicy.createHeader(XWPFHeaderFooterPolicy.DEFAULT);

  // header's first paragraph
  paragraph = header.getParagraphArray(0);
  if (paragraph == null) paragraph = header.createParagraph();
  paragraph.setAlignment(ParagraphAlignment.LEFT);

  // create tab stops
  CTTabStop tabStop = paragraph.getCTP().getPPr().addNewTabs().addNewTab();
  tabStop.setVal(STTabJc.CENTER);
  int twipsPerInch =  1440;
  tabStop.setPos(BigInteger.valueOf(3 * twipsPerInch));

  tabStop = paragraph.getCTP().getPPr().getTabs().addNewTab();
  tabStop.setVal(STTabJc.RIGHT);
  twipsPerInch =  1440;
  tabStop.setPos(BigInteger.valueOf(6 * twipsPerInch));

  // first run in header's first paragraph, to be for first text box
  run = paragraph.createRun(); 
 
  // create inline text box in run
  CTGroup ctGroup = CTGroup.Factory.newInstance();

  CTShape ctShape = ctGroup.addNewShape();
  ctShape.setStyle("width:80pt;height:24pt");
  CTTxbxContent ctTxbxContent = ctShape.addNewTextbox().addNewTxbxContent();
  XWPFParagraph textboxparagraph = new XWPFParagraph(ctTxbxContent.addNewP(), (IBody)header);
  XWPFRun textboxrun = textboxparagraph.createRun();
  textboxrun.setText("The TextBox 1...");
  textboxrun.setFontSize(10);

  Node ctGroupNode = ctGroup.getDomNode(); 
  CTPicture ctPicture = CTPicture.Factory.parse(ctGroupNode);
  CTR cTR = run.getCTR();
  cTR.addNewPict();
  cTR.setPictArray(0, ctPicture);

  // add tab to run
  run.addTab();

  // second run in header's first paragraph, to be for logo picture
  run = paragraph.createRun();  

  // add the picture in the headers run
  String imgFile="Logo.png";
  XWPFPicture picture = run.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, Units.toEMU(195), Units.toEMU(22));

  String blipID = "";
  for(XWPFPictureData picturedata : header.getAllPackagePictures()) {
   blipID = header.getRelationId(picturedata);
  }
  picture.getCTPicture().getBlipFill().getBlip().setEmbed(blipID);

  // add tab to run
  run.addTab();

  // third run in header's first paragraph, to be for second text box
  run = paragraph.createRun();  

  // create inline text box in run
  ctGroup = CTGroup.Factory.newInstance();

  ctShape = ctGroup.addNewShape();
  ctShape.setStyle("width:80pt;height:24pt");
  ctTxbxContent = ctShape.addNewTextbox().addNewTxbxContent();
  textboxparagraph = new XWPFParagraph(ctTxbxContent.addNewP(), (IBody)header);
  textboxrun = textboxparagraph.createRun();
  textboxrun.setText("The TextBox 2...");
  textboxrun.setFontSize(10);

  ctGroupNode = ctGroup.getDomNode(); 
  ctPicture = CTPicture.Factory.parse(ctGroupNode);
  cTR = run.getCTR();
  cTR.addNewPict();
  cTR.setPictArray(0, ctPicture);

  // create header end


  // create footer start
  XWPFFooter footer = headerFooterPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT);

  paragraph = footer.getParagraphArray(0);
  if (paragraph == null) paragraph = footer.createParagraph();
  paragraph.setAlignment(ParagraphAlignment.CENTER);

  run = paragraph.createRun();  
  run.setText("The Footer:");

      
  doc.write(new FileOutputStream("test.docx"));

 }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...