【Code with SOLO】用 SOLO 为 OneNote 打造页面内标题导航目录宏,解决长文档无导航的痛点

1. 摘要

       OneNote 作为常用的笔记工具,缺少类似 Word 的页内标题导航功能,在长文档中定位内容非常不便。我借助 TRAE SOLO,从零开始调研、探索、迭代,最终基于 Onetastic 宏平台,实现了一个完整的页内标题导航目录工具——支持一键生成可点击目录、自动跳转标题、可选"回到目录"链接、目录更新与删除,大幅提升了 OneNote 长文档的阅读和编辑效率。


OneNote界面

2. 背景

       我是一名日常使用 OneNote 做笔记的用户。在使用过程中,我发现 OneNote(Office 2021 版本)存在一个明显的痛点:页面内没有标题导航功能。当笔记页面内容较多、包含大量标题时,只能通过手动滚动来查找目标内容,效率很低。
       Word 自带"导航窗格",可以按标题快速跳转,但 OneNote 始终没有提供类似功能。我希望能够通过某种方式,在 OneNote 页面内自动生成一个可点击的目录,点击即可跳转到对应标题,从而解决这个长期困扰我的问题。

3. 实践过程

3.1 任务拆解

       面对这个需求,我首先和 SOLO 一起将任务拆解为以下几个关键步骤:


任务拆解
  1. 调研可行方案:了解 OneNote 支持哪些扩展方式(插件、脚本、API 等)
  2. 选择技术路线:评估各方案的可行性,确定最终实现方式
  3. 编写核心代码:实现目录生成、超链接跳转等核心功能
  4. 迭代优化:根据实际测试结果,修复问题、完善功能

3.2 方案调研与探索

       我最初的想法是做一个类似 Word 侧边栏的悬浮导航,和 SOLO 一起经历了多轮方案探索:


方案探索

方案一:OneNote JavaScript API

  • SOLO 帮我调研了 OneNote 的 JavaScript API(Office Web Add-in)
  • 发现该 API 仅支持网页版 OneNote,不支持桌面版,直接排除

方案二:Microsoft Graph API

  • SOLO 调研了 Graph API for OneNote
  • 发现 Graph API 返回的段落 ID 与 OneNote 内部的 object-ID 不一致,无法生成精确到段落的跳转链接,排除

方案三:C# WinForms 侧边栏 + COM API

  • SOLO 帮我创建了一个完整的 C# WinForms 项目,通过 OneNote COM API(OneNote.Application)获取页面内容
  • 使用 GetHyperlinkToObject 生成 onenote:// 协议的段落级跳转链接
  • 通过 Type.InvokeMember + ParameterModifier 解决了 COM interop 的 out 参数兼容问题
  • 实现了一个可拖拽的悬浮侧边栏窗口
  • 问题:侧边栏是独立窗口,无法嵌入 OneNote 内部;且标题列表获取不稳定,最终放弃

方案四:Onetastic 宏(最终方案)

  • Onetastic 是 OneNote 最流行的第三方增强工具,支持自定义宏
  • 宏可以直接操作 OneNote 页面对象(Paragraph、Outline、Text 等)
  • 可以集成到 OneNote 工具栏,使用方便
  • 确定采用此方案

3.3 Onetastic 宏开发

       确定方案后,SOLO 开始编写 Onetastic 宏代码。过程中遇到了不少 Onetastic 宏语言的特殊限制和实际问题:

踩坑一:宏语言语法限制

     
踩坑一
  • Onetastic 宏不支持 null{}(字典字面量)、MessageBox 等常见语法
  • SOLO 逐步调整:null 改为直接遍历、{} 改为 Array() + Array_PushBack()、移除所有 MessageBox 调用

踩坑二:目录更新时重复生成

  • 初版代码在目录已存在时,不会更新而是重新生成一个新目录
  • 原因是只做了"是否存在目录"的判断,没有"清除旧条目再插入新条目"的逻辑
  • 修复:添加了旧目录检测和清除逻辑

踩坑三:删除目录时条目残留


踩坑三
  • 勾选"删除目录"后,"目录"标题和"回到目录"文字被删了,但目录条目本身没删
  • 原因是目录条目的检测条件过于严格(要求段落只有一个 Text 且含超链接)
  • 修复:改为遍历所有 Text 对象,只要任一含超链接就认定为目录条目

