使用freemark导出word中的表格并合并行和列
2020-10-15 本文已影响0人
我又不喜欢下雨
先看下合并行的导出的效果图
新建一个word,再添加一个表格,并使用$表达式占位(这个word后期没有什么用,只是用来做成模板而已)。其中hl命名成自己喜欢的名字,当然随便命名也无所谓,后面我们可以在模板中继续修改这个名称
docx格式的模板
然后使用编辑器打开此xml并使用格式化工具进行格式化,如下


然后把这个新建的word另存为xml

然后使用编辑器打开此xml并使用格式化工具进行格式化,如下
<w:tbl>
<w:tblPr>
<w:tblW w:w="0" w:type="auto"/>
<w:tblBorders>
<w:top w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
<w:left w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
<w:bottom w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
<w:right w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
<w:insideH w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
<w:insideV w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
</w:tblBorders>
<w:tblLook w:val="04A0"/>
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="2074"/>
<w:gridCol w:w="2074"/>
<w:gridCol w:w="2074"/>
<w:gridCol w:w="2074"/>
</w:tblGrid>
<w:tr wsp:rsidR="009B0F92" wsp:rsidRPr="00962941" wsp:rsidTr="00962941">
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="0054462A" wsp:rsidRPr="00962941" wsp:rsidRDefault="0054462A">
<w:r wsp:rsidRPr="00962941">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>英雄类型</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="0054462A" wsp:rsidRPr="00962941" wsp:rsidRDefault="0054462A">
<w:r wsp:rsidRPr="00962941">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>英雄数量</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="0054462A" wsp:rsidRPr="00962941" wsp:rsidRDefault="0054462A">
<w:r wsp:rsidRPr="00962941">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>英雄名称</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="0054462A" wsp:rsidRPr="00962941" wsp:rsidRDefault="0054462A">
<w:r wsp:rsidRPr="00962941">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>备注</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<w:tr wsp:rsidR="009B0F92" wsp:rsidRPr="00962941" wsp:rsidTr="00962941">
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="00F73C8C" wsp:rsidRPr="00962941" wsp:rsidRDefault="00CD3E6F">
<w:r wsp:rsidRPr="00962941">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>$</w:t>
</w:r>
<w:r wsp:rsidRPr="00962941">
<w:t>{hl.heroType}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="00F73C8C" wsp:rsidRPr="00962941" wsp:rsidRDefault="00CD3E6F">
<w:r wsp:rsidRPr="00962941">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>$</w:t>
</w:r>
<w:r wsp:rsidRPr="00962941">
<w:t>{hl.heroNum}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="00F73C8C" wsp:rsidRPr="00962941" wsp:rsidRDefault="00CD3E6F">
<w:r wsp:rsidRPr="00962941">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>$</w:t>
</w:r>
<w:r wsp:rsidRPr="00962941">
<w:t>{hl.heroName}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="00F73C8C" wsp:rsidRPr="00962941" wsp:rsidRDefault="00CD3E6F">
<w:r wsp:rsidRPr="00962941">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>$</w:t>
</w:r>
<w:r wsp:rsidRPr="00962941">
<w:t>{hl.remark}</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</w:tbl>
上面可以看到我们的表达式已经被拆分了。我们自己手动把他们合并起来。
<w:tr>是表格中的行
<w:tc>是一行当中的一列
在<w:tc>下的<w:tcPr>添加{(hl.endMerge)!''}
在需要开始合并的地方加上<w:vmerge w:val='restart'/>,其他地方都放<w:vmerge/>
如下:
<w:tbl>
<w:tblPr>
<w:tblW w:w="0" w:type="auto"/>
<w:tblBorders>
<w:top w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
<w:left w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
<w:bottom w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
<w:right w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
<w:insideH w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
<w:insideV w:val="single" w:sz="4" wx:bdrwidth="10" w:space="0" w:color="auto"/>
</w:tblBorders>
<w:tblLook w:val="04A0"/>
</w:tblPr>
<w:tblGrid>
<w:gridCol w:w="2074"/>
<w:gridCol w:w="2074"/>
<w:gridCol w:w="2074"/>
<w:gridCol w:w="2074"/>
</w:tblGrid>
<w:tr wsp:rsidR="00371C13" wsp:rsidRPr="0019677B" wsp:rsidTr="0019677B">
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="0054462A" wsp:rsidRPr="0019677B" wsp:rsidRDefault="0054462A">
<w:r wsp:rsidRPr="0019677B">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>英雄类型</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="0054462A" wsp:rsidRPr="0019677B" wsp:rsidRDefault="0054462A">
<w:r wsp:rsidRPr="0019677B">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>英雄数量</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="0054462A" wsp:rsidRPr="0019677B" wsp:rsidRDefault="0054462A">
<w:r wsp:rsidRPr="0019677B">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>英雄名称</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="0054462A" wsp:rsidRPr="0019677B" wsp:rsidRDefault="0054462A">
<w:r wsp:rsidRPr="0019677B">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>备注</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
<#list heroList as hl><!--循环后台传过来的数据(heroList要和后台传过来的数据名称对应,as后面跟的是一个别名,这个别名需要和下面的$表达式相对应)-->
<w:tr wsp:rsidR="00371C13" wsp:rsidRPr="0019677B" wsp:rsidTr="0019677B">
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
<!--startMerge和endMerge是java map中的key或者java对象中的属性-->
<!-- (hl.startMerge)!'' 的意思就是hl为空或者hl中的属性startMerge为空就显示!后面的字符串-->
<!-- hl.startMerge!'' 的意思就是hl中的属性startMerge为空就显示!后面的字符串,如果你的对象都为空的话就会报错-->
${(hl.startMerge)!''}<!--判断对象中是否有startMerge,没有就直接为空字符串-->
${(hl.endMerge)!''}<!--判断对象中是否有endMerge,没有就直接为空字符串-->
</w:tcPr>
<w:p wsp:rsidR="00F73C8C" wsp:rsidRPr="0019677B" wsp:rsidRDefault="00CD3E6F">
<w:r wsp:rsidRPr="0019677B">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${(hl.heroType)!''}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
${(hl.startMerge)!''}
${(hl.endMerge)!''}
</w:tcPr>
<w:p wsp:rsidR="00F73C8C" wsp:rsidRPr="0019677B" wsp:rsidRDefault="00CD3E6F">
<w:r wsp:rsidRPr="0019677B">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${(hl.heroNum)!''}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="00F73C8C" wsp:rsidRPr="0019677B" wsp:rsidRDefault="00CD3E6F">
<w:r wsp:rsidRPr="0019677B">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${(hl.heroName)!''}</w:t>
</w:r>
</w:p>
</w:tc>
<w:tc>
<w:tcPr>
<w:tcW w:w="2074" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
</w:tcPr>
<w:p wsp:rsidR="00F73C8C" wsp:rsidRPr="0019677B" wsp:rsidRDefault="00CD3E6F">
<w:r wsp:rsidRPr="0019677B">
<w:rPr>
<w:rFonts w:hint="fareast"/>
</w:rPr>
<w:t>${(hl.remark)!''}</w:t>
</w:r>
</w:p>
</w:tc>
</w:tr>
</#list>
</w:tbl>
然后开始组织数据
@GetMapping("/mergeRows")
public AjaxResponse mergeRows() {
final String startMerge = "<w:vmerge w:val='restart'/>";
final String endMerge = "<w:vmerge/>";
List<Map<String,Object>> heroList = new LinkedList<>();
Map<String,Object> map1 = new LinkedHashMap<>();
Map<String,Object> map2 = new LinkedHashMap<>();
Map<String,Object> map3 = new LinkedHashMap<>();
Map<String,Object> map4 = new LinkedHashMap<>();
Map<String,Object> map5 = new LinkedHashMap<>();
Map<String,Object> map6 = new LinkedHashMap<>();
Map<String,Object> map7 = new LinkedHashMap<>();
map1.put("heroType","上单");
map1.put("heroNum",3);
map1.put("heroName","德莱厄斯");
map1.put("remark","懦弱之举,我绝不姑息");
map1.put("startMerge",startMerge);
map2.put("heroType","上单");
map2.put("heroNum",3);
map2.put("heroName","贾克斯");
map2.put("remark","一个能打的都没有");
map2.put("endMerge",endMerge);
map3.put("heroType","上单");
map3.put("heroNum",3);
map3.put("heroName","普朗克");
map3.put("remark","吓老子一跳");
map3.put("endMerge",endMerge);
map4.put("heroType","打野");
map4.put("heroNum",1);
map4.put("heroName","努努");
map4.put("remark","雪人知道该怎么做");
map4.put("startMerge",startMerge);
map5.put("heroType","中单");
map5.put("heroNum",2);
map5.put("heroName","泰隆");
map5.put("remark","刀下生,刀下死");
map5.put("startMerge",startMerge);
map6.put("heroType","中单");
map6.put("heroNum",2);
map6.put("heroName","维迦");
map6.put("remark","我会让你知道什么是残忍");
map6.put("endMerge",endMerge);
map7.put("heroType","合计");
map7.put("heroNum",6);
map7.put("column","3");
map7.put("remark","我会让你知道什么是残忍");
heroList.add(map1);
heroList.add(map2);
heroList.add(map3);
heroList.add(map4);
heroList.add(map5);
heroList.add(map6);
// heroList.add(map7);
Map<String,Object> dataMap = new HashMap<>();
dataMap.put("heroList",heroList);
String url = "src/main/resources/public";
Configuration configure = new Configuration(Configuration.getVersion());
configure.setDefaultEncoding("utf-8");
WordUtil wordUtil = new WordUtil();
WordUtil.getInstance();
wordUtil.createDoc(dataMap,url,"mergeRows.xml","/mergeRows.doc");
return AjaxResponse.success();
}