今天客户提出要求,要求把表数据导出成为word文档格式。导成word格式的这种需求很寻常,但是看到word模板里面的这种单选框和多选框(如下图),要求实现选中效果,我就有点懵B了。到处百度,google,查询了下,发现好多都是要使用office开发工具来实现,我觉得太麻烦,驾驭不住。

最后想到有没有单选框或者复选框这样的特殊字符。于是在搜狗输入法里面查询特殊,发现还真有特殊字符,但是字符效果不太符合我要求,单选框选中效果太丑,复选框选中效果是方框里面打叉形式,瞬间就被我PASS掉了。皇天不负有心人,终于让我在word的特殊字符中找到想要的效果( Word > 插入 > 符号 > 其他符号(M)..), 也就是字体 Wingdings有我们需要的特殊字符

这里先展示下最终导出的显示效果(如下图),可以看到复选框和单选框被选中的效果都已经有了

这种方式唯一的弱点就是: 无法导出的doc文档没有真正的点击效果,也就是你打开word文档,点击复选框,复选框不会被置为选中效果,只是使用特殊字符,实现展示上的选中和非选中效果而已,但是对我的需求来说已经够用了。

下面就来看下较为完整的代码实现:

一: 首先是创建freemark的word导出模板, word模板如下图所示:

其中${XXXX} 形式的语法为freemarker的语法,不多介绍了。这里有个问题就是,${survey_date} 这样的语法内容在第二步导出的word xml文档中,容易被打断。有的建议是用类似文本编辑器编写好后一次性黏贴到word里面,不要在word里面一个个字符去输入,但是我发现即使都是复制黏贴进去的也会出现被打断的情况。不过没关系,后面会说明如何校正回来。

二: 将文档保存为word 2003 XML文档格式

网络上有些文章是说导出为Word 2003 XML文档格式,可以支持2003版本的word,具体因为我电脑没有2003 word,,没有尝试过,所以我也不确定是不是能兼容2003版本word。

三: 修改XML文档内容

这时候你如果使用寻常的编辑器打开第二个步骤生成的xml文件,发现是一堆没有格式化过的XML文档,非常难处理。有网络大神说使用【firstobject XML Editor】来打开,但是我安装后,打开xml文件,直接卡死。于是我用另一个编辑器【Visual Studio Code】,直接右键点击下 “格式化文件” (如果你没有这个功能,可能要安装下插件,在扩展里面,搜索下 xml format 就会发现有好几个XML format插件。)

通过查找  "${" 发现很多freemark的语法内容被打乱了,如下:

调整后效果如下:

然后我们需要将单选框和复选框的判断条件加上,通过查看XML文档,找到复选框/单选框所在位置:

红色部分指定使用Wingdings字体中的特殊字符,通过事先插入特殊字符(单选/复选),我找到分别代表单选框和复选框特殊字符的wordXML内容:

<w:sym w:font="Wingdings" w:char="F0A8"/>   复选框没选中
<w:sym w:font="Wingdings" w:char="F0FE"/>   复选框选中<w:sym w:font="Wingdings" w:char="F0A1"/>   单选框没选中
<w:sym w:font="Wingdings" w:char="F0A4"/>   单选框选中

现在要做的仅仅是使用freemark判断条件,来判断是要展示复选框选中效果还是非选中效果:

使用Freemark判断条件,来判断单选框选中效果:

然后剩下的无非是重复性劳动,一个个修改过去,反正我是眼睛都瞪累了才全部改完的。

最后记得把生成的XML文件,修改后缀名为 XXXX.ftl 放到你自己Freemarker的模板加载路径中去。

四: Spring加入Freemarker配置并导出doc文件

spring,application文件直接加入相关Freemarker配置,并加入freemarker相关jar包,这里简要展示下配置信息:

