当前位置: 首页 > web >正文

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;}
}
http://www.xdnf.cn/news/19029.html

相关文章:

  • 设计模式理解
  • Shader开发(十七)着色器中的纹理采样与渲染
  • 农业物联网:科技赋能现代农业新篇章
  • 数模笔记day01(数据预处理、K-means聚类、遗传算法、概率密度分布)
  • UE5蓝图接口的创建和使用方法
  • 有鹿机器人如何用科技与创新模式破解行业难题
  • linux下的网络编程(2)
  • 智能体协作体系核心逻辑:Prompt、Agent、Function Calling 与 MCP 解析
  • AV1到达开始和约束时间
  • 分治法——二分答案
  • XFile v2 系统架构文档
  • Ansible 核心模块与实操练习
  • 第十三章项目资源管理--13.3 规划资源管理
  • Apifox 8 月更新|新增测试用例、支持自定义请求示例代码、提升导入/导出 OpenAPI/Swagger 数据的兼容性
  • 手写MyBatis第37弹: 深入MyBatis MapperProxy:揭秘SQL命令类型与动态方法调用的完美适配
  • AI赋能前端性能优化:核心技术与实战策略
  • Swift 解法详解 LeetCode 364:嵌套列表加权和 II
  • 713 乘积小于k的子数组
  • git学习 分支管理(branching)合并分支
  • golang13 单元测试
  • Office 2024 长期支持版(Mac中文)Word、Execl、PPT
  • Node.js 多版本管理工具 nvm 的安装与使用教程(含镜像加速与常见坑)
  • 共识算法如何保障网络安全
  • Java全栈开发面试实战:从基础到微服务的深度探索
  • k8s集群Prometheus部署
  • 1 vs 10000:如何用AI智能体与自动化系统,重构传统销售客户管理上限?
  • Wi-Fi数据包发送机制:从物理层到MAC层的深度解析
  • 记录使用ruoyi-flowable开发部署中出现的问题以及解决方法(二)
  • 贴片式TE卡 +北京君正+Rk瑞芯微的应用
  • 直线拟合方法全景解析:最小二乘、正交回归与 RANSAC