背景

之前有的教辅标注需求,在导出题库的时候希望顺便导出可以查看word,方便线下预览成品效果,因为只是用来预览并且为了沿用前端的样式,当时方案就是直接生成html,写个word的文件头,这样就可以用word打开查看了,文件头如下:

  1. <html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
  2. </html>

直接在html里面填充内容即可,将后缀一改,word(伪)就生成了,但是这样的word有个致命的缺陷(客户机器必须联网,否则wor当中图片无法加载),并且随着业务的发展,导出的word客户想再次导入系统,这种html格式无法正常识别。需要导出标准格式的word并且顺便提了个需求,希望标注中latex公式在word中可以编辑

常见的word导出方案

  • Apache POI
  • FreeMark模板引擎生成xml格式文档
  • Aspose word(商业付费)
  • Spire.Doc(有商业版也有免费版)

其中Aspose word是不支持Latex公式的;使用Apache POI基本上是把Latex转成mathMl然后再写入到word中去,需要用到fmath两个jar包,在网上找了一些,没有找到正规取到,先pass;FreeMark写入其实也用到了fmath,需要将latex转成mathml格式,再写入到word的xml模板中,不过二次加工调用的引擎不支持xml编码的格式的word,所以此方案也pass

使用Spire.Doc导出支持编辑latex公式的word

依赖

  1. <dependency>
  2. <groupId>e-iceblue</groupId>
  3. <artifactId>spire.doc.free</artifactId>
  4. <version>3.9.0</version>
  5. </dependency>

创建Document对象和Section

  1. Document document = new Document();
  2. Section section = document.addSection();

创建段落,设置前后边距

  1. Paragraph paragraph = section.addParagraph();
  2. paragraph.getFormat().setLineSpacing(15);
  3. paragraph.getFormat().setBeforeSpacing(20);

写入文字及设置中英文字体

  1. TextRange textRange = paragraph.appendText(text);
  2. textRange.getCharacterFormat().setFontNameFarEast("宋体");
  3. textRange.getCharacterFormat().setFontNameNonFarEast("Times New Roman");

写入latex公式

  1. OfficeMath math = new OfficeMath(paragraph.getDocument());
  2. paragraph.getItems().add(math);
  3. math.fromLatexMathCode(latexFormat(innerPojo.latex));
  4. /**
  5. * 这里spire.doc有一些缺陷,对于一些符号支持的不是很好,大于等于小于等于,这里做一下替换,连续中文也做了\mbox{}包裹,这个是基于latex的经验,但是实际并没有什么用,spire.doc不支持带有中文的latex公式渲染,可能版本太低了,所以不能正常渲染就直接显示图片
  6. */
  7. private String latexFormat(String latex) {
  8. if (latex.contains("leqslant")) {
  9. latex = latex.replace("leqslant", "leq");
  10. }
  11. if (latex.contains("geqslant")) {
  12. latex = latex.replace("geqslant", "geq");
  13. }
  14. StringBuilder latexBuilder = new StringBuilder();
  15. boolean isChinese = false;
  16. String regexStr = "[\u4E00-\u9FA5]";
  17. for (Character c : latex.toCharArray()) {
  18. Matcher chineseMatch = Pattern.compile(regexStr).matcher(c.toString());
  19. if (chineseMatch.find()) {
  20. if (isChinese) {
  21. latexBuilder.append(c);
  22. } else {
  23. latexBuilder.append("\\mbox{").append(c);
  24. isChinese = true;
  25. }
  26. continue;
  27. } else {
  28. if (isChinese) {
  29. isChinese = false;
  30. latexBuilder.append("}");
  31. }
  32. latexBuilder.append(c);
  33. }
  34. }
  35. return latexBuilder.toString();
  36. }

绘制表格

spire.doc中api中无法直接再段落中直接添加表格,需要先添加一个文本框,然后在文本框的内部再添加表格,这里事先把表格的二维数组绘制好

  1. TextBox textBox = paragraph.appendTextBox(500, 20 * innerPojo.rows);
  2. textBox.getFormat().setHorizontalAlignment(ShapeHorizontalAlignment.Inside);
  3. textBox.getFormat().setNoLine(true);
  4. Table table = textBox.getBody().addTable(true);
  5. table.resetCells(innerPojo.rows, innerPojo.lines);
  6. for (int i = 0; i < innerPojo.rowLines.size(); i++) {
  7. List<String> rowLine = innerPojo.rowLines.get(i);
  8. for (int j = 0; j < rowLine.size(); j++) {
  9. appendWithFont(rowLine.get(j), table.get(i, j).addParagraph());
  10. }
  11. }
  12. // 设置文本框样式嵌入型
  13. textBox.setTextWrappingStyle(TextWrappingStyle.Inline);

这个版本的api找了一下,没有发现可以让文本框的高度自适应的方法,或许收费版本会好很多

插入图片

控制一下图片宽度不要超过500,高度不要超过300

  1. DocPicture picture = paragraph.appendPicture(innerPojo.getImage());
  2. log.info("pictureSize,Width:{},Height:{}", picture.getWidth(), picture.getHeight());
  3. if (picture.getWidth() > 500) {
  4. BigDecimal rate = BigDecimal.valueOf(500).divide(BigDecimal.valueOf(picture.getWidth()), 8, BigDecimal.ROUND_DOWN);
  5. picture.setHeight(picture.getHeight() * rate.floatValue());
  6. picture.setWidth(500);
  7. } else if (picture.getHeight() > 300) {
  8. BigDecimal rate = BigDecimal.valueOf(300).divide(BigDecimal.valueOf(picture.getHeight()), 8, BigDecimal.ROUND_DOWN);
  9. picture.setWidth(picture.getWidth() * rate.floatValue());
  10. picture.setHeight(300);
  11. }

