我一直在尝试使用Apache POI将.png图片添加到.docx文件头中。我没有找到对我有帮助的方法。有人知道怎么做吗?这段代码我只能添加文本。
XWPFDocument docc = new XWPFDocument(); CTP ctpHeader = CTP.Factory.newInstance(); CTR ctrHeader = ctpHeader.addNewR(); CTText ctHeader = ctrHeader.addNewT(); String headerText = "mi encabezado"; ctHeader.setStringValue(headerText); XWPFParagraph headerParagraph = new XWPFParagraph(ctpHeader, docc); XWPFParagraph[] parsHeader = new XWPFParagraph[1]; parsHeader[0] = headerParagraph; header.createHeader(XWPFHeaderFooterPolicy.DEFAULT, parsHeader);
Word使用页眉和页脚以及页眉中的图像创建文档的示例:
Word
import java.io.FileOutputStream; import java.io.FileInputStream; import java.io.IOException; 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.CTSectPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTabStop; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTabJc; import java.math.BigInteger; public class CreateWordHeaderFooter { 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 CTSectPr sectPr = doc.getDocument().getBody().addNewSectPr(); XWPFHeaderFooterPolicy headerFooterPolicy = new XWPFHeaderFooterPolicy(doc, sectPr); XWPFHeader header = headerFooterPolicy.createHeader(XWPFHeaderFooterPolicy.DEFAULT); paragraph = header.getParagraphArray(0); paragraph.setAlignment(ParagraphAlignment.LEFT); CTTabStop tabStop = paragraph.getCTP().getPPr().addNewTabs().addNewTab(); tabStop.setVal(STTabJc.RIGHT); int twipsPerInch = 1440; tabStop.setPos(BigInteger.valueOf(6 * twipsPerInch)); run = paragraph.createRun(); run.setText("The Header:"); run.addTab(); run = paragraph.createRun(); String imgFile="Koala.png"; run.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, Units.toEMU(50), Units.toEMU(50)); // create footer start XWPFFooter footer = headerFooterPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT); paragraph = footer.getParagraphArray(0); paragraph.setAlignment(ParagraphAlignment.CENTER); run = paragraph.createRun(); run.setText("The Footer:"); doc.write(new FileOutputStream("test.docx")); } }
编辑2016年3月29日:
这一直有效,直到Apache poi 3.13。现在,在3.14版本中,它的工作方式不再更多。原因:POI将不再在标题段落中保存图像的blip参考。
/word/header1.xml:
/word/header1.xml
使用3.13编译并运行的代码:
... <pic:blipFill><a:blip r:embed="rId1"/> ...
使用3.14编译并运行的相同代码:
... <pic:blipFill><a:blip r:embed=""/> ...
编辑2016年3月31日:
找到了问题。有人认为public final PackageRelationship getPackageRelationship()需要弃用。因此在XWPFRun.java代码中public XWPFPicture addPicture(...)已更改
public final PackageRelationship getPackageRelationship()
XWPFRun.java
public XWPFPicture addPicture(...)
从3.13版开始:
... CTBlipFillProperties blipFill = pic.addNewBlipFill(); CTBlip blip = blipFill.addNewBlip(); blip.setEmbed(picData.getPackageRelationship().getId()); ...
到版本3.14:
... CTBlipFillProperties blipFill = pic.addNewBlipFill(); CTBlip blip = blipFill.addNewBlip(); blip.setEmbed(parent.getDocument().getRelationId(picData)); ...
但parent.getDocument()就是XWPFDocument永远,而picData可能是关系到XWPFHeaderFooter。
parent.getDocument()
XWPFDocument
picData
XWPFHeaderFooter
public XWPFPicture addPicture(...)程序员一开始就已经知道这一点。
... if (parent.getPart() instanceof XWPFHeaderFooter) { XWPFHeaderFooter headerFooter = (XWPFHeaderFooter)parent.getPart(); relationId = headerFooter.addPictureData(pictureData, pictureType); picData = (XWPFPictureData) headerFooter.getRelationById(relationId); } else { XWPFDocument doc = parent.getDocument(); relationId = doc.addPictureData(pictureData, pictureType); picData = (XWPFPictureData) doc.getRelationById(relationId); } ...
因此,如果确实应执行折旧,if..else则在设置blipID时也必须使用此折旧。但是为什么要贬值呢?
if..else
Apache POI 3.14版本 大声笑
import java.io.FileOutputStream; import java.io.FileInputStream; import java.io.IOException; 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.CTSectPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTabStop; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTabJc; import java.math.BigInteger; public class CreateWordHeaderFooter { 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 CTSectPr sectPr = doc.getDocument().getBody().addNewSectPr(); XWPFHeaderFooterPolicy headerFooterPolicy = new XWPFHeaderFooterPolicy(doc, sectPr); XWPFHeader header = headerFooterPolicy.createHeader(XWPFHeaderFooterPolicy.DEFAULT); paragraph = header.getParagraphArray(0); paragraph.setAlignment(ParagraphAlignment.LEFT); CTTabStop tabStop = paragraph.getCTP().getPPr().addNewTabs().addNewTab(); tabStop.setVal(STTabJc.RIGHT); int twipsPerInch = 1440; tabStop.setPos(BigInteger.valueOf(6 * twipsPerInch)); run = paragraph.createRun(); run.setText("The Header:"); run.addTab(); run = paragraph.createRun(); String imgFile="Koala.png"; XWPFPicture picture = run.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, Units.toEMU(50), Units.toEMU(50)); System.out.println(picture); //XWPFPicture is added System.out.println(picture.getPictureData()); //but without access to XWPFPictureData (no blipID) String blipID = ""; for(XWPFPictureData picturedata : header.getAllPackagePictures()) { blipID = header.getRelationId(picturedata); System.out.println(blipID); //the XWPFPictureData are already there } picture.getCTPicture().getBlipFill().getBlip().setEmbed(blipID); //now they have a blipID also System.out.println(picture.getPictureData()); // create footer start XWPFFooter footer = headerFooterPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT); paragraph = footer.getParagraphArray(0); paragraph.setAlignment(ParagraphAlignment.CENTER); run = paragraph.createRun(); run.setText("The Footer:"); doc.write(new FileOutputStream("test.docx")); } }
编辑2017年3月28日:
在apache poi3.16 Beta 2版中,此问题似乎已解决,因为以下代码在apache poi3.16 Beta 2版中有效:
apache poi
import java.io.FileOutputStream; import java.io.FileInputStream; import java.io.IOException; 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.CTSectPr; import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTTabStop; import org.openxmlformats.schemas.wordprocessingml.x2006.main.STTabJc; import java.math.BigInteger; public class CreateWordHeaderFooter2 { 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 CTSectPr sectPr = doc.getDocument().getBody().addNewSectPr(); XWPFHeaderFooterPolicy headerFooterPolicy = new XWPFHeaderFooterPolicy(doc, sectPr); XWPFHeader header = headerFooterPolicy.createHeader(XWPFHeaderFooterPolicy.DEFAULT); paragraph = header.createParagraph(); paragraph.setAlignment(ParagraphAlignment.LEFT); CTTabStop tabStop = paragraph.getCTP().getPPr().addNewTabs().addNewTab(); tabStop.setVal(STTabJc.RIGHT); int twipsPerInch = 1440; tabStop.setPos(BigInteger.valueOf(6 * twipsPerInch)); run = paragraph.createRun(); run.setText("The Header:"); run.addTab(); run = paragraph.createRun(); String imgFile="Koala.png"; run.addPicture(new FileInputStream(imgFile), XWPFDocument.PICTURE_TYPE_PNG, imgFile, Units.toEMU(50), Units.toEMU(50)); // create footer start XWPFFooter footer = headerFooterPolicy.createFooter(XWPFHeaderFooterPolicy.DEFAULT); paragraph = footer.createParagraph(); paragraph.setAlignment(ParagraphAlignment.CENTER); run = paragraph.createRun(); run.setText("The Footer:"); doc.write(new FileOutputStream("test.docx")); } }