freemarker 模板导出docx 及合并
//添加目录
public static void generateTOC(XWPFDocument document)
throws InvalidFormatException, FileNotFoundException, IOException {
String findText = "toc";//word模板段落标识(在此标识处生成目录)
String replaceText = "";
for (XWPFParagraph p : document.getParagraphs()) {
for (XWPFRun r : p.getRuns()) {
int pos = r.getTextPosition();
String text = r.getText(pos);
System.out.println(text);
if (text != null && text.contains(findText)) {
text = text.replace(findText, replaceText);
r.setText(text, 0);
addField(p, "TOC \\o \"1-3\" \\h \\z \\u");
// addField(p, "TOC \\h");
break;
}
}
}
}
private static void addField(XWPFParagraph paragraph, String fieldName) {
CTSimpleField ctSimpleField = paragraph.getCTP().addNewFldSimple();
ctSimpleField.setInstr(fieldName);
ctSimpleField.setDirty(STOnOff.TRUE);
ctSimpleField.addNewR().addNewT().setStringValue("<<fieldName>>");
}
前提
word.docx 模板更改后缀为zip
打开zip 获取 word 文件夹种document.xml
在document.xml 种填充所需参数${}格式,循环添加<#list items as item></#list>
document.xml 放入项目templates 文件夹中
工具代码
public class FreeMarkUtils {
private static Logger logger = LoggerFactory.getLogger(FreeMarkUtils.class);
public static Configuration getConfiguration() {
// 创建配置实例
Configuration configuration = new Configuration(Configuration.VERSION_2_3_28);
// 设置编码
configuration.setDefaultEncoding("utf-8");
configuration.setClassForTemplateLoading(FreeMarkUtils.class, "/templates");// 换成自己对应的目录
return configuration;
}
/**
* 获取模板字符串输入流
*
* @param dataMap
* 参数
* @param templateName
* 模板名称
* @return
*/
public static ByteArrayInputStream getFreemarkerContentInputStream(Map<String, Object> dataMap,
String templateName) {
ByteArrayInputStream in = null;
try {
// 获取模板
Template template = getConfiguration().getTemplate(templateName);
StringWriter swriter = new StringWriter();
// 生成文件
template.process(dataMap, swriter);
in = new ByteArrayInputStream(swriter.toString().getBytes("utf-8"));// 这里一定要设置utf-8编码
// 否则导出的word中中文会是乱码
} catch (Exception e) {
logger.error("", e);
}
return in;
}
public static void createDocx(Map<String, Object> dataMap, OutputStream outputStream, String zipPath) {
ZipOutputStream zipout = null;
try {
/*
* //图片配置文件模板 ByteArrayInputStream documentXmlRelsInput =
* FreeMarkUtils.getFreemarkerContentInputStream(dataMap,
* documentXmlRels);
*/
// 内容模板
ByteArrayInputStream documentInput = FreeMarkUtils.getFreemarkerContentInputStream(dataMap, "document.xml");
// 最初设计的模板
// File docxFile = new
// File(WordUtils.class.getClassLoader().getResource(template).getPath());
File docxFile = new File(zipPath);// 换成自己的zip路径
if (!docxFile.exists()) {
docxFile.createNewFile();
}
@SuppressWarnings("resource")
ZipFile zipFile = new ZipFile(docxFile);
Enumeration<? extends ZipEntry> zipEntrys = zipFile.entries();
zipout = new ZipOutputStream(outputStream);
// 开始覆盖文档------------------
int len = -1;
byte[] buffer = new byte[1024];
while (zipEntrys.hasMoreElements()) {
ZipEntry next = zipEntrys.nextElement();
InputStream is = zipFile.getInputStream(next);
if (next.toString().indexOf("media") < 0) {
zipout.putNextEntry(new ZipEntry(next.getName()));
if ("word/document.xml".equals(next.getName())) {// 如果是word/document.xml由我们输入
if (documentInput != null) {
while ((len = documentInput.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
documentInput.close();
}
} else {
while ((len = is.read(buffer)) != -1) {
zipout.write(buffer, 0, len);
}
is.close();
}
}
}
} catch (Exception e) {
System.out.println("word导出失败:" + e.getStackTrace());
logger.error("TET", e);
} finally {
if (zipout != null) {
try {
zipout.close();
} catch (IOException e) {
System.out.println("io异常");
}
}
if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
System.out.println("io异常");
}
}
}
}
// 两个对象进行追加
public static XWPFDocument mergeWord(XWPFDocument document, XWPFDocument doucDocument2) throws Exception {
XWPFDocument src1Document = document;
XWPFParagraph p = src1Document.createParagraph();
// 设置分页符
p.setPageBreak(true);
CTBody src1Body = src1Document.getDocument().getBody();
XWPFDocument src2Document = doucDocument2;
CTBody src2Body = src2Document.getDocument().getBody();
// XWPFParagraph p2 = src2Document.createParagraph();
XmlOptions optionsOuter = new XmlOptions();
optionsOuter.setSaveOuter();
String appendString = src2Body.xmlText(optionsOuter);
String srcString = src1Body.xmlText();
String prefix = srcString.substring(0, srcString.indexOf(">") + 1);
String mainPart = srcString.substring(srcString.indexOf(">") + 1, srcString.lastIndexOf("<"));
String sufix = srcString.substring(srcString.lastIndexOf("<"));
String addPart = appendString.substring(appendString.indexOf(">") + 1, appendString.lastIndexOf("<"));
CTBody makeBody = CTBody.Factory.parse(prefix + mainPart + addPart + sufix);
src1Body.set(makeBody);
return src1Document;
}
}
业务代码
单个word导出
@RequestMapping("/export")
public void export(@RequestBody JSONObject json, HttpServletResponse res) throws Exception {
JSONObject detail = taskService.detail(json);
Map<String, Object> beanParams = new HashMap<>();
beanParams.put("userTestName", detail.getString("user_test_name"));
beanParams.put("postName", detail.getString("post_name"));
beanParams.put("deptName", detail.getString("dept_name"));
beanParams.put("testDate", DateUtils.formatDateDay(detail.getDate("test_date")));
beanParams.put("testUserName", detail.getString("test_user_name"));
beanParams.put("remarks",
StringUtils.isEmpty(detail.getString("remarks_")) ? "" : detail.getString("remarks_"));
beanParams.put("responsibilitys", detail.getJSONArray("responsibility_ids"));
beanParams.put("zf", detail.getInteger("zf"));
// 读到流中
File outFile = new File(ConfigUtils.getConfigValue("responsibility", "") + ".docx");
try {
FreeMarkUtils.createDocx(beanParams, new FileOutputStream(outFile),
ConfigUtils.getConfigValue("responsibility", "") + ".zip");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
InputStream inStream = new FileInputStream(outFile);// 文件的存放路径
// 设置输出的格式
res.setContentType("application/octet-stream; charset=utf-8");
res.setHeader("Content-Disposition", "attachment; filename=" + Encodes.urlEncode("安全生产责任制.doc"));
res.setCharacterEncoding("utf-8");
// 循环取出流中的数据
byte[] b = new byte[100];
int len;
try {
while ((len = inStream.read(b)) > 0)
res.getOutputStream().write(b, 0, len);
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
合并多个word导出
@RequestMapping("/exports")
public void exports(@RequestBody JSONObject json, HttpServletResponse res) throws Exception {
json.put("enabled_state_id", "1");
List<JSONObject> taskList = taskService.findAllList(json);
if (taskList != null && taskList.size() > 0) {
XWPFDocument docs = null;
for (JSONObject task : taskList) {
json.put("id_", task.getString("id_"));
JSONObject detail = taskService.detail(json);
Map<String, Object> beanParams = new HashMap<>();
beanParams.put("userTestName", detail.getString("user_test_name"));
beanParams.put("postName", detail.getString("post_name"));
beanParams.put("deptName", detail.getString("dept_name"));
beanParams.put("testDate", DateUtils.formatDateDay(detail.getDate("test_date")));
beanParams.put("testUserName", detail.getString("test_user_name"));
beanParams.put("remarks",
StringUtils.isEmpty(detail.getString("remarks_")) ? "" : detail.getString("remarks_"));
beanParams.put("responsibilitys", detail.getJSONArray("responsibility_ids"));
beanParams.put("zf", detail.getInteger("zf"));
//导出指定文件
File outFile = new File("d:/test.docx");
//指定修改word后缀为zip路径
try {
FreeMarkUtils.createDocx(beanParams, new FileOutputStream(outFile),"d:/test.zip");
} catch (FileNotFoundException e) {
e.printStackTrace();
}
if (taskList.indexOf(task) == 0) {
docs = new XWPFDocument(new FileInputStream(outFile));
}
if (taskList.indexOf(task) == 1) {
docs = FreeMarkUtils.mergeWord(docs, new XWPFDocument(new FileInputStream(outFile)));
}
if (taskList.indexOf(task) > 1) {
docs = FreeMarkUtils.mergeWord(docs, new XWPFDocument(new FileInputStream(outFile)));
}
}
if (docs != null) {
docs.write(res.getOutputStream());
docs.close();
}
// 设置输出的格式
res.setContentType("application/octet-stream; charset=utf-8");
res.setHeader("Content-Disposition", "attachment; filename=" + Encodes.urlEncode("安全生产责任制.doc"));
res.setCharacterEncoding("utf-8");
} else {
}
}
浙公网安备 33010602011771号