记录一次详细的java利用freemarker生成word模板和坑

          需求描述: 根据公司纪律小组的电子违规记录,生成word综合分析文档。形式如: 

1. 上班时间打游戏

(1)XXX在XXX时间打游戏

图片

(2)XXXX在上班时间刷微博

图片

2.迟到

(1)XXX迟到

图片

....

     所用技术:freemaker ;系统环境: cent os

 制作模板的步骤别的博客里基本都有,和把map写进模板的代码大同小异,我也是抄别的博客里的。

我就说说遇到的坑和解决方法吧

1. 想要准确的复制成功 一定要复制一个<w:p>... </w:p>标签,这表示一个段落,里面带格式和内容

2. 最后模板生成时,我用的是xml 2003格式的,因为里面要图片,我看普通的xml格式里图片,是把图片存在一个统一地方,需要的地方是个引用。时间紧迫,我就用2003的,图片转为base64直接存在字段里。

3.生成结果: 最后生成文件时,保存的格式是xml格式,直接改后缀会打不开。我找了一个下午加晚上没找到好的解决方法,时间紧任务多,只能先搁置着。pageoffice打开xml格式的文件没问题。因为服务器是Linux,有个jacob包不能用。我现在解决方法就是加一行提示,请下载之后打开方式用word打开,并且另存为word格式。

4. freemaker循环对象

这个放心 正常循环,支持对象里的对象再一次循环。

附 :实体类和模板文件关键部分 关键部分加粗

@Data
@Accessors( chain = true)
public class ReportDataModel {
    String retitle;
    List<ReportItem>  items;
}

@Data
public class ReportItem {
    String itemdata;
    String itempic;
}

 

<#list recordData as record><w:p wsp:rsidR="001E6155" wsp:rsidRDefault="001E6155" wsp:rsidP="002E6BEF"><w:pPr><w:overflowPunct w:val="off"/><w:spacing w:line="560" w:line-rule="exact"/><w:ind w:first-line-chars="200" w:first-line="640"/><w:rPr><w:rFonts w:ascii="楷体" w:fareast="楷体" w:h-ansi="楷体" w:cs="方正仿宋_GBK" w:hint="fareast"/><wx:font wx:val="楷体"/><w:sz w:val="32"/><w:sz-cs w:val="32"/></w:rPr></w:pPr><w:r><w:rPr><w:rFonts w:ascii="楷体" w:fareast="楷体" w:h-ansi="楷体" w:cs="方正仿宋_GBK" w:hint="fareast"/><wx:font wx:val="楷体"/><w:sz w:val="32"/><w:sz-cs w:val="32"/></w:rPr><w:t>${record.retitle}</w:t></w:r></w:p><#list record.items as item><w:p wsp:rsidR="002C503E" wsp:rsidRDefault="001E6155" wsp:rsidP="002C503E"><w:r><w:rPr><w:rFonts w:ascii="方正仿宋_GBK" w:fareast="方正仿宋_GBK" w:hint="fareast"/><wx:font wx:val="方正仿宋_GBK"/><w:sz w:val="32"/><w:sz-cs w:val="32"/></w:rPr><w:tab/></w:r><w:r><w:rPr><w:rFonts w:ascii="方正仿宋_GBK" w:fareast="方正仿宋_GBK" w:hint="fareast"/><wx:font wx:val="方正仿宋_GBK"/><w:sz w:val="32"/><w:sz-cs w:val="32"/></w:rPr><w:tab/></w:r><w:proofErr w:type="spellStart"/><w:r><w:rPr><w:rFonts w:ascii="方正仿宋_GBK" w:fareast="方正仿宋_GBK" w:hint="fareast"/><wx:font wx:val="方正仿宋_GBK"/><w:sz w:val="32"/><w:sz-cs w:val="32"/></w:rPr><w:t>${item.itemdata}</w:t></w:r><w:proofErr w:type="spellEnd"/></w:p><w:p wsp:rsidR="002C503E" wsp:rsidRDefault="0061702B" wsp:rsidP="002C503E"><w:r><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://0300000"+item_index+1+".jpg"}" xml:space="preserve">${item.itempic}

</w:binData><v:shape id="_x56fe__x7247__x0020_1" o:spid="_x0000_i1025" type="#_x0000_t75" alt="大厅【音】_20190111135230431" style="width:441.8pt;height:248.75pt;visibility:visible;mso-wrap-style:square"><v:imagedata src="${"wordml://0300000"+item_index+1+".jpg"}" o:title="大厅【音】_20190111135230431"/></v:shape></w:pict></w:r></w:p>

</#list>

</#list>

如果我帮助了你 可以给我一口咖啡喝吗

 

在Web应用中,有时需要按照固定的模板将数据导出到Word,如流程审批单,在流程处理完成后将处理过程按照流程单的要求导出,有时程序中需要实现生成标准Word文档,要求能够打印,并且保持页面样式不变,常见的方案有POI、iText、JACOB、JSP几种方式,POI读取Word文档比较适合、对于生成文档样式比较难控制,iText操作Excel还可以,对Word的操作功能有限,JACOB操作Word实现复杂,并且无法将服务部署到Linux平台,要求安装office,对于实现固定格式的报表实现困难,对于JSP直接输出方式样式控制难。 Word从2003开始支持XML格式,用XML+Freemarder还做就很简单了,大致的思路是先用office2003或者2007编辑好 word的样式,然后另存为xml,将xml翻译为FreeMarker模板,最后用java来解析FreeMarker模板并输出Doc。经测试这样方式生成word文档完全符合office标准,样式、内容控制非常便利,打印也不会变形,生成的文档和office中编辑文档完全一样。具体实现过程如下: 1、 首先用office【版本要2003以上,以下的不支持xml格式】编辑文档的样式,将需要动态填充的内容使用Freemarker标签替换:Word文档样式如下: 2、 将Word文档另存为XML格式,将后缀名“xml”修改为“ftl” 3、 使用Freemarker填充内容,代码如下: [java] view plaincopyprint? 1. package com.test.freemarker.report; 2. 3. 4. 5. import java.io.BufferedWriter; 6. 7. import java.io.File; 8. 9. import java.io.FileOutputStream; 10. 11. import java.io.IOException; 12. 13. import java.io.OutputStreamWriter; 14. 15. import java.io.Writer; 16. 17. import java.util.HashMap; 18. 19. import java.util.Map; 20. 21. 22. 23. import freemarker.template.Configuration; 24. 25. import freemarker.template.Template; 26. 27. import freemarker.template.TemplateException; 28. 29. 30. 31. public class DocumentHandler { 32. 33. private Configuration configuration = null; 34. 35. 36. 37. public DocumentHandler() { 38. 39. configuration = new Configuration(); 40. 41. configuration.setDefaultEncoding("utf-8"); 42. 43. } 44. 45. 46. 47. public void createDoc() { 48. 49. // 要填入模本的数据文件 50. 51. Map dataMap = new HashMap(); 52. 53. getData(dataMap); 54. 55. // 设置模本装置方法和路径,FreeMarker支持多种模板装载方法。可以重servlet,classpath,数据库装载, 56. 57. // 这里我们的模板是放在com.havenliu.document.template包下面 58. 59.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值