本文记录,用 VBA 读取 OneNote 的方法!小白贡献,语失莫怪!
问题背景:
我在 OneNote 里有上百篇笔记,可 OneNote 自己,却无法导出全部的标题。于是我千方百计,想要读取 OneNote 的文件,来获取标题和日志信息。尝试了各种方案,都没能读出 OneNote 的数据。最后过了好久好久,才找到了这种,基于 Excel VBA 的解决方式!那么接下来,我们就来看下它的代码!在篇尾还会再讲下,我尝试过的其他方式,也许哪位路过的大神,能解决掉其中的问题!
代码如下:
- 首先要注意,这个代码是要添加到 Excel VBA 编辑器里的!因为 OneNote 里根本就没有 VBA 编辑器,所以只能通过 Excel 里的 VBA 编辑器,来实现 OneNote 的操控和读取!
- 然后要注意,在运行代码前,需先添加几个 Reference (引用库)!
- Microsoft OneNote 12.0 Object Library
- Microsoft OneNote 15.0 Object Library
- Microsoft XML, V3.0
- 不同的 Office 可能会出现,这几个库的版本不一样,那么就需要根据你的库的版本,去微调下这个代码!否则会报错!
- 另外这个代码中,似乎只能使用 Early Binding (静态绑定),无法使用 Late Binding (动态绑定),不知道为什么!例如代码中的 OneNote 对象,只能采用Set OneNote = New OneNote.Application的方式,而无法采用Set OneNote = CreateObject("OneNote.Application")的方式!不知道这是不是因为,我是手动添加的 OneNote 的那几个库!
- 'Add the following references (adjust to your office version):
- '- Microsoft OneNote 12.0 Object Library
- '- Microsoft OneNote 15.0 Object Library
- '- Microsoft XML, v3.0
- Sub ListOneNotePages()
- 'OneNote will be started, if it's not running.
- Dim OneNote As OneNote.Application
- Set OneNote = New OneNote.Application
- 'Get XML data (oneNotePagesXml) represents OneNote pages
- Dim oneNotePagesXml As String
- OneNote.GetHierarchy "", OneNote12.HierarchyScope.hsPages, oneNotePagesXml
- 'OneNote.GetHierarchy "", 4, oneNotePagesXml
- 'Use the MSXML Library to parse the XML.
- Dim doc As MSXML2.DOMDocument
- Set doc = New MSXML2.DOMDocument
- If doc.LoadXML(oneNotePagesXml) Then
- 'Find all the Page nodes in the one namespace.
- Dim nodes As MSXML2.IXMLDOMNodeList
- Set nodes = doc.DocumentElement.SelectNodes("//one:Page")
- Dim node As MSXML2.IXMLDOMNode
- Dim pageName As String
- Dim sectionName As String
- Dim pageContent As String
- Dim temp As String
- 'Go through each page, and print out page content
- For Each node In nodes
- pageName = node.Attributes.getNamedItem("name").Text
- Debug.Print "Page name: "; vbCrLf & " " & pageName
- Call OneNote.GetPageContent(GetAttributeValueFromNode(node, "ID"), pageContent, piBasic)
- Debug.Print " content: " & pageContent
- Next
- Else
- MsgBox "OneNote XML Data failed to load."
- End If
- End Sub
- Private Function GetAttributeValueFromNode(node As MSXML2.IXMLDOMNode, attributeName As String) As String
- If node.Attributes.getNamedItem(attributeName) Is Nothing Then
- GetAttributeValueFromNode = "Not found."
- Else
- GetAttributeValueFromNode = node.Attributes.getNamedItem(attributeName).Text
- End If
- End Function
复制代码 几个关键的函数:
- GetHierarchy这个方法,就只能 Get 到 PageID 和页面名字什么的,也就能读取页面的 metadata,而不是页面的真正的 Content!而若想要 Get 到页面的内容,就需要下面这个方法了!所以 GetHierarchy 所能读取的,就只有笔记本的 outline 大纲结构而已,而不是笔记的实质性内容!而这个大纲的深度,也就只能是从 1 到 4 的深度了!到 4 就是到了每页标题的深度了,也就是最深的深度了!
- GetPageContent这个方法,所返回的,则就是真正的 XML 格式的,页面的全部内容了!
- MSXML2的这个库,就只是用来解析 XML 文本的,让我们可以,按类别选取所需的内容!
Remote Procedure Call Failed 报错:
- 这个报错,我的理解是,它是在说,无法访问你要用的那个程序!具体为什么无法访问,我到现在也还是不知道!
- 在上面 VBA 的解决方案里,我只是把代码里的 OneNote12.Application,改成了 OneNote.Application 就解决了!具体为什么,不知道!但这个报错,确实就没了!我猜测是因为 OneNote 的版本的问题,之前报错,是因为它一直找不到 OneNote14.Application 这个本版本,但细节的问题就不讨论了!
- 但在 Python 的 win32com 方案里,则是一直都卡在,这个报错这里,一直没能过去!也因此在 Python 的解决方案里,到了最后也没能读取任何的 OneNote Page!
OneNote 无法启动问题:
- 如果发现,运行了 Python 的代码后,自己的 OneNote 显示正在清理,无法打开!不用担心,只需去资源管理器里,把 OneNote.exe 这个任务关掉即可。然后 OneNote 就可以正常打开了!
其他解决方案:
其实在 Excel VBA 的解决方案之前,还尝试了很多很多其他的方案,那也粗略的说一下吧,
- 在 OneNote 中添加 COM 插件,使其能运行宏,类似于 VBA!这个插件叫做Onetastic!据说这个插件的作者,正是原 OneNote 开发团队的成员,所以其实这个插件的质量很高,但就是要花钱买,所以最后也没采用这个方案!还有一个插件,叫Gem for OneNote,也很强悍,但不符合我的需求!OneNote 的插件还有很多,感兴趣的同学,可以去看下面的链接!
- 就是自己开发插件,让其能在 OneNote 中运行。这个要求有点高,这种大神应该就不用,看我这篇文章了。所以如果有能力,这也确实是个选项!
- 就是使用 Python 的 win32com,其实 win32com 也是使用的 windows 自己的 com 接口,但 Python 毕竟是通过一个第三库,在做这件事情,所以这个库,要是运行不畅,或者出什么问题,作为小白,就真是很难解决了!就例如一直困扰我的,Remote Procedure Call Failed 报错问题,就到现在也没能解决!这个报错很可能是,更深层的 com 服务的问题,很可能是 onenote.dll 没了什么的,但这已经超出小白的范畴了。
- 就是还有各种 Python 的第三方库,例如:pyOneNote,onepy 什么的!我自己几乎都试一遍了,基本没一个好使的,都是很久之前的库了!我觉得这可能是,很少有人会去操控 OneNote,所以在这上面花心思的人就很少,这也是为什么,我找了很久,都找不到答案!所以才决定写这篇文章,希望能给需要的人,一点方便!
可用的 Python 代码:
至于下列代码里,为什么都是 OneNote.Application.12 我也不知道!但如果你的不好使,也可以改成 OneNote.Application.14 试试!但在我的电脑里,只有 OneNote.Application.12 好使!- # 输出页面结构信息
- import win32com.client
- oneapp = win32com.client.Dispatch('OneNote.Application.12')
- result = oneapp.GetHierarchy("",4)
- print(result)
- ## 输出所有页面的标题
- import win32com.client
- oneapp = win32com.client.Dispatch('OneNote.Application.12')
- result = oneapp.GetHierarchy("",4)
- from bs4 import BeautifulSoup
- soup = BeautifulSoup(result, 'xml')
- for tag in soup.find_all('one:Page'):
- print(tag.attrs['name'])
- # 试图输出任何一个页面的内容 (报错暂时无解)
- # >>> Error occurred: (-2147023170, 'The remote procedure call failed)
- import win32com.client
- onapp = win32com.client.Dispatch('OneNote.Application.12')
- result = onapp.GetHierarchy("",4)
- print(result)
- pageID = "任何上面输出过的PageID"
- content = onapp.GetPageContent(pageID)
- print(content)
复制代码 后期应用:
被 VBA 读取出来的,是 OneNote 每个页面的全部内容!信息量很大,都是 XML 形式的!之后的处理,完全取决于各自的需求!好的就写到这里了,希望能有帮助,(^_^)b
关于 OneNote 附件的问题:
OneNote 虽然能读取页面的全部内容,但却没有任何接口,去读取或导出,页面里的附件!所以这也是个很无语的问题,尝试了很久,依然找不到什么解决方案!理论上附件应该就是储存在 OneNote 的文件里,但实际上你就是找不着,也无法导出!可能是被 OneNote 加密了!这也是个目前未解决的问题!若有大神有什么办法,还望不吝指点!多谢!
Reference:
- Automate Onenote 2010 From Excel 2007, using VBA - Stack Overflow
- Updating OneNote from VBA Excel - Stack Overflow
- OneNote developer reference | Microsoft Learn
- reading xml files in vb6 - Stack Overflow
- Top 11 Microsoft OneNote Add-ins
- Onetastic for OneNote
- Is there a way to talk to OneNote through code? - Stack Overflow
- Creating a Page in a Notebook in OneNote 2010 | Microsoft Learn
- Using Excel VBA to Push Content to OneNote
- Enumerations (OneNote developer reference) | Microsoft Learn
- OneNote add-ins documentation | Microsoft Learn
- OneNote 开发人员参考 | Microsoft Learn
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |