Analysis Automation

Office Scripts vs VBA: what each can still do in 2026

VBA reaches the whole PC but not the browser. Office Scripts can run on a schedule but sees only the workbook. A table from Microsoft's docs, and what to move.

The short read

Office Scripts runs in Excel on the web and in Power Automate flows, and VBA runs in neither.

  • VBA still reaches Outlook, Word, files and DLLs. Office Scripts sees only the workbook, and flows allow 1,600 Run script calls per user a day.
  • Windows blocks macros in internet files by default, and VBScript, which some macros call, will be turned off by default around 2026 or 2027.

What you can do with this

Ask of each macro: does it touch anything outside the workbook? Keep those in VBA. Move the workbook-only jobs that need a browser or a schedule, and search for VBScript.RegExp.

A laptop on a white desk showing charts and icons on a dark screen, with a metal mug and a plant nearby.
Photo: rawpixel, CC0
In this article
  1. Only Office Scripts runs in the browser and in flows
  2. VBA reaches the whole PC, and that is the risk
  3. VBScript is leaving Windows, and some macros lean on it
  4. Office Scripts sees only the workbook, by design
  5. Power Automate is the scheduler, with hard limits
  6. Licenses: VBA comes with desktop Excel
  7. The same job in both languages differs in three details
  8. Python in Excel is not a replacement for either
  9. What this means for you
  10. How we made this

Microsoft’s own comparison page puts the split in one line: VBA macros “are developed for desktop solutions” and Office Scripts “are designed for secure, cross-platform, cloud-based solutions.” For a small office with a folder of .xlsm files, that line sets the limits. A browser tab and a 6 a.m. flow with nobody at the PC are two places VBA can’t go.

On October 20, 2026, we read Microsoft’s documentation and built the table below from it. Then we wrote one small job both ways. Our view, in short: keep VBA for anything that reaches outside the workbook, and move the workbook-only jobs that must run in a browser or with nobody at the keyboard.

Only Office Scripts runs in the browser and in flows

Every row comes from a Microsoft page listed under Sources. The differences page itself was last updated in November 2023, so where a newer page says more, the newer page wins.

VBA macros Office Scripts
Excel for Windows Yes Version 2210 or later
Excel for Mac Yes Yes
Excel on the web No. Macros stay in the file but can’t run or be edited Yes
Excel for iOS No No
Word, Outlook, PowerPoint Yes No, Excel only
Run by Power Automate No connector Yes, the Run script action
Language VBA TypeScript 4.0.3, with no any type and no eval
Where the code lives Inside the workbook, saved as .xlsm (.xlsx can’t hold it) .osts files in the author’s OneDrive, or on SharePoint
What it can reach The whole desktop: COM and OLE, DLLs, the file system The workbook only
Calls to the web “No convenient way” fetch from Excel only; it fails inside Power Automate
Events such as open or change Yes No
Starts when Someone runs it, or an event fires Someone runs it, presses a script button, or a flow calls it
Recorder Record Macro on the Developer tab Action Recorder on web, Windows, Mac
License Built into desktop Excel A business or education plan; Personal and Family in preview
Admin switch Allow all or none, or only signed macros On or off for the tenant or one group

Two rows matter most for a small office. Office Scripts is the only one of the two that runs in Excel on the web. And it is the only one Power Automate can start, so it is the only one that can update a workbook “without even opening Excel.”

VBA reaches the whole PC, and that is the risk

VBA’s strength is reach. Microsoft’s VBA guide says it can work with “two or more Office applications at the same time.” Its own samples create an Outlook email and copy an Outlook contact into Word.

FileSystemObject “provides access to a computer’s file system.” The Declare statement lets it call procedures in a DLL. VBA macros “have the same security clearance as Excel,” says the differences page, which “gives them full access to your desktop.”

That reach is why Microsoft changed the default. “VBA macros are a common way for malicious actors to gain access to deploy malware and ransomware,” its admin guide says. So Office on Windows now blocks macros in files from the internet.

The change started rolling out to Current Channel on July 27, 2022. Semi-Annual Enterprise Channel got it on January 10, 2023.

The test is the Mark of the Web, a tag Windows adds to downloads and email attachments. A macro file that carries it opens with a Security Risk banner, and that banner has no Enable content button. Office on a Mac, on the web, and on iOS and Android devices is not affected.

The fixes Microsoft lists are concrete. Right-click the file, choose Properties and tick Unblock.

Files opened from OneDrive or SharePoint with Open in Desktop App, or synced by the OneDrive client, don’t get the mark. A Trusted Location skips the check entirely, which is why Microsoft says to use those “sparingly.” Group policies for this exist only in Microsoft 365 Apps for enterprise, not in Apps for business.

