1. word文档中,需要填充数据的地方统一使用变量的形式,格式如下:${变量名}。
  2. 注意:变量"${变量名}"建议先在记事本中写好,再粘贴到“XXX合同.docx”中,避免出现“变量分段”的问题。该版本目前只支持“.docx”格式的文件,不支持“.doc”格式。
    具体实现,直接下载参考以下三个类即可:
  3. 编写XWPFDocument类的实现类,重写插入图片的方法:

```java
/*** @Description: 重写XWPFDocument的方法,插入图片*/
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(XWPFRun run,String blipId, int id, int width, int height) {final int EMU = 9525;width *= EMU;height *= EMU;//旧版本方法 .getPackageRelationship() 在该依赖包下已被删除//String blipId = getAllPictures().get(id).getPackageRelationship().getId();//在docment下创建XWPFRun 图片会被添加到文档末尾
//        CTInline inline = createParagraph().createRun().getCTR().addNewDrawing().addNewInline();CTInline inline =run.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>";//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");}
}
  1. 编写POI工具类POIWordUtil:
public class POIWordUtil {/*** 根据模板生成新word文档* 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入** @param inputUrl  模板存放地址* @param outputUrl 新文档存放地址* @param textMap   需要替换的信息集合* @param tableList 需要插入的表格信息集合* @return 成功返回true, 失败返回false*/public static boolean changWord(String inputUrl, String outputUrl,Map<String, Object> textMap, List<String[]> tableList) {//模板转换默认成功boolean changeFlag = true;try {//获取docx解析对象CustomXWPFDocument document = new CustomXWPFDocument(POIXMLDocument.openPackage(inputUrl));//解析替换文本段落对象POIWordUtil.changeText(document, textMap);//解析替换表格对象POIWordUtil.changeTable(document, textMap, tableList);//生成新的wordFile file = new File(outputUrl);if (!file.getParentFile().exists()) {file.getParentFile().mkdirs();}FileOutputStream stream = new FileOutputStream(file);document.write(stream);stream.close();} catch (IOException e) {e.printStackTrace();changeFlag = false;}return changeFlag;}/*** 替换段落文本** @param document docx解析对象* @param textMap  需要替换的信息集合*/public static void changeText(XWPFDocument document, Map<String, Object> textMap) {//获取段落集合List<XWPFParagraph> paragraphs = document.getParagraphs();for (XWPFParagraph paragraph : paragraphs) {//判断此段落时候需要进行替换String text = paragraph.getText();if (checkText(text)) {List<XWPFRun> runs = paragraph.getRuns();for (XWPFRun run : runs) {//替换模板原来位置run.setText((String) changeValue(run.toString(), textMap), 0);}}}}/*** 替换表格对象方法** @param document  docx解析对象* @param textMap   需要替换的信息集合* @param tableList 需要插入的表格信息集合*/public static void changeTable(CustomXWPFDocument document, Map<String, Object> textMap,List<String[]> tableList) {//获取表格对象集合List<XWPFTable> tables = document.getTables();for (int i = 0; i < tables.size(); i++) {//只处理行数大于等于2的表格,且不循环表头XWPFTable table = tables.get(i);if (table.getRows().size() > 1) {//判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入if (checkText(table.getText())) {List<XWPFTableRow> rows = table.getRows();//遍历表格,并替换模板eachTable(document, rows, textMap);} else {
//                  System.out.println("插入"+table.getText());insertTable(table, tableList);}}}}/*** 遍历表格,包含对图片内容的替换** @param rows    表格行对象* @param textMap 需要替换的信息集合*/public static void eachTable(CustomXWPFDocument document, List<XWPFTableRow> rows, Map<String, Object> textMap) {for (XWPFTableRow row : rows) {List<XWPFTableCell> cells = row.getTableCells();for (XWPFTableCell cell : cells) {//判断单元格是否需要替换if (checkText(cell.getText())) {List<XWPFParagraph> paragraphs = cell.getParagraphs();for (XWPFParagraph paragraph : paragraphs) {List<XWPFRun> runs = paragraph.getRuns();for (XWPFRun run : runs) {
//                            run.setText(changeValue(run.toString(), textMap),0);Object ob = changeValue(run.toString(), textMap);if (ob instanceof String) {run.setText((String) ob, 0);} else if (ob instanceof Map) {run.setText("", 0);Map pic = (Map) ob;int width = Integer.parseInt(pic.get("width").toString());int height = Integer.parseInt(pic.get("height").toString());int picType = getPictureType(pic.get("type").toString());byte[] byteArray = (byte[]) pic.get("content");ByteArrayInputStream byteInputStream = new ByteArrayInputStream(byteArray);try {String ind = document.addPictureData(byteInputStream, picType);document.createPicture(run, ind, document.getNextPicNameNumber(picType), width, height);} catch (Exception e) {e.printStackTrace();}}}}}}}}/*** 为表格插入数据,行数不够添加新行** @param table     需要插入数据的表格* @param tableList 插入数据集合*/public static void insertTable(XWPFTable table, List<String[]> tableList) {//创建行,根据需要插入的数据添加新行,不处理表头for (int i = 1; i < tableList.size(); i++) {XWPFTableRow row = table.createRow();}//遍历表格插入数据List<XWPFTableRow> rows = table.getRows();for (int i = 1; i < rows.size(); i++) {XWPFTableRow newRow = table.getRow(i);List<XWPFTableCell> cells = newRow.getTableCells();for (int j = 0; j < cells.size(); j++) {XWPFTableCell cell = cells.get(j);cell.setText(tableList.get(i - 1)[j]);}}}/*** word跨列合并单元格*/public static void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) {for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) {XWPFTableCell cell = table.getRow(row).getCell(cellIndex);if (cellIndex == fromCell) {// The first merged cell is set with RESTART merge valuecell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);} else {// Cells which join (merge) the first one, are set with CONTINUEcell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);}}}/*** word跨行并单元格*/public static void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {XWPFTableCell cell = table.getRow(rowIndex).getCell(col);if (rowIndex == fromRow) {// The first merged cell is set with RESTART merge valuecell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);} else {// Cells which join (merge) the first one, are set with CONTINUEcell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);}}}/*** 单元格设置字体* @param cell* @param cellText*/private static void getParagraph(XWPFTableCell cell,String cellText){CTP ctp = CTP.Factory.newInstance();XWPFParagraph p = new XWPFParagraph(ctp, cell);p.setAlignment(ParagraphAlignment.CENTER);XWPFRun run = p.createRun();run.setText(cellText);CTRPr rpr = run.getCTR().isSetRPr() ? run.getCTR().getRPr() : run.getCTR().addNewRPr();CTFonts fonts = rpr.isSetRFonts() ? rpr.getRFonts() : rpr.addNewRFonts();fonts.setAscii("仿宋");fonts.setEastAsia("仿宋");fonts.setHAnsi("仿宋");cell.setParagraph(p);}/*** 判断文本中时候包含$** @param text 文本* @return 包含返回true, 不包含返回false*/public static boolean checkText(String text) {boolean check = false;if (text.indexOf("$") != -1) {check = true;}return check;}/*** 匹配传入信息集合与模板** @param value   模板需要替换的区域* @param textMap 传入信息集合* @return 模板需要替换区域信息集合对应值*/public static Object changeValue(String value, Map<String, Object> textMap) {Object obj = null;Set<Map.Entry<String, Object>> textSets = textMap.entrySet();for (Map.Entry<String, Object> textSet : textSets) {//匹配模板与替换值 格式${key}String key = "${" + textSet.getKey() + "}";if (value.indexOf(key) != -1) {obj = textSet.getValue();}}if (!(obj instanceof Map)) {//模板未匹配到区域替换为空if (obj != null && checkText(obj.toString())) {obj = "";}}return obj;}/*** 根据图片类型,取得对应的图片类型代码** @param picType* @return int*/private static int getPictureType(String picType) {int res = CustomXWPFDocument.PICTURE_TYPE_PICT;if (picType != null) {if (picType.equalsIgnoreCase("png")) {res = CustomXWPFDocument.PICTURE_TYPE_PNG;} else if (picType.equalsIgnoreCase("dib")) {res = CustomXWPFDocument.PICTURE_TYPE_DIB;} else if (picType.equalsIgnoreCase("emf")) {res = CustomXWPFDocument.PICTURE_TYPE_EMF;} else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")) {res = CustomXWPFDocument.PICTURE_TYPE_JPEG;} else if (picType.equalsIgnoreCase("wmf")) {res = CustomXWPFDocument.PICTURE_TYPE_WMF;}}return res;}/*** 将输入流中的数据写入字节数组** @param in* @return*/public static byte[] inputStream2ByteArray(InputStream in, boolean isClose) {byte[] byteArray = null;try {int total = in.available();byteArray = new byte[total];in.read(byteArray);} catch (IOException e) {e.printStackTrace();} finally {if (isClose) {try {in.close();} catch (Exception e2) {System.out.println("关闭流失败");}}}return byteArray;}}
  1. 在实际业务类中应用代码实例:
        String file =  "H:/export_template.docx";//doc 模板文件位置String outputUrl =  "H:/doc/test.doc";//文件输出地址Map<String, Object> testMap = new HashMap<>();testMap.put("name", data.get("name").toString());testMap.put("sex", data.get("sex").toString());String photo = data.get("photo").toString();Map<String, Object> header = new HashMap<>();header.put("width", 150);header.put("height", 200);header.put("type", photo.substring(photo.indexOf(".") + 1));FileInputStream in = new FileInputStream("H:/img/test.png");header.put("content", POIWordUtil.inputStream2ByteArray(in, true));testMap.put("photo", header);POIWordUtil.changWord(file, outputUrl, testMap, null);

使用POI根据合同定义模板生成新的模板并且填充数据(包括图片)相关推荐

  1. Android poi 根据已有模板生成新的doc文档

    最新要做个根据已有doc模板生成新的doc文件项目,查了相关资料,比较好用的是poi和jword,但是jword需要付费,免费30天:但是poi也有弊端,最新版的说是支持java,不支持Android ...

  2. 通过一个word模板来生成新的word并且填充内容

    关于用Java编写生成word文档,动态添加数据到word文档的一些心得,经过翻阅了无数的有用的和无用的资料以后,总算找到了一种靠谱的方法 1.概述 经过反反复复的查阅资料,总算找到了一个靠谱的生成w ...

  3. 根据pdf模板生成新的pdf文件(Java)

    根据pdf模板生成新的pdf文件 一.项目依赖 二.所用工具类 三.其他资料 一.项目依赖 1.maven版本:3.5.x 2.pom文件依赖 <!--itext的依赖jar--> < ...

  4. java根据pdf模板生成新的pdf

    文章目录 第一步 制作模板 第二步 引入POM 第三步 根据模板生成PDF 如何填充图片数据 如何让填充的数据进行换行 总结 最近有需求要根据现有的PDF模板生成新的PDF出来,网上资料一大堆,主要总 ...

  5. Python通过word模板生成新的word文件

    功能自定义好的word文档,生成新的word文件 模块地址:https://docxtpl.readthedocs.io/en/latest/ 使用模块 docxtpl 安装方式 在线安装 pip i ...

  6. Excel信息批量替换Word模板生成新文件

    Python批量处理Excel文件信息替换Word模板 原由和思路 工具准备 1. 前期处理 1.1 数据处理 1.2 模板处理 2. 编写代码 2.1 使用Pycharm新建项目ExcelToWor ...

  7. java 模板生成excel_java通过模板导出excel的一个实例

    写之前,大家请先下好poi的相关jar包,网上遍地都是,不多说 这个是按钮 这个是相关事件 // 导出按钮 $('#exportBtn').click(function(){ txtBeginDate ...

  8. C#动态生成Word文档并填充数据(一)

    忽然觉得生成word这个东东很好玩,就搜来看看,自己动手了一下,还是比较有意思的哦~~ [摘要] 要利用 C# 的自动化功能创建新的 Word 文档,请执行以下8个步骤 [全文] 要利用 C# 的自动 ...

  9. r生成新的dataframe_R语言中数据框的定义与使用

    在R语言中,数据框(dataframe)组织数据的结构与矩阵相似,但是其各列的数据类型可以不相同.一般情况,数据框的每列是一个变量,每行是一个观测样本.虽然,数据框内不同的列可以是不同的数据模式,但是 ...

最新文章

  1. jQuery mobile 中div圆角弹出层
  2. php xml对象解析_php解析xml 的四种简单方法(附实例)
  3. linux 查看libevent 安装目录,linux下libevent安装配置与简介 以及 linux库文件搜索路径的配置...
  4. Android-View点击水波纹特效
  5. subprocess中执行git命令报告no such file or directory一例
  6. 桂林电子科技大学C语言大作业,桂林电子科技大学c语言程序设计习题集及答案qvzaewzm.doc...
  7. 给页面加速,干掉Dom Level 0 Event
  8. java 上传 进度,关于 javaweb的文件上传实时显示进度
  9. 属马的人性格有什么缺点和优点?
  10. 【AAAI2021】纠结于联合学习中的建模方法?快来看看图网络显式建模!
  11. Delay-Doppler equalization(8)(时延多普勒均衡)⭐
  12. MySql: 事务特性ACID、三大并发读、四种事务隔离级别
  13. 重置linux红帽登录密码,红帽(RHEL)Linux 忘记root密码后重置密码
  14. 2018年10月29日英语学习
  15. Origin画图技巧之回归(标准值与预测值)
  16. 在Mac上如何查看自己是否安装过jdk以及对应版本?
  17. 新生赛第一题:dls的黑粉
  18. 云原生监控报警可视化
  19. 我30岁了,转行学软件自动化测试可以吗? 排除法告诉你答案
  20. 史上最全软件测试工程师常见的面试题总结(百度、oppo、中软国际、华为)备战金三银四

热门文章

  1. 编写一个python程序用来计算投资回收期_智慧职教云课堂Python程序设计基础(九江职业技术学院)题目答案...
  2. Wireshark下载及安装
  3. 操作系统 宏内核和微内核的区别
  4. 移动支付战火连绵,支付宝、微信支付、云闪付APP或将三足鼎立?
  5. c语言快递费计算用switch,求助。。关于用switch编写简易计算器
  6. 《精通Python爬虫框架Scrapy》欢迎来到异步社区!
  7. 怎么把html变成桌面壁纸,怎么把抖音视频设置成桌面 抖音视频设置壁纸教程
  8. 龙芯1C ls1c300b的openwrt以及安装过程
  9. Linux下Mysql数据库浅析(一)
  10. 【CSS】CSS 特性 ① ( CSS 层叠性 | 样式冲突 | 就近原则选择样式 )