Skip to main content
如果你用 Word 写过论文或教材,大概遇到过这种需求:全文几十上百个 MathType 公式,字体要从 Times New Roman 统一成某种正文字体,字号要从 12pt 改成 10.5pt。一个一个双击改,不现实。于是你会去找 MathType 菜单里的 Format Equations——批量格式化。 它能用。很多人也一直在用。但这篇文章不是功能说明书,而是想把一件事讲清楚: 当你点下「批量格式化」之后,电脑里到底发生了什么? 把这条路径看明白,后面那些常见抱怨——卡、慢、一次只能跑一个文档、不敢中途打断——就不再是玄学,而是这套设计的直接后果。
若你的目标是批量改配置并刷新显示,更直接的路径是 mathtype-re-render,而不是死盯官方批量格式化进度条。

它表面上在做什么

从用户视角,流程很短:
  1. 在 MathType 里定好目标样式(字体、字号、间距等偏好)
  2. 回到 Word,打开批量格式化
  3. 选择「整篇文档」或「仅选区」
  4. 等进度跑完
结束后,文档里的公式看起来都换成了新样式。功能定位很明确:按同一套偏好,统一改文档中已有 MathType 公式的外观。 问题在于:它统一外观的方式,并不是「在原公式上改几个样式字段」,而是另一套更重的机制。

公式在 Word 里究竟是什么

理解批量格式化,先要理解 MathType 公式在 Word 中的存在形式。 它们通常不是 Word 原生公式(OMML),而是 OLE 嵌入对象。OLE(Object Linking and Embedding)是 Windows 上一套老资格的对象嵌入协议:宿主程序(这里是 Word)保存一块「属于别的程序」的数据;需要编辑时,再把控制权交给那个程序(这里是 MathType)。 在对象模型里,这类公式大致长这样:
  • 出现在文档的 InlineShapes(行内嵌入图形)集合中
  • 带有 OLEFormat
  • 程序标识(ProgID)通常是 Equation.DSMT4
所以 Word 并不「理解」公式内部的数学结构。它只知道:这里嵌了一块 MathType 的东西,要改它,就得找 MathType。 这一点决定了后面所有设计——格式化无法由 Word 单独完成,必须把 MathType 拉进流程。

点下批量格式化之后:逐步发生了什么

官方批量格式化(包括 SDK 里无界面版本的 FormatEquations)本质上是一个循环。对文档里每一个目标公式,大致重复下面几步。

1. 在 Word 里定位下一个公式

插件或 VBA 遍历当前文档(或选区)里的嵌入对象,筛出 ProgID 为 Equation.DSMT4 的项。每找到一个,就进入单公式处理。

2. 连上 MathType

Word 侧并不是直接「调用一个纯函数改样式」。常见链路是:
MT6.DLL 的职责很具体:管理与 MathType 的连接,必要时启动 MathType,再把请求转过去。API 层对应的是连接/断开一类调用(如 MTAPIConnect / MTAPIDisconnect,或经 WLL 封装的 MTInitAPI / MTTermAPI)。 也可以从 OLE 对象本身出发:对公式执行 DoVerb,按注册表里的 verb 把 MathType 服务器拉起来,再通过 IDataObject / IOleObject 读写数据。殊途同归——都要唤醒并占用 MathType 这个进程。

3. 取出公式数据

连接建立后,需要把「这个公式现在是什么」交给 MathType。常见路径包括:
  • 把公式内容放到剪贴板,再让 MathType 从剪贴板读取
  • 或通过 OLE 的 IDataObject::GetData 取出 MTEF(MathType 内部格式)、MathML 等
此时真正的数学内容和样式偏好,才进入 MathType 的处理范围。

4. 按新偏好生成结果

MathType 套用你在批量格式化里指定的偏好源——文档内偏好、MathType 默认偏好、剪贴板上的样例公式,或偏好文件——对当前公式做变换。 注意:这一步的产品语义是「格式化」,实现上往往更接近 用新偏好重新生成一份公式结果,而不是在原对象上做一次轻量属性更新。

5. 写回 Word:删旧,插新

这是整条链路里最「笨」、也最影响体感的一步。 处理完一个公式后,Word 里原来的 OLE 对象通常会被 删除,再在同一位置 插入 一个符合新配置的新公式对象。版面要重排,对象集合要更新,文档要变脏。然后循环进入下一个公式,从头再来。 所以批量格式化的真实节奏是:
不是「扫一遍,批量改字段」,而是 对每个公式完整走一遍跨进程往返