踩坑四:遍历中删除导致内容误删

  • foreach 遍历中直接调用 RemoveObject,会导致集合变化后迭代器跳过元素
  • 表现为:更新目录时第一行正文内容被误删
  • 修复:改为"先收集到数组,循环结束后统一删除"的安全模式

踩坑五:空行位置异常


踩坑五
  • 目录末尾的空行有时出现在倒数第二个标题和最后一个标题之间
  • 原因是 InsertObject 的位置参数计算错误
  • 修复:重构为"先删旧目录(含标题和空行)→ 插入条目 → 插入标题 → 插入空行"的四步流程,新增和更新走同一条路径

3.4 关键 Prompt 示例

       在整个过程中,我与 SOLO 的交互经历了从模糊到精确的演进:

  • 初始需求:“对于微软的OneNote,目前的一个痛点是没有类似于word的那种页内导航…现在,我希望你通过编写脚本或插件等,来实现这个页内标题目录”
  • 方向调整:“现在不行,我希望做一个类似于插件或扩展的内容,也就是安装后可以直接存在于OneNote的工具栏”
  • 方案切换:“请你重新做整个项目,我希望是在OneNote内的工具栏上,具体而言,你可以参考onetastic的做法”
  • 问题修复:“现在有个问题,这个空行没有在目录最后面,而是在倒数第二个标题和最后一个标题之间”
  • 逻辑重构:“请你在我这一版代码上进行修改…我希望你把更新目录部分代码重构,逻辑是先删除目录再新增目录”

       每次遇到问题,我只需描述现象,SOLO 就能定位原因并给出精确的修改方案。

4. 成果展示

最终功能及效果

      完成的 Onetastic 宏实现了以下功能:

  • 自动生成目录:收集页面中所有标题(h1-h6),生成带超链接的可点击目录
   
生成目录
  • 标题跳转:点击目录条目即可跳转到对应标题位置

标题跳转
  • "回到目录"链接:可选在每个标题旁添加链接,方便快速返回目录

回到目录
  • 目录更新:添加或删除标题后重新运行,自动刷新目录

目录更新
  • 一键删除:删除目录及所有关联的"回到目录"链接
   
一键删除
  • 选项记忆:自动保存上次使用的选项
  • 表格标题支持:能识别表格内的标题

宏文件

       最终宏文件已保存为 页面导航标题导航目录.ontm,并上传到了官方macroland,可直接下载到 Onetastic 使用。

安装使用

  1. 安装 Onetastic for OneNote
  2. 下载安装宏 页面内标题导航目录
  3. 在任意 OneNote 页面运行宏,按需勾选选项

5. 效果与总结

提效成果

  • 之前:在长笔记页面中查找某个标题,需要反复滚动页面,耗时且容易遗漏
  • 之后:运行宏即可生成完整目录,一键跳转到任意标题,效率提升显著
  • 整个开发过程从需求提出到最终完成,借助 SOLO 完成了 4 种技术方案的调研评估完整的宏代码编写多次问题定位与修复

SOLO 在流程中的角色

       SOLO 在整个过程中承担了核心工作:

  1. 技术调研:独立调研了 OneNote JavaScript API、Graph API、COM API、Onetastic 宏等多种技术方案,给出了详细的可行性分析
  2. 代码编写:从 PowerShell 脚本到 C# WinForms 项目再到 Onetastic 宏,跨越三种技术栈完成代码编写
  3. 问题诊断:面对各种运行时问题(语法错误、逻辑 bug、集合遍历安全等),能快速定位根因并给出修复方案
  4. 方案重构:根据实际测试反馈,多次重构核心逻辑(如从后往前删改为先收集再删、统一新增和更新路径等)

总结

  • 先调研再动手:面对不熟悉的领域(如 OneNote 扩展开发),先让 SOLO 全面调研可行方案,避免走弯路
  • 小步迭代:每完成一个功能点就测试,发现问题及时反馈,逐步完善
  • 描述现象而非方案:遇到 bug 时,只需描述"发生了什么",让 SOLO 判断"为什么"并给出修复方案
  • 勇于推翻重来:当 C# 方案遇到瓶颈时,果断切换到 Onetastic 宏方案,最终用更简单的方式实现了更好的效果