<bean id="freeMarkerConfigurer" class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer"><property name="templateLoaderPaths" value="/template/ftl" /><property name="freemarkerSettings"><props><prop key="defaultEncoding">UTF-8</prop><prop key="url_escaping_charset">utf-8</prop><prop key="locale">zh_CN</prop><!-- FreeMarker默认每隔N秒检查模板是否被更新,如果已经更新了,就会重新加载并分析模板。 但经常检查模板是否更新可能比较耗时。如果你的应用运行在生产模式下,而且你预期模板不会经常更新,   则可以将更新的延迟时间延长至一个小时或者更久。 可以通过为freemarkerSettings属性设置template_update_delay达到这一目的 -->  <prop key="template_update_delay">3600</prop><prop key="tag_syntax">auto_detect</prop><prop key="whitespace_stripping">true</prop><prop key="classic_compatible">true</prop><prop key="number_format">0.######</prop><prop key="boolean_format">true,false</prop><prop key="datetime_format">yyyy-MM-dd HH:mm:ss</prop><prop key="date_format">yyyy-MM-dd</prop><prop key="time_format">HH:mm:ss</prop></props></property>   </bean> 

简单展示下Java代码调用Freemarker生成doc:

private String generalDoc(String storePath, String unid, String templateName) throws Exception {Template template = null;Writer out = null;String docName = null; //文件名String docPath = ResourceUtils.assemblyPath(storePath, docName);; //完整文件路径try {// 输出文件out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(docPath), "UTF-8"));Map<String, Object> dataModel = getTemplateDataModel(unid);      //组织数据template = freeMarkerConfigurer.getConfiguration().getTemplate(templateName);//freemark居然这么差,需要手动指定版本?template.process(dataModel, out);//template.process(dataModel, out, new BeansWrapperBuilder(Configuration.VERSION_2_3_24).build());} catch (Exception e) {throw e;} finally {// 关闭流IOUtils.closeQuietly(out);}return docPath;}

这里需要注意的可能就是,如果是需要使用JavaBean形式反射机制进行属性访问的话,可能需要使用new BeansWrapperBuilder(Configuration.VERSION_2_3_24).build()  方式构建BeansWrapper。

private Map<String, Object> getTemplateDataModel(String unid) {Map<String, Object> row = getGermplasmForMap(unid);  //根据id获取数据,返回数据为map形式if(row == null) { //数据不存在throw new RuntimeException("数据不存在");}row.put("no", "1号表");row.put("dept_province", "福建省");row.put("survey_place", "延平区大大乡小小村");ArrayList<String> treeCategoryList = new ArrayList<String>();treeCategoryList.add("国家Ⅰ级重点保护植物");treeCategoryList.add("省外引进树种");row.put("tree_category_list", treeCategoryList);return row;}

=========================================导出异常记录=============================================

1. 导出的文件,无法打开,,

解决办法:  将生成的testlpf_b2_10.doc文件,修改为testlpf_b2_10.xml,使用VS Code打开,找到1349行,发现有个特殊字符, 通过转义来解决。

2. freemarker模板中不支持 直接使用顿号 、

附录:word2007-xml存储标签属性说明文件

地址: http://www.doc88.com/p-402265130456.html

Java导出带有单选款(radio)和复选框(checkbox)选中效果的word doc文档-Freemarker实现方式相关推荐

  1. 使用easyui框架form控件,单选按钮radio或复选框checkbox样式问题

    为什么80%的码农都做不了架构师?>>>    easyui只提供了textbox文本框,未提供单选按钮radio或复选框checkbox控件,在使用过程中,会存在单选按钮radio ...

  2. [Ext JS] 3.5 单选框 Radio与复选框CheckBox

    Radio 与Checkbox Radio 单选框,意思是当有一组同名的单选框时,一次只能选择一个.有单选框,也就有复选框(checkbox),对应的复选框就可以选择多个. Radio 和 Check ...

  3. VUE项目中 获得多个复选框 checkbox 选中的值(jquery)+ 解决 Uncaught TypeError: Cannot read property ‘push‘ of undefine

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家.点击跳转到教程. 1. 表格生成后第一列是复选框,效果: 表格是直接循环展示的后台返回数据,代码写法: 2. 得复选框 ...

  4. 用jquery修改默认的单选框radio或者复选框checkbox选择框样式

    默认的radio和checkbox选框很难看.我去看了一下qq注册的页面.发现单选和复选框并没有用<input>,居然是用是A标签.然后用css背景图片展示选择框,用JavaScript控 ...

  5. jsTree复选框checkbox选中和节点选择相互独立

    jsTree插件仅点击checkbox选中和文本分离和jstree只能点击checkbox选中的实现方法 在默认情况下,jstree 每次点击节点都会选中当前节点前的 checkbox jstree ...

  6. 微信小程序多选复选框checkbox。微信小程序官方文档bug

    由于个人从事微信小程序开发相关工作,在查询相关文档时(微信官方文档-小程序-表单组件-checkbox),发现示例代码中的一处错误. 问题出现原因:根据文档示例代码提示,设置本人本地代码,却发现下图红 ...

  7. CSS3重新定义input中呆若木鸡的默认复选框CheckBox和单选框Radio样式

    <!DOCTYPE html> <html> <head><meta charset="UTF-8"><style>/* ...

  8. bootstrap带有下拉按钮的输入框_关于bootstrap--表单(下拉select、输入框input、文本域textare复选框checkbox和单选按钮radio)...

    html 里面的 role 本质上是增强语义性,当现有的HTML标签不能充分表达语义性的时候,就可以借助role来说明.通常这种情况出现在一些自定义的组件上,这样可增强组件的可访问性.可用性和可交互性 ...

  9. 复选框(checkbox)、单选框(radiobox)的使用

    复选框(checkbox).单选框(radiobox)的使用 复选框: HTML: // 复选框 <input type="checkbox" name="chec ...

最新文章

  1. cisco 2950 3550 端口速率限制实现方法
  2. Mercurial和Git有什么区别?
  3. python多线程同步与互斥_Python之多线程:线程互斥与线程同步
  4. socket与http
  5. Linux 下 Redis 安装教程
  6. 当我们在UI上点add button增加新的search criteria之后,是framework做的处理把新的row render出来
  7. 解决VC不包含stdint.h头文件问题
  8. 一个端口扫描的小程序
  9. C#系列四《C#运算符与表达式》
  10. 很幽默的讲解六种Socket I/O模型C++程序设计
  11. 超详细mac新手教程-Mac界面篇
  12. 开心消消乐h5版游戏案例分享
  13. 草图大师SketchUp2020安装详细教程(官方中文版)
  14. VMware centos7镜像安装详细步骤
  15. python中国地图代码 上色_用Python绘制中国地图
  16. 大屏布局css,前端大屏项目的屏幕适配方案
  17. 关于高速光耦6n137的使用总结_高速光耦6n137典型应用电路图汇总(多谐振荡/光电隔离器/光耦开关)...
  18. 君士坦丁堡升级要点详解
  19. Hitters数据集数据分析
  20. LaTeX中绘制分块矩阵(矩阵中绘制横竖线)

热门文章

  1. 机器人运动学仿真笔记
  2. R代码学习(1)——算术运算、关系运算、逻辑运算
  3. 初学MSP430F5529定时器
  4. java 中的 while和 do...while语句的区别
  5. 学校校园学生寝室管理查寝打分系统 毕业设计毕设源码毕业论文开题报告参考(3)宿舍管理员功能
  6. 5G/NR PDSCH之频域资源分配
  7. 惠普测试c语言,HP的分院测试转自HP超话
  8. 【matplotlib】20.其他图
  9. C语言:一维数组—一个萝卜一个坑问题
  10. Windows10:关于触摸板的驱动不适用的问题