实现思路:
一、制作模板
1、在word中无非三种格式,文字、图片、表格,目前我所涉及到的业务中只有这三个,其他情况没涉及到没研究,首先需要准备一个模板文件,即xml格式的模板,通过打开一个空白的word文档,另存为xml文件,即可得到一个空白的word模板(可使用notepad++工具打开)
2、获取到空白文档的模板后,再新建一个word,填充文字,再另存为xml,打开并对比之前空白的模板之间的差异,可以找出添加文字后加了哪些代码。如果需要表格,则在空白文档加入加入表格,然后保存为xml文件打开查看代码,对比差异,可以知道具体的代码代表的意思。
3、图片方面的处理,同样是在空白文档中添加图片,然后查看xml代码,其中图片是以base64形式出现的,在替换图片的过程中,是需要将图片的base64码进行替换,所有的需要动态改变的数据,都使用freemarker标签的形式替换,如果不了解的,自行去了解一下freemarker标签的使用,具体的在xml中的代码的代表意思,可以到百度查找。
二、填充模板
1、后台使用jsoup解析HTML代码后,获取html代码中的值,保存到map中。文字段落,图片,表格,可分开处理。解析的HTML代码是通过百度UEditor生成的代码,如果是需要解析完整的正规的html代码,需要另外写解析标签的代码。
2、解析HTML时,可对应保存HTML中标签存在的属性,对应xml中的属性,通过实体来进行设置,遍历标签时,获取实体属性即可
3、填充模板保存后的文件仍然是xml格式的文件,需要另外处理,将文件另存为docx格式的word文档
实现代码:
注意:代码仅可以作为参考,即使完全复制,也不一定适合你,仅仅提供一个思路和参考,是否值得借鉴,需要自己评估,或者有更好的方法,欢迎留言评论一起交流
模板代码:(xml模板的代码,只贴出body中的代码)
<w:body>
<wx:sect>
<!-- 判断第一部分是文字段落,并遍历第一部分的段落 -->
<#if part1 == "paragraph">
<#list paragraphList1 as paragraph>
<w:p wsp:rsidR="0050577F" wsp:rsidRPr="00177379" wsp:rsidRDefault="00177379">
<w:pPr>
<w:jc w:val="${paragraph.align}"/>
<w:rPr>
<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
<wx:font wx:val="宋体"/>
<w:color w:val="${paragraph.color}"/>
<#if paragraph_index==0>
<w:sz w:val="30"/>
<w:sz-cs w:val="30"/>
<#else>
<w:sz w:val="${paragraph.size}"/>
<w:sz-cs w:val="${paragraph.size}"/>
</#if>
</w:rPr>
<w:spacing w:line="${paragraph.lineHeight}" w:line-rule="auto"/>
</w:pPr>
<!-- 遍历段落中的wr,每个wr可定义对应的文字属性,如果内容不为空,则执行文字遍历循环 -->
<#list paragraph.wrList as wr>
<#if wr.content??>
<w:r>
<w:rPr>
<w:rFonts w:ascii="${wr.font}" w:fareast="${wr.font}" w:h-ansi="${wr.font}" w:hint="fareast"/>
<wx:font wx:val="${wr.font}"/>
<w:color w:val="${wr.color}"/>
<#if paragraph_index==0>
<w:sz w:val="30"/>
<w:sz-cs w:val="30"/>
<#else>
<w:sz w:val="${paragraph.size}"/>
<w:sz-cs w:val="${paragraph.size}"/>
</#if>
${wr.bold}
${wr.tilt}
${wr.underLine}
</w:rPr>
<w:t>${wr.content}</w:t>
</w:r>
</#if>
<!-- 如果是图片,则在wr上添加图片 -->
<#if wr.hasImg == 1>
<#list wr.imgList as image>
<w:r wsp:rsidRPr="006E22D7">
<w:rPr>
<w:noProof/>
</w:rPr>
<w:pict>
<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHeight"/>
<v:f eqn="sum @10 21600 0"/>
</v:formulas>
<v:path o:extrusionok="f" gradientshapeok="t" o:connecttype="rect"/>
<o:lock v:ext="edit" aspectratio="t"/>
</v:shapetype>
<w:binData w:name="wordml://${image.imgName}.png" xml:space="preserve">${image.imgBase64}</w:binData>
<v:shape id="${image.imgId}" o:spid="_x0000_i1025" type="#_x0000_t75" style="width:${image.width}pt;height:${image.height}pt;visibility:visible;mso-wrap-style:square">
<v:imagedata src="wordml://${image.imgName}.png" o:title="${image.imgName}"/>
</v:shape>
</w:pict>
</w:r>
</#list>
</#if>
</#list>
</w:p>
</#list>
</#if>
<!-- 如果第一部分是表格,则填充表格 -->
<#if part1 == "table">
<w:tbl>
<w:tblPr>
<w:tblW w:w="8522" w:type="dxa"/>
<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="${table.tblLook}"/>
</w:tblPr>
<w:tblGrid>
<!-- 表格列,定义的表格有多少列,则遍历显示多少个网格 -->
<#list table.gridColList as gridCol>
${gridCol}
</#list>
</w:tblGrid>
<!-- 遍历表格中的行,tr -->
<#list table.trList as tr>
<w:tr wsp:rsidR="00616293" wsp:rsidRPr="00616293" wsp:rsidTr="00616293">
<w:trPr>
<!-- 设置行高属性 -->
<w:trHeight w:val="${tr.height}"/>
</w:trPr>
<!-- 遍历行中的列 -->
<#list tr.tdList as td>
<w:tc>
<w:tcPr>
<!-- 列宽属性 -->
<w:tcW w:w="${td.width}" w:type="dxa"/>
<w:shd w:val="clear" w:color="auto" w:fill="auto"/>
<w:tcBorders>
${td.top}
${td.right}
${td.bottom}
${td.left}
</w:tcBorders>
${td.gridSpan}
${td.merge}
</w:tcPr>
<!-- 遍历单元格中的段落文字 -->
<#list td.paragraphList as paragraph>
<w:p wsp:rsidR="0050577F" wsp:rsidRPr="00177379" wsp:rsidRDefault="00177379">
<w:pPr>
<!-- 设置单元格中段落的属性 -->
<w:jc w:val="${paragraph.align}"/>
<w:rPr>
<w:rFonts w:ascii="宋体" w:h-ansi="宋体" w:hint="fareast"/>
<wx:font wx:val="宋体"/>
<w:color w:val="${paragraph.color}"/>
<#if tr_index==0>
<w:sz w:val="30"/>
<w:sz-cs w:val="30"/>
<#else>
<w:sz w:val="${paragraph.size}"/>
<w:sz-cs w:val="${paragraph.size}"/>
</#if>
</w:rPr>
<w:spacing w:line="${paragraph.lineHeight}" w:line-rule="auto"/>
</w:pPr>
<!-- 遍历段落中的wr -->
<#list paragraph.wrList as wr>
<!-- 如果内容不为空,则执行文字遍历循环 -->
<#if wr.content??>
<w:r>
<w:rPr>
<w:rFonts w:ascii="${wr.font}" w:fareast="${wr.font}" w:h-ansi="${wr.font}" w:hint="fareast"/>
<wx:font wx:val="${wr.font}"/>
<w:color w:val="${wr.color}"/>
<#if tr_index==0>
<w:sz w:val="30"/>
<w:sz-cs w:val="30"/>
<#else>
<w:sz w:val="${paragraph.size}"/>
<w:sz-cs w:val="${paragraph.size}"/>
</#if>
${wr.bold}
${wr.tilt}
${wr.underLine}
</w:rPr>
<w:t>${wr.content}</w:t>
</w:r>
</#if>
<!-- 如果是图片,则在wr上添加图片 -->
<#if wr.hasImg == 1>
<!-- 遍历图片 -->
<#list wr.imgList as image>
<w:r wsp:rsidRPr="006E22D7">
<w:rPr>
<w:noProof/>
</w:rPr>
<w:pict>
<v:shapetype id="_x0000_t75" coordsize="21600,21600" o:spt="75" o:preferrelative="t" path="m@4@5l@4@11@9@11@9@5xe" filled="f" stroked="f">
<v:stroke joinstyle="miter"/>
<v:formulas>
<v:f eqn="if lineDrawn pixelLineWidth 0"/>
<v:f eqn="sum @0 1 0"/>
<v:f eqn="sum 0 0 @1"/>
<v:f eqn="prod @2 1 2"/>
<v:f eqn="prod @3 21600 pixelWidth"/>
<v:f eqn="prod @3 21600 pixelHeight"/>
<v:f eqn="sum @0 0 1"/>
<v:f eqn="prod @6 1 2"/>
<v:f eqn="prod @7 21600 pixelWidth"/>
<v:f eqn="sum @8 21600 0"/>
<v:f eqn="prod @7 21600 pixelHei