导出效果如下图:

后续有时间再实验一下poi方式的公式导出

参考连接

https://www.e-iceblue.cn/spiredocforjavatext/set-character-format-in-word-in-java.html

使用spire.doc导出支持编辑Latex公式的标准格式word的更多相关文章

  1. Latex公式导出word,Latex转换MathML使用POI导出公式可编辑的Word文件

    背景 之前在 使用spire.doc导出支持编辑Latex公式的标准格式word 博客中写过,使用spire.doc来生成word,不得不说spire.doc的api操作起来还是比较方便,但是使用的过 ...

  2. 使用Spire.Doc来转换文本

    使用Spire.Doc来转换文本 前段时间,我为不熟悉这个产品的读者们写了一篇关于我对 Spire.Doc的初识印象.Spire.Doc是一个专业的Word .NET库,它是专门为开发人员设计的用来快 ...

  3. SPIRE.DOC - .NET开发者的福利

    SPIRE.DOC - .NET开发者的福利 前面我们使用过Spire.XLS for .NET Component创建Excel文件.最近试用了下.DOC 方面的API.这次测试的产品是.通过使用S ...

  4. [.NET] 开头不讲"Hello Word",读尽诗书也枉然 : Word 操作组件介绍 - Spire.Doc

    开头不讲"Hello Word",读尽诗书也枉然 : Word 操作组件介绍 - Spire.Doc [博主]反骨仔 [原文地址]http://www.cnblogs.com/li ...

  5. 开头不讲"Hello Word",读尽诗书也枉然 : Word 操作组件介绍 - Spire.Doc (转)

      [原文地址]http://www.cnblogs.com/liqingwen/p/5898368.html 序 本打算过几天简单介绍下组件 Spire.XLS,突然发现园友率先发布了一篇,既然 x ...

  6. 使用Spire.Doc组件利用模板导出Word文档

    以前一直是用Office的组件实现Word文档导出,但是让客户在服务器安装Office,涉及到版权:而且Office安装,包括权限配置也是比较麻烦. 现在流行使用第三方组件来实现对Office的操作, ...

  7. PowerPoint 中插入 Latex 公式

    做 PPT 用 Latex Beamer 毕竟还是太麻烦,Beamer 毕竟还是更适合学术性的,各种定义各种公式的那种,遇到要画各种图,插入各种图片,进行错综复杂的排版就比较棘手了. 最终还是 Pow ...

  8. 为WLW开发Latex公式插件

    WLW是写博客的利器,支持离线.格式排版等,而且拥有众多的插件.博客园推荐了代码插入插件,但是没有提供WLW的公式编译插件.目前我的一般做法是:先在Word下使用MathType编辑好公式,然后将公式 ...

  9. 【好文翻译】一步一步教你使用Spire.Doc转换Word文档格式

    背景: 年11月,微软宣布作为ECMA国际主要合作伙伴,将其开发的基于XML的文件格式标准化,称之为"Office Open XML" .Open XML的引进使office文档结 ...

随机推荐

  1. [第七篇]——Docker Hello World之Spring Cloud直播商城 b2b2c电子商务技术总结

    Docker Hello World Docker 允许你在容器内运行应用程序, 使用  docker run 命令来在容器内运行一个应用程序. 输出Hello world xxx@xxx:~$ do ...

  2. [第一篇]——Docker 教程之Spring Cloud直播商城 b2b2c电子商务技术总结

    Docker 教程 Docker 是一个开源的应用容器引擎,基于 Go 语言 并遵从 Apache2.0 协议开源. Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级.可移植的容器中,然 ...

  3. 【转】shell脚本中echo显示内容带颜色的实现方法

    shell脚本中echo显示内容带颜色的实现方法 shell脚本里使用echo输出颜色  

  4. 动态规划精讲(一)LC 最长递增子序列的个数

    最长递增子序列的个数 给定一个未排序的整数数组,找到最长递增子序列的个数. 示例 1: 输入: [1,3,5,4,7]输出: 2解释: 有两个最长递增子序列,分别是 [1, 3, 4, 7] 和[1, ...

  5. CentOS8安装ntp实现时间同步

    在CentOS8.0中默认不再支持ntp软件包,时间同步将由chrony来实现,像我这种习惯了ntp同步时间的,一时难以去适应chrony. 本文将通过wlnmp提供的源,来安装ntp服务 添加wln ...

  6. chrome 的手机调试工具 toggle device toolbar

    chrome 的手机调试工具 toggle device toolbar 是否可以模拟到不同系统,如苹果系统和安卓系统.

  7. requests接口自动化-数据库参数化

    数据库参数化的场景 部分接口,参数其他方式获取不到,可以去数据库去获取,如手机验证码 安装pymysql 配置文件 def sql_conf(): # 定义数据库的配置 host='127.0.0.1 ...

  8. MySQL update 链表 (一个表数据当做条件错误时候的转换)

    MySQL语句一: UPDATE lesson_p set solve_status = 6 where lesson_p_id in (SELECT lp.lesson_p_id FROM `les ...

  9. python学习笔记(一)-基础知识

    O.解释型语言和编译型语言 编译型语言就是先把写好的程序翻译成计算机语言然后执行,就是所谓的一次编译到处运行,比如c.c++就是编译型语言,这样的语言特点是运行速度快,但是需要事先把程序编译好才可以. ...

  10. prometheus+grafana实现服务监控

    一.安装prometheus: 下载相应的版本 :https://prometheus.io/download/ 解压: Linux:tar -zxvf XXX.tar.gz windows:直接下载 ...