文章介绍了对Word中表格单元格合并,导出功能。
1.1新建Word模板,选择好需要的字体大小,居中样式等(下图是遍历数据,采用${} 占位)
1.2将Word文件另存为XML文件格式保存桌面,然后改掉文件后缀为ftl,将ftl文件直接拖到IDEA中打开(显示一行Ctrl+Alt+L调正),文中报错信息可忽略:
#### 以下错误可以忽略,其他错误需改正 ####
URI is not registered (Settings | Languages & Frameworks | Schemas and DTDs))
Cannot resolve symbol 'dcterms:W3CDTF'
1.3查看ftl文件中的列名,${}是否都在<w:t></w:t>中,如果标签内有其他内容删除即可
<w:tc>
<w:tcPr>
<w:tcW w:w="1253" w:type="dxa"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:jc w:val="center"/>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:eastAsiaTheme="minorEastAsia"/>
<w:b/>
<w:bCs/>
<w:vertAlign w:val="baseline"/>
<w:lang w:val="en-US" w:eastAsia="zh-CN"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia"/>
<w:b/>
<w:bCs/>
<w:vertAlign w:val="baseline"/>
<w:lang w:val="en-US" w:eastAsia="zh-CN"/>
</w:rPr>
<w:t>序号</w:t>
</w:r>
</w:p>
</w:tc>
1.4IDEA中开始敲代码(条件:姓名相同则合并单元格,依次推,多种情况合并也可使用)
//1.1查询结果
List<Student> list=studentInformationMapper.selectAll();
//1.2java中循环list判断对象的姓名是否相同
Map<String,String> map = new HashMap<>();
//组织合并
map.put("pre","0"); //上一个对象中的姓名
map.put("name","0");//当前对象
map.put("next","0");//下一个对象中的姓名
for(int i=0;i<list.size();i++){
//保存他的前一个元素是否需要合并
if(i>0){
list.get(i).getMap().put("pre",list.get(i-1).getMap().get("organ"));
}
//保存他的后一个元素是否需要合并
if(i<list.size()-1){
list.get(i).getMap().put("next",list.get(i+1).getMap().get("organ"));
}
}
//注意:getMap 需要在Student实体类中 添加属性 private Map<String,String> map;
//1.2 将结果放入map中 resultList为别名(随意),在ftl文件中要对应
Map<String,Object> map = new HashMap<>();
map.put("resultList",list)
map.put("map",map)
1.5FTL文件中遍历标签,结尾处</#list>结束,A相当于一个Student对象
1.6FTL文件合并
<w:tc>
<w:tcPr>
<w:tcW w:w="1253" w:type="dxa"/>
<#--合并姓名-->
<#if A.map.name == "1">
<#if A.map.pre== "0">
<w:vMerge w:val="restart"/>
<#else>
<w:vMerge/>
</#if>
<#else>
<#if A.map.pre != "0">
<w:vMerge/>
</#if>
</#if>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p>
<w:pPr>
<w:pStyle w:val="2"/>
<w:keepNext w:val="0"/>
<w:keepLines w:val="0"/>
<w:widowControl/>
<w:suppressLineNumbers w:val="0"/>
<w:shd w:val="clear" w:fill="FFFFFF"/>
<w:jc w:val="center"/>
<w:rPr>
<w:color w:val="444444"/>
<w:vertAlign w:val="baseline"/>
</w:rPr>
</w:pPr>
<w:r>
<w:rPr>
<w:rFonts w:hint="eastAsia" w:asciiTheme="minorEastAsia"
w:hAnsiTheme="minorEastAsia" w:eastAsiaTheme="minorEastAsia"
w:cstheme="minorEastAsia"/>
<w:color w:val="auto"/>
<w:sz w:val="21"/>
<w:szCs w:val="21"/>
<w:shd w:val="clear" w:fill="FFFFFF"/>
</w:rPr>
<w:t>${A.name}</w:t>
</w:r>
</w:p>
</w:tc>
1.8加载FTL文件输出文件流,返回给前端,ftl文件位于当前模块的Resource下
//加载FTL模板所用到的APi
Configuration configuration = new Configuration(new Version("2.3.23"));
configuration.setDefaultEncoding("utf-8");
configuration.setClassForTemplateLoading(this.getClass(), "/");
//以utf-8的编码读取ftl文件
Template template = null;
try {
template = configuration.getTemplate("学生信息.ftl", "utf-8");
} catch (IOException ex) {
throw new Exception("读取ftl文件失败!", ex);
}
Writer writer = null;
// 4.生成 Word文档的全路径名称
File outFile = new File("学生信息.docx");
writer = new OutputStreamWriter(new FileOutputStream(outFile), "utf-8");
// 6.装载数据
template.process(map, writer);
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
response.setHeader("Content-Dispostion","attachment;filename="+"学生信息.docx");
// 7.读取生成好的 Word文档
File file = new File("学生信息.docx");
FileInputStream is = new FileInputStream(file);
OutputStream os = response.getOutputStream();
byte[] b = new byte[1024];
int length;
while ((length = is.read(b)) > 0) {
os.write(b, 0, length);
}
os.flush();
os.close();
writer.flush();
writer.close();
return null;
小贴士:
<#--Word分页符--> <w:p ><w:r><w:br w:type="page" /></w:r></w:p>