spire.doc在word中生成公式

=依赖,需要在官网下载然后安装到maven中=

xml 复制代码
      <dependency>
            <groupId>e-iceblue</groupId>
            <artifactId>spire.doc.free</artifactId>
            <version>5.3.2</version>
        </dependency>

=这段代码可以替换word中的latex文本替换为latex公式=

java 复制代码
package com.kd.distributeSimulate.aiConversation.entity;

import com.spire.doc.*;
import com.spire.doc.documents.*;
import com.spire.doc.fields.*;
import com.spire.doc.fields.omath.*;

import java.util.regex.*;

public class LatexFormulaReplacer {

    public static void main(String[] args) {
        // 输入和输出文件路径
        String inputFilePath = "123.docx";
        String outputFilePath = "output_with_formulas.docx";
        
        // 加载Word文档
        Document doc = new Document();
        doc.loadFromFile(inputFilePath);
        
        // 处理文档中的所有LaTeX公式
        replaceLatexFormulas(doc);
        
        // 保存文档
        doc.saveToFile(outputFilePath, FileFormat.Docx);
        System.out.println("LaTeX公式替换完成!输出文件: " + outputFilePath);
    }
    private static void replaceLatexFormulasInTable(Table table,Document doc) {
        Pattern pattern = Pattern.compile("\\$(.*?)\\$");
        // 遍历表格的所有行
        for (Object rowObj : table.getRows()) {
            TableRow row = (TableRow) rowObj;

            // 遍历行中的所有单元格
            for (Object cellObj : row.getCells()) {
                TableCell cell = (TableCell) cellObj;

                // 处理单元格中的所有段落
                for (Object paragraphObj : cell.getParagraphs()) {
                    Paragraph paragraph = (Paragraph) paragraphObj;
                    String paragraphText = paragraph.getText();
                    Matcher matcher = pattern.matcher(paragraphText);

                    // 记录处理偏移量,因为替换后文本长度会变化
                    int offset = 0;

                    // 查找所有匹配的LaTeX公式
                    while (matcher.find()) {
                        // 计算实际位置(考虑之前的替换导致的偏移)
                        int startPos = matcher.start() - offset;
                        int endPos = matcher.end() - offset;
                        String fullMatch = matcher.group(0); // 包含$的完整匹配
                        String latexFormula = matcher.group(1); // 仅LaTeX内容

                        System.out.println("找到公式: " + latexFormula);

                        // 创建OfficeMath对象并设置LaTeX公式
                        OfficeMath math = new OfficeMath(doc);
                        math.fromLatexMathCode(latexFormula);

                        // 查找包含当前匹配文本的TextRange及其在段落中的索引
                        TextRangeInfo rangeInfo = findTextRangeWithPosition(paragraph, startPos, endPos);
                        if (rangeInfo == null) {
                            continue;
                        }

                        TextRange targetRange = rangeInfo.textRange;
                        int rangeIndex = rangeInfo.index;
                        int relativeStart = rangeInfo.relativeStart;
                        int relativeEnd = rangeInfo.relativeEnd;

                        // 拆分文本为三部分:公式前、公式、公式后
                        String textBefore = targetRange.getText().substring(0, relativeStart);
                        String textAfter = targetRange.getText().substring(relativeEnd);

                        // 移除原始文本范围
                        paragraph.getChildObjects().remove(targetRange);

                        // 插入公式前的文本(如果不为空)
                        if (!textBefore.isEmpty()) {
                            TextRange beforeRange = new TextRange(doc);
                            beforeRange.setText(textBefore);
                            paragraph.getChildObjects().insert(rangeIndex, beforeRange);
                            rangeIndex++; // 插入后索引增加,确保后续元素位置正确
                        }

                        // 插入公式对象
                        paragraph.getChildObjects().insert(rangeIndex, math);
                        rangeIndex++;

                        // 插入公式后的文本(如果不为空)
                        if (!textAfter.isEmpty()) {
                            TextRange afterRange = new TextRange(doc);
                            afterRange.setText(textAfter);
                            paragraph.getChildObjects().insert(rangeIndex, afterRange);
                        }

                        // 更新偏移量(原始长度 - 新内容长度,公式对象不占文本长度)
                        offset += fullMatch.length();
                    }
                }
            }
        }
    }
    /**
     * 替换文档中所有用$包裹的LaTeX文本为公式对象,保留前后文本
     * @param doc Word文档对象
     */
    public static void replaceLatexFormulas(Document doc) {
        // 正则表达式匹配$包裹的LaTeX公式(非贪婪模式)
        Pattern pattern = Pattern.compile("\\$(.*?)\\$");
        
        // 遍历所有节
        for (Object sectionObj : doc.getSections()) {
            Section section = (Section) sectionObj;
            // 处理节中的表格
            for (Object tableObj : section.getTables()) {
                Table table = (Table) tableObj;
                replaceLatexFormulasInTable(table,doc);
            }
            // 遍历所有段落
            for (Object paragraphObj : section.getParagraphs()) {
                Paragraph paragraph = (Paragraph) paragraphObj;
                
                // 获取段落文本
                String paragraphText = paragraph.getText();
                Matcher matcher = pattern.matcher(paragraphText);
                
                // 记录处理偏移量,因为替换后文本长度会变化
                int offset = 0;
                
                // 查找所有匹配的LaTeX公式
                while (matcher.find()) {
                    // 计算实际位置(考虑之前的替换导致的偏移)
                    int startPos = matcher.start() - offset;
                    int endPos = matcher.end() - offset;
                    String fullMatch = matcher.group(0); // 包含$的完整匹配
                    String latexFormula = matcher.group(1); // 仅LaTeX内容
                    
                    System.out.println("找到公式: " + latexFormula);

                    // 创建OfficeMath对象并设置LaTeX公式
                    OfficeMath math = new OfficeMath(doc);
                    math.fromLatexMathCode(latexFormula);
                    
                    // 查找包含当前匹配文本的TextRange及其在段落中的索引
                    TextRangeInfo rangeInfo = findTextRangeWithPosition(paragraph, startPos, endPos);
                    if (rangeInfo == null) {
                        continue;
                    }
                    
                    TextRange targetRange = rangeInfo.textRange;
                    int rangeIndex = rangeInfo.index;
                    int relativeStart = rangeInfo.relativeStart;
                    int relativeEnd = rangeInfo.relativeEnd;
                    
                    // 拆分文本为三部分:公式前、公式、公式后
                    String textBefore = targetRange.getText().substring(0, relativeStart);
                    String textAfter = targetRange.getText().substring(relativeEnd);
                    
                    // 移除原始文本范围
                    paragraph.getChildObjects().remove(targetRange);
                    
                    // 插入公式前的文本(如果不为空)
                    if (!textBefore.isEmpty()) {
                        TextRange beforeRange = new TextRange(doc);
                        beforeRange.setText(textBefore);
                        paragraph.getChildObjects().insert(rangeIndex, beforeRange);
                        rangeIndex++; // 插入后索引增加,确保后续元素位置正确
                    }
                    
                    // 插入公式对象
                    paragraph.getChildObjects().insert(rangeIndex, math);
                    rangeIndex++;
                    
                    // 插入公式后的文本(如果不为空)
                    if (!textAfter.isEmpty()) {
                        TextRange afterRange = new TextRange(doc);
                        afterRange.setText(textAfter);
                        paragraph.getChildObjects().insert(rangeIndex, afterRange);
                    }
                    
                    // 更新偏移量(原始长度 - 新内容长度,公式对象不占文本长度)
                    offset += fullMatch.length();
                }
            }
        }
    }
    
