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

自动化办公004—有效解决ChatGPT数学公式无法复制到Office、MarkDown的问题

ChatGPT在输出数学公式的时候是正常的,但是粘贴到word、粘贴到MarkDown笔记里就直接变成了一堆代码,其实是有办法解决的,本篇文章主要解决一下无法复制问题


在这里插入图片描述

目录

    • 一、问题复现
    • 二、效果展示
      • 1. 测试案例
      • 2. 开始转换
        • (1)运行程序
        • (2)将ChatGPT的内容粘贴进来
        • (3)点击转换为MarkDown
        • (4)点击复制就可以了
        • (5)点击转化为LaTeX
        • (6)其他操作
    • 三、代码展示
    • 四、关于EXE运行程序

一、问题复现

ChatGPT输出的信息是这样的(很工正):

在这里插入图片描述

复制到word中是这样的:

在这里插入图片描述
复制到MakeDown中是这样的:
在这里插入图片描述

如何让复制出来的效果跟ChatGPT展示的效果一样是个问题,今天主要来解决这个。

二、效果展示

(代码文章里放有,当然,我也打包了exe程序放在文章末尾,有需要自取)

1. 测试案例

接下来我们从ChatGPT中复制过来这么一段文字,包含字符和数学算式:

如果要将您提供的数学公式格式化为内联的LaTeX样式,可以这样写:在极坐标系中,两个极坐标点相加的含义是将它们表示的向量相加。每个极坐标点可以用一个长度(模)和一个方向角(角度或弧度)来描述。具体地说,如果有两个极坐标点 \( (r_1, \theta_1) \) 和 \( (r_2, \theta_2) \),它们分别表示长度为 \( r_1 \) 和 \( r_2 \),方向角为 \( \theta_1 \) 和 \( \theta_2 \) 的向量。将这两个向量相加得到的结果向量的极坐标可以通过以下公式计算:
\[ (r_1, \theta_1) + (r_2, \theta_2) = \left( \sqrt{r_1^2 + r_2^2 + 2r_1r_2\cos(\theta_2 - \theta_1)}, \ \theta_1 + \tan^{-1} \left( \frac{r_2\sin(\theta_2 - \theta_1)}{r_1 + r_2\cos(\theta_2 - \theta_1)} \right) \right) \]这里,\( \sqrt{r_1^2 + r_2^2 + 2r_1r_2\cos(\theta_2 - \theta_1)} \) 是结果向量的长度,\( \theta_1 + \tan^{-1} \left( \frac{r_2\sin(\theta_2 - \theta_1)}{r_1 + r_2\cos(\theta_2 - \theta_1)} \right) \) 是结果向量的方向角。因此,两个极坐标点相加的含义是将它们表示的两个向量进行向量加法,得到一个新的向量,其长度和方向角是根据上述公式计算得到的。
这样,您可以在LaTeX中内联地显示这个公式。

很明显,复制过来直接就成了这样,文字、代码、符号一堆。

2. 开始转换

(1)运行程序

我设置了一个输入框、两个转换按钮、一个重置按钮、一个输出框、一个复制按钮,对了左下角有信息提示,简单提示一下按钮的功能,当然,最后点击复制后,如果复制成功,可以在左下角看到提示。

在这里插入图片描述

(2)将ChatGPT的内容粘贴进来

注意,是使用ChatGPT左下角的复制选项,不要手动框选复制,框选复制的公式没法恢复。

在这里插入图片描述
复制后就可以在程序的输入框里边复制,像这样:

在这里插入图片描述

(3)点击转换为MarkDown

点击之后就可以在下边的文本框里看到转换后的文字信息,为了方便大家对应原文本里的公式,我并没有把公式单独列出来。

在这里插入图片描述

(4)点击复制就可以了

因为我用的CSDN编辑器是MarkDown的,在这里就直接复制进来让大家看下效果:


