使用spire.doc导出支持编辑Latex公式的标准格式word

背景

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


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

常见的word导出方案

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

其中AsposePDF for JAVA是从V19.4版本开始支持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 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);
}

导出效果如下图:

使用spire.doc导出支持编辑Latex公式的标准格式word

使用spire.doc导出支持编辑Latex公式的标准格式word

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

参考连接

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

Original: https://www.cnblogs.com/surging-dandelion/p/15487783.html
Author: 蒲公英的狂想
Title: 使用spire.doc导出支持编辑Latex公式的标准格式word

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/579574/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • SQL优化之Oracle函数索引

    SQL查询条件使用函数优化 背景: 由于数据原因表关联只能使用函数对数据进行分隔 select B.* from TABLE_A A cross join TABLE_B B wh…

    Java 2023年6月5日
    0109
  • 入门clash 及 proxy 坑点

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    Java 2023年6月7日
    084
  • Java 14中对switch的增强,终于可以不写break了

    面对这样的 if语句,你是不是很难受呢? if (flag == 1) { log.info("didispace.com: 1"); } else if (f…

    Java 2023年6月9日
    086
  • 二叉搜索树,一个简单但是非常常见的数据结构

    前言 今天leetcode的每日一题450是关于删除二叉搜索树节点的,题目要求删除指定值的节点,并且需要保证二叉搜索树性质不变,做完之后,我觉得这道题将二叉搜索树特性凸显的很好,首…

    Java 2023年6月9日
    085
  • Java基础-续1

    方法 概念 在JS中,我们把方法称之为函数。在java我们称之为方法。 方法就是一个黑匣子。我们不需要知道内部是如何执行的,只要按照要求调用,就能完成必要的功能。 方法申明的语法:…

    Java 2023年6月7日
    064
  • 开机启动VM WARE 某台虚拟机

    新建一个批处理,内容如下: -T 是类型, ws 是 vm ware workstation ,其它类型如:vm ware player. 开始,运行”shell:st…

    Java 2023年5月30日
    065
  • HM2022ssm-mp4.2【DML增删改编程控制(2)】

    逻辑删除 3.1 需求 这是一个员工和其所签的合同表,关系是一个员工可以签多个合同,是一个一(员工)对多(合同)的表 员工ID为1的张业绩,总共签了三个合同,如果此时他离职了,我们…

    Java 2023年6月5日
    090
  • LinkMovementMethod「解决点击ClickableSpan触发view点击事件」

    上一篇写过自定义展开收起的textview,不过最近发现有个问题。 那就是在列表页中,如果点击了全部,会触发view的点击事件,导致展开后接着进入了详情。 这显然不是想要的结果。 …

    Java 2023年6月7日
    094
  • 深入理解Apollo核心机制之灰度发布——创建灰度

    概述 ApolloPortal创建灰度后都做了什么呢?Apollo是如何维护主版本与灰度版本关系的呢? 其实创建灰度非常简单,可以看到下图中”Cluster&#8221…

    Java 2023年6月6日
    079
  • 三,手写SpringMVC框架,第三次改进

    1 . 解决跳转问题:添加一个 login 方法,跳转返回一个字符串。 中央控制器DispacherServlet 调用EmpController ,所以字符串返回给中央控制器。如…

    Java 2023年6月16日
    074
  • 修改IntelliJ IDEA代码头注释

    posted @2016-04-05 10:09 聊聊IT那些事 阅读(502 ) 评论() 编辑 Original: https://www.cnblogs.com/FCWORL…

    Java 2023年6月6日
    073
  • 设计模式(单例模式)

    单例模式:保证类在内存中只有一个对象。 如何保证类在内存中只有一个对象呢? A:把构造方法私有 B:在成员位置自己创建一个对象—-私有化并静态化 C:通过一个公共的方法…

    Java 2023年6月5日
    068
  • Linux命令拾遗-常用的辅助开发类命令

    原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处。 简介 之前介绍了大量的命令,有基础操作相关的,也有问题诊断相关的,但Linux中还有一类命令,被时常…

    Java 2023年6月7日
    094
  • java环境配置

    一、环境配置 1、打开”开始->计算机->属性->高级系统设置->环境变量”2、设置环境变量(当前最新的是1.8.0_25),如下:…

    Java 2023年5月29日
    078
  • Axis2在cmd处理wsdl时,找不到JAVA_HOME,The JAVA_HOME environment variable is not defined

    Axis2在cmd处理wsdl时,找不到JAVA_HOME,The JAVA_HOME environment variable is not defined 报了这个错误: 可是…

    Java 2023年5月29日
    0115
  • 单例模式–还没从工厂中逃脱出来?看来是注定单身了..

    前言 上次我们聊了聊一个略微重量级的工厂模式,不知道你是否消化完从工厂中逃脱出来了呢?不是我说,今天的单例模式,恰恰好相反了,孤孤单单,看来是注定单身了.. 先来看看单例模式在jd…

    Java 2023年6月5日
    093
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球