您的位置:首页技术文章
文章详情页

Java 实现word模板转为pdf

【字号: 日期:2022-05-24 17:26:24浏览:56作者:猪猪
1. pom相关依赖

工具poi-tl (操作word文档模板) + jacob (将操作后的word模板转为pdf)

<!-- poi-tl的pom依赖 --> <dependency> <groupId>com.deepoove</groupId> <artifactId>poi-tl</artifactId> <version>1.9.1</version></dependency>

<!-- jacob的pom依赖(需自行导入.jar包) --><dependency> <groupId>com.jacob</groupId> <artifactId>jacob</artifactId> <version>1.17</version> <scope>system</scope> <systemPath>${project.basedir}/src/main/resources/lib/jacob.jar</systemPath></dependency>2. 对word模板进行插入数据操作

使用poi-tl操作word需要创建一个用于向word插入数据的Map<String, Object>集合, word模板中标签格式为'{{标签}}', 其中标签内容为Map<String, Object> 的key.

// 项目根路径String abPath = new File('').getAbsolutePath() + '/src/main/resources';// 创建用于插入数据的MapMap<String, Object> map = new HashMap<>();map.put(<k>, <v>);...// 填充word文档XWPFTemplate template = XWPFTemplate.compile(abPath + '<模板路径>').render(map);// 输出文档template.writeAndClose(new FileOutPutStream('<输出路径>'));3. 对word模板的表格执行插入数据操作(动态表格)

使用poi-tl操作word的表格,动态的插入数据,需要用到poi-tl的可选插件进行自定义渲染策略, 首先在word需要操作的表格中的任意单元格添加标签“{{标签}}”

自定义渲染策略

