spire.doc在word中生成公式
=依赖,需要在官网下载然后安装到maven中=
<dependency><groupId>e-iceblue</groupId><artifactId>spire.doc.free</artifactId><version>5.3.2</version></dependency>
=这段代码可以替换word中的latex文本替换为latex公式=
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;}
}