openlang

The workbook outlives whoever wrote the macro

Open almost any inherited workbook and the first line under the module header is the same. On Error Resume Next. Not around one risky call. At the top, for everything.

It is easy to see how it gets there. Someone's macro stops with a run-time error, someone else pastes that line in, the macro stops stopping, and everyone moves on. (The macro also stops doing whatever the failing line was for, but nobody sees that part.) The statement stays in effect until On Error GoTo 0 or until the procedure exits, so in a long Sub it covers far more than the line that caused the trouble.

The other classic is a module without Option Explicit. A misspelled variable quietly becomes a fresh Variant that is always empty, and the totals still look plausible.

None of this is a VBA syntax problem. It is what happens when the next person can't tell which errors were expected. My fix is boring. Tick Require Variable Declaration in the editor so new modules get Option Explicit, and wrap the one risky call in On Error Resume Next, a check of Err.Number, then On Error GoTo 0.

The conversation continues 4

Follow the reasoning
  1. Permalink

    Oh no, this one is so easy to write by accident. In Python it's a generator that loops over rows, parses inside a try, and on any exception just does continue. It reads like a filter. It is a filter, one that silently drops the rows you most needed to see.

    What helped me was making the skip visible. The generator yields the good rows and appends the bad ones, with their exception, to a list the caller gets back. Or narrow it, so except ValueError instead of a bare except, and let anything else surface. Same advice as yours, really, just with Err.Number spelled differently.

    Do people ever log the skipped rows in VBA, or is that considered too fancy for a workbook?

  2. Permalink

    It is partly a language problem. When silencing an error takes one line and checking it takes five, people silence it, and TypeScript has the same habit with better manners. Put as Invoice on a parsed JSON body, or let an any leak out of one helper, and the red squiggles disappear exactly the way the run-time error did. The compiler stops complaining. The data is still whatever came over the wire.

    The cast sits where the checking should have happened. Validate at the edge, once, then let narrowing carry real information inward. Anything else is On Error Resume Next for the type checker.

  3. Permalink

    value = parse(row) rescue nil is the Ruby one-liner for people who find even the cast too much work. It rescues any StandardError and hands you a nil, which then travels three methods before something finally complains about it. And if the call failed for a reason you actually cared about, the nil looks exactly the same.

  4. Permalink

    ES2019 made the catch binding optional, so try { load() } catch {} is now the shortest legal way to swallow everything in JavaScript. Same disease. The workbook version at least lives in one file. In JS it is usually three packages down, in something nobody on the project has opened.

Other sides of the same question

  1. A review comment needs an ownership relation

    “Just use weak everywhere” is a review comment the author can't really answer. Take a class instance that stores a callback,…

    Replies 1swift