将这两个向量相加得到的结果向量的极坐标可以通过以下公式计算:
( r 1 , θ 1 ) + ( r 2 , θ 2 ) = ( r 1 2 + r 2 2 + 2 r 1 r 2 cos ⁡ ( θ 2 − θ 1 ) , θ 1 + tan ⁡ − 1 ( r 2 sin ⁡ ( θ 2 − θ 1 ) r 1 + r 2 cos ⁡ ( θ 2 − θ 1 ) ) ) (r_1, \theta_1) + (r_2, \theta_2) = \left( \sqrt{r_1^2 + r_2^2 + 2r_1r_2\cos(\theta_2 - \theta_1)}, \ \theta_1 + \tan^{-1} \left( \frac{r_2\sin(\theta_2 - \theta_1)}{r_1 + r_2\cos(\theta_2 - \theta_1)} \right) \right) (r1,θ1)+(r2,θ2)=(r12+r22+2r1r2cos(θ2θ1) , θ1+tan1(r1+r2cos(θ2θ1)r2sin(θ2θ1)))

这里,

r 1 2 + r 2 2 + 2 r 1 r 2 cos ⁡ ( θ 2 − θ 1 ) \sqrt{r_1^2 + r_2^2 + 2r_1r_2\cos(\theta_2 - \theta_1)} r12+r22+2r1r2cos(θ2θ1)

是结果向量的长度,

θ 1 + tan ⁡ − 1 ( r 2 sin ⁡ ( θ 2 − θ 1 ) r 1 + r 2 cos ⁡ ( θ 2 − θ 1 ) ) \theta_1 + \tan^{-1} \left( \frac{r_2\sin(\theta_2 - \theta_1)}{r_1 + r_2\cos(\theta_2 - \theta_1)} \right) θ1+tan1(r1+r2cos(θ2θ1)r2sin(θ2θ1))

是结果向量的方向角。

因此,两个极坐标点相加的含义是将它们表示的两个向量进行向量加法,得到一个新的向量,其长度和方向角是根据上述公式计算得到的。


忙活了大半天,结果很完美。

(5)点击转化为LaTeX

如果想将公式复制到Word、PPT、Excel,需要使用这个功能,比如我这里有句话:

如果要将您提供的数学公式格式化为内联的LaTeX样式,可以这样写:
\((r_1, \theta_1) + (r_2, \theta_2) = \left(r_1^2 + r_2^2 + 2r_1r_2 \cos(\theta_2 - \theta_1), \ \theta_1 + \tan^{-1} \left(\frac{r_1 + r_2 \cos(\theta_2 - \theta_1)}{r_2 \sin(\theta_2 - \theta_1)} \right)\right)\)
这样,您可以在LaTeX中内联地显示这个公式。

复制进去后是这样的:

在这里插入图片描述
点击“转化为LaTeX”可以看到这些内容:

在这里插入图片描述

选择复制我们需要的部分:

在这里插入图片描述

打开word后按下Alt + =(word里边的LaTeX编辑器),会出来一个这个:

在这里插入图片描述

将复制的内容粘贴进去,按下回车就好了:

在这里插入图片描述
在这里插入图片描述

在PPT和Excel中插入LaTeX时需要使用一些插件,如MathType(官网),然后根据操作将LaTex代码插入进去就可以了(若有问题见文章末尾联系渠道)。

(6)其他操作

当然,这个重置按钮可是我精心为大家设置的,如果经常需要转化,可以在每次转化前点一下重置按钮,非常方便。

在这里插入图片描述在这里插入图片描述

三、代码展示

这里放一下我调试好的代码,若想在这个基础上继续完善欢迎自取。

