一、首先制作word模版(这里需要注意的是文件后缀是docx不能是doc),${xxxx}是一会要替换的内容

关于为何必须是docx后缀可以看这篇文章https://www.cnblogs.com/ct-csu/p/8178932.html

二、添加poi所需要的jar包文件,我用的maven对jar包进行管理

三、由于poi自身bug,会出现图片无法显示问题,这里需要自定义一个类继承XWPFDocument类,接下来使用的都是我们自己创建的这个类来操作word对象,这个

类对XWPFDocument进行了继承,所以不用担心会有什么问题

package com.newdo.base;import java.io.IOException;
import java.io.InputStream;import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;/*** word  导出工具类*/
public class CustomXWPFDocument extends XWPFDocument{public CustomXWPFDocument(InputStream in) throws IOException {super(in);}public CustomXWPFDocument() {super();}public CustomXWPFDocument(OPCPackage pkg) throws IOException {super(pkg);}
}

四、接下来就是导出word的工具类了

package com.newdo.base;import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;import javax.servlet.http.HttpServletResponse;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;import com.jacob.activeX.ActiveXComponent;
import com.jacob.com.ComThread;
import com.jacob.com.Dispatch;/*** word 导出工具类*/
public class WordUtils {/*** 用于判断导出的word是否转pdf*/public static int judgment = 0;public WordUtils() {judgment = 0;}/*** 根据模板生成word* * @param path      模板的路径* @param params    需要替换的参数* @param tableList 需要插入的参数* @param fileName  生成word文件的文件名* @param response*/public void getWord(String path, Map<String, Object> params, List<String[]> tableList, String fileName,HttpServletResponse response) throws Exception {String saveRoute = path.substring(0, path.indexOf("\\"));File file = new File(path);InputStream is = new FileInputStream(file);CustomXWPFDocument doc = new CustomXWPFDocument(is);this.replaceInPara(doc, params); // 替换文本里面的变量this.replaceInTable(doc, params, tableList); // 替换表格里面的变量OutputStream os = null;if (judgment == 0) {fileName = java.net.URLDecoder.decode(fileName, "UTF-8");os = new FileOutputStream(saveRoute + "\\word\\" + fileName);doc.write(os);String pdf = fileName.substring(0, fileName.lastIndexOf(".")) + ".pdf"; // 截掉wToPdfChange(saveRoute + "\\word\\" + fileName, saveRoute + "\\word\\" + pdf);try {System.out.println("========================pdf下载开始========================");// path是指欲下载的文件的路径。file = new File(saveRoute + "\\word\\" + pdf);// 取得文件名。String filename = URLEncoder.encode(file.getName(), "utf-8");// 取得文件的后缀名。String ext = filename.substring(filename.lastIndexOf(".") + 1).toUpperCase();// 以流的形式下载文件。is = new BufferedInputStream(new FileInputStream(saveRoute + "\\word\\" + pdf));byte[] buffer = new byte[is.available()];is.read(buffer);// 清空responseresponse.reset();// 设置response的Headerresponse.addHeader("Content-Disposition", "attachment;filename=" + filename);response.addHeader("Content-Length", "" + file.length());os = new BufferedOutputStream(response.getOutputStream());response.setContentType("application/octet-stream");os.write(buffer);os.flush();System.out.println("========================pdf下载结束========================");} catch (IOException ex) {ex.printStackTrace();}} else {//          os = response.getOutputStream();fileName = java.net.URLDecoder.decode(fileName, "UTF-8");os = new FileOutputStream(saveRoute + "\\word\\" + fileName);response.setHeader("Content-Disposition", "attachment; filename=" + fileName);doc.write(os);judgment = 0;}this.close(os);this.close(is);}/*** word 转 pdf* * @param wordFile word 的路径 word 的路径* @param pdfFile  pdf 的路径*/public static void wToPdfChange(String wordFile, String pdfFile) {ActiveXComponent app = null;Dispatch document = null;System.out.println("========================开始转换========================");try {// 打开wordSystem.out.println("开始打开word");app = new ActiveXComponent("Word.Application");// 获得word中所有打开的文档Dispatch documents = app.getProperty("Documents").toDispatch();System.out.println("打开文件: " + wordFile);// 打开文档document = Dispatch.call(documents, "Open", wordFile, false, true).toDispatch();// 如果文件存在的话,不会覆盖,会直接报错,所以我们需要判断文件是否存在File target = new File(pdfFile);if (target.exists()) {target.delete();}System.out.println("另存为: " + pdfFile);Dispatch.call(document, "SaveAs", pdfFile, 17);} catch (Exception e) {System.out.println("转换失败" + e.getMessage());} finally {// 关闭office
//          app.invoke("Quit", 0);if (document != null) {// 关闭文档Dispatch.call(document, "Close", false);}if (app != null) {app.invoke("Quit", 0);}// 获取系统类型String osName = System.getProperty("os.name");// 判断是系统类型if (osName.toLowerCase().startsWith("win")) {System.out.println(osName);// window系统String killCmd = "taskkill /f /im wps.exe";String killCmd1 = "taskkill /f /im wpscenter.exe";Process p;try {p = Runtime.getRuntime().exec(killCmd);p = Runtime.getRuntime().exec(killCmd1);int runnngStatus = p.waitFor();System.out.println("已杀" + runnngStatus);} catch (IOException e) {e.printStackTrace();System.out.println("转换失败" + e.getMessage());} catch (InterruptedException e) {e.printStackTrace();System.out.println("转换失败" + e.getMessage());}}}System.out.println("========================转换结束========================");}/*** 替换段落里面的变量* * @param doc    要替换的文档* @param params 参数*/private void replaceInPara(CustomXWPFDocument doc, Map<String, Object> params) {Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();XWPFParagraph para;while (iterator.hasNext()) {para = iterator.next();this.replaceInPara(para, params, doc);}}/*** 替换段落里面的变量** @param para   要替换的段落* @param params 参数*/private void replaceInPara(XWPFParagraph para, Map<String, Object> params, CustomXWPFDocument doc) {List<XWPFRun> runs;Matcher matcher;if (this.matcher(para.getParagraphText()).find()) {runs = para.getRuns();int start = -1;int end = -1;String runsIndex = "";String str = "";for (int i = 0; i < runs.size(); i++) {XWPFRun run = runs.get(i);String runText = run.toString().trim();if (!runText.equals("") && (runText.indexOf("${")!=-1 || runText.equals("}"))){if ('$' == runText.charAt(0) && '{' == runText.charAt(1)) {start = i;runsIndex += i+",";}if ((start != -1)) {str += runText;}if ('}' == runText.charAt(runText.length() - 1)) {if (start != -1) {end = i;for (int k = start; k <= end; k++) {para.removeRun(k);k--;end--;}}}}}//            for (int i = start; i <= end; i++) {//              para.removeRun(i);
//              i--;
//              end--;
//          }int doInt = 0;String[] runsIns = runsIndex.split(",");for (int k=0;k<runsIns.length;k++){if (!"".equals(str)) {for (Map.Entry<String, Object> entry : params.entrySet()) {String key = entry.getKey();if (str.indexOf(key) != -1) {Object value = entry.getValue();if (value instanceof String) {str = str.replace(key, value.toString());if (((String) str).indexOf("\r") > 0) {// 设置换行String[] text = str.toString().split("\r");para.removeRun(0);for (int f = 0; f < text.length; f++) {if (f == 0) {// 此处不缩进因为word模板已经缩进了。para.createRun().setText(text[f].trim());} else {para.createRun().addCarriageReturn();// 硬回车// 注意:wps换行首行缩进是三个空格符,office要的话可以用// run.addTab();缩进或者四个空格符para.createRun().setText(text[f]);}}} else {//                              para.createRun().setText((String) value);int num = 0;if (doInt==0){num = CFunc.ToInt(runsIns[k]);}else{num = CFunc.ToInt(runsIns[k])+doInt;}para.insertNewRun(num).setText((String) value);doInt++;}// para.createRun().setText(str, 0);break;} else if (value instanceof Map) {str = str.replace(key, "");Map pic = (Map) value;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 {// int ind =// doc.addPicture(byteInputStream,picType);// doc.createPicture(ind, width , height,para);doc.addPictureData(byteInputStream, picType);para.createRun().setText(str, 0);break;} catch (Exception e) {e.printStackTrace();}}}}}}}}/*** 为表格插入数据,行数不够添加新行** @param table     需要插入数据的表格* @param tableList 插入数据集合*/private static void insertTable(XWPFTable table, List<String[]> tableList) {// 创建行,根据需要插入的数据添加新行,不处理表头for (int i = 0; i < tableList.size(); i++) {XWPFTableRow row = table.createRow();}// 遍历表格插入数据List<XWPFTableRow> rows = table.getRows();int length = table.getRows().size();for (int i = 1; i < length - 1; i++) {XWPFTableRow newRow = table.getRow(i);List<XWPFTableCell> cells = newRow.getTableCells();for (int j = 0; j < cells.size(); j++) {XWPFTableCell cell = cells.get(j);String s = tableList.get(i - 1)[j];cell.setText(s);}}}/*** 替换表格里面的变量* * @param doc    要替换的文档* @param params 参数*/private void replaceInTable(CustomXWPFDocument doc, Map<String, Object> params, List<String[]> tableList) {Iterator<XWPFTable> iterator = doc.getTablesIterator();XWPFTable table;List<XWPFTableRow> rows;List<XWPFTableCell> cells;List<XWPFParagraph> paras;while (iterator.hasNext()) {table = iterator.next();
//          System.out.println("------------>" + table.getRows().size());if (table.getRows().size() > 1) {// 判断表格是需要替换还是需要插入,判断逻辑有$为替换,表格无$为插入if (this.matcher(table.getText()).find()) {rows = table.getRows();for (XWPFTableRow row : rows) {cells = row.getTableCells();for (XWPFTableCell cell : cells) {paras = cell.getParagraphs();for (XWPFParagraph para : paras) {this.replaceInPara(para, params, doc);}}}} else {insertTable(table, tableList); // 插入数据}}}}/*** 正则匹配字符串** @param str* @return*/private Matcher matcher(String str) {Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE);Matcher matcher = pattern.matcher(str);return matcher;}/*** 根据图片类型,取得对应的图片类型代码** @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) {e2.getStackTrace();}}}return byteArray;}/*** 关闭输入流** @param is*/public void close(InputStream is) {if (is != null) {try {is.close();} catch (IOException e) {e.printStackTrace();}}}/*** 关闭输出流** @param os*/public void close(OutputStream os) {if (os != null) {try {os.close();} catch (IOException e) {e.printStackTrace();}}}
}

五、word转pdf文件我们需要用到一个jacob.jar(下载地址在文章下面 )的一个包,将该jar包放入项目中的resources文件下的lib中

maven中引入本地jar包

同时需要将jacob中的dll文件放到自己的jdk环境中,将 dll 文件拷贝到 C:\Program Files\Java\jdk1.8.0_191\jre\bin (这是我自己的jdk位置)下,或者拷贝到当前项目运行的 jdk 的目录下的 jre/bin 目录下

这里的文件多少位(×64或×86)是根据自己的电脑来的

完成以上操作word才能正常转换为pdf文件

六、最后就是进行测试了,我是用的是springboot框架,这里放出测试代码