VBScript is leaving Windows, and some macros lean on it

The second change is slower. In a September 2025 post, Microsoft’s Wenjun Gong named two VBA habits that depend on VBScript: running external .vbs files, and referencing VBScript’s library for regular expressions (VBScript.RegExp).

The plan has three phases. Today VBScript stays on by default. In “approximately 2026 or 2027” it will be turned off by default.

At an unnamed date it will be removed from Windows, and then “calling .vbs scripts from VBA will no longer be supported.” RegExp references will break “unless the Office client is updated to a supported build.”

That build is Office Version 2508 (Build 19127.20154) on Windows, which puts RegExp classes into VBA itself. Replying to a reader in the comments, Gong added: “We did not make any change to Scripting.FileSystemObject and Scripting.Dictionary.” So the check is short: search your modules for .vbs and VBScript.RegExp.

Office Scripts sees only the workbook, by design

Office Scripts trades reach for safety. Scripts “only have access to the workbook, not the machine hosting the workbook,” and they get no sign-in token for the user. There is no file system, no other Office app and no DLL.

Web calls exist, with limits. A script can use fetch when it runs inside Excel. But “there is no way to sign in or use OAuth2,” so keys must be hard-coded or read from somewhere else.

Scripts stored on SharePoint can’t make the calls at all. In a flow, fetch fails with “fetch is not defined,” and Microsoft points you to Power Automate’s own HTTP actions instead.

Storage is the quiet trap. Scripts live as .osts files in the author’s OneDrive, under /Documents/Office Scripts/.

Sharing a script with a workbook links it rather than attaching it, and the script “remain[s] in the script creator’s OneDrive.” When that person leaves, what happens to the script depends on your OneDrive retention policy. Scripts saved to a SharePoint site “are owned by your team,” which makes that the safer home for anything shared, unless the script uses fetch.

Power Automate is the scheduler, with hard limits

Office Scripts has no workbook events. A script runs when a person starts it or “when a Power Automate flow calls the script.” The built-in scheduler inside Excel is “temporarily disabled,” Microsoft’s overview says, so a flow is now the way to run a script daily.

The platform limits page gives the numbers:

  • 1,600 Run script calls per user per day, reset at 12:00 a.m. UTC.
  • A 120-second timeout for each synchronous call.
  • At most 30,000,000 bytes (28.6 MB) of parameters per call.
  • 5 MB per request or response to the workbook, and 5 million cells per range.

A hypothetical flow that runs one script on 40 workbooks every hour makes 960 calls a day, inside the cap. For scripts that run long, Microsoft says to speed them up or “split your Excel automation into multiple script calls.”

Flows also change behavior. Power Automate runs each script “in independent Excel sessions,” so getActiveWorksheet returns the first sheet unless the script activated another, and getSelectedRange throws. Pivot refreshes do nothing. And “Power Automate always uses UTC,” while a person in Excel gets local time, so “today” can differ by a day.

Licenses: VBA comes with desktop Excel

VBA “requires no special licensing” in desktop Excel. Office Scripts needs a business or education plan. Microsoft’s list names Office 365 Business and Business Premium, ProPlus, Enterprise E1, E3 and E5, F3, and the education plans A3 and A5.

The list uses Office 365 plan names, so if your plan goes by another name, look for the Automate tab in Excel on the web before you plan a move. Personal and Family plans get Office Scripts only as a preview through the Microsoft 365 Insider program, and can’t share scripts through workbooks.

Admins have little to do. Office Scripts is “turned on by default” for everyone, and a change to its settings “can take up to 48 hours” to apply.

The same job in both languages differs in three details

Here is one small job written twice. On a sheet called Invoices, color every unpaid row whose due date has passed. Then copy those rows to a fresh sheet called Overdue. Both assume the table starts in cell A1, with due dates in column C and the status in column D.

The VBA version:

Sub CopyOverdue()
    ' Table starts in A1: headers, due date in C, status in D.
    Dim src As Worksheet, dst As Worksheet, data As Range
    Dim r As Long, outRow As Long, due As Variant

    Set src = ThisWorkbook.Worksheets("Invoices")
    Set data = src.UsedRange

    Application.DisplayAlerts = False   ' delete without the prompt
    On Error Resume Next                ' no Overdue sheet yet is fine
    ThisWorkbook.Worksheets("Overdue").Delete
    On Error GoTo 0
    Application.DisplayAlerts = True

    Set dst = ThisWorkbook.Worksheets.Add(After:=src)
    dst.Name = "Overdue"
    data.Rows(1).Copy dst.Range("A1")
    outRow = 2

    For r = 2 To data.Rows.Count
        due = data.Cells(r, 3).Value
        If VarType(due) = vbDate Then
            If due < Date And data.Cells(r, 4).Text <> "Paid" Then
                data.Rows(r).Interior.Color = RGB(255, 199, 206)
                data.Rows(r).Copy dst.Cells(outRow, 1)
                outRow = outRow + 1
            End If
        End If
    Next r
