差異處
這裏顯示兩個版本的差異處。
java:apache_poi:word_imagesreplacement [2014/02/07 17:45] tony |
java:apache_poi:word_imagesreplacement [2023/06/25 09:48] |
||
---|---|---|---|
行 1: | 行 1: | ||
- | {{tag>java poi}} | ||
- | ====== Word - Images Replacement ====== | ||
- | ===== Problem ===== | ||
- | 需求很單純,在我們有了自動抓圖程式後,接著就是要自動取代文件圖片了。經過研究一番,目前我只有辦法去取代Word 2007的圖片,2003並沒找到相應的操作API。 | ||
- | ===== How to? ===== | ||
- | 在Word2007中,本文是使用XWPFDocument物件去操作,而XWPFDocument(本文)下包含了多個XWPFParagraph(段落)。XWPFParagraph包含多個XWPFRun(文字屬性描述區塊),XWPFRun則包含CTR(Run的描述屬性)。\\ | ||
- | \\ | ||
- | 要達到需求,我們必須去loop本文內容,插入新圖片並刪除原本的圖片。我的範例僅僅將原本圖片大小讀出來,接著再把圖片依據這個大小插入到Word中。做法很直覺,廢話不多說,看code: | ||
- | <file java TestWord2007.java> | ||
- | public static void main(String[] args) throws Exception { | ||
- | String testFile = "testdata/test.docx"; | ||
- | String targetFile = "testdata/test_c.docx"; | ||
- | String image = "./testdata/Desert.jpg"; | ||
- | |||
- | InputStream is = null; | ||
- | OutputStream os = null; | ||
- | |||
- | try { | ||
- | is = new FileInputStream(testFile); | ||
- | os = new FileOutputStream(targetFile); | ||
- | |||
- | CustomXWPFDocument doc = new CustomXWPFDocument(is); | ||
- | int count = 0; | ||
- | for( XWPFParagraph para : doc.getParagraphs()){ | ||
- | List<XWPFRun> runs = para.getRuns(); | ||
- | for( XWPFRun run : runs ){ | ||
- | List<CTDrawing> drawings = run.getCTR().getDrawingList(); | ||
- | |||
- | int size = drawings.size(); | ||
- | for( int i = 0 ; i < size ; i++ ){ | ||
- | CTPositiveSize2D ps2d = drawings.get(0).getInlineList().get(0).getExtent(); | ||
- | String blipId = addPictureData(image, doc); | ||
- | doc.createPicture(run.getCTR(), | ||
- | blipId, doc.getNextPicNameNumber(XWPFDocument.PICTURE_TYPE_PNG), | ||
- | ps2d.getCx(), ps2d.getCy()); | ||
- | |||
- | run.getCTR().removeDrawing(0); | ||
- | |||
- | count++; | ||
- | } | ||
- | } | ||
- | } | ||
- | doc.write(os); | ||
- | |||
- | System.out.println("Replace " + count + " image(s)."); | ||
- | } finally { | ||
- | Cleaner.close(is); | ||
- | Cleaner.close(os); | ||
- | } | ||
- | } | ||
- | private static String addPictureData(String image, CustomXWPFDocument doc) | ||
- | throws FileNotFoundException, InvalidFormatException { | ||
- | InputStream images = null; | ||
- | try { | ||
- | images = new FileInputStream(image); | ||
- | return doc.addPictureData(images, XWPFDocument.PICTURE_TYPE_JPEG); | ||
- | } finally { | ||
- | Cleaner.close(images); | ||
- | } | ||
- | } | ||
- | </file> | ||
- | \\ | ||
- | 在這我繼承XWPFDocument類別去定義了CustomXWPFDocument,是由於XWPFDocument本身的createPicture存在bug,會造成輸出的Word無法正常開啟。 | ||
- | <file java CustomXWPFDocument.java> | ||
- | import java.io.IOException; | ||
- | import java.io.InputStream; | ||
- | |||
- | import org.apache.poi.openxml4j.opc.OPCPackage; | ||
- | import org.apache.poi.xwpf.usermodel.XWPFDocument; | ||
- | import org.apache.xmlbeans.XmlException; | ||
- | import org.apache.xmlbeans.XmlToken; | ||
- | import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps; | ||
- | import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D; | ||
- | import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline; | ||
- | import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTR; | ||
- | |||
- | public class CustomXWPFDocument extends XWPFDocument { | ||
- | public CustomXWPFDocument() { | ||
- | super(); | ||
- | } | ||
- | |||
- | public CustomXWPFDocument(OPCPackage opcPackage) throws IOException { | ||
- | super(opcPackage); | ||
- | } | ||
- | |||
- | public CustomXWPFDocument(InputStream in) throws IOException { | ||
- | super(in); | ||
- | } | ||
- | | ||
- | public void createPicture(CTR ctr, String blipId,int id, long width, long height) { | ||
- | //inal int EMU = 9525; | ||
- | //width *= EMU; | ||
- | //height *= EMU; | ||
- | //String blipId = getAllPictures().get(id).getPackageRelationship().getId(); | ||
- | |||
- | | ||
- | CTInline inline = ctr.addNewDrawing().addNewInline(); | ||
- | | ||
- | String picXml = "" + | ||
- | "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">" + | ||
- | " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" + | ||
- | " <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">" + | ||
- | " <pic:nvPicPr>" + | ||
- | " <pic:cNvPr id=\"" + id + "\" name=\"Generated\"/>" + | ||
- | " <pic:cNvPicPr/>" + | ||
- | " </pic:nvPicPr>" + | ||
- | " <pic:blipFill>" + | ||
- | " <a:blip r:embed=\"" + blipId + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>" + | ||
- | " <a:stretch>" + | ||
- | " <a:fillRect/>" + | ||
- | " </a:stretch>" + | ||
- | " </pic:blipFill>" + | ||
- | " <pic:spPr>" + | ||
- | " <a:xfrm>" + | ||
- | " <a:off x=\"0\" y=\"0\"/>" + | ||
- | " <a:ext cx=\"" + width + "\" cy=\"" + height + "\"/>" + | ||
- | " </a:xfrm>" + | ||
- | " <a:prstGeom prst=\"rect\">" + | ||
- | " <a:avLst/>" + | ||
- | " </a:prstGeom>" + | ||
- | " </pic:spPr>" + | ||
- | " </pic:pic>" + | ||
- | " </a:graphicData>" + | ||
- | "</a:graphic>"; | ||
- | |||
- | //CTGraphicalObjectData graphicData = inline.addNewGraphic().addNewGraphicData(); | ||
- | XmlToken xmlToken = null; | ||
- | try { | ||
- | xmlToken = XmlToken.Factory.parse(picXml); | ||
- | } catch(XmlException xe) { | ||
- | xe.printStackTrace(); | ||
- | } | ||
- | inline.set(xmlToken); | ||
- | //graphicData.set(xmlToken); | ||
- | |||
- | inline.setDistT(0); | ||
- | inline.setDistB(0); | ||
- | inline.setDistL(0); | ||
- | inline.setDistR(0); | ||
- | |||
- | CTPositiveSize2D extent = inline.addNewExtent(); | ||
- | extent.setCx(width); | ||
- | extent.setCy(height); | ||
- | |||
- | CTNonVisualDrawingProps docPr = inline.addNewDocPr(); | ||
- | docPr.setId(id); | ||
- | docPr.setName("Picture " + id); | ||
- | docPr.setDescr("Generated"); | ||
- | } | ||
- | |||
- | public void createPicture(String blipId,int id, int width, int height) { | ||
- | createPicture(createParagraph().createRun().getCTR(), blipId, id, width, height); | ||
- | } | ||
- | } | ||
- | </file> | ||
- | |||
- | 友藏內心獨白: 熬夜好幾天非常累,偷懶減少對code的說明。 | ||
- | ===== Reference ===== | ||
- | * [[http://blog.csdn.net/zhyh1986/article/details/8717585|在Word2007插入圖片後無法開啟檔案的Bug]] | ||
- | |||
- | ===== ===== | ||
- | ---- | ||
- | \\ | ||
- | ~~DISQUS~~ |