Office-JS 和 VBA 插件 如何混合在一起



是否可以将OfficeJS命令按钮放置在自定义VBA加载项面板上,就像.xlam文件一样构建?
* 我仍然希望混合 VBA 和 OfficeJS

这是未经测试的,但我相信沿着这些路线可以完成这项工作:

使用CustomXMLPart.dataNodeReplaced事件:

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服务器,您可以将其发送到JavaScript。为此,您必须使用 Mswsock.dll并调用 accept 方法(我认为(。

<小时 />

编辑:

自从我最初的回答以来,已经过去了这么多月亮,现在我确实有更多的细节。我尝试将NodeAfterInsertNodeAfterReplaceVBA 事件与customXmlPart.setXml(sXML);一起使用,但这不会触发事件。这是Microsoft选择不解决的问题。因此,目前没有事件驱动的通信。

在这种情况下,通过XML的唯一选择是使用Excel VBA中的Application.OnTime()和Javascript中的setInterval()轮询更改。

HTTP服务器仍然是一种可能性,但至少需要从VBA托管HTTP服务器。完全有可能(这是一个C++示例(,但需要深入了解 Winsock API 和低级编程。

<小时 />

编辑2

我创建了一个库,可以促进单向消息发送。

  1. 下载并导入VBA代码
  2. 导入脚本实验室要点
  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

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

将数据从 JavaScript 发送到 VBA 可以使用相同的桥接,但具有for="vb"属性。但是,这还没有连接起来,请注意,这需要在 VBA 端进行轮询,可能来自工作簿/工作表对象。

否,不能从 Web 加载项与 VBA 宏或 COM 加载项进行交互。 请记住,Web 加载项就像网页一样,因为它们是沙盒化的,无法与操作系统或已安装的程序通信(至少没有帮助程序或代理应用程序/库(。

所以,这有点旧了,但我发现了一种从officeJS向VBA发送消息的方法。它依赖于 CustomXMLParts.PartAfterAdd 事件。

本质上,在 vba 中创建一个监视器类,如下所示:

Public WithEvents parts as CustomXMLParts
Private Sub Class_Initialize
set parts = ActiveWorkbook.CustomXMLParts
End Sub
Private Sub parts_PartAfterAdd(ByVal objPart As CustomXMLPart)
MsgBox("Message received!")
end Sub
Private Sub parts_PartBeforeDelete(ByVal objPart As CustomXMLPart)
MsgBox("Message received!")
end Sub

现在您可以添加或删除自定义XML,此事件将触发,但是officeJS添加customXMLPart的方式有点奇怪。它会创建一个空白消息,然后对其进行更改。但事件在消息空白的情况下触发。此外,在方法中执行时会冻结,因此在消息为非空之前,您不能只使用Application.Wait。您也不应该从 vba 中删除CustomXMLPart,因为这会在 javascript 中引发错误。

您还可以将其与发送消息CustomProperty结合使用,并附有警告。该值必须介于 1 到 255 个字符之间,0 会导致 OOM 异常,大于 255 的任何值都将被截断。

我需要这个笨拙的解决方法来从 officeJS 发送消息以调用一些 VBA 来执行仅在 VBA 中可用的功能。由于 javascript 在事件处理程序完成之前不会恢复,因此我还可以将同一属性上的消息写回 officeJS 以报告状态或其他内容。

如何从 VBA 启动通信?可悲的是,我还没有找到一种非侵入性的方法。

编辑: 围绕这些事件的文档很糟糕,但CustomXMLParts.PartAfterLoad将在填充 XML 后触发。这意味着您可以简化所有内容,只需侦听单个 XML 事件即可将消息发送到 vba。

我在 vba 监视器中包含一个要点,它将侦听特定命名空间的 xml 消息: https://gist.github.com/mburbea/5300f41173a2eaae477dc4eb7cc69db1

相关内容

最新更新