r/vba

The future of VBA language isn’t about replacing it. It’s about supercharging it.
▲ 9 r/vba

The future of VBA language isn’t about replacing it. It’s about supercharging it.

Recently, I engaged with a Redditor about the usefulness of ASF in daily VBA programming. The conversation considered the increasing number of attempts to modernize VBA. There are many solutions out there providing tools to users with specific goals: parsing json files, dealing with file encryption, evaluating expressions.

Despite that, very few authors focus their efforts to tackle the oldest pain point for VBA programmers: the frozen primitives (array, collection, dictionary), the motivation for the vast majority of boilerplate code. From this, specialized tools like u/senipah VBA Better Array, u/sancarn stdVBA, u/cristianbuse VBA Array Tools, Tim hall VBA JSON and many others came about. Almost all these libraries can be placed in the tooling category, since they focus on dealing with a specific problem (with the exception of stdVBA for being a framework to make VBA more ergonomic and kill VBA boilerplate code).

Those incredible projects have served as inspiration for many developers and paved the road for new projects that modernize VBA. ASF inherited some of those authors' philosophies, especially the one shown by u/sancarn: make code more ergonomic and go far beyond being a simple tool. As an example, here is a test from a 400+ test suite available for this scripting language:

'@TestMethod("sort")
Private Sub sort_chain_on_objects()
    On Error GoTo TestFail
    Dim Globals As ASF_Globals
    Dim jsonResponse As String
    jsonResponse = _
        "{" & _
        "  users: [" & _
        "    { id: 1, name: 'Alice', sales: 15000, active: true }," & _
        "    { id: 2, name: 'Bob', sales: 8000, active: false }," & _
        "    { id: 3, name: 'Charlie', sales: 22000, active: true }" & _
        "  ]" & _
        "};"
    GetResult "let response = " & jsonResponse & _
        "let topSellers = response.users" & _
        "  .filter(fun(u) { return u.active && u.sales > 10000 })" & _
        "  .map(fun(u) { return { name: u.name, bonus: u.sales * 0.1 } })" & _
        "  .sort(fun(a, b) {" & _
        "    if (a.bonus > b.bonus) { return -1 };" & _
        "    if (a.bonus < b.bonus) { return 1 };" & _
        "    return 0;" & _
        "  });" & _
        "print(topSellers);", True
    Set Globals = scriptEngine.GetGlobals
    With Globals
        actual = CStr(.gRuntimeLog(.gRuntimeLog.Count))
    End With
    expected = "PRINT:[ { name: 'Charlie', bonus: 2200 }, { name: 'Alice', bonus: 1500 } ]"
    Assert.AreEqual expected, actual
TestExit:
    Exit Sub
TestFail:
    Assert.Fail "Test raised an error: #" & err.Number & " - " & err.Description
    Resume TestExit
End Sub

I think if we, as a community of people that really love VBA, can improve our loved language even more, we can make possible that which almost all people think impossible. As an example, we have Web View embedding web pages in userforms and inspiring a new development generation!

u/ws-garcia — 19 hours ago
▲ 52 r/vba

I built a full audio engine for VBA. No DLLs, no COM wrappers, no addins. Just a .bas file

What is it?

Riff is a WASAPI audio engine written entirely in native VBA. Drop one .bas module into your workbook and you get:

  • Polyphonic playback (up to 32 simultaneous voices)
  • Load audio from disk or straight from a Byte array in memory
  • A full DSP pipeline per voice: Reverb, Chorus, Flanger, Delay, 3-Band EQ, Compressor, Distortion, Bitcrusher, Ring Modulator, Tremolo, Auto-Pan, Stereo Width
  • Procedural oscillators (Sine, Square, Sawtooth, Noise)
  • Fade in/out, loop regions, per-voice pitch shifting and seeking
  • 8 audio buses so you can group things like music, sfx, UI sounds separately
  • Per-voice and master peak meters for VU displays
  • Works on x86 and x64 Office without any changes

How does it work?

This is where it got out of hand.

