「褀氏生物」完成数千万元A轮融资
06-18
背??景有一天,产品经理递给我一份文字报告。我仔细一看,这份文档有大大小小的标题层次、格式良好的段落、各种饼图、趋势图,当然还有颜色循环交替的报告。
其复杂程度不亚于小明的学习报告。我准备通过某首歌曲来搜索关键词:java+word+export。
我立即想出了很多成熟的解决方案。通过横向和纵向比较,结合本次报告样式较多、用户可以灵活选择从不同模块导出的特点,最终我决定使用Freemarker动态替换模板数据导出word文档。
至于导出文档的最终格式,有两种选择: 应该使用 doc 还是 docx 格式的文档?每当我面临人生的选择时,我都会非常谨慎。最终我选择使用docx格式(原因会在文末解释),但是为了给大家更多的选择,满足更多的业务场景,小明借此机会给大家介绍一下两种使用 freemarker 导出 Word 文档的方法。
。 Idea FreeMarker是一个基于Java的模板引擎,最初专注于使用MVC软件架构生成动态网页。
然而,它是一个通用模板引擎,不依赖于 servlet、HTTP 或 HTML,因此它通常也用于生成源代码、配置文件或电子邮件。这时候我们就用它来动态生成xml文件,然后导出word文档。
整体流程如下: 准备WPS,由金山软件有限公司发布,用于办公软件最常用的文本编辑、表格、演示等功能。没错,就是这款国产办公软件。
除了它的强制登录之外,我也是第一次发现它在导出文档时像老朋友一样友好。 (Word解析的XML文件可读性很强,我不会告诉一般人) 开发工具(IDEA、Visual Studio Code等)自己喜欢、用得舒服的就是最好的。
实现Freemarker模板引擎的集成本项目使用的框架仍然是Springboot。这个框架非常方便集成各种组件,就不详细说了。
Freemarker 的这次集成也不例外。首先,我们在项目中添加依赖 spring-boot-starter-freemarkerpom.xml 文件,如下: 代码语言:javascript copy
application.yml 添加配置代码 language: javascript copy spring: freemarker: template-loader-path: classpath:/templates cache: false # 开发环境缓存关闭 suffix: xml charset: UTF-8 生成doc格式文档。这里,先使用freemarker。
以 doc 格式导出 word 文档的示例。首先,将docxTemplate.docx(调整后的样式模板文档)另存为WORD XML文档(*.xml)。
注意:如果您使用的是 Visual Studio Code 开发工具,请务必检查您使用的 xml 格式化插件是否会优化您的 xml 标签。例如:
使用Visual Studio Code的同学,天啊!小明这里推荐大家使用这个插件:XML Language Support by Red Hat 现在,我们将使用freemarker语法来编辑docTemplete.xml,比如使用占位符${}来替换当前文档的文本,从而实现动态生成文本的目的,直接输入代码即可。代码语言:javascript copy public static Configuration getConfiguration(){ //创建配置实例 Configuration configuration = new Configuration(Configuration.VERSION_2_3_28); //设置编码configuration.setDefaultEncoding("utf-8");配置.setClassForTemplateLoading(WordUtil.class , "/templates"); returnconfiguration;} /** * 生成doc文件* * @param ftlFileName 模板ftl文件名 * @param params 动态传入数据参数 * @param outFilePath 最终生成的doc文件完整保存路径*/ public void ftlToDoc (String ftlFileName, Map params, String outFilePath) { try { /** 加载模板文件**/ 模板 template = configuration.getTemplate(ftlFileName); /** 指定输出word文件的路径**/ File docFile = new File(outFilePath); FileOutputStream fos = new FileOutputStream(docFile);写入器 bufferedWriter = new BufferedWriter(new OutputStreamWriter(fos, "utf-8"), 0);template.process(params, bufferedWriter); if (bufferedWriter != null) { bufferedWriter.close(); } } catch (TemplateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }生成docx格式文档,带有高能警告!在成功使用Freemarker动态导出doc格式的文档后,相信大家都和我一样兴奋。
但上面的操作只是一个小小的铺垫。接下来我们看看如何导出docx格式的文档。
小明相信大家都会看到。官方惊呆了!这不,大开眼界!首先告诉大家一个秘密:docx格式的文档实际上是ZIP格式的压缩文件!什么?你不相信吗?验证方法如下:Windows朋友将docx文档修改为ZIP格式(将.docx后缀修改为.zip),然后通过解压工具解压。
MacOS的朋友可以直接使用unzip命令来解压word文档。解压后我们会发现该文件居然有自己的目录结构! document.xml文件用于存储核心数据、文本、表格、图片引用等。
media目录用于存储所有文档的图片。 _rels目录下的document.xml.rels存储配置信息,例如图片引用关系,即在document.xml中引用的id对应于media中的哪张图片。
获取zip中的document.xml文档和_rels文件夹中的document.xml.rels文档是显而易见的。如果我们想根据数据动态导出不同的word文档,我们只需要:通过 freemarker 将这些数据填充到 document.xml 中,并将图片配置信息填充到 document.xml.rels 文档中,然后使用文件流将此图片写入media目录中替换现有图片,最后添加填充好的document.xml和document.xml .rels,media即可以流式方式写入zip,输出docx文档!上代码吧嗯,由于篇幅限制,代码可以在文末找到。
Github地址问题和解决方案。当然,当每个人第一次尝试做某件事时,它可能不会一蹴而就。
例如,导出word时,您可能会遇到以下问题。特殊字符问题:有些文本数据不可避免地包含特殊字符,例如:< > @ ! $&等。
解决办法:这些特殊字符如果不进行转义,会导致单词无法打开。例如表中超链接的&符号需要替换为&。
如果您的文档在Office中打开,会提示文件已损坏。 ,90%是由特殊符号引起的。
我们可以打开文档。例如: 代码语言:javascript copy
如果直接按照之前的比例将图像放入文档中,会导致生成的文档中的图像变形。思路:首先将文档中的图片设置为原图,然后锁定宽高比,调整图片到合适的大小,从document.xml中解压文档,获取图片对应的宽高值此时的word,如下图: 为了保证文档中不同像素比例的宽高不变形,我们需要固定cy的值,然后动态获取表示的宽度cx的值word中当前图像的像素比例基于固定比例。
计算方法如下: 公式: 代码语言: javascript copy a/b = x/y。其中,a代表word中图片的宽度值,b代表word中图片的高度值,x代表前端传过来的图片的宽度(单位:像素),y代表前端传过来的图像的高度(单位:像素)。
因此,给定b、x、y,根据公式,我们可以求出a;我在文章的最后。当然,还有一些需要注意的地方:如果word中有很多模块,使用Freemarker语法时要更加小心;为什么小明要导出docx格式的文档呢? (不是因为产品经理提出的需求吗?)因为该文档是doc格式的,小明尝试导出后发现该文档不是合法的doc文档。
这体现在:在手机(微信、钉钉)上无法正常预览、office提示以xml格式打开等。因此,在导出doc文档时,我们填写完document后得到的是什么呢。
我们平时使用的生产环境是Linux……因此,经过深思熟虑和权衡,我们最终选择导出docx格式的文档。这个方法很完美,也保证了目前主流应用的正常预览。
敲黑板!导出docx文档最重要的思想就是用这些数据写入并覆盖模板文件(在业务中,相当于后门列表),并重新输出zip格式的压缩文件。这个文件就是我们最终想要的文档。
以上就是小明单词导出的来龙去脉。已经在线平稳运行了几十个日日夜夜。
如果您曾经遇到过或目前正在遇到Word文档导出和开发的问题,欢迎您与我们讨论和交流。相关链接:我上传了工具类,包括doc和docx的导出,导出word文档时特殊符号的转义,以及将图片转换为Base64进行文件输出的方法。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-18
06-18
06-17
06-17
06-18
06-18
最新文章
【玩转GPU】ControlNet初学者生存指南
【实战】获取小程序中用户的城市信息(附源码)
包雪雪简单介绍Vue.js:开学
Go进阶:使用Gin框架简单实现服务端渲染
线程池介绍及实际案例分享
JMeter 注释 18 - JMeter 常用配置组件介绍
基于Sentry的大数据权限解决方案
【云+社区年度征文集】GPE监控介绍及使用