制作模板及代碼參考:https://blog.csdn.net/u014231523/article/details/88933319
https://blog.csdn.net/action5362603/article/details/84546012
新建符合需要的docx文檔,后綴名改為zip,解壓之后使用占位符更改word文件夾下的document.xml文件中對應內容,參考如下:
<#list titleList as title>
</#list>
為集合循環取值
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <w:document xmlns:wpc="http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:m="http://schemas.openxmlformats.org/officeDocument/2006/math" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:wp14="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" xmlns:wp="http://schemas.openxmlformats.org/drawingml/2006/wordprocessingDrawing" xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main" xmlns:w14="http://schemas.microsoft.com/office/word/2010/wordml" xmlns:w10="urn:schemas-microsoft-com:office:word" xmlns:w15="http://schemas.microsoft.com/office/word/2012/wordml" xmlns:wpg="http://schemas.microsoft.com/office/word/2010/wordprocessingGroup" xmlns:wpi="http://schemas.microsoft.com/office/word/2010/wordprocessingInk" xmlns:wne="http://schemas.microsoft.com/office/word/2006/wordml" xmlns:wps="http://schemas.microsoft.com/office/word/2010/wordprocessingShape" xmlns:wpsCustomData="http://www.wps.cn/officeDocument/2013/wpsCustomData" mc:Ignorable="w14 w15 wp14"> <w:body> <w:p> <w:pPr><w:keepLines w:val="0"/><w:spacing w:after="400"/><w:ind w:firstLine="160"/><w:jc w:val="center"/></w:pPr><w:r><w:rPr><w:b/><w:sz w:val="32"/></w:rPr><w:t>${theme}</w:t></w:r> </w:p> <w:p><w:pPr><w:rPr><w:b w:val="0"/><w:color w:val="0066FF"/><w:sz w:val="24"/></w:rPr></w:pPr></w:p> <#list titleList as title> <w:p><w:pPr><w:rPr><w:b/><w:sz w:val="32"/></w:rPr></w:pPr> <w:r><w:rPr><w:rFonts w:hint="eastAsia" w:eastAsia="宋體"/><w:b w:val="0"/><w:color w:val="000000"/><w:sz w:val="24"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t>${title.content}</w:t></w:r><w:r><w:rPr><w:b w:val="0"/><w:color w:val="000000"/><w:sz w:val="24"/></w:rPr><w:t xml:space="preserve"> </w:t></w:r><w:r><w:rPr><w:b w:val="0"/><w:color w:val="0066FF"/><w:sz w:val="24"/></w:rPr><w:t>[單選題]</w:t></w:r></w:p><w:p><w:pPr><w:rPr><w:b w:val="0"/><w:color w:val="0066FF"/><w:sz w:val="24"/></w:rPr></w:pPr></w:p> <w:tbl> <w:tblPr><w:tblStyle w:val="2"/><w:tblW w:w="3868" w:type="pct"/><w:tblInd w:w="0" w:type="dxa"/><w:tblBorders><w:top w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:left w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:bottom w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:right w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideH w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideV w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/></w:tblBorders><w:tblLayout w:type="autofit"/><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPr><w:tblGrid><w:gridCol w:w="3507"/><w:gridCol w:w="3086"/></w:tblGrid> <w:tr> <w:tblPrEx><w:tblBorders><w:top w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:left w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:bottom w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:right w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideH w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideV w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/></w:tblBorders><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPrEx><w:trPr><w:trHeight w:val="500" w:hRule="atLeast"/></w:trPr><w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="E0E0E0"/><w:vAlign w:val="center"/></w:tcPr><w:p><w:pPr><w:jc w:val="center"/></w:pPr><w:r><w:t>選項</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="E0E0E0"/><w:vAlign w:val="center"/></w:tcPr><w:p><w:pPr><w:jc w:val="center"/></w:pPr><w:r><w:t>比例</w:t></w:r></w:p></w:tc> </w:tr> <w:tr> <w:tblPrEx><w:tblBorders><w:top w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:left w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:bottom w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:right w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideH w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideV w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/></w:tblBorders><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPrEx><w:trPr><w:trHeight w:val="500" w:hRule="atLeast"/></w:trPr> <w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="FFFFFF"/><w:vAlign w:val="center"/></w:tcPr><w:p><w:pPr><w:jc w:val="left"/><w:rPr><w:rFonts w:hint="default" w:eastAsia="宋體"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr></w:pPr><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:eastAsia="宋體"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t>${title.optionsA}</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="FFFFFF"/><w:vAlign w:val="center"/></w:tcPr><w:p><w:pPr><w:jc w:val="center"/><w:rPr><w:rFonts w:hint="default" w:eastAsia="宋體"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr></w:pPr><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:eastAsia="宋體"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t>${title.countA}</w:t></w:r></w:p></w:tc> </w:tr> <w:tr> <w:tblPrEx><w:tblBorders><w:top w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:left w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:bottom w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:right w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideH w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideV w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/></w:tblBorders><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPrEx><w:trPr><w:trHeight w:val="500" w:hRule="atLeast"/></w:trPr><w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="F9F9F9"/><w:vAlign w:val="center"/></w:tcPr><w:p><w:pPr><w:jc w:val="left"/></w:pPr><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:eastAsia="宋體"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t>${title.optionsB}</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="F9F9F9"/><w:vAlign w:val="center"/></w:tcPr><w:p><w:pPr><w:jc w:val="center"/><w:rPr><w:rFonts w:hint="default" w:eastAsia="宋體"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr></w:pPr><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:eastAsia="宋體"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t>${title.countB}</w:t></w:r></w:p></w:tc> </w:tr> <w:tr> <w:tblPrEx><w:tblBorders><w:top w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:left w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:bottom w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:right w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideH w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideV w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/></w:tblBorders><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPrEx><w:trPr><w:trHeight w:val="500" w:hRule="atLeast"/></w:trPr><w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="FFFFFF"/><w:vAlign w:val="center"/></w:tcPr><w:p><w:pPr><w:jc w:val="left"/></w:pPr><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:eastAsia="宋體"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t>${title.optionsC}</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="FFFFFF"/><w:vAlign w:val="center"/></w:tcPr><w:p><w:pPr><w:jc w:val="center"/></w:pPr><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:eastAsia="宋體"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t>${title.countC}</w:t></w:r></w:p></w:tc> </w:tr> <w:tr> <w:tblPrEx><w:tblBorders><w:top w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:left w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:bottom w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:right w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideH w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/><w:insideV w:val="single" w:color="D7D7D7" w:sz="4" w:space="0"/></w:tblBorders><w:tblCellMar><w:top w:w="0" w:type="dxa"/><w:left w:w="108" w:type="dxa"/><w:bottom w:w="0" w:type="dxa"/><w:right w:w="108" w:type="dxa"/></w:tblCellMar></w:tblPrEx><w:trPr><w:trHeight w:val="500" w:hRule="atLeast"/></w:trPr><w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="E0E0E0"/><w:vAlign w:val="center"/></w:tcPr><w:p><w:pPr><w:jc w:val="left"/></w:pPr><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:eastAsia="宋體"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t>${title.optionsD}</w:t></w:r></w:p></w:tc><w:tc><w:tcPr><w:shd w:val="clear" w:color="auto" w:fill="E0E0E0"/><w:vAlign w:val="center"/></w:tcPr><w:p><w:pPr><w:jc w:val="center"/></w:pPr><w:r><w:rPr><w:rFonts w:hint="eastAsia" w:eastAsia="宋體"/><w:lang w:val="en-US" w:eastAsia="zh-CN"/></w:rPr><w:t>${title.countD}</w:t></w:r></w:p></w:tc> </w:tr> </w:tbl> <w:p><w:pPr><w:rPr><w:b w:val="0"/><w:color w:val="0066FF"/><w:sz w:val="24"/></w:rPr></w:pPr></w:p> </#list> <w:p><w:bookmarkStart w:id="0" w:name="_GoBack"/><w:bookmarkEnd w:id="0"/></w:p><w:sectPr><w:pgSz w:w="11906" w:h="16838"/><w:pgMar w:top="1440" w:right="1800" w:bottom="1440" w:left="1800" w:header="708" w:footer="708" w:gutter="0"/><w:cols w:space="708" w:num="1"/><w:docGrid w:linePitch="360" w:charSpace="0"/></w:sectPr> </w:body></w:document>
更改完成后將document.xml拷貝至項目resource源下的templates目錄下
package com.stylefeng.guns.core.util; import java.io.*; import java.util.Enumeration; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; import freemarker.template.Configuration; import freemarker.template.Template; /** * Word文檔工具類 * @Author xWang **/ public class WordUtil { public static Configuration getConfiguration(){ //創建配置實例 Configuration configuration = new Configuration(Configuration.VERSION_2_3_28); //設置編碼 configuration.setDefaultEncoding("utf-8"); configuration.setClassForTemplateLoading(WordUtil.class, "/templates");//換成自己對應的目錄 return configuration; } /** * 獲取模板字符串輸入流 * @param dataMap 參數 * @param templateName 模板名稱 * @return */ public static ByteArrayInputStream getFreemarkerContentInputStream(Map dataMap, String templateName) { ByteArrayInputStream in = null; try { //獲取模板 Template template = getConfiguration().getTemplate(templateName); StringWriter writer = new StringWriter(); //生成文件 template.process(dataMap, writer); in = new ByteArrayInputStream(writer.toString().getBytes("utf-8"));//這里一定要設置utf-8編碼 否則導出的word中中文會是亂碼 } catch (Exception e) { System.err.println("模板生成錯誤"); } return in; } /** * 生成docx文檔 * @param dataMap 數據參數 * @param outputStream 輸出流 * @param document 模板xml文件名稱 * @param templatesZipPath docx后綴名改為zip文檔的路徑地址(路徑加文件名全路徑地址) * @return * @author xWang */ public static void createDocx(Map dataMap, OutputStream outputStream,String document,String templatesZipPath) { ZipOutputStream zipout = null; try { //內容模板 ByteArrayInputStream documentInput = WordUtil.getFreemarkerContentInputStream(dataMap, document); File docxFile = new File(templatesZipPath); if (!docxFile.exists()) { docxFile.createNewFile(); } 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.err.println("導出失敗:"+e.getStackTrace()); }finally { if(zipout!=null){ try { zipout.close(); } catch (IOException e) { System.err.println("io異常"); } } if(outputStream!=null){ try { outputStream.close(); } catch (IOException e) { System.err.println("io異常"); } } } } }
測試
List<Integer> list = new ArrayList(); list.add(1); list.add(2); list.add(3); Map<String,Object> map = new HashMap<>();
map.put("theme","測試"); map.put("titleList",list); String output_file_name = "test.docx"; String templatesZipPath = "D/templates/templates.zip";
// 清空response
response.reset();
//設置ContentType字段值
response.setContentType("application/octet-stream");
response.setCharacterEncoding("UTF-8");
try {
//解決文件名為中文時的亂碼問題
String downloadFileName = URLEncoder.encode(output_file_name,"UTF-8");
// 設置response的Header
response.addHeader("Content-Disposition", "attachment;filename=" + downloadFileName);
OutputStream outputStream = response.getOutputStream();
WordUtil.createDocx(map,outputStream,"document.xml",templatesZipPath);
}catch (FileNotFoundException e){
}catch (IOException e){
}
finally {
}
需要的依賴(maven坐標)
<!--生成word文檔所需--> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.28</version> </dependency> <dependency> <groupId>dom4j</groupId> <artifactId>dom4j</artifactId> <version>1.6.1</version> </dependency>