Is it possible to place OfficeJS command button to Custom VBA Addin panel built like .xlam file?
* I still have hope to mix VBA and OfficeJS

- 287
- 1
- 2
- 12
-
https://stackoverflow.com/questions/75299140/can-i-call-a-pre-xisting-macro-via-the-office-add-in-javascript-library – FreeSoftwareServers Feb 01 '23 at 17:21
-
https://stackoverflow.com/questions/42946274/is-it-possible-to-run-a-macro-on-button-in-task-paneweb-using-office-app – FreeSoftwareServers Feb 01 '23 at 17:21
3 Answers
This is untested, but I believe something along these lines will do the job:
Use the 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.
});
});
}
In VBA use:
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>")
As said I am unsure whether this will work totally, but it's a nice (kinda hacky) method of doing the job. Alternatively you could set up a HTTP server with VBA, which you can send HTTP requests to the JavaScript. To do that, you'd have to use Mswsock.dll and call the accept method, (I think).
EDIT:
So many moons have passed since my initial answer and now I do have a little more detail. I tried using the NodeAfterInsert
and NodeAfterReplace
VBA events alongside customXmlPart.setXml(sXML);
, however this does not trigger an event. This is an issue which Microsoft has chosen not to fix. As such there is no event-driven communication possible currently.
In which case the only option, via XML, is to poll for changes with Application.OnTime()
in Excel VBA and setInterval()
in Javascript.
The HTTP server is still a possibility but would at least require hosting a HTTP server from VBA. Entirely possible (here is a C++ example), but requires deep knowledge of Winsock API and low level programming.
Edit 2
I've created a library which facilitates 1-way message sending.
- Download and import the VBA code
- Import the scriptlab gist
- Download and run the sample VBA code.
'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
You should see that we can print "hello world" and "hello 1" ... "hello 10", in the JavaScript console.
Sending data from JavaScript to VBA can use the same bridge but with the for="vb"
attribute. However this isn't connected up yet, mind that this would require polling on the VBA side, likely from a workbook/worksheet object.

- 2,575
- 20
- 45
-
Care to expand on this? Confirm if it works and expand a bit? Perhaps delve into the http server idea as well? Thanks! This looks promising, but didn't work in my quick trial. – FreeSoftwareServers Jan 03 '22 at 02:13
-
@FreeSoftwareServers Unfortunately I've not yet built a library for this, I did get it working in the past though. Note that events however don't trigger at all. Instead you have to use polling in both the Javascript and VBA sides. As for the HTTP server idea, that requires creating a server in VBA, a far greater task. Something I already planned to make a library for, but don't have one yet. There are many VB6 ones though, which you could probably use :) Just search for `VB6 HTTP server` – Sancarn Jan 03 '22 at 05:51
-
Looked into it a little, looks like few VB6 implementations use winsock directly, so will have to reverse engineer C++ code instead E.G. https://gist.github.com/quantumcore/9ccd4212c3d2bbae0de6ca607a85797a – Sancarn Jan 03 '22 at 05:58
-
@FreeSoftwareServers check out [this sample](https://github.com/sancarn/VbaJsBridge) and Edit2 in the above post. – Sancarn Jan 04 '22 at 00:03
-
This is pretty close to something that works (not the vb6 http server), you can use `CustomXMLParts` add/remove events to send a message to vba. I wrote an answer explaining that in details. – Michael B Jul 29 '23 at 14:56
No, you cannot interact with VBA macros or COM add-ins from a web add-in. Remember that web add-ins are just like web pages, in that they are sandboxed and cannot communicate with the OS or installed programs (at least without helper or broker applications/libraries).

- 5,706
- 2
- 22
- 38
-
OK. I see what I cannot run from OfficeJs VBA. And is it true for over way Run from VBA Office.Js ? – Evgeniy Rasyuk Jul 19 '17 at 05:52
-
Correct, VBA cannot communicate with web add-ins or use the JavaScript for Office or Graph APIs – Eric Legault Jul 19 '17 at 15:34
-
2Your answer seems a bit misleading... I read [here](http://rockthecode.io/blog/javascript-and-excel/) that it's possible to read and edit the values of ranges using OfficeJS. Thus it appears possible to setup a message relay between JS and VBA. There also exists [setXml](https://dev.office.com/reference/add-ins/excel/customxmlpart) function for setting custom XML parts. This could also potentially be used for communication between VBA and JS right? – Sancarn Mar 07 '18 at 12:01
-
VBA is not being used by the JavaScript for Office API - it is interacting with the application internally – Eric Legault Mar 12 '18 at 00:54
-
You're correct. VBA is not being used by OfficeJS, but OfficeJS could be being used by VBA with this technique (using `eval()`). But in the end, they can at least communicate with one another... Which is a good enough work around for most people :) – Sancarn Mar 18 '18 at 20:36
-
No, OfficeJS cannot be used by VBA! All the JS in the add-in is sandboxed and cannot interact with the Office Object Models directly nor call VBA functions or vice-versa. – Eric Legault Mar 20 '18 at 21:01
So, this is a bit old, but I've discovered a method of sending a message to VBA from officeJS. It relies on the CustomXMLParts.PartAfterAdd event.
Essentially in vba create a monitor class something like::
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
Now you can add or remove customXML and this event will fire, but the way officeJS adds a customXMLPart
is a bit odd. It creates a blank message and then alters it. But the event fires with the message blank. Also execution is frozen while in the method, so you can't just use Application.Wait
until the message is non-empty. You also should not delete the CustomXMLPart
from vba as that will throw an error in javascript.
What you can also do is use this in conjunction with a CustomProperty
to send a message, with caveats. The value must be between 1 and 255 characters, 0 causes an OOM exception, and anything above 255 will be truncated.
I need this hacky workaround to send a message from officeJS to call some VBA to do functionality only available in VBA. Since the javascript won't resume until the eventhandler finishes, I can also write a message on the same property back to officeJS to report status or whatnot.
Whatabout initiating communication from VBA? Sadly, I haven't found a non-intrusive way to do that.
Edit:
The documentation around these events are awful, but CustomXMLParts.PartAfterLoad
will fire after the XML was populated. Meaning you can simplify everything and just have a single XML event to listen on to send messages to vba.
I've included a gist with the vba monitor that will listen to xml messages of a particular namespace: https://gist.github.com/mburbea/5300f41173a2eaae477dc4eb7cc69db1

- 7,512
- 3
- 31
- 57
-
You can actually send messages to js from VBA using [the library in my post](https://github.com/sancarn/VbaJsBridge). Really cool that that event works. I tried `NodeAfterInsert` and `NodeAfterReplace` but they didn't work. Very useful! – Sancarn Jul 29 '23 at 22:37
-
1I dislike having to have a polling eventhandler, but yeah it seems stupid that the `context.document.customXmlParts` is only available from word. `Excel.CustomXmlPart` lacks events. It also sucks that the vba event fires before the message is populated. – Michael B Jul 31 '23 at 17:47
-
Yeah totally fair dislike to have :) Still, I think it's worth it, especially given that MSO team are refusing to add FFI support. – Sancarn Aug 03 '23 at 19:23
-
-
[Foreign Function Interface](https://en.wikipedia.org/wiki/Foreign_function_interface) i.e. Equivalent to `Declare Function x lib "mylib.dll"` in VBA and ultimately therefore the COM object model too. – Sancarn Aug 03 '23 at 21:49