背景

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

<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">
</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

依赖

<dependency>
<groupId>e-iceblue</groupId>
<artifactId>spire.doc.free</artifactId>
<version>3.9.0</version>
</dependency>

创建Document对象和Section

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

创建段落,设置前后边距

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

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

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

写入latex公式

OfficeMath math = new OfficeMath(paragraph.getDocument());
paragraph.getItems().add(math);
math.fromLatexMathCode(latexFormat(innerPojo.latex)); /**
* 这里spire.doc有一些缺陷,对于一些符号支持的不是很好,大于等于小于等于,这里做一下替换,连续中文也做了\mbox{}包裹,这个是基于latex的经验,但是实际并没有什么用,spire.doc不支持带有中文的latex公式渲染,可能版本太低了,所以不能正常渲染就直接显示图片
*/
private String latexFormat(String latex) {
if (latex.contains("leqslant")) {
latex = latex.replace("leqslant", "leq");
}
if (latex.contains("geqslant")) {
latex = latex.replace("geqslant", "geq");
}
StringBuilder latexBuilder = new StringBuilder();
boolean isChinese = false;
String regexStr = "[\u4E00-\u9FA5]";
for (Character c : latex.toCharArray()) {
Matcher chineseMatch = Pattern.compile(regexStr).matcher(c.toString());
if (chineseMatch.find()) {
if (isChinese) {
latexBuilder.append(c);
} else {
latexBuilder.append("\\mbox{").append(c);
isChinese = true;
}
continue;
} else {
if (isChinese) {
isChinese = false;
latexBuilder.append("}");
}
latexBuilder.append(c);
}
}
return latexBuilder.toString();
}

绘制表格

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

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

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

插入图片

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

DocPicture picture = paragraph.appendPicture(innerPojo.getImage());
log.info("pictureSize,Width:{},Height:{}", picture.getWidth(), picture.getHeight());
if (picture.getWidth() > 500) {
BigDecimal rate = BigDecimal.valueOf(500).divide(BigDecimal.valueOf(picture.getWidth()), 8, BigDecimal.ROUND_DOWN);
picture.setHeight(picture.getHeight() * rate.floatValue());
picture.setWidth(500);
} else if (picture.getHeight() > 300) {
BigDecimal rate = BigDecimal.valueOf(300).divide(BigDecimal.valueOf(picture.getHeight()), 8, BigDecimal.ROUND_DOWN);
picture.setWidth(picture.getWidth() * rate.floatValue());
picture.setHeight(300);
}

导出效果如下图:

后续有时间再实验一下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. 从零开始学习SQL SERVER(1)--- 了解SQL

    SQL是什么 SQL (发音为 sequal ['  sikwəl ' ]) SQL指 Structured Query Language 结构化查询语言,是用于访问和处理数据库的标准的计算机语言. ...

  2. go语言游戏服务端开发(三)——服务机制

    五邑隐侠,本名关健昌,12年游戏生涯. 本教程以Go语言为例.   P2P网络为服务进程间.服务进程与客户端间通信提供了便利,在这个基础上可以搭建服务. 在服务层,通信包可以通过定义协议号来确定该包怎 ...

  3. form表单提交失败

    在使用一个登录/注册模板的时候,发现form表单不了,但是删除模板引用的js后就正常了,查看js文件的源码,有一个 const firstForm = document.getElementById( ...

  4. 阿里云短信功能php

    1. 引入文件: https://help.aliyun.com/document_detail/53111.html?spm=a2c1g.8271268.10000.99.5a8ddf25gG0wW ...

  5. Spring Cloud Hystrix 学习(三)请求合并

    什么是请求合并?我们先来看两张图: 上方的两张图中,第二张可以看出服务端只执行了一次响应,这就是请求合并.客户端新增的请求合并模块,内部存在一个等待的时间窗口,将一定时间段内满足条件的请求进行合并,以 ...

  6. LR11自带网站

    LR自带的飞机订票系统 启动服务:安装路径\HP\LoadRunner\WebTours下的StartServer.bat 打开网页:地址  http://127.0.0.1:1080/WebTour ...

  7. 不关闭selinux下配置php+httpd访问KingbaseES

    在不关闭selinux的情况下使httpd+php+KingbaseES正常使用1.正常设置php.apache 除了正常流程外还需要在/etc/sysconfig/httpd最后追加LD_LIBRA ...

  8. YbtOJ#573-后缀表达【二分图匹配】

    正题 题目链接:https://www.ybtoj.com.cn/contest/115/problem/2 题目大意 给出一个包含字母变量和若干种同级操作符的后缀表达式.求一个等价的表达式满足该表达 ...

  9. Django整理(五) - 请求与响应 - request对象

    请求对象 一.客户端传参的几种方式 1. 通过URL路径(path)传递,例如:http://127.0.0.1:8000/news/1/2,两个参数:id和page 2. 通过 query stri ...

  10. 10.1 HTTP

    1.跨网络的主机间通讯 套接字Socket是进程间通信IPC的一种实现,允许位于不同主机(或同一主机)上不同进程之间通信和数据交换 在建立通信连接的每一端,进程间的传输要有两个标志:IP地址和端口号, ...