End Sub

The Office Scripts version:

function main(workbook: ExcelScript.Workbook) {
  // Table starts in A1: headers, due date in C, status in D.
  const src = workbook.getWorksheet("Invoices");
  const data = src?.getUsedRange();
  if (!src || !data) {
    throw new Error("No Invoices sheet, or it is empty");
  }
  const values = data.getValues();

  workbook.getWorksheet("Overdue")?.delete();
  const dst = workbook.addWorksheet("Overdue");
  dst.getRange("A1").copyFrom(data.getRow(0));

  // Excel stores dates as serial numbers: day 25569 is January 1, 1970.
  const now = new Date();
  const today = Date.UTC(now.getFullYear(), now.getMonth(), now.getDate()) / 86400000 + 25569;

  let outRow = 1;
  for (let r = 1; r < values.length; r++) {
    const due = values[r][2];
    if (typeof due === "number" && due < today && values[r][3] !== "Paid") {
      data.getRow(r).getFormat().getFill().setColor("#FFC7CE");
      dst.getCell(outRow, 0).copyFrom(data.getRow(r));
      outRow++;
    }
  }
}

The two look alike, but three details differ. VBA reads a date cell as a Date, while getValues returns a plain number. So the script builds today’s serial number itself, with the 25569 offset from Microsoft’s date samples.

The macro reads cell by cell, while the script reads every value once, before the loop, as Microsoft’s performance guide advises. And run from a flow, its “today” is the UTC date. For an office west of UTC, that date turns over before local midnight, so a late-day run counts invoices due today as overdue.

What we checked: the script passes the TypeScript compiler in strict mode against the Office Scripts signatures it uses. That was compiler version 5.9.3, not the 4.0.3 that Office Scripts runs.

We ran it once against a mock workbook of six rows. It marked and copied the two overdue rows and left the paid row, the row due today, the blank date and the text date alone. We did not run either version in Excel.

Two gaps remain. Neither version clears old highlights, so a row paid since the last run stays colored. And a plain number in column C counts as a date in the script but not in the macro.

Python in Excel is not a replacement for either

Python in Excel “runs the Python code used by Excel in a secure container on the Microsoft Cloud,” Microsoft says. The code “doesn’t have access to your computer, devices, or account” and “doesn’t have network access.” It reads only the data a formula references.

It runs for Enterprise and Business users on Windows and Mac and in Excel on the web, but not on iPad, iPhone or Android. Faster premium compute needs an add-on license. Use it to analyze a range. With no access to the PC or the network, it can’t replace a macro that saves files or sends mail.

What this means for you

The decision comes down to one question per macro: does it touch anything outside this workbook?

Keep VBA when the macro drives Outlook or Word, touches files on disk or a DLL, or runs on a workbook event such as open or save. A script can’t do those itself. A flow around it can cover part of the gap: Microsoft’s samples pair scripts with flows that send email and Teams messages.

Clear the two security items while you are there. Keep shared macro files on OneDrive or SharePoint and open them with Open in Desktop App or through the sync client, so the Mark of the Web isn’t added. Then search the code for .vbs and VBScript.RegExp before Windows turns VBScript off.

Move to Office Scripts when the job stays inside the workbook and people open it in a browser, or when it should run with no one at the PC. Start with the Action Recorder, which captures cell edits and formatting, then tidy the code.

The traps that bite during a move, all from Microsoft’s own pages:

  • No Workbook_Open or change events. Use a scheduled or event-driven flow instead.
  • getActiveWorksheet and getSelectedRange assume a person is looking. In a flow, name the sheet.
  • fetch works when you press Run and fails in the flow.
  • Dates come back as numbers, and flows run on UTC.
  • The script lives in someone’s OneDrive. Move shared scripts to a SharePoint site before that person leaves.
  • In Teams, scripts run only in Teams on the web.

If you are already moving email or file jobs out of macros, our guides to email data into Excel and saving Outlook attachments use the same Power Automate pieces.

This week, list every .xlsm file the office uses and mark each macro “outside” or “inside.” Move the inside ones that people open in a browser or want on a schedule first, and leave the rest where they work.

How we made this

We read Microsoft’s documentation and its VBScript post on October 20, 2026, and built the table from them. We type-checked the Office Script and ran it once against a six-row mock workbook in Node. Neither version ran in Excel, and the VBA was not run at all.

Sources