/** * 自定义渲染策略 * * @author */public class DetailTablePolicy extends DynamicTableRenderPolicy { // 表格起始行行数 int tableStartRow = 1; /** * 自定义渲染策略 * * @data 传入的封装好的数据 */ @Override public void render(XWPFTable table, Object data) throws Exception { // 如果数据为空,直接返回 if (null == data) return; // 封装数据List的数据封装对象 NdrwhkhzbData detailData = (NdrwhkhzbData) data;// 获取当前列表行高 int height = table.getRow(2).getHeight(); // 从封装对象中获取数据集合 List<RowRenderData> datas = detailData.getNdrwhkhzbs(); if (null != datas) { // 循环移除空白表格中数据数量的空白行 for (int i = 1; i < datas.size() + 2; i++) {table.removeRow(i); } // 循环插入数据 for (int i = 0; i < datas.size(); i++) {// 新增一行空白行XWPFTableRow insertNewTableRow = table.insertNewTableRow(tableStartRow);// 设置行高insertNewTableRow.setHeight(height);// 循环添加单元格(4为每行单元格数量)for (int j = 0; j < 4; j++) { insertNewTableRow.createCell();}// 填充表格TableRenderPolicy.Helper.renderRow(table.getRow(tableStartRow), datas.get(i)); } } }}

把自定义渲染策略当做工具类, 在主逻辑中直接配置使用

/** * 操作年度任务和考核指标表 * * @throws IOException 输入输出流异常 */ private void createNdrwhkhzb(Integer uid, String dirPath) throws IOException { PageData datas = new PageData(); NdrwhkhzbData detailTable = new NdrwhkhzbData(); List<RowRenderData> nds = new ArrayList<>(); // 根据uid查询年度任务和考核指标数据 List<NdrwhkhzbEntity> list = ndrwhkhzbService.selectNdrwhkhzbByUid(uid); for (NdrwhkhzbEntity ndrwhkhzbEntity : list) { RowRenderData rrd = Rows.of(ndrwhkhzbEntity.getNd(), ndrwhkhzbEntity.getNdrw(), ndrwhkhzbEntity.getNdkhzb() , ndrwhkhzbEntity.getZyrwdsjjd()).center().create(); nds.add(rrd); } detailTable.setNdrwhkhzbs(nds); datas.setNdrwhkhzbData(detailTable); // 配置表格 Configure config = Configure.builder().bind('detail_table', new DetailTablePolicy()).build(); // 调用渲染策略进行填充 XWPFTemplate template =XWPFTemplate.compile(dirPath + '/' + uid + '_Complete.docx', config).render(datas); // 写入表格中 template.writeToFile(dirPath + '/' + uid + '_Complete.docx'); }

用到的一些实体类

// PageDatapublic class PageData { @Name('detail_table') private NdrwhkhzbData ndrwhkhzbData; public NdrwhkhzbData getNdrwhkhzbData() { return ndrwhkhzbData; } public void setNdrwhkhzbData(NdrwhkhzbData ndrwhkhzbData) { this.ndrwhkhzbData = ndrwhkhzbData; }}// NdrwhkhzbDatapublic class NdrwhkhzbData { private List<RowRenderData> ndrwhkhzbs; public List<RowRenderData> getNdrwhkhzbs() { return ndrwhkhzbs; } public void setNdrwhkhzbs(List<RowRenderData> ndrwhkhzbs) { this.ndrwhkhzbs = ndrwhkhzbs; }}4. 将编辑好的Word转为pdf格式(jacob)

这里将word转为pdf时需要用到jacob, 这里需要将jacob的dll文件放到jdk和jre的bin目录下, 下载的jacob中dll文件一般为两个版本, X86为32位, X64为64位, 根据自己安装的jdk版本添加所对应的dll文件

/** 将 .docx 转换为 .pdf*/ ActiveXComponent app = null; String wordFile = dirPath + '/' + uid + '_Complete.docx'; String pdfFile = dirPath + '/' + dirName + '.pdf'; System.out.println('开始转换...'); // 开始时间 long start = System.currentTimeMillis(); try { // 打开word app = new ActiveXComponent('Word.Application'); // 设置word不可见,很多博客下面这里都写了这一句话,其实是没有必要的,因为默认就是不可见的,如果设置可见就是会打开一个word文档,对于转化为pdf明显是没有必要的 //app.setProperty('Visible', false); // 获得word中所有打开的文档 Dispatch documents = app.getProperty('Documents').toDispatch(); System.out.println('打开文件: ' + wordFile); // 打开文档 Dispatch documentP = Dispatch.call(documents, 'Open', wordFile, false, true).toDispatch(); // 如果文件存在的话,不会覆盖,会直接报错,所以我们需要判断文件是否存在 File target = new File(pdfFile); if (target.exists()) { target.delete(); } System.out.println('另存为: ' + pdfFile); // 另存为,将文档报错为pdf,其中word保存为pdf的格式宏的值是17 Dispatch.call(documentP, 'SaveAs', pdfFile, 17); // 关闭文档 Dispatch.call(documentP, 'Close', false); // 结束时间 long end = System.currentTimeMillis(); System.out.println('转换成功,用时:' + (end - start) + 'ms'); } catch (Exception e) { e.getMessage(); System.out.println('转换失败' + e.getMessage()); } finally { // 关闭office app.invoke('Quit', 0); }5. 通过lo流将生成好的文件传到浏览器下载

/* * 下载pdf */String fileName = dirName + '.pdf';File file = new File(dirPath + '/' + fileName);if (file.exists()) { BufferedInputStream bis = null; FileInputStream fis = null; try { response.setHeader('Content-disposition', 'attachment; filename=' + fileName); byte[] buff = new byte[2048]; fis = new FileInputStream(file); bis = new BufferedInputStream(fis); OutputStream os = response.getOutputStream(); int i = bis.read(buff); while (i != -1) { os.write(buff, 0, i); i = bis.read(buff); } os.close(); } catch (Exception e) { e.printStackTrace(); } finally { assert fis != null; fis.close(); assert bis != null; bis.close(); }}6. 最后的Controller整体代码

package org.example.controller;import com.deepoove.poi.XWPFTemplate;import com.deepoove.poi.config.Configure;import com.deepoove.poi.data.Includes;import com.deepoove.poi.data.RowRenderData;import com.deepoove.poi.data.Rows;import com.jacob.activeX.ActiveXComponent;import com.jacob.com.Dispatch;import org.example.entity.*;import org.example.service.*;import org.example.utils.DetailTablePolicy;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.annotation.Scope;import org.springframework.stereotype.Controller;import org.springframework.util.DigestUtils;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.ResponseBody;import javax.servlet.http.HttpServletResponse;import javax.servlet.http.HttpSession;import java.io.*;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;/** * 创建pdf控制器 * * @author: yoojyn * @data: 2021/1/11 */@Controller@RequestMapping('/createPdfController')public class CreatePdfController { @Autowired private IKtfmService ktfmService; @Autowired private IKtjbxxService ktjbxxService; @Autowired private IKtbyxfxService ktbyxfxService; @Autowired private IZtmbhkhzbService ztmbhkhzbService; @Autowired private INdrwhkhzbService ndrwhkhzbService; @Autowired private IKtjfysjsmService ktjfysjsmService; @Autowired private IXjxhkxxfxService xjxhkxxfxService; /** * 生成word文件 * * @param session 作用域 */ @Scope('prototype') @ResponseBody @RequestMapping('/createPdf') public void createPdf(HttpSession session, HttpServletResponse response) { // 获取当前用户id Userinfo loginedUser = (Userinfo) session.getAttribute('loginedUser'); Integer uid = loginedUser.getUid(); String dirName = DigestUtils.md5DigestAsHex((uid + '_国家重大专项任务合同申报').getBytes()); String dirPath = 'D:/' + dirName; String abPath = new File('').getAbsolutePath() + '/src/main/resources'; try { // 创建用于存储中间文件的文件夹 new File(dirPath).mkdirs(); // 创建用于存储数据的map集合 Map<String, Object> map = new HashMap<>(); // 获取封面数据 createKtfm(uid, map); // 获取基本信息数据 createJbxx(uid, map); // 获取必要性分析 createByxfx(uid, map); // 获取总体目标和考核指标 createZtmbhkhzb(uid, map); // 获取经费预算及说明 createJfysjsm(uid, map); // 查询附件 XjxhkxxfxEntity xjxhkxxfxEntity = xjxhkxxfxService.selectXjxhkxxfxByUid(uid); // 设置下一步处理表格要用到的标签 map.put('page9', Includes.ofLocal(abPath + '/static/file/upload/' + xjxhkxxfxEntity.getFilename()).create()); map.put('detail_table', '{{detail_table}}'); // 填充文档 XWPFTemplate template = XWPFTemplate.compile(abPath + '/static/file/moban/moban.docx').render(map); // 输出文档 template.writeAndClose(new FileOutputStream(dirPath + '/' + uid + '_Complete.docx')); // 操作年度任务和考核指标表 createNdrwhkhzb(uid, dirPath); } catch (IOException e) { e.printStackTrace(); } try { /* * 将 .docx 转换为 .pdf */ ActiveXComponent app = null; String wordFile = dirPath + '/' + uid + '_Complete.docx'; String pdfFile = dirPath + '/' + dirName + '.pdf'; System.out.println('开始转换...'); // 开始时间 long start = System.currentTimeMillis(); try {// 打开wordapp = new ActiveXComponent('Word.Application');// 设置word不可见,很多博客下面这里都写了这一句话,其实是没有必要的,因为默认就是不可见的,如果设置可见就是会打开一个word文档,对于转化为pdf明显是没有必要的//app.setProperty('Visible', false);// 获得word中所有打开的文档Dispatch documents = app.getProperty('Documents').toDispatch();System.out.println('打开文件: ' + wordFile);// 打开文档Dispatch documentP = Dispatch.call(documents, 'Open', wordFile, false, true).toDispatch();// 如果文件存在的话,不会覆盖,会直接报错,所以我们需要判断文件是否存在File target = new File(pdfFile);if (target.exists()) { target.delete();}System.out.println('另存为: ' + pdfFile);// 另存为,将文档报错为pdf,其中word保存为pdf的格式宏的值是17Dispatch.call(documentP, 'SaveAs', pdfFile, 17);// 关闭文档Dispatch.call(documentP, 'Close', false);// 结束时间long end = System.currentTimeMillis();System.out.println('转换成功,用时:' + (end - start) + 'ms'); } catch (Exception e) {e.getMessage();System.out.println('转换失败' + e.getMessage()); } finally {// 关闭officeapp.invoke('Quit', 0); } /* * 下载pdf */ String fileName = dirName + '.pdf'; File file = new File(dirPath + '/' + fileName); if (file.exists()) {BufferedInputStream bis = null;FileInputStream fis = null;try { response.setHeader('Content-disposition', 'attachment; filename=' + fileName); byte[] buff = new byte[2048]; fis = new FileInputStream(file); bis = new BufferedInputStream(fis); OutputStream os = response.getOutputStream(); int i = bis.read(buff); while (i != -1) { os.write(buff, 0, i); i = bis.read(buff); } os.close();} catch (Exception e) { e.printStackTrace();} finally { assert fis != null; fis.close(); assert bis != null; bis.close();} } } catch (Exception e) { e.printStackTrace(); } finally { delDir(new File(dirPath)); } } /** * 删除文件夹 * * @param file 文件夹对象 */ private void delDir(File file) { if (file.isFile()) { file.delete(); } if (file.isDirectory()) { File[] files = file.listFiles(); for (File f : files) {f.delete(); } file.delete(); } } /** * 储存经费预算及说明 * * @param uid 用户id * @param map 储存数据的map集合 */ private void createJfysjsm(Integer uid, Map<String, Object> map) { // 根据用户编号查询经费预算及说明 KtjfysjsmEntity ktjfysjsmEntity = ktjfysjsmService.getDatesByUid(uid); // 添加到map集合 map.put('zjzyczzj', ktjfysjsmEntity.getZjzyczzj()); map.put('zjdfczzj', ktjfysjsmEntity.getZjdfczzj()); map.put('zjdwzczj', ktjfysjsmEntity.getZjdwzczj()); map.put('zjqt', ktjfysjsmEntity.getZjqt()); } /** * 操作年度任务和考核指标表 * * @throws IOException 输入输出流异常 */ private void createNdrwhkhzb(Integer uid, String dirPath) throws IOException { PageData datas = new PageData(); NdrwhkhzbData detailTable = new NdrwhkhzbData(); List<RowRenderData> nds = new ArrayList<>(); // 根据uid查询年度任务和考核指标数据 List<NdrwhkhzbEntity> list = ndrwhkhzbService.selectNdrwhkhzbByUid(uid); for (NdrwhkhzbEntity ndrwhkhzbEntity : list) { RowRenderData rrd = Rows.of(ndrwhkhzbEntity.getNd(), ndrwhkhzbEntity.getNdrw(), ndrwhkhzbEntity.getNdkhzb() , ndrwhkhzbEntity.getZyrwdsjjd()).center().create(); nds.add(rrd); } detailTable.setNdrwhkhzbs(nds); datas.setNdrwhkhzbData(detailTable); Configure config = Configure.builder().bind('detail_table', new DetailTablePolicy()).build(); XWPFTemplate template =XWPFTemplate.compile(dirPath + '/' + uid + '_Complete.docx', config).render(datas); template.writeToFile(dirPath + '/' + uid + '_Complete.docx'); } /** * 储存总体目标和考核指标 * * @param uid 用户id * @param map 储存数据的map集合 */ private void createZtmbhkhzb(Integer uid, Map<String, Object> map) { // 根据用户编号查询总体目标和考核指标 ZtmbhkhzbEntity ztmbhkhzbEntity = ztmbhkhzbService.selectZtmbhkhzbByUid(uid); // 添加到map集合 map.put('page6', ztmbhkhzbEntity.getZtmbhkhzb()); } /** * 储存必要性分析数据 * * @param uid 用户id * @param map 储存数据的map集合 */ private void createByxfx(Integer uid, Map<String, Object> map) { // 根据用户编号查询必要性分析数据 KtbyxfxEntityWithBLOBs ktbyxfxEntity = ktbyxfxService.selectKtbyxfxByUid(uid); // 添加到map集合 map.put('page5_ktyzx', ktbyxfxEntity.getKtyzx()); map.put('page5_ktysfgc', ktbyxfxEntity.getKtysf()); map.put('page5_ktyq', ktbyxfxEntity.getKtyq()); } /** * 储存基本信息数据 * * @param uid 用户编号 * @param map 储存数据的map集合 */ private void createJbxx(Integer uid, Map<String, Object> map) { // 根据用户编号查询基本信息数据 KcjbxxEntity kcjbxxEntity = ktjbxxService.selectKtjbxxByUid(uid); // 添加到map集合 map.put('page3_ktmc', kcjbxxEntity.getKtmc()); map.put('page3_ktmj', kcjbxxEntity.getKtmj()); map.put('page3_yjwcsj', kcjbxxEntity.getYjwcsj()); map.put('page3_kyhdlx', kcjbxxEntity.getKthdlx()); map.put('page3_yqcglx', kcjbxxEntity.getYqcglx()); map.put('page3_dwmc', kcjbxxEntity.getDwmc()); map.put('page3_dwxz', kcjbxxEntity.getDwxz()); map.put('page3_txdz', kcjbxxEntity.getTxdz()); map.put('page3_yzbm', kcjbxxEntity.getYzbm()); map.put('page3_szdq', kcjbxxEntity.getSzdq()); map.put('page3_dwzgbm', kcjbxxEntity.getDwzgbm()); map.put('page3_lxdh', kcjbxxEntity.getLxdh()); map.put('page3_zzjgdm', kcjbxxEntity.getZzjgdm()); map.put('page3_czhm', kcjbxxEntity.getCzhm()); map.put('page3_dwclsj', kcjbxxEntity.getDwclsj()); map.put('page3_dzxx', kcjbxxEntity.getDzxx()); } /** * 储存课题封面数据 * * @param uid 用户编号 * @param map 储存数据的map集合 */ private void createKtfm(Integer uid, Map<String, Object> map) { // 根据用户编号查询封面数据 KtfmEntity ktfmEntity = ktfmService.selectKtfmByUid(uid); // 添加到map集合 map.put('page1_zxmc', '5G总体及关键器件'); map.put('page1_xmbh', '2016ZX03001_001'); map.put('page1_xmmc', '新一代宽带无线移动通信网'); map.put('page1_ktbh', '2016ZX03001_001_002'); map.put('page1_ktmc', '5G高性能基站A/D、D/A转换器试验样片研发'); map.put('page1_zrdw', 'program_test'); map.put('page1_ktzz', ktfmEntity.getKtfzr()); map.put('page1_ktnx1', '2016-01-01'); map.put('page1_ktnx2', '2017-12-31'); map.put('page1_tbrq', '2020-12-28'); map.put('page1_nian', '二一'); map.put('page1_yue', '一'); }}

以上就是Java 实现word模板转为pdf的详细内容,更多关于Java word模板转为pdf的资料请关注好吧啦网其它相关文章!

标签: word
相关文章: