1. 程式人生 > >java/poi讀取word,並替換word中的文字內容,向word中插入圖片的操作

java/poi讀取word,並替換word中的文字內容,向word中插入圖片的操作

先貼程式碼,注:部分程式碼源自網路其他前輩的文章,這裡只是做一個功能整合。

package fcjTool;  
  
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.poi.xwpf.usermodel.XWPFParagraph;
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;  
  
public class CustomXWPFDocument extends XWPFDocument {
    public CustomXWPFDocument(InputStream in) throws IOException {
        super(in);
    }
    
    public CustomXWPFDocument() {
        super();
    }
    
    public CustomXWPFDocument(OPCPackage pkg) throws IOException {
        super(pkg);
    }
    
    public void createPicture(int id, int width, int height,XWPFParagraph paragraph) {
        final int EMU = 9525;
        width *= EMU;
        height *= EMU;
        String blipId = getAllPictures().get(id).getPackageRelationship()
                .getId();    
    
        CTInline inline = paragraph.createRun().getCTR()    
                .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>";    
    
        inline.addNewGraphic().addNewGraphicData();
        XmlToken xmlToken = null;
        try {    
            xmlToken = XmlToken.Factory.parse(picXml);
        } catch (XmlException xe) {    
            xe.printStackTrace();    
        }    
        inline.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("圖片" + id);    
        docPr.setDescr("descr");    
    }    
}
此類為操作word文字內容的具體實現類
package fcjTool;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.List;

import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

/**
 * 使用POI,讀取word 2007,並實現修改文字內容,在指定位置插入圖片,替換表格中的文字內容,並寫回到word中
 * @author 付程俊
 *
 */
public class POIReadAndWriteWord2007 {
	public static void main(String[] args) {
		/**原始檔的路徑,注:只支援word2007,或許還支援word 2010,其他待測試*/
		String filePath = "E:\\test\\POIRedAndWrite.docx";
		String tips = POIReadAndWriteWord2007.readwriteWord(filePath);
		System.out.println(tips);
	}
	/**讀取並操作word2007中的內容*/
	public static String readwriteWord(String filePath){
		File isExist = new File(filePath);
		/**判斷原始檔是否存在*/
		if(!isExist.exists()){
			return "原始檔不存在!";
		}
		CustomXWPFDocument document;
		try {
			/**開啟word2007的檔案*/
			OPCPackage opc = POIXMLDocument.openPackage(filePath);
			document = new CustomXWPFDocument(opc);
			/**替換word2007的純文字內容*/
			List<XWPFRun> listRun;
			List<XWPFParagraph> listParagraphs = document.getParagraphs();
			for (int i = 0; i < listParagraphs.size(); i++) {
				listRun = listParagraphs.get(i).getRuns();
				for (int j = 0; j < listRun.size(); j++) {
					if("#{text}#".equals(listRun.get(j).getText(0))){
						listRun.get(j).setText("替換的純文字內容!",0);
					}
				}
			}
			/**取得文字的所有表格*/
			Iterator<XWPFTable> it = document.getTablesIterator();
			while(it.hasNext()){/**迴圈操作表格*/
				XWPFTable table = it.next();
				List<XWPFTableRow> rows = table.getRows();
				for(XWPFTableRow row:rows){/**取得表格的行*/
					List<XWPFTableCell> cells = row.getTableCells();
					for(XWPFTableCell cell:cells){/**取得單元格*/
						if("#{img}#".equals(cell.getText())){/**判斷單元格的內容是否為需要替換的圖片內容*/
							File pic = new File("E:\\test\\xiaosimm.png");
							FileInputStream is = new FileInputStream(pic);
							cell.removeParagraph(0);
							XWPFParagraph pargraph = cell.addParagraph();
							document.addPictureData(is, XWPFDocument.PICTURE_TYPE_PNG);
							document.createPicture(document.getAllPictures().size()-1, 600, 395, pargraph);
							if(is != null){
								is.close();
							}
						}
						List<XWPFParagraph> pars = cell.getParagraphs();
						for(XWPFParagraph par:pars){
							List<XWPFRun> runs = par.getRuns();
							for(XWPFRun run:runs){
								run.removeBreak();
							}
						}
						if("#{table}#".equals(cell.getText())){/**判斷單元格中是否為需要替換的文字內容*/
							cell.removeParagraph(0);
							cell.setText("替換表格中的文字內容!");
						}
					}
				}
			}
			String downloadPath = "D:\\replace.docx";
			OutputStream os = new FileOutputStream(downloadPath);
			document.write(os);
			if(os != null){
				os.close();
			}
			if(opc != null){
				opc.close();
			}
			return "檔案轉換成功!路徑為:"+downloadPath;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return filePath;
	}

	/**複製檔案的方法*/
	public static void copyFile(String oldPath, String newPath) {
		try {
			int bytesum = 0;
			int byteread = 0;
			File oldfile = new File(oldPath);
			if (oldfile.exists()) { //檔案存在時
				InputStream inStream = new FileInputStream(oldPath); //讀入原檔案
				FileOutputStream fs = new FileOutputStream(newPath);
				byte[] buffer = new byte[1444];
				while ( (byteread = inStream.read(buffer)) != -1) {
					bytesum += byteread; //位元組數 檔案大小
					System.out.println(bytesum);
					fs.write(buffer, 0, byteread);
				}
				inStream.close();
				fs.close();
			}
		}
		catch (Exception e) {
			System.out.println("複製單個檔案操作出錯");
			e.printStackTrace();
		}
	}
}
注:此操作只支援word2007及以上版本。在指定位置插入圖片時,必須將需要替換的文字放在單元格中。檔案操作完後,會對原始檔也進行操作,也就是會將原始檔的需要替換的內容也替換掉,就不能達到重複利用原始檔的效果,因此我在下面貼出了複製檔案的方法,將原始檔複製一份,再對複製檔案進行操作,這樣就可以使原始檔多次複用。

感謝其他前輩的程式碼,因為功能做了很久了,所以不記得部分原始碼的出處了。如果有朋友知道,就貼在回覆中。也可以在下面留言,大家一起探討。