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 方法(我认为)。
编辑:
自从我最初的回答以来已经过去了很多个月,现在我确实有了更多的细节。我尝试将 NodeAfterInsert
和 NodeAfterReplace
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 以方便单向消息发送。
- 下载并导入 VBA code
- 导入 scriptlab gist
- 下载并运行示例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 对象。
是否可以将 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 方法(我认为)。
编辑:
自从我最初的回答以来已经过去了很多个月,现在我确实有了更多的细节。我尝试将 NodeAfterInsert
和 NodeAfterReplace
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 以方便单向消息发送。
- 下载并导入 VBA code
- 导入 scriptlab gist
- 下载并运行示例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 对象。