Office-JS & VBA Addin 如何混合在一起

Office-JS & VBA Addin How to mix together

是否可以将 OfficeJS 命令按钮放置到像 .xlam 文件一样构建的自定义 VBA 插件面板?
* 我仍然希望混合 VBA 和 OfficeJS

不,您不能与 Web 插件中的 VBA 宏或 COM 插件交互。请记住,Web 加载项就像网页一样,因为它们是沙盒化的,无法与 OS 或已安装的程序通信(至少没有助手或代理 applications/libraries)。

这是未经测试的,但我相信按照这些思路可以完成这项工作:

使用CustomXMLPart.dataNodeReplaced event:

function addNodeReplacedEvent() {
    Office.context.document.customXmlParts.getByIdAsync("vbaJSBridge", function (result) {
        var xmlPart = result.value;
        xmlPart.addHandlerAsync(Office.EventType.DataNodeReplaced, function (eventArgs) {
            // do stuff with xmlPart
            // here you should be able to receive information sent from VBA,
            // and return any data necessary.
        });
    });
}

在VBA中使用:

Dim part As CustomXMLPart 

' Returns a custom xml part by its ID:
Set part= ActiveDocument.CustomXMLParts.SelectByID("vbaJSBridge") 

part.LoadXML("<data id="vbaJSBridge">some data</data>")

如前所述,我不确定这是否完全有效,但这是完成这项工作的一种不错的(有点老套)方法。或者,您可以使用 VBA 设置 HTTP 服务器,您可以将 HTTP 请求发送到 JavaScript。为此,您必须使用 Mswsock.dll 并调用 accept 方法(我认为)。


编辑:

自从我最初的回答以来已经过去了很多个月,现在我确实有了更多的细节。我尝试将 NodeAfterInsertNodeAfterReplace VBA 事件与 customXmlPart.setXml(sXML); 一起使用,但这不会触发事件。 This is an issue which Microsoft has chosen not to fix。因此,目前无法进行 event-driven 通信。

在这种情况下,唯一的选择是通过 XML 轮询 Excel VBA 中的 Application.OnTime() 和 [=] 中的 setInterval() 的更改72=].

HTTP 服务器仍然是可能的,但至少需要从 VBA 托管一个 HTTP 服务器。完全可能 (here is a C++ example),但需要深入了解 Winsock API 和低级编程。


编辑 2

我创建了 a library 以方便单向消息发送。

  1. 下载并导入 VBA code
  2. 导入 scriptlab gist
  3. 下载并运行示例VBA代码。

'Requires JsBridge from here:             https://github.com/sancarn/VbaJsBridge
'ScriptLab test can be downloaded here:   https://gist.github.com/sancarn/b974b650f4b451ff2de51861af1671b1
Sub test()
  Dim js As JsBridge: Set js = JsBridge.Create("test")
  Call js.SendMessageSync("hello world")

  Dim col as new collection
  For i = 1 to 10
    'Add action to a collection so we can check it's status later
    col.add js.SendMessage("hello " & i)
  next
End Sub

您应该看到我们可以在 JavaScript 控制台中打印“hello world”和“hello 1”...“hello 10”。

从 JavaScript 向 VBA 发送数据可以使用相同的网桥,但具有 for="vb" 属性。然而,这还没有连接起来,请注意这需要在 VBA 端进行轮询,可能来自 workbook/worksheet 对象。