Excel VBAでシートの存在有無を判定する場合にループ使うのは冗長だなーと思ったのだが、実はOn Errorステートメントを使うとすっきりと書けた、という話。
元ネタはExcel VBA If WorkSheet(“wsName”) Exists - Stack Overflow
本論
Excel VBAでシートが存在するかどうか判定しくて調べていたのだが、日本語で検索するとSheets
やWorksheets
をループするサンプルがよく出てくる*1。
ただ、これらのサンプルはあるシートの存在有無を確認するために、ループで全部のシートをなめるので無駄な処理だ。
どうにかならないものかと英語でぐぐったらStack Overflowに綺麗な解決策があった。
以下はExcel VBA If WorkSheet(“wsName”) Exists - Stack OverflowにおけるTim Williamさんの回答
Function SheetExists(SheetName As String, Optional wb As Excel.Workbook) Dim s As Excel.Worksheet If wb Is Nothing Then Set wb = ThisWorkbook On Error Resume Next Set s = wb.Sheets(SheetName) On Error GoTo 0 SheetExists = Not s Is Nothing End Function
SheetNameのシートが存在しない場合に、あえてエラーを発生させた上でOn Errorステートメントを使って値を取得しないままとしているのが肝。
存在する場合は普通に処理が進んだ結果、変数sに値が入るので戻り値の
Not s Is Nothing
はTrueに、存在しない場合は、
wb.Sheets(SheetName)
がエラーになるが、On Error Resume Next
が有効なので次の処理へ変数sが空のまま次の処理へ進み、戻り値のNot s Is Nothing
はfalseになるというわけ
こんな風にOn Error Resume Next
の後、即座にOn Error GoTo 0
で無効化するパターンは応用が利きそうな気がする。
難しいコードではないのだけれど、まったく思いつかなかった。
参考
- はてなブログの Markdown で「この言語はどうやってシンタックスハイライトさせたらいい?」を考える - Corredor ⇒はてなにはvbaのシンタックスハイライトはないので、とりあえず上記を参考にvbとした
追記
5/24追記:投稿した内容のライセンスは? - ヘルプ センター - スタック・オーバーフローにも記載がある通り、Stack Overflow上の記事はCreative Commons Attribution-Share Alike でライセンスされている*2*3。なのでこの記事もライセンスに従って継承しCC-BY-SAとします(引用要件を満たしているかも微妙なので)。