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(); //换行
java POI导出多张图片到表格(占位符方式)相关推荐
- java POI对word中的表格动态插入固定数据,以及插入不确定数量的的数据
java POI对word中的表格动态插入固定数据,以及插入不具体的数据 遇到个项目本来是用Execl导出的,相对简单,客户要求用Word导出,并按照他们给的模板进行导出: 从网上百度了一下,然后自己 ...
- java poi 导出中利用sum函数实现合计功能
java poi 导出中利用sum函数实现合计功能 之前也写过导出功能但是没有写过合计.所以记录下来当做笔记. for(int i = 0; i < arrSize; i++) {JSONObj ...
- poi导出word文件(带表格)
poi导出word文件(带表格) 一.背景介绍 现有业务需求根据前端页面上所选的时间和列,来生成word表格,方便打印. 二.POM <dependency><groupId> ...
- POI导出word文件中表格合并方法(行合并,列合并)
项目中遇到记录一下 POI导出word文件中表格合并方法(行合并,列合并) . // word表格跨列合并单元格//row 指定行.fromCell 开始列数.toCell 结束列数.public v ...
- java poi 导出excel不能超过65536行
java poi 导出excel不能超过65536行 报这个异常 Exception in thread "main" java.lang.IllegalArgumentExcep ...
- java读取word文档的复杂表格_poi读取word表格 java POI 如何读取word的表格中的表格...
poi 操作word 2007 (如何删除word中的某一个表格)小编忘了哪年哪月的哪日小编在哪面墙上刻下张脸张微笑着忧伤着凝望小编的脸. public static void changeTable ...
- Java输出PPT文件(二) - 占位符数据替换
Java输出PPT文件(二) - 占位符数据替换 文章目录 Java输出PPT文件(二) - 占位符数据替换 0. 前言 1. 依赖 2. 代码 3. 测试 3.1 模板准备 3.2 替换结果 4. ...
- 【C 语言】文件操作 ( 配置文件读写 | 写出或更新配置文件 | 逐行遍历文件文本数据 | 获取文件中的文本行 | 查询文本行数据 | 追加文件数据 | 使用占位符方式拼接字符串 )
文章目录 一.逐行遍历文件文本数据 1.获取文件中的文本行 2.查询文本行数据 3.追加文件数据 4.使用占位符方式拼接字符串 二.完整代码示例 一.逐行遍历文件文本数据 1.获取文件中的文本行 调用 ...
- java poi导出Excel表格超大数据量解决方案
Java实现导出excel表格功能,大部分都会使用apache poi,apache poi API 地址 POI之前的版本不支持大数据量处理,如果数据过多则经常报OOM错误,有时候调整JVM大小效果 ...
最新文章
- PHP安装扩展mcrypt以及相关依赖项 【PHP安装PECL扩展的方法】
- iphone完整版的http上传请求协议
- 物料编码原则有码还是无码
- 科学计算机乱码,软件界面乱码可以这么“破”
- 事务和分布式事务解释
- 使用ab进行页面的压力测试
- [译] 如何用ps制作泼水字
- 学习统计学,必看的书单推荐
- GFLOPs、GMACs、FMA之间的关系
- 金仓数据库KingbaseES与Oracle大对象类型之间的区别
- Ubuntu找不到wifi适配器问题及解决办法
- java笔记5 抽象类和接口
- 源码编译更新nginx到最新版本,并开始nginx支持http2协议模块.
- 机器学习 —— 周志华
- 第十五章 Caché WebSocket
- 迅雷下载器-FDM,看2019新年大电影
- java基于ssm的个人博客系统个人博客网站个人博客项目源码
- win7 共享 win10 打印机
- VIVO推送接入 OPPO推送接入 客户端+服务端
- uniapp实现点击加载更多
热门文章
- 阿里京东带头打劫,下一个被干掉的就是你
- [Linux]Linux下网络配置文件总结(转)
- 雾里散步——这次聊聊自已
- 网页设计精粹:网页中那些迷人的按钮设计
- 点是否在面内算法(Point-In-Polygon Algorithm)
- 注水法比特功率分配介绍及MATLAB实现
- select into from 与 insert into select 区别鉴赏
- python 利用pyttsx3文字转语音
- spinbox 上下箭头事件_[React] 3 - 自动绑定 (事件绑定)
- map for循环_Java_foundations_1 如何遍历Map