VBA has no audio APIs and no background threads, so Riff works around both with raw Windows calls:

  • WASAPI (IAudioClient, IAudioRenderClient) is driven through raw COM VTable calls using DispCallFunc from oleaut32.dll. No type libraries, no CreateObject, just pointer math.
  • Media Foundation (IMFSourceReader) decodes any audio file (WAV, MP3, AAC, whatever) into raw PCM at load time, already resampled to match the device's native format.
  • The DSP loop runs on a 15ms SetTimer callback. Since VBA can't be a timer callback target directly, Riff writes a small machine-code thunk at runtime into VirtualAlloc'd executable memory. The thunk checks EbMode from vbe7.dll before doing anything. If VBA is in break or design mode, it kills the timer itself and exits cleanly instead of taking Excel down with it.
  • All 32 voices share one contiguous 1D Single array (about 23 MB) as the ring buffer for time-based effects. It has to be 1D because VBA 2D arrays are column-major, and RtlZeroMemory on a single row of a 2D array does the wrong thing.

When would you actually use this?

Honestly, probably never. But:

  • Excel games or interactive tools that need sound
  • Dashboard alerts where different events have different audio cues
  • UI sounds for things like confirmations, errors, hover feedback
  • Showing someone DSP concepts in an environment they definitely already have installed
  • Making your coworkers very confused when they see Excel touching WASAPI in Task Manager

The API is pretty simple:

RiffOpen

Dim buf As Long
buf = RiffLoad("C:\sounds\alert.wav")

Dim v As Long
v = RiffPlay(buf)
RiffVoiceReverbMix(v) = 0.3
RiffVoiceEqBass(v) = 1.6
RiffFadeOut v, 2.0

Or just generate sound directly without any file:

Dim v As Long
v = RiffPlayOscillator(0, 440.0) ' sine wave at A4
RiffVoiceChorusDepth(v) = 0.4
RiffFadeOut v, 0.5

I also wrote a full API Reference and an Architecture doc with diagrams of the DSP pipeline, WASAPI init sequence, and how the thunk compilation works, if anyone wants to go deeper.

Github: https://github.com/uesleibros/riff

u/UesleiDev — 5 days ago
▲ 18 r/vba

Update on my single-file VBA audio engine: WAV export, better DSP, BLEP oscillators and Freeverb-style reverb

I posted Riff here earlier and got a lot of really useful feedback, so I wanted to share a follow-up update.

For context, Riff is a single-file VBA audio engine built on WASAPI and Media Foundation. The goal is still the same: no external DLLs, no COM registration, no references, no installer. Just import Riff.bas, call RiffOpen, and play audio directly from VBA.

The first thread helped a lot. A few people pointed out real issues and interesting future directions, so I spent some time cleaning things up and adding some of the missing pieces.

The biggest fixes and additions in this update:

  • Fixed the VBA7 vs Win64 LongLong issue in the Media Foundation decoding path
  • Updated the examples so RiffOpen is clearly required before playback
  • Added WAV export for loaded buffers
  • Added offline oscillator rendering directly to WAV
  • Added biquad-based EQ, low-pass, and high-pass filters
  • Added BLEP-style band-limited oscillators to reduce aliasing on square and saw waves
  • Reworked the reverb into a Freeverb-style implementation
  • Improved validation around buffer handles, loop regions, seeking, and memory-loaded audio
  • Updated the README and API reference

The WAV export part was added because someone asked whether Riff could generate audio files instead of only playing audio. That was not available in the first version, but now it is.

Example:

Dim buf As Long
buf = RiffLoad("C:\sounds\sound.mp3")

RiffExportBufferWav buf, "C:\sounds\export.wav"

Oscillator rendering is also possible now:

RiffRenderOscillatorWav 0, 440, 3, "C:\sounds\sine.wav"
RiffRenderOscillatorWav 1, 110, 2, "C:\sounds\square.wav"
RiffRenderOscillatorWav 2, 220, 2, "C:\sounds\saw.wav"

I also experimented with direct vtable calls inside the Media Foundation decoding loop to reduce DispCallFunc overhead, but I reverted that path for now. It was too unstable in VBA and could crash Excel. I would rather keep the engine stable than ship a risky optimization just because it looks clever.

That said, the typelib discussion from the previous thread got me thinking a lot. There is clearly a bigger problem around making lower-level Windows APIs more accessible from VBA, especially for 64-bit Office, without forcing every developer to manually deal with raw pointers, vtable offsets, broken tooling, or incomplete definitions.

So this update is not just “Riff got better audio”. It also made me think that maybe these projects should not live only under my personal profile forever.

Would it make sense to create a small team or organization focused specifically on serious VBA research and tooling? Something dedicated to projects like Riff, low-level Windows API access, audio, networking, typelibs, Office automation internals, and modern experiments around what VBA can still do today?

