コロナ禍で表面化した負の遺産(Excel VBA)


要約

テレワークにより、自分の派遣先の負の遺産が可視化された。
VBAのマクロは言語設計の古さからデバッグしにくいコードが生産されやすい。
特に例外処理には最低限に抑えよう。

※なお、本内容は自分の業務の特定を防ぐために発生時の状況やコード内容は架空のものを使用しています。

発生したトラブル

テレワークをしているAさんから、業務で使っているマクロが使えなくなったとの報告があった。
詳しく聞き取りを行っても、例外が発生している様子はなく、ただ期待されている成果物が出力されていない状態だった。

調査

バグ調査を行ったのは自分だが、マクロ自体を書いたのは先人である。
しかも自分は派遣されてから日が浅く、業務内容を理解しきれていなかった。
(その上自分も含めてチーム全員がVBAはあまり詳しくないようだった。)

成果物の生成方法を先人に確認し、社内ネットワーク上にあるファイルを読み取っていることを確認し、
仕方ないからバグの原因がわかるようにMsgBoxを大量に配置して実行してもらい、
何が起きているかを確認した。

その結果、今回のトラブルは3つの要因のあわせ技になっていたことがわかった。

原因

VBAの例外を回避できない関数と、社内ネットワークに接続していなかったこと、
それと製作者とVBAの例外に対する意識の甘さが原因の特定が困難な挙動を起こしていた。
(VBAは一回滅んだほうが良いんじゃないかな)

大雑把に書けば、次のようなコードが今回のトラブルの要因になっていた。


Sub Macro1()
    On Error Resume Next

    Dim a As String
    Dim b As String
    ' 以下初期化が少し続く

    Activesheet.Range("全部").ShowAllData ' フィルタ設定がなければ例外が発生する

    If Function1 Then
        ' 成果物を作る処理
    End If

End Sub

Function Function1() As Boolean
    Dim wb As WorkBook
    Function1 = False
    wb := Workbooks.Open("社内ネットワーク上のファイル")
    Function1 = True
End Function

まず、ShowAllData関数はその範囲にかかっているすべてのフィルタ効果を解除する効果を持つ。
これはそもそもフィルタがかかっていなければ確定で例外を吐くようになっている。
仕方ないからOn Error Resume Nextで失敗時のフォローを行っているようだ。

Q. さて、では普段は正常に動いているこのMacro1を、社内のネットワークへアクセスできない人が使用したらどうなるだろう。
A. Function1でエラーが発生するため、Macro1のエラー処理によりFunction1の戻り値がFalseの状態で処理が帰ってしまい、成果物を作る処理に入らなくなってしまう。しかも正常に動作しているように見える。

対応

vbaで例外を握りつぶす場合は必要最低限の部分に留め、必要なくなったらOn Error Goto 0を使用して
把握できていないエラーが発生するようにして、エラー発生後のダウンタイムを最低限に抑えよう。

真の要因への対応

そもそもVBAなんていう全てが時代遅れのクソツールを使うのをやめたほうが良いんじゃないかな