Search code examples
javascriptexcelvbatypescriptoffice-js

Can Office-JS trigger a VBA Workbook or Worksheet Event Procedure?


I'm trying to see if there is a way to do something in Office-JS that would trigger an event procedure to run in Excel VBA, but it looks like VBA events are disabled during the execution of the JavaScript code.

Let's say for example that I have a workbook with a worksheet named "Sheet1" and in that sheet module I have the following code:

Private Sub Worksheet_Change(ByVal Target As Range)
    If Target.Address = "$A$1" And Target.Value2 <> vbNullString Then
        MsgBox Target.Value2
    End If
End Sub

What I'm expecting is that if I change the content of cell A1, the new content will be displayed in a message box, but if I run the following snippet in Script Lab (based of the blank snippet), the event does not get triggered even though cell A1 gets edited successfully:

$("#run").click(() => tryCatch(run));

async function run() {
  await Excel.run(async (context) => {

    const sheet = context.workbook.worksheets.getItem("Sheet1");
    sheet.getRange("A1").values = 'Hello from Office-JS';

    await context.sync();
  });
}

/** Default helper for invoking an action and handling errors. */
async function tryCatch(callback) {
  try {
    await callback();
  } catch (error) {
    // Note: In a production add-in, you'd want to notify the user through your add-in's UI.
    console.error(error);
  }
}

So my question would be: Is there a way to set things up so that the JavaScript code can trigger the Worksheet_Change event and if not, is there another worksheet or workbook event that can be triggered?

A bit of context: I was trying to find a solution to this question and thought that a good workaround would be to write VBA code to a cell with Office-JS and then use the Worksheet_Change event procedure to execute the VBA code written in that cell.

Unfortunately, that didn't work so far, but I think it's worth asking this more specific question as solving this would be the last stepping stone in order to allow VBA code to be executed from Office-JS (which would be pretty nice).


Solution

  • After some more testing, I managed to find that the Workbook_NewSheet event procedure of the workbook object gets triggered by creating a new worksheet with Office-Js:

    var sheets = context.workbook.worksheets;
    var sheet = sheets.add("NewSheet");
    sheet.getRange("A1").values = [["Hello from Office-JS"]];
    

    So, it would be possible to have the following code in the ThisWorkbook Module to display the Message box in that context:

    Private Sub Workbook_NewSheet(ByVal Sh As Object)
        If Sh.Name = "NewSheet" Then
            If Sh.Range("$A$1").Value2 <> vbNullString Then
                MsgBox Sh.Range("$A$1").Value2
            End If
        End If
    End Sub
    

    The nice thing here is that even if the Office-JS code writes to the sheet after creating it, the event in VBA only gets to run after the JavaScript code has finished meaning that the value in cell A1 will be changed in time for when the VBA code runs.