I am curious if people would find that useful, or if it is better to keep everything as individual projects under my own GitHub.

reddit.com
u/UesleiDev — 4 days ago
▲ 10 r/vba

ASF: Introducing shared COM prototyping in VBA

After a hiatus in development, during which I devoted a great deal of time to other applications and studies, I am pleased to introduce ASF v3.1.3. This version offers improved usability and introduces the ability to share hacks on native Office COM objects, making prototypes fully portable across modules. Prototype definitions can now be exported and imported like any other ASF symbol, enabling shared prototype libraries. Here is an example of how this new feature works:

// prototypes.vas
export prototype.COM.Range addStyle(color) {
    this.Interior.Color = color;
};

export prototype.COM.Worksheet highlight(rng, color) {
    rng.addStyle(color);
};

// main_prototype.vas
scwd(wd);
import { Range_addStyle, Worksheet_highlight } from './prototypes.vas';
// Prototypes are live immediately after import
let ws = $1.ActiveSheet;
let rng = ws.Range('J1:L3');
rng.addStyle(65535);          // yellow
ws.highlight(rng, 255);       // red
return rng.Interior.Color

Here is the driving VBA code:

Private Sub module_system_prototype_imports()
    Dim result As Long
    Dim wd As String
    Dim eng As New ASF
    wd = ThisWorkbook.path
    With eng
        .AppAccess = True
        .InjectVariable "wd", wd
        result = CLng(.Execute(wd & "\main_prototype.vas", ThisWorkbook))
    End With
    'Expected: 255
End Sub

And here is the execution trace:

=== Runtime Log ===
RUN Program: 
CALL: ActiveSheet() -> <Worksheet>
CALL: range('J1:L3') -> <Range>
CALL: addstyle(65535) -> 
CALL: __PROTOTYPE_RANGE_ADDSTYLE(65535) -> 
CALL: Interior() -> <Interior>
CALL: highlight(<Range>, 255) -> 
CALL: __PROTOTYPE_WORKSHEET_HIGHLIGHT(<Range>, 255) -> 
CALL: addstyle(255) -> 
CALL: __PROTOTYPE_RANGE_ADDSTYLE(255) -> 
CALL: Interior() -> <Interior>
CALL: Interior() -> <Interior>
CALL: Color() -> 255
CALL: @anon() -> 255
u/ws-garcia — 4 days ago
▲ 7 r/vba

How to make "Text to Columns" more dynamic?

I have a bunch of CSV files on which I need to use the Excel Text to Columns feature in order for them to be converted to Columns. When I used the "Record Macro" feature the output I get is the following:

Sub testing()

Dim wb As Workbook
Set wb = Workbooks.Open(sTEST, , , 5)

Range("A:A").TextToColumns Destination:=Range("A1"), DataType:=xlDelimited, _
    TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
    Semicolon:=True, Comma:=False, Space:=False, Other:=False, FieldInfo _
    :=Array(Array(1, 1), Array(2, 1), Array(3, 1), Array(4, 1), Array(5, 1), Array(6, 1), _
    Array(7, 1), Array(8, 1), Array(9, 1), Array(10, 1), Array(11, 1), Array(12, 1), Array(13, 1 _
    ), Array(14, 1), Array(15, 1), Array(16, 1), Array(17, 1), Array(18, 1), Array(19, 1), Array _
    (20, 1), Array(21, 1), Array(22, 1), Array(23, 1), Array(24, 1), Array(25, 1), Array(26, 1), _
    Array(27, 1), Array(28, 1), Array(29, 1), Array(30, 1), Array(31, 1), Array(32, 1), Array( _
    33, 1), Array(34, 1), Array(35, 1), Array(36, 1), Array(37, 1), Array(38, 1), Array(39, 1), _
    Array(40, 1), Array(41, 1), Array(42, 1), Array(43, 1), Array(44, 1), Array(45, 1), Array( _
    46, 1), Array(47, 1), Array(48, 1), Array(49, 1), Array(50, 1), Array(51, 1), Array(52, 1), _
    Array(53, 1), Array(54, 1), Array(55, 1), Array(56, 1), Array(57, 1), Array(58, 1), Array( _
    59, 1), Array(60, 1), Array(61, 1), Array(62, 1), Array(63, 1), Array(64, 1), Array(65, 1), _
    Array(66, 1), Array(67, 1), Array(68, 1), Array(69, 1), Array(70, 1), Array(71, 1), Array( _
    72, 1), Array(73, 1), Array(74, 1), Array(75, 1), Array(76, 1), Array(77, 1), Array(78, 1), _
    Array(79, 1), Array(80, 1), Array(81, 1), Array(82, 1), Array(83, 1), Array(84, 1), Array( _
    85, 1), Array(86, 1), Array(87, 1), Array(88, 1), Array(89, 1), Array(90, 1), Array(91, 1), _
    Array(92, 1), Array(93, 1), Array(94, 1)), TrailingMinusNumbers:=True

