差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

java:apache_poi:word_imagesreplacement [2014/02/07 17:50]
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>​ 
-這裡是透過新增一筆在尾巴,接著刪除index 0那筆去做到類似替換的效果。但如果是文繞圖或特別調整的圖片,不僅僅只是讀取圖片大小,可能還要去取得設定的樣式做處理。如果之後有類似的需求我再研究並分享。 
-\\ 
-我繼承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~~