java POI导出多张图片到表格(占位符方式)
? ? ? ? 最近做的項目,需要將一些信息導出到word中。在網上找了好多解決方案,現在將這幾天的總結分享一下。
? ? ? ? 目前來看,java導出word大致有6種解決方案:
1:Jacob是Java-COM?Bridge的縮寫,它在Java與微軟的COM組件之間構建一座橋梁。使用Jacob自帶的DLL動態鏈接庫,并通過JNI的方式實現了在Java平臺上對COM程序的調用。DLL動態鏈接庫的生成需要windows平臺的支持。該方案只能在windows平臺實現,是其局限性。
2:Apache?POI包括一系列的API,它們可以操作基于MicroSoft?OLE?2?Compound?Document?Format的各種格式文件,可以通過這些API在Java中讀寫Excel、Word等文件。他的excel處理很強大,對于word還局限于讀取,目前只能實現一些簡單文件的操作,不能設置樣式。
3:Java2word是一個在java程序中調用?MS?Office?Word?文檔的組件(類庫)。該組件提供了一組簡單的接口,以便java程序調用他的服務操作Word?文檔。?這些服務包括:?打開文檔、新建文檔、查找文字、替換文字,插入文字、插入圖片、插入表格,在書簽處插入文字、插入圖片、插入表格等。填充數據到表格中讀取表格數據?,1.1版增強的功能:?指定文本樣式,指定表格樣式。如此,則可動態排版word文檔。是一種不錯的解決方案。
4:iText是著名的開放源碼的站點sourceforge一個項目,是用于生成PDF文檔的一個java類庫。通過iText不僅可以生成PDF或rtf的文檔,而且可以將XML、Html文件轉化為PDF文件。功能強大。
5:JSP輸出樣式,該方案實現簡單,但是處理樣式有點缺陷,簡單的導出可以使用。
6:用XML做。Word從2003開始支持XML格式,大致的思路是先用office2003或者2007編輯好word的樣式,然后另存為xml,將xml翻譯為FreeMarker模板,最后用java來解析FreeMarker模板并輸出Doc。經測試這樣方式生成的word文檔完全符合office標準,樣式、內容控制非常便利,打印也不會變形,生成的文檔和office中編輯文檔完全一樣。
綜合以上資料的參考,和網上的一些意見,最后我選擇了,第2種用POI做導出方案。
? ? ?
? ? ?使用POI導出到word,首先你要設置導出的word模板,在要填充的模板中填入表達式,如下圖所示。
占位符盡量用英文,并且保證在同一個模板里不重復。
POI的思路就是取到模板文件,然后將數據替換占位符填充模板,生成一個新的word文檔。
數據放到一個map里,key就是占位符名字,value如果是文字,就是字符串,如果是圖片,還得特殊處理(見下文)
?
/*** * 讀取word模板并替換變量字段* * @param fileName 模板名* @param contentMap 要替換的內容* @return word的Document* @throws IOException*/public XWPFDocument replaceDocForDispatch(String fileName, Map<String, Object> contentMap) throws IOException {try {Map<String, Object> newContentMap = new HashMap<String, Object>();Resource filePath = resourceLoader.getResource("classpath:config" + System.getProperty("file.separator") + fileName);File file = filePath.getFile();String path = file.getPath();// 讀取模板CustomXWPFDocument doc = null;try {OPCPackage pack = POIXMLDocument.openPackage(path);doc = new CustomXWPFDocument(pack); //處理會簽,會簽里有多個審批意見,領導簽名,審批時間if(contentMap.containsKey("hq")) {List list = (List)contentMap.get("hq");List leaderList = getLeaderList();for(int i=0;i<list.size();i++) {String operator = list.get(i).toString();if(leaderList.contains(operator)) {Object o = this.getSignImageByAccount(operator);list.remove(i);list.add(i, o);}}}// 處理段落List<XWPFParagraph> paragraphList = doc.getParagraphs();processParagraphs2(paragraphList, contentMap, doc);// 處理表格Iterator<XWPFTable> it = doc.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) {List<XWPFParagraph> paragraphListTable = cell.getParagraphs();processParagraphs2(paragraphListTable, contentMap, doc);}}}} catch (Exception e) {e.printStackTrace();}return doc;} catch (Exception e) {return null;}} /*** * 通過人員名字獲取對應的簽名圖片* * @param fileName 模板名* @param contentMap 要替換的內容* @return word的Document* @throws IOException*/private Object getSignImageByAccount(String name) {String account = dao.selectacountBylastname(name);String url = dao.selectpicurlByacount(account);// 獲取電子簽名url異常處理try {if (url == null) {return name;}else {Map<String, Object> imageMap = this.getImageMap(url, 70, 25);return imageMap;}} catch (Exception e) {return name;}}/*** 獲取圖片參數* * @param url* @param width* @param height* @return* @throws IOException*/private Map<String, Object> getImageMap(String url, int width, int height) throws IOException {Map<String, Object> imageMap = new HashMap<String, Object>();imageMap.put("width", width);imageMap.put("height", height);imageMap.put("type", "jpg");imageMap.put("content", CustomXWPFDocument.inputStream2ByteArray(new FileInputStream(url), true));return imageMap;} /*** 處理段落* * @param paragraphList*/public static void processParagraphs2(List<XWPFParagraph> paragraphList, Map<String, Object> param,CustomXWPFDocument doc) {List leaderList = getLeaderList();if (paragraphList != null && paragraphList.size() > 0) {for (XWPFParagraph paragraph : paragraphList) {List<XWPFRun> runs = paragraph.getRuns();for (int i = 0; i < runs.size(); i++) {XWPFRun run = runs.get(i);String text = run.getText(0);if (text != null&?m.containsKey(text)) {Object value = param.get(text);if (value instanceof String) {// 文本替換text = value.toString();run.setText(text,0);} else if (value instanceof List) {run.setText("",0);List list = (List)value;for(int j=0;j<list.size();j++) {Object o = list.get(j);if(o instanceof String) {XWPFRun run1 = paragraph.createRun();run1.setText(o.toString());run1.setFontSize(run.getFontSize());run1.setFontFamily(run.getFontFamily());run1.setBold(run.isBold());run1.addTab();}else if (o instanceof Map) {// 圖片替換creactPic(doc,paragraph,(Map)o);}if(j%3==0&&j!=0) {XWPFRun run1 = paragraph.createRun();run1.addBreak();}}}}}}}} /*** 添加圖片* @param map*/private static void creactPic(CustomXWPFDocument doc,XWPFParagraph paragraph,Map picParam) {Map pic = (Map) picParam;int width = Integer.parseInt(pic.get("width").toString());int height = Integer.parseInt(pic.get("height").toString());byte[] byteArray = (byte[]) pic.get("content");ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);try {String ind = doc.addPictureData(byteInputStream, 5);int id = doc.getAllPictures().size() - 1;doc.createPicture(id, width, height, paragraph, ind);} catch (Exception e) {e.printStackTrace();}}在表格里寫圖片的關鍵方法是createPicture
?
?
/*** @param id* @param width 寬* @param height 高* @param paragraph 段落* @param blipId*/public void createPicture(int id,int width, int height, XWPFParagraph paragraph,String blipId) {final int EMU = 9525;width *= EMU;height *= EMU;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);}圖片被替換后效果如下:
?
?word的模型是
整個是一個document
然后里面有多很多個paragraph,
段落
段落和段落之間按照回車換行分割
每一段內,又可以有多個range,如果是文字,就放入XWPFRun里,然后run1.setText(o.toString());
還可以設置字體,大小,對齊方式,空格,換行
?
run1.setFontSize(run.getFontSize()); run1.setFontFamily(run.getFontFamily()); run1.setBold(run.isBold()); run1.addTab(); run1.addBreak(); //換行 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的java POI导出多张图片到表格(占位符方式)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java常见的几种排序算法-插入、选择、
- 下一篇: PL/SQL Developer 和 i