    /**
     * 辅助类:存储TextRange及其位置信息
     */
    private static class TextRangeInfo {
        TextRange textRange;
        int index; // 在段落子对象中的索引
        int relativeStart; // 在TextRange中的起始位置
        int relativeEnd; // 在TextRange中的结束位置
        
        TextRangeInfo(TextRange tr, int idx, int rs, int re) {
            textRange = tr;
            index = idx;
            relativeStart = rs;
            relativeEnd = re;
        }
    }
    
    /**
     * 在段落中查找包含指定位置范围的TextRange及其详细位置信息
     * @param paragraph 段落对象
     * @param startPos 起始位置(段落文本中的绝对位置)
     * @param endPos 结束位置(段落文本中的绝对位置)
     * @return 包含TextRange及位置信息的对象,未找到返回null
     */
    private static TextRangeInfo findTextRangeWithPosition(Paragraph paragraph, int startPos, int endPos) {
        int currentPos = 0;
        int childIndex = 0;
        
        for (Object obj : paragraph.getChildObjects()) {
            if (obj instanceof TextRange) {
                TextRange textRange = (TextRange) obj;
                String text = textRange.getText();
                int textLength = text.length();
                
                // 检查当前TextRange是否包含目标位置范围
                if (currentPos <= startPos && currentPos + textLength >= endPos) {
                    // 计算在当前TextRange中的相对位置
                    int relativeStart = startPos - currentPos;
                    int relativeEnd = endPos - currentPos;
                    
                    // 确保相对位置在有效范围内
                    if (relativeStart >= 0 && relativeEnd <= textLength) {
                        return new TextRangeInfo(textRange, childIndex, relativeStart, relativeEnd);
                    }
                }
                
                currentPos += textLength;
            }
            childIndex++;
        }
        
        return null;
    }
}
相关推荐
code bean18 分钟前
【C#】获取不重复的编码(递增,非GUID)
开发语言·c#
阿里嘎多哈基米28 分钟前
二、JVM 入门——(三)栈
java·开发语言·jvm·线程·
lovebugs36 分钟前
🚀 Kubernetes核心命令详解:Java开发者必备指南
java·后端·kubernetes
快乐肚皮41 分钟前
IntelliJ IDEA Debug 模式功能指南
java·ide·intellij-idea·debug
_風箏1 小时前
SpringBoot【ElasticSearch集成 02】Java HTTP Rest client for ElasticSearch Jest 客户端集成
java·后端·elasticsearch
雷达学弱狗1 小时前
anaconda本身有一个python环境(base),想用别的环境就是用anaconda命令行往anaconda里创建虚拟环境
开发语言·python
野犬寒鸦1 小时前
力扣hot100:字母异位词分组和最长连续序列(49,128)
java·数据结构·后端·算法·哈希算法
浮游本尊1 小时前
Java学习第14天 - 微服务架构与Spring Cloud
java
燃尽余火1 小时前
Knife4j 文档展示异常的小坑
java·开发语言·spring
渣哥2 小时前
如果没有双亲委派,Java 会乱成什么样?
java