 @Overridepublic void contractPrintDetail(HttpServletRequest request, HttpServletResponse response, Map<String, Object> mapArgu) {//查询出来的数据Map<String,Object> map = contractPrintMapper.mySelect(mapArgu);WordUtils wordUtil = new WordUtils();Map<String, Object> params = new LinkedHashMap<String, Object>();List<String[]> testList = new ArrayList<String[]>();params.put("${DWMC}",map.get("DWMC"));params.put("${DWDZ}",map.get("DWDZ"));params.put("${FDDBR}",map.get("FDDBR"));params.put("${XM}",map.get("XM"));params.put("${XBMC}",map.get("XBMC"));params.put("${LXDH}",map.get("LXDH"));params.put("${JG}",map.get("JG"));params.put("${ZS}",map.get("ZS"));params.put("${SFZHM}",map.get("SFZHM"));params.put("${GWMC}",map.get("GWMC"));try{String path = CFunc.clobToString((Clob) map.get("HTMB"));String name = CFunc.ToString(map.get("XM")) + "_" + CFunc.ToString(map.get("HTLX"))+"合同.docx";String filename = URLEncoder.encode(name, "utf-8");response.setContentType(request.getServletContext().getMimeType(filename));wordUtil.getWord(path, params, testList, filename, response);}catch (Exception e){e.printStackTrace();}

七、最后生成的pdf文档
  

POI官网:https://poi.apache.org/
Apache POI Word 简易示例文档:https://my.oschina.net/skymozn/blog/3189732
JACOB:https://sourceforge.net/projects/jacob-project/?source=typ_redirect

参考链接:
https://www.cnblogs.com/duanrantao/p/8682897.html

使用poi根据模版生成word文档并转换成PDF文件相关推荐

  1. 使用poi根据模版生成word文档并转换成PDF文件(可处理doc文件与docx文件版)

    该篇文章是<使用poi根据模版生成word文档并转换成PDF文件>后续解决传入文件为doc文档或docx的处理方法 /*** 根据模板生成word** @param path 模板的路径* ...

  2. Java根据word模板生成word文档并转成PDF文件

    1. 处理word模板 1.1 定义word模版 1.2 定义完我们的模板之后,我们要将文档保存为xml的格式 定义完我们的模板之后,我们要将文档保存为xml的格式 1.3 xml格式化 生成的xml ...

  3. 手机word文档怎么转换成pdf?分享两种方法

    手机word文档怎么转换成pdf?在如今信息化的时代,电子文档已经成为人们日常办公不可或缺的一部分.随着科技的不断进步,电子文档的格式也在不断发展.PDF作为电子文档的一种重要格式,被广泛使用.那么, ...

  4. PPT文档怎么转换成PDF文件?告诉你3种好用的方法

    不知道经常需要进行演讲的小伙伴们,你们平时在制作完PPT文稿后,将文稿发送到其它设备上的时候,会不会出现格式错乱的问题呢?如果会的话也不用太过担心,我们只要将PPT文件转换为PDF格式就可以了,这是因 ...

  5. 使用poi根据模版生成word文档,支持插入图片,复制表格,插入、循环插入数据,继承模板大部分格式及样式(优化版)

    一.制作word模版,${xxxx}是一会要替换的内容,最下面的表格是要插入数据,根据是否以$开头来判断是需要替换还是插入数据, 注意如果是需要循环插入数据,制作的表格模版需要一行全部输入井号#,格式 ...

  6. Jacob Java程序把Word文档直接转换成Html文件

    2019独角兽企业重金招聘Python工程师标准>>> Jacob是Java和Windows下的Com桥,通过它我们可以在Java程序中调用COM组件.如果你的JDK是1.4,那你需 ...

  7. 基于C++的OpenCV项目实战——文档照片转换成扫描文件

    基于C++的OpenCV项目实战--文档照片转换成扫描文件 一.背景 前段时间都是基于Python的OpecCV进行一些学习和实践,但小的知识点并没有应用到实际的项目中:并且基于Python的版本的移 ...

  8. Java通过POI或Freemarker生成word文档,使用Jfreechart创建统计图表

    最近做了一个使用Java生成统计分析报告word文档的功能,有提前制作好的word文档,其中共包含了普通文本变量,普通表格,动态表格.统计图表(柱状图.饼状图.折线图等),在此记录下POI和freem ...

  9. 【PDF制作电子杂志】云展网教程 | Word/Excel文档如何转换成PDF

    WORD转PDF教程请打开链接查看:点击<如何将word文件转换成pdf文件> EXCEL转PDF教程请打开链接查看:点击<怎样将Excel转化为PDF>

最新文章

  1. app息屏后ajax请求不执行_息屏时钟app下载-息屏时钟软件下载v1.0 安卓版
  2. findwindowex子窗口类型有哪几种_SQL-窗口函数
  3. 洛谷 P1966 火柴排队 —— 思路
  4. 客户和顾客是一个意思吗_“啤酒度数”和“啤酒酒精度”一个意思吗?
  5. django 学习-13 Django文件上传
  6. 广东电网笔试_内容多,备考时间少?广东电网笔试如何准备?
  7. Security+ 学习笔记4 社会工程攻击
  8. 网络篇 使用Visio来画网络拓扑图01
  9. 电脑出现无法访问您试图使用的功能所在的网络位置怎么办?(清除软件卸载残留)
  10. 浅析Relaxed Ordering对PCIe系统稳定性的影响
  11. 使用Springboot+Feign Clients快速搭建REST客户端应用
  12. 徒步运动软件怎么申请测试,徒步,不仅是体质健康的锻炼和检测,还是心理健康成长的过程...
  13. 云原生数据湖以存储、计算、数据管理等能力通过信通院评测认证
  14. 【案例】绘制国际象棋棋盘?(turtle 登场)
  15. 准研究生获刑3年!竟是因为……
  16. 教师的常用教学软件_数学教学软件不知道怎么选择?来看看这些软件
  17. ACM学习历程—BestCoder 2015百度之星资格赛1002 列变位法解密(vector容器)
  18. 编写测试用例需要考虑的一些因素
  19. 软件测试面试:拿到一个版本(产品),如何开展测试?
  20. python手机号定位_python手机号前7位归属地爬虫

热门文章

  1. 社会工程学 | cobalstrike批量发送邮件方法
  2. weui 使用教程及问题解决方法
  3. c#中关于list去重的问题
  4. 创业合伙人时代,股权激励正解
  5. 于千万人之中, 你是匠人!
  6. 苹果ios8_苹果没在发布会宣布的内容:iOS 14新增五笔输入法
  7. C++ P1137 旅行计划
  8. 各位,有可以推荐一下华强北耳机的靠谱渠道吗?
  9. 【有利可图网】PS实战系列:制作液态油漆特效水彩艺术文字效果
  10. Hibernate 之强大的HQL查询