「与 MathType 通信」到底指什么

日常说「插件要和 MathType 通信」,容易让人联想到网络 API。这里不是。 这里的通信是 同一台机器上的进程间协作,建立在 Windows 的 COM / OLE 之上: 一次成功的单公式格式化,至少涉及:
  1. Word 对象模型操作(找 shape、删、插)
  2. COM/OLE 激活与数据交换
  3. 有时还有系统剪贴板作为中转
每一环都有成本。公式一多,成本线性叠加。更关键的是:这些环节大多 不适合并行

为什么它只能逐个做

「不支持多线程」「不能多文档同时跑」听起来像功能缺失,其实更像架构后果。 第一,MathType 服务器倾向于被独占使用。
官方 API 里能看到类似「MathType 已在使用中」的错误状态。设计假设是:一边连着一个 MathType,把活干完,而不是开一堆 worker 同时改公式。
第二,Office 自动化和 OLE 嵌入对象,通常活在串行友好的环境里。
Word 的对象模型、UI 线程、嵌入对象的激活与关闭,对并发本来就挑剔。两个线程同时删插同一文档里的 shape,或同时抢同一条 OLE 会话,很容易变成不可预期的状态。
第三,剪贴板是共享资源。
如果格式化路径依赖剪贴板中转,那它在系统级就是全局的。两个任务同时「把公式放进剪贴板再取出来」,会互相踩。
第四,删旧插新依赖文档的当前结构。
每处理完一个公式,文档的 shapes 集合和布局都可能变。下一步「下一个公式」的定位,建立在上一步完成之后的文档状态上。这天然是队列,不是 map-reduce。
于是批量格式化的并行度,基本上就是:一次一个公式,通常还一次一个文档。

为什么在普通电脑上特别卡

慢,不只是因为 MathType「老」。是宿主、通信、写回三层叠在一起。 Word 本身就重。
批量过程中,Word 要反复参与定位、删除、插入、刷新显示。文档越大、公式越多、机器越普通,UI 卡顿和内存压力越明显。你以为在跑 MathType,其实很大一部分时间 Word 也在干活。
跨进程往返很贵。
每个公式都可能触发:激活服务器、读数据、写数据、关闭会话。对用户来说是「改个字号」;对系统来说是一次完整的 OLE 事务。
删插比原地修改更伤。
如果只是改对象内部的样式字段,成本会小得多。删掉再插入,等于让 Word 不断重构局部文档结构。这是可观察的:公式很多时,进度不是「匀速算一下」,而更像「一下一下地砸文档」。
把这三件事放在一起,批量格式化的体验就稳定地落在:能用,但沉,而且很难靠「再等等」变成现代工具该有的那种安静后台任务。

这套设计从哪来,卡在哪

站在 MathType 诞生和流行的年代看,这套路径说得通:
  • 公式是专用编辑器的私有对象
  • Word 通过 OLE 托管第三方内容是主流做法
  • 「交给原厂程序处理,再嵌回来」是可靠的集成方式
它优先保证的是:结果仍是合法的 MathType 对象,样式来源可控,行为与手动编辑一致。 它没有优先保证的是:
  • 在弱机器上批量处理数百个公式依然流畅
  • 多文档队列、多线程加速
  • 不打开 Word UI 也能离线改格式
所以今天会觉得它「古早」,往往不是因为某个按钮难用,而是因为 问题规模变了,约束没变。论文公式密度更高,批量需求更频繁,用户对「后台跑完、机器还能干别的」的预期也更高。而批量格式化仍绑定在「Word + 单路 MathType 会话 + 逐个删插」这条路上。

读懂之后,你会怎么选

如果你只是偶尔改十来个公式,官方批量格式化仍然是最省事的选择:路径成熟,结果符合 MathType 自己的规则。 如果你经常面对这些情况——
  • 单文档公式数量很大
  • 需要一次处理很多文档
  • 机器配置一般,开着 Word 批量跑会明显拖死工作节奏
  • 想把格式化嵌进自己的工具链,而不是盯着 Word 进度条
——那「绕过官方批量格式化」就不是为了标新立异,而是为了换一条更轻的路径:尽量少打扰 Word UI,尽量减少逐个 OLE 往返,尽量避免删旧插新式的写回。 前提是你先承认一件事:官方批量格式化慢,常常不是实现写烂了,而是它忠实地走完了一条注定偏重的架构。 看清这条架构,才谈得上要不要绕开它,以及绕开之后你必须自己接管哪些责任。