End Sub

Most of this logic is ok, but the Imbedded Array convention is something I am not clear on. I do understand that each of these 94 imbedded Arrays represent a column (I can see that my file has 94 columns). I am not actually sure how to manipulate with this feature. Is there a way to write a dynamic "looping" operation? Maybe next time I will have 50 columns or 10. Thank you for any guidance!

reddit.com
u/TonIvideo — 6 days ago
▲ 82 r/vba

Whenever I open my VBE...

Our VBA, who art in Excel,
Hallowed be thy Code.
Thy IDE come,
Thy Macro be run,
In Access as it is in Excel.
Give us this day our daily DoEvents,
And forgive us our GoTos,
As we forgive those who label against us.
Lead us not into Python,
But deliver us from JavaScript.
For thine is ThisWorkbook,
The ActiveSheet, and the Range,
Forever and ever,
End Sub.
reddit.com
u/sancarn — 7 days ago
▲ 8 r/vba

How to check if a date is a numeric date or a string date?

In a lot of my automations I am requiring the user to input a date as a numeric date. This way I don't care what the users regional formatting is, as the date will ultimately always convert to a number anyway. Consequently I need a way to check if a date is numeric (can be converted to a number) or a string (can not be converted to a number if one switches between the short date and number formats from the front end). For now I came up with the following solution:

On Error GoTo EndDateCheck

If IsNumeric(CLng(INI.Range("INT_ITD"))) = False Then

  EndDateCheck:
  MsgBox "The date is not numeric."
  End

End If

On Error GoTo 0

The above works well, but I am wondering if there is a simpler way to check (thus I am not outright looking for a "solution", but I am more after design efficiency), which doesn't involve the on error statement.

reddit.com
u/TonIvideo — 8 days ago
▲ 6 r/vba

Export to pdf from exc

I have a simple line of vba within a very old excel workbook that exports a sheet to a pdf file. The resulting pdf file however always has a company logo in a picture format pasted at the top. The originating excel sheet does not have this anywhere. Any idea how this picture is being pasted every time? I’ve looked everywhere I just can’t see where it’s coming from.

reddit.com
u/jeanpicard724 — 8 days ago
▲ 65 r/vba+2 crossposts

I made a Discord bot that runs from a hidden Excel sheet. Because why not.

So I've been working on a native WebSocket module for VBA called Wasabi, and at some point I asked myself: "can I connect this to Discord's gateway and make a bot?" The answer is yes, and it's glorious and completely unnecessary.

The concept

Discord's bot API is just a WebSocket connection to wss://gateway.discord.gg. Once connected, Discord sends you a JSON payload with an op code telling you to identify yourself. You send back your bot token and intents, and from that point on you receive events (messages, reactions, etc.) as JSON frames. You respond to them by hitting Discord's REST API with plain HTTP calls.

That's it. No SDK needed. Just WebSocket + JSON parsing.

Step 1: Get a bot token

Go to https://discord.com/developers/applications, create an application, add a bot, copy the token. Enable the "Message Content Intent" under the bot settings or it won't receive message content.

Step 2: Import Wasabi

Download Wasabi.bas from https://github.com/uesleibros/wasabi/releases and import it into your VBA project via File > Import File. No references to enable, no DLLs to register.

Step 3: Connect to the gateway and keep it alive

Discord requires you to send a heartbeat payload every N milliseconds (it tells you the interval on connect). Here's a minimal loop that handles that:

#If VBA7 Then
    Private Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long
#Else
    Private Declare Function GetTickCount Lib "kernel32" () As Long
#End If

