Java实现word模板转为pdf
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";
// 创建⽤于插⼊数据的Map
Map<String, Object> map = new HashMap<>();
map.put(<k>, <v>);
...
// 填充word⽂档
XWPFTemplate template = XWPFTemplatepile(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 = Row(2).getHeight();
// 从封装对象中获取数据集合
List<RowRenderData> datas = Ndrwhkhzbs();
if (null != datas) {
// 循环移除空⽩表格中数据数量的空⽩⾏
for (int i = 1; i < datas.size() + 2; 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++) {
}
// 填充表格
Row(tableStartRow), (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.Nd(), Ndrw(), Ndkhzb()
, Zyrwdsjjd()).center().create();
nds.add(rrd);
}
detailTable.setNdrwhkhzbs(nds);
datas.setNdrwhkhzbData(detailTable);
// 配置表格
Configure config = Configure.builder().bind("detail_table", new DetailTablePolicy()).build();
// 调⽤渲染策略进⾏填充
XWPFTemplate template =
XWPFTemplatepile(dirPath + "/" + uid + "_Complete.docx", config).render(datas);
// 写⼊表格中
template.writeToFile(dirPath + "/" + uid + "_Complete.docx");
}
⽤到的⼀些实体类
// PageData
public class PageData {
@Name("detail_table")
private NdrwhkhzbData ndrwhkhzbData;
public NdrwhkhzbData getNdrwhkhzbData() {
return ndrwhkhzbData;
}
public void setNdrwhkhzbData(NdrwhkhzbData ndrwhkhzbData) {
this.ndrwhkhzbData = ndrwhkhzbData;
}
}
// NdrwhkhzbData
public 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 = Property("Documents").toDispatch();
System.out.println("打开⽂件: " + wordFile);
// 打开⽂档
Dispatch documentP = Dispatch.call(documents, "Open", wordFile, false, true).toDispatch(); // 如果⽂件存在的话,不会覆盖,会直接报错,所以我们需要判断⽂件是否存在
File target = new File(pdfFile);
if (ists()) {
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) {
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 (ists()) {
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 = OutputStream();
int i = ad(buff);
while (i != -1) {
os.write(buff, 0, i);
i = ad(buff);
}
os.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
assert fis != null;
fis.close();
assert bis != null;
bis.close();
}
}
6. 最后的Controller整体代码
ller;
import com.deepoove.poi.XWPFTemplate;
import com.fig.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.Dispatch;
ity.*;
ample.service.*;
ample.utils.DetailTablePolicy;
import org.springframework.beans.factory.annotation.Autowired;
import t.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) Attribute("loginedUser");
Integer uid = Uid();
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/" + Filename()).create());
map.put("detail_table", "{{detail_table}}");
// 填充⽂档
XWPFTemplate template = XWPFTemplatepile(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 {
// 打开word
app = new ActiveXComponent("Word.Application");
// 设置word不可见,很多博客下⾯这⾥都写了这⼀句话,其实是没有必要的,因为默认就是不可见的,如果设置可见就是会打开⼀个word⽂档,对于转化为pdf明显是没有必要的 //app.setProperty("Visible", false);
// 获得word中所有打开的⽂档
Dispatch documents = Property("Documents").toDispatch();
System.out.println("打开⽂件: " + wordFile);
// 打开⽂档
Dispatch documentP = Dispatch.call(documents, "Open", wordFile, false, true).toDispatch(); // 如
果⽂件存在的话,不会覆盖,会直接报错,所以我们需要判断⽂件是否存在
File target = new File(pdfFile);
if (ists()) {
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) {
System.out.println("转换失败" + e.getMessage());
} finally {
// 关闭office
app.invoke("Quit", 0);
}
/*
* 下载pdf
*/
String fileName = dirName + ".pdf";
File file = new File(dirPath + "/" + fileName);
if (ists()) {
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 = OutputStream();
int i = ad(buff);
while (i != -1) {
os.write(buff, 0, i);
i = ad(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) {
// 根据⽤户编号查询经费预算及说明
java浏览器下载KtjfysjsmEntity ktjfysjsmEntity = DatesByUid(uid);
// 添加到map集合
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论