需要解决的问题
指定模板,导出一页Word
如上图,给定一个模板,在数据库中获取信息,填充模板并导出为Word
如果需要填充图片,需要在你们自己的模板中,插入一张图片,然后转为xml文件,把插入图片的位置变为可供FreeMarker的占位符${xxx}即可。
- 在Word模板中插入图片,
2. 将Word另存为xml文件,我这里另存的是Word 2003 XML文档
3. 格式化xml,找到xml文件中插入的图片位置
在线 XML 格式化 | 菜鸟工具
下图就是插入图片的位置
可见Word将这张图片转为Base64字符串(/9j/4AAQSkZJRgABAQAA....)进行存储,这部分的标签内容大致如下:
<w:tc>
<w:tcPr>
<w:tcW w:w="6312" w:type="dxa"/>
<w:gridSpan w:val="3"/>
<w:vAlign w:val="center"/>
</w:tcPr>
<w:p wsp:rsidR="00997438" wsp:rsidRPr="00DB1FC4" wsp:rsidRDefault="00DB1FC4" wsp:rsidP="00DB1FC4">
<w:pPr>
<w:spacing w:after="0" w:line="240" w:line-rule="auto"/>
<w:jc w:val="center"/>
<w:rPr>
<w:rFonts w:hint="fareast"/>
<w:sz w:val="28"/>
<w:sz-cs w:val="32"/>
</w:rPr>
</w:pPr>
<w:r wsp:rsidRPr="00DB1FC4">
<w:rPr>
<w:noProof/>
<w:sz w:val="28"/>
<w:sz-cs w:val="32"/>
</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://每个图片的唯一id.jpg" xml:space="preserve">${Base64字符串,可以替换的地方}</w:binData>
<v:shape id="图片 1" o:spid="_x0000_i1025" type="#_x0000_t75" style="width:269.4pt;height:183pt;visibility:visible">
<v:imagedata src="wordml://每个图片的唯一id.jpg" o:title=""/>
</v:shape>
</w:pict>
</w:r>
</w:p>
</w:tc>
也就是说,我们只要将${Base64字符串,可以替换的地方} 替换成我们自己的Base64字符串,就可以完成在Word中灵活插入图片。
这里需要注意几点
- 替换的 base64字符串不能带dataxxxx这种前缀
- 每个图片都有一个唯一的id,在
w:binData标签中声明
<w:binData w:name="wordml://每个图片的唯一id.jpg" xml:space="preserve">${Base64字符串,可以替换的地方}</w:binData>
在v:imagedata中使用
<v:imagedata src="wordml://每个图片的唯一id.jpg" o:title=""/>
所以如果需要插入多张图片,可以考虑在w:binData中声明图片唯一id的占位符,例如:
<w:binData w:name="wordml://${picId}.jpg" xml:space="preserve">${baseStr}</w:binData>
<v:imagedata src="wordml://${picId}.jpg" o:title=""/>
- 如果模板中需要插入图片,一定要在自己的模板中插入图片然后再进行修改,不要复制上面的代码,不然就算成功渲染,word文件也打不开。因为插入图片后,文件头尾内容,相较于原本没有图片时会发生变化。
指定模板,导出多页重复Word
打印多页需要自己用xml进行尝试,比如在我的xml外层,有一个<wx:sect>标签,
如果我把他复制一份
那我Word中的表格就会变成两个,所以只要循环写<wx:sect>,就可以完成多页重复的导出
- 我这里没有加分页符,如果结尾带上分页符再进行赋值,每个表格只会占一页
- 注意图片id需要唯一
代码
具体代码可以参考:使用FreeMarker,导出Word或者Excel
只要模板正确,图片的插入,只需要将图片转为base64字符串,然后将占位符替换掉就可以。