Sub RunDiscordBot()
    Dim token As String
    token = "YOUR_BOT_TOKEN_HERE"

    Dim handle As Long
    If Not WebSocketConnect("wss://gateway.discord.gg/?v=10&encoding=json", handle) Then
        MsgBox "Failed to connect to Discord gateway."
        Exit Sub
    End If

    Dim msg As String
    Dim heartbeatInterval As Long
    Dim lastHeartbeat As Long
    Dim identified As Boolean

    identified = False
    lastHeartbeat = 0

    Do While WebSocketIsConnected(handle)
        msg = WebSocketReceive(handle)

        If Len(msg) > 0 Then
            Dim op As Long
            op = ExtractOp(msg) ' parse the "op" field from JSON

            ' Hello payload: Discord sends heartbeat interval
            If op = 10 Then
                heartbeatInterval = ExtractHeartbeatInterval(msg)
                lastHeartbeat = GetTickCount()

                ' Identify
                If Not identified Then
                    Dim identifyPayload As String
                    identifyPayload = "{""op"":2,""d"":{""token"":""" & token & """,""intents"":33280,""properties"":{""os"":""windows"",""browser"":""excel"",""device"":""excel""}}}"
                    WebSocketSend identifyPayload, handle
                    identified = True
                End If

            ' Dispatch: actual events like MESSAGE_CREATE
            ElseIf op = 0 Then
                Call HandleEvent(msg, token)
            End If
        End If

        ' Send heartbeat when due
        If GetTickCount() - lastHeartbeat >= heartbeatInterval Then
            WebSocketSend "{""op"":1,""d"":null}", handle
            lastHeartbeat = GetTickCount()
        End If

        DoEvents
    Loop

    WebSocketDisconnect handle
End Sub

Step 4: Handle a message event

When op = 0 and the event type is MESSAGE_CREATE, you get the channel ID and message content from the JSON. Then you can reply via Discord's REST API using XMLHTTP:

Sub HandleEvent(ByVal payload As String, ByVal token As String)
    If InStr(payload, "MESSAGE_CREATE") = 0 Then Exit Sub

    Dim channelId As String
    Dim content As String
    channelId = ExtractField(payload, "channel_id")
    content = ExtractField(payload, "content")

    If content = "!ping" Then
        Call SendDiscordMessage(channelId, "Pong! (sent from Excel)", token)
    End If
End Sub

Sub SendDiscordMessage(ByVal channelId As String, ByVal message As String, ByVal token As String)
    Dim http As Object
    Set http = CreateObject("MSXML2.XMLHTTP")
    Dim url As String
    url = "https://discord.com/api/v10/channels/" & channelId & "/messages"
    Dim body As String
    body = "{""content"":""" & message & """}"
    
    http.Open "POST", url, True
    http.setRequestHeader "Authorization", "Bot " & token
    http.setRequestHeader "Content-Type", "application/json"
    http.Send body
    
    Do While http.readyState <> 4
        DoEvents
    Loop
End Sub

Where to go from here

This is just the skeleton. From here you can:

  • Read/write cells based on Discord commands ("!get A1" returns the cell value, "!set A1 42" writes to it)
  • Trigger macros remotely by sending a command from Discord
  • Post alerts to a channel when a cell value crosses a threshold (combine with a Worksheet_Change event)
  • Run the bot from a hidden sheet so it sits quietly in the background while you use the spreadsheet normally

The browser and device fields in the identify payload are set to "excel" in the example above. Discord doesn't validate these, but it's a fun touch.

Full module docs and source: https://github.com/uesleibros/wasabi

u/UesleiDev — 11 days ago
▲ 28 r/vba

Wasabi just hit Awesome VBA + Update v2.3.8

I am very pleased to announce a significant milestone for the Wasabi project. After several in depth technical discussions with sancarn, the creator of the renowned stdVBA library, Wasabi has been officially included in the Awesome VBA list. This is a meaningful recognition for a project that originated from a specific need within a niche PowerPoint gaming community and has now matured into a robust tool for general purpose networking.

For those who are not familiar with the project, Wasabi is a self contained .bas module designed to provide a complete networking stack for VBA. It requires zero external dependencies, zero references, and no registration of COM DLLs. It implements WebSockets (WSS), raw TCP, and full Proxy support directly within the VBA environment.

The core of Wasabi architecture relies on machine code thunks for both x86 and x64 architectures. These thunks handle critical operations such as memory zeroing, byte searching, and WebSocket masking outside the standard VBA stack. This creates a vital safety layer. In typical VBA networking, the application often crashes if the editor enters break mode or encounters an unhandled error while a Windows message pump is active. Wasabi assembly thunks act as a firewall, intercepting these events and preventing the host application from closing abruptly.

The repository was recently updated to version 2.3.8-beta. This update focused on hardening the protocol implementations and expanding compatibility with modern standards.

  1. Native MQTT 5.0 Implementation The MQTT parser has been significantly overhauled to move beyond the legacy 3.1.1 standard. Wasabi now natively supports the MQTT 5.0 protocol. This includes the correct processing of variable byte integers for the remaining length field and the mandatory property length fields in CONNECT, SUBSCRIBE, and PUBLISH packets. We have successfully validated this implementation against modern brokers like HiveMQ and EMQX, as well as testing tools like MQTTX. MQTTX Reported by u/Savings_Mission_534 (https://www.reddit.com/r/vba/comments/1t9q3nc/comment/ol4zycm)
  2. RFC 6455 Hardening and Protocol Compliance We have reinforced the WebSocket frame parser to be strictly compliant with RFC 6455. The parser now performs strict validation of reserved bits (RSV2 and RSV3). According to the specification, if these bits are set without a negotiated extension, the connection must be terminated with a protocol error code 1002. Additionally, the handling of TLS fragments during reassembly was improved to ensure that data remains contiguous and valid even during high volume or fragmented transmissions.
  3. Memory Management and Buffer Optimization The internal routine for buffer allocation, EnsureBufferCapacity, was rewritten to handle larger data streams more efficiently. The previous limits were found to be too restrictive for certain industrial applications. The module now supports data payloads of up to 256MB by utilizing a more aggressive growth strategy and safer memory pointers, which is a significant leap for the VBA environment.
  4. Closing Handshake Logic The Finite State Machine (FSM) for connection teardown was refined. Wasabi now correctly handles the STATE_CLOSING status, ensuring that it sends the closing frame and waits for the server echo before fully releasing the socket resources. This prevents half open connections and potential memory leaks during rapid connect and disconnect cycles.

Looking ahead, the goal is to further increase the stability and reach of the module. There is an ongoing plan to eventually integrate these networking capabilities into a dedicated class for the stdVBA library, making it even easier for developers to build modern, connected applications.

Contributions through Pull Requests, detailed bug reports, or architectural suggestions via GitHub Issues are highly encouraged. Whether you are interested in Win32 API hacks, IoT integration, or real time data synchronization within Office, Wasabi provides a solid foundation to explore these limits.

Github: https://github.com/uesleibros/wasabi

Release: https://github.com/uesleibros/wasabi/releases/tag/v2.3.8-beta

I want to thank the members of this sub who provided technical feedback on previous versions. Your insights were crucial in identifying edge cases and refining the memory management logic. We continue to push the boundaries of what is possible within the VBA environment.

reddit.com
u/UesleiDev — 11 days ago
▲ 14 r/vba+1 crossposts

This project started in a rather unexpected place. A group of friends of mine have the hobby of building entire games inside PowerPoint using VBA. They kept hitting the same wall: there was no clean, reliable way to get real‑time communication working inside VBA. I wanted to help them, and that’s how Wasabi came to life. It is a single .bas module that acts as a full WebSocket and secure WebSocket client, written entirely in native VBA using Winsock and the Windows Schannel security provider.

Because it’s just a plain VBA module, you can use it in any Office host that runs VBA: Excel, PowerPoint, Word, Access, Outlook, and more. You import the file and you’re ready to go. No references to add, no DLLs to register, no external dependencies at all. It works on 32‑bit and 64‑bit Office, from Windows XP to Windows 11.

Under the hood it handles secure sockets over TLS via Schannel, so you can connect to wss:// endpoints without relying on a browser or third‑party library. An integrated MQTT 3.1.1 client lets you talk to brokers like Mosquitto directly from any VBA‑enabled program, which opens the door to IoT projects and industrial automation. There is support for corporate proxy authentication using NTLM and Kerberos, so it fits right into enterprise environments where the network expects Integrated Windows Authentication. The connection layer includes automatic reconnection, an optional heartbeat, and per‑message deflate compression as defined in RFC 7692. Masking keys for outgoing frames are generated using CryptGenRandom, which keeps the randomness cryptographically sound.

This becomes genuinely useful in practice when you need real‑time data inside Office. You can stream quotes from Binance or Coinbase straight into an Excel spreadsheet with millisecond latency. You can build dashboards that update live without polling HTTP endpoints. You can write a Discord or Slack bot that runs from Access or Excel. You can connect legacy VBA tools to modern event buses over WebSockets or MQTT, bridging old and new without complex middleware. And yes, you can even add real‑time multiplayer to a PowerPoint game if the mood strikes.

Getting started takes a few minutes. Grab the Wasabi.bas file from the releases page, open the VBA editor in your host of choice, and choose File → Import File.

The project is open source under the MIT license. The full documentation covering the API reference, error handling, and internal architecture lives in the GitHub repository folder docs. That same group of friends is already testing multiplayer PowerPoint games through Wasabi, and seeing it work across different Office apps at the same time still feels a little magical.

If you have ever wanted to add real‑time capabilities to a VBA project and found the built‑in options lacking, this module might save you a lot of low‑level pain. I would be glad to hear your thoughts, ideas, or use cases.

Repository: https://github.com/uesleibros/wasabi

Releases (download just the .bas): https://github.com/uesleibros/wasabi/releases

u/UesleiDev — 14 days ago
▲ 62 r/vba

9 quick tips to improve your VBA macro performance.

1 Turn off everything but the essentials in VBA;

The below code sample shows you how to enable/disable:

  • Manual calculations
  • Screen updates
  • Animations

​

Option Explicit

Dim lCalcSave As Long
Dim bScreenUpdate As Boolean

Sub SwitchOff(bSwitchOff As Boolean)
    Dim ws As Worksheet

    With Application
        If bSwitchOff Then
            ' OFF
            lCalcSave = .Calculation
            bScreenUpdate = .ScreenUpdating
            .Calculation = xlCalculationManual
            .ScreenUpdating = False
            .EnableAnimations = False

            For Each ws In ActiveWorkbook.Worksheets
                ws.DisplayPageBreaks = False
            Next ws
        Else
            ' ON
            If .Calculation <> lCalcSave And lCalcSave <> 0 Then
                .Calculation = lCalcSave
            End If
            .ScreenUpdating = bScreenUpdate
            .EnableAnimations = True
        End If
    End With
End Sub

Sub Main()
    SwitchOff True
    MyFunction
    SwitchOff False
End Sub

2. Disabling Office animations through system settings;

Animations can be disabled across Windows by accessing the Ease of Access Center.

Animations can be disabled in Excel specifically, under the Advanced or Ease of Access tab, within the File > Options menu.

Please see the following link for more information: https://support.office.com/en-us/article/turn-off-office-animations-9ee5c4d2-d144-4fd2-b670-22cef9fa025a

3 Disabling Office animations through registry settings

Office animations can be disabled across multiple computers by setting the appropriate registry key via a group policy setting. 

HIVE: HKEY_CURRENT_USER
Key Path: Software\Microsoft\Office\16.0\Common\Graphics
Key Name: DisableAnimations
Value type: REG_DWORD
Value data: 0x00000001 (1)

4 Removing unnecessary selects

The select method is common to see in VBA code, however it is often added to the macro where it isn’t needed. Select can trigger cell events such as animations and conditional formatting which slow the macro down, so removing unnecessary selects can significantly speed up your macro.

The following example shows the code before and after making the change to remove unnecessary selects.

Before

Sheets("Order Details").Select
Columns("AC:AH").Select
Selection.ClearContents

After

Sheets("Order Details").Columns("AC:AH").ClearContents

 4 Removing unnecessary selects

The select method is common to see in VBA code, however it is often
added to the macro where it isn’t needed. Select can trigger cell events
such as animations and conditional formatting which slow the macro
down, so removing unnecessary selects can significantly speed up your
macro.
The following example shows the code before and after making the change to remove unnecessary selects.

 Before
Sheets("Order Details").Select
Columns("AC:AH").Select
Selection.ClearContents

After
Sheets("Order Details").Columns("AC:AH").ClearContents

5 Using the With statement to read object properties

When working with objects, use the With statement to reduce the number of times object properties are read. The following example shows the code before and after making the change to use the With statement.

 

Before

Range("A1").Value = "Hello"
Range("A1").Font.Name = "Calibri"
Range("A1").Font.Bold = True
Range("A1").HorizontalAlignment = xlCenter

After

With Range("A1")
  .Value2 = "Hello" 
  .HorizontalAlignment = xlCenter
    With .Font
      .Name = "Calibri"
      .Bold = True
    End With
End With

6 Using ranges and arrays

Reading and writing to cells in Excel from VBA is expensive. There is an overhead that is incurred every time data moves between VBA and Excel.

This means that you should try to reduce the number of times you pass data between VBA and Excel. This is where ranges are useful. Instead of reading and writing to each cell individually in a loop, read the entire range into an array at the start, loop through the array, and then write the entire array back at the end. The following example code shows how a range can be used to read and write the values once, instead of reading each cell individually.

Dim vArray As Variant
Dim iRow As Long
Dim iCol As Long
Dim dValue As Double

vArray = Range("A1:C10000").Value2

For iRow = LBound(vArray, 1) To UBound(vArray, 1)
    For iCol = LBound(vArray, 2) To UBound(vArray, 2)
        If IsNumeric(vArray(iRow, iCol)) Then
            dValue = CDbl(vArray(iRow, iCol))
            If dValue > 0 Then
                dValue = dValue * dValue
            End If
            vArray(iRow, iCol) = dValue
        End If
    Next iCol
Next iRow

Range("A1:C10000").Value2 = vArray

7 Use .Value2 instead of .Text or .Value

There are different ways that you can retrieve values from a cell, and which property you use can make a different in the performance of your code.

.Text is commonly used to retrieve the value of a cell – it returns the formatted value of a cell. Getting the formatting of a cell is more complex than just retrieving a value, and makes .Text quite slow.

.Value is an improvement over .Text, as this mostly gets the value from the cell, without formatting. However for cells formatted as a date or currency, .Value will return a VBA date or VBA currency (which may truncate decimal places).

.Value2 gives the underlying value of the cell. As it involves no formatting, .Value2 is faster than .Value. .Value2 is faster than .Value when processing numbers (there is no significant difference with text), and is much faster using a variant array.

8 Bypass the clipboard (copy and paste)

When you use the Macro Recorder to record operations that use copy and paste, the code will use the copy and paste methods by default. However, within VBA code, it is much faster to bypass the clipboard and use internal operations instead. By default, copying will copy everything, including formulas, values and formatting. You can make copying faster by only copying values or formulas, without the formatting. The following example shows the code before and after making the change to bypass the clipboard.

Before

Range("A1").Select
Selection.Copy
Range("A2").Select
ActiveSheet.Paste

After

' Approach 1: copy everything (formulas, values and formatting
Range("A1").Copy Destination:=Range("A2")

' Approach 2: copy values only
Range("A2").Value2 = Range("A1").Value2

'Approach 3: copy formulas only
Range("A2").Formula = Range("A1")

9. Use Option Explicit to catch undeclared variables

Option Explicit is one of the available Module directives in VBA that instructs VBA how to treat the code within the code module. Setting Option Explicit requires all variables to be declared and will give compile errors if an undeclared variable is used. This helps catch incorrectly typed variable names and improves performance with all variable types being defined at compile time, instead of being inferred at runtime.

This can be set by typing: Option Explicit at the top of each module in your project or by checking the "Require Variable Declaration" option under Tools -> Options in the VBA editor. 

reddit.com
u/Good-Willingness2234 — 15 days ago
▲ 1 r/vba

Automation with VBA

Hello everyone,

I would like to know how analysts are using VBA in Excel in their daily work.

I currently work as a data analyst, and part of my role is to create different types of analysis reports. For example, I analyze sales evolution in Grand Surfaces and other local sales by article and by category and other kpis etc.. to identify which products perform well and which do not.

Most of the time, I use tools like Claude AI and Google Gemini to help structure my analysis by explaining my data and the expected output by one simple click and loge generate well performed analysis and reports (even if it's huge page) in one simple click

For data preparation, I usually:

Clean product names

Standardize category names

Use functions like VLOOKUP, SUMIF DATEEVAL for fixing date NB.SI.ENS, etc. to calculate totals and revenue

However, I am looking for innovative ways to use VBA to automate data cleaning. Any ideas?

My goal is to create simple macros so that even a beginner could run them and clean the dataset automatically.

Unfortunately, I cannot use Microsoft Power BI in my environment, but I can use Microsoft Power Query

I will also begin developing a more interactive dashboard using VBA. This dashboard will explain all (KPIs) and provide guidance on the appropriate placement for pie charts, histograms, and line charts.

reddit.com
u/Fluffy-Difficulty882 — 13 days ago