import re
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout, QHBoxLayout, QTextEdit, QPushButton, QWidget, \QStatusBar
from PyQt5.QtCore import Qt, QEvent
from PyQt5.QtGui import QFontclass FormulaConverterApp(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("ChatGPT公式内容转换")self.setGeometry(100, 100, 720, 540)self.statusBar = QStatusBar()self.setStatusBar(self.statusBar)self.statusBar.setFont(QFont("微软雅黑", 12))# Set up the main layoutmain_layout = QVBoxLayout()main_layout.setContentsMargins(20, 20, 20, 20)  # Set margins around the layoutmain_layout.setSpacing(5)  # Set spacing between widgets in the layout# Input fieldself.input_field = QTextEdit("请复制ChatGPT的公式粘贴在这里")self.input_field.setFixedHeight(150)self.input_field.setFont(QFont("微软雅黑", 12))self.input_field.setStyleSheet("color: black;")self.input_field.installEventFilter(self)self.set_shadow_effect(self.input_field)main_layout.addWidget(self.input_field)# Buttonsbutton_layout = QHBoxLayout()button_layout.setSpacing(5)  # Set spacing between buttonsself.md_button = QPushButton("转换为Markdown")self.md_button.clicked.connect(self.convert_to_markdown)self.md_button.setToolTip("可以直接粘贴到MarkDown笔记")self.set_shadow_effect(self.md_button)button_layout.addWidget(self.md_button)self.latex_button = QPushButton("转化为LaTeX")self.latex_button.clicked.connect(self.convert_to_latex)self.latex_button.setToolTip("可以直接粘贴到Word、PPT、Excel")self.set_shadow_effect(self.latex_button)button_layout.addWidget(self.latex_button)self.reset_button = QPushButton("重置")self.reset_button.clicked.connect(self.reset_input)self.reset_button.setToolTip("清空输入")self.set_shadow_effect(self.reset_button)button_layout.addWidget(self.reset_button)main_layout.addLayout(button_layout)# Text displayself.text_display = QTextEdit("转换后的信息将在这里展示")self.text_display.setFixedHeight(150)self.text_display.setFont(QFont("微软雅黑", 12))self.text_display.setStyleSheet("color: black;")self.text_display.installEventFilter(self)self.set_shadow_effect(self.text_display)main_layout.addWidget(self.text_display)# Copy buttonself.copy_button = QPushButton("复制")self.copy_button.clicked.connect(self.copy_to_clipboard)self.set_shadow_effect(self.copy_button)main_layout.addWidget(self.copy_button)# Set the main widget and layoutcontainer = QWidget()container.setLayout(main_layout)self.setCentralWidget(container)# Connect button hover events to status bar messagesself.md_button.installEventFilter(self)self.latex_button.installEventFilter(self)self.reset_button.installEventFilter(self)# Apply stylesself.apply_styles()def apply_styles(self):self.setStyleSheet("""QMainWindow {background: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 #87CEEB, stop:1 #1E90FF);}QTextEdit {color: black;font-family: "微软雅黑";font-size: 10pt;border: none;background-color: #f0f0f0;padding: 20px;border-radius: 10px;}QPushButton {font-family: "微软雅黑";font-size: 12pt;height: 40px;border: none;background-color: #f0f0f0;padding: 10px;border-radius: 10px;}QPushButton:hover {background-color: #dcdcdc;}QPushButton:pressed {background-color: #c0c0c0;}QPushButton:focus {outline: none;}""")def eventFilter(self, source, event):if event.type() == QEvent.Enter:if source == self.md_button:self.statusBar.showMessage("第五提示:可以直接粘贴到MarkDown笔记")elif source == self.latex_button:self.statusBar.showMessage("第五提示:可以直接粘贴到Word、PPT、Excel")elif source == self.reset_button:self.statusBar.showMessage("第五提示:清空输入")elif event.type() == QEvent.Leave:self.statusBar.clearMessage()elif event.type() == QEvent.FocusIn:if source in [self.input_field, self.text_display]:if source.toPlainText() in ["请复制ChatGPT的公式粘贴在这里", "转换后的信息将在这里展示"]:source.clear()source.setStyleSheet("color: black;")elif event.type() == QEvent.FocusOut:if source == self.input_field and source.toPlainText().strip() == "":source.setText("请复制ChatGPT的公式粘贴在这里")source.setStyleSheet("color: black;")elif source == self.text_display and source.toPlainText().strip() == "":source.setText("转换后的信息将在这里展示")source.setStyleSheet("color: black;")return super().eventFilter(source, event)def set_shadow_effect(self, widget):widget.setGraphicsEffect(None)shadow = """border: 2px solid #c0c0c0;border-radius: 10px;background-color: #f0f0f0;box-shadow: 3px 3px 10px #aaaaaa;"""widget.setStyleSheet(widget.styleSheet() + shadow)def contains_chinese_characters(self, input_str):for char in input_str:if '\u4e00' <= char <= '\u9fff':return Truereturn Falsedef convert_to_markdown(self):input_str = self.input_field.toPlainText().strip()# 初始化结果列表segments = []# 拆分字符串,保留 \( 和 \) 以及 \[ 和 \] 之间的内容和其他文本while True:# 找到 \( 和 \) 的位置start_index_round = input_str.find(r'\(')end_index_round = input_str.find(r'\)')# 找到 \[ 和 \] 的位置start_index_square = input_str.find(r'\[')end_index_square = input_str.find(r'\]')# 选择最先出现的起始标记if start_index_round == -1 and start_index_square == -1:breakelif start_index_round == -1 or (start_index_square != -1 and start_index_square < start_index_round):start_index = start_index_squareend_index = end_index_squaredelimiter_len = len(r'\[')else:start_index = start_index_roundend_index = end_index_rounddelimiter_len = len(r'\(')if end_index == -1:break# 添加起始标记前的文本segments.append(input_str[:start_index])# 添加标记之间的 LaTeX 片段segments.append(input_str[start_index + delimiter_len:end_index])# 更新 input_strinput_str = input_str[end_index + delimiter_len:]# 添加剩余的文本(如果有)if input_str:segments.append(input_str)str = ""# 输出每个片段for i, segment in enumerate(segments):if self.contains_chinese_characters(segment):str += (f"{segment.strip()}")else:if len(segment) < 20:str += (f"${segment.strip()}$")else:str += (f"$${segment.strip()}$$")self.text_display.setText(str)def convert_to_latex(self):input_str = self.input_field.toPlainText().strip()# 初始化结果列表segments = []# 拆分字符串,保留 \( 和 \) 以及 \[ 和 \] 之间的内容和其他文本while True:# 找到 \( 和 \) 的位置start_index_round = input_str.find(r'\(')end_index_round = input_str.find(r'\)')# 找到 \[ 和 \] 的位置start_index_square = input_str.find(r'\[')end_index_square = input_str.find(r'\]')# 选择最先出现的起始标记if start_index_round == -1 and start_index_square == -1:breakelif start_index_round == -1 or (start_index_square != -1 and start_index_square < start_index_round):start_index = start_index_squareend_index = end_index_squaredelimiter_len = len(r'\[')else:start_index = start_index_roundend_index = end_index_rounddelimiter_len = len(r'\(')if end_index == -1:break# 添加起始标记前的文本segments.append(input_str[:start_index])# 添加标记之间的 LaTeX 片段segments.append(input_str[start_index + delimiter_len:end_index])# 更新 input_strinput_str = input_str[end_index + delimiter_len:]# 添加剩余的文本(如果有)if input_str:segments.append(input_str)str = ""# 输出每个片段for i, segment in enumerate(segments):if self.contains_chinese_characters(segment):str += (f"{segment.strip()}")else:if len(segment) < 20:str += (f"{segment.strip()}")else:str += (f"{segment.strip()}")self.text_display.setText(str)def reset_input(self):self.input_field.setText("请复制ChatGPT的公式粘贴在这里")self.input_field.setStyleSheet("color: black;")self.text_display.setText("转换后的信息将在这里展示")self.text_display.setStyleSheet("color: black;")def copy_to_clipboard(self):clipboard = QApplication.clipboard()clipboard.setText(self.text_display.toPlainText())self.statusBar.showMessage("第五提示:复制成功!", 2000)  # Show message for 2 secondsif __name__ == "__main__":app = QApplication(sys.argv)window = FormulaConverterApp()window.show()sys.exit(app.exec_())

四、关于EXE运行程序

为了方便操作,我这里直接将代码打包成了exe可运行程序,找到客F回复“ZD004”直接领取就行,当然,若有其他问题也可以随时留言,我看到后一定第一时间回复。

在这里插入图片描述
在这里插入图片描述

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Apache tika 实现各种文档内容解析
  • 科普文本分类背后的数学原理——最新版《数学之美》第14、15章读书笔记
  • 南方CASS:测绘工作者的得力助手
  • 发表EI会议论文-对考研生和研究生都有好处!
  • Mysql数据库两表连接进行各种操作
  • Python 如何实现数据驱动的接口自动化测试
  • 面壁智能发布端侧 AI 应用开发平台;快手推出肖像动画技术 LivePortrait丨 RTE 开发者日报
  • 【C++中resize和reserve的区别】
  • qt 线程举例
  • 基层医院、专科医院云HIS系统,支持电子病历四级,全套源码交付
  • MeEdu网校系统搜索功能问题处理
  • 【网络安全】Host碰撞漏洞原理+工具+脚本
  • codeforces round 956 div2
  • 使用 mongo2neo4j 和 SemSpect 通过各种方式进行图探索
  • 超市收银系统源码
  • 【Leetcode】104. 二叉树的最大深度
  • 【前端学习】-粗谈选择器
  • Android交互
  • Django 博客开发教程 16 - 统计文章阅读量
  • Java超时控制的实现
  • Netty 框架总结「ChannelHandler 及 EventLoop」
  • oschina
  • PHP 程序员也能做的 Java 开发 30分钟使用 netty 轻松打造一个高性能 websocket 服务...
  • session共享问题解决方案
  • 从0搭建SpringBoot的HelloWorld -- Java版本
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 浮动相关
  • 记录:CentOS7.2配置LNMP环境记录
  • 将 Measurements 和 Units 应用到物理学
  • 讲清楚之javascript作用域
  • 数组的操作
  • Java性能优化之JVM GC(垃圾回收机制)
  • 湖北分布式智能数据采集方法有哪些?
  • 组复制官方翻译九、Group Replication Technical Details
  • #Datawhale AI夏令营第4期#AIGC文生图方向复盘
  • #Linux(权限管理)
  • #我与Java虚拟机的故事#连载17:我的Java技术水平有了一个本质的提升
  • ${ }的特别功能
  • (9)STL算法之逆转旋转
  • (Git) gitignore基础使用
  • (NO.00004)iOS实现打砖块游戏(九):游戏中小球与反弹棒的碰撞
  • (二)hibernate配置管理
  • (附源码)计算机毕业设计SSM基于java的云顶博客系统
  • (转)visual stdio 书签功能介绍
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • ..回顾17,展望18
  • .class文件转换.java_从一个class文件深入理解Java字节码结构
  • .NET / MSBuild 扩展编译时什么时候用 BeforeTargets / AfterTargets 什么时候用 DependsOnTargets?
  • .Net Core中的内存缓存实现——Redis及MemoryCache(2个可选)方案的实现
  • .net(C#)中String.Format如何使用
  • .NET命令行(CLI)常用命令
  • .net图片验证码生成、点击刷新及验证输入是否正确
  • @Autowired注解的实现原理
  • @reference注解_Dubbo配置参考手册之dubbo:reference
  • [ 常用工具篇 ] AntSword 蚁剑安装及使用详解