ExcelVBAのバッドノウハウ

# 概要
ExcelVBAでありがち、やめとけ、な `ExcelVBAあるいはVB系特有` のバッドノウハウをまとめてみます。

# 背景
ちょっと前に、ひっでぇ野良マクロの改修をやったので。
身近に初学者さんが現れたので。ちょっと書けるようになった頃に見てもらおうと思ってます。
私も独学組なので、思いもしないバッドノウハウを踏んでたらこの機会に気づけたらいいななどと思ったりなんかして

# 予防線
書き始め当初は`ExcelVBA特有の` としてました。
ですが、VBAって基本VBらしいですし、私は「VB」は知らないので、境界がよくわかりません。
何より今回最悪のバッドノウハウとして扱う `On Error` もどうやらVB由来のものみたいです。
とうわけで `VB系特有` を足しました。
VBガチ勢の方からすると境界の曖昧さがむず痒いかもしれませんがご容赦ください。。。

# 評価指標
影響度を星1つ～5つで評価します。
段階分けしたのはぶっちゃけ、 `On Error` 系を最上位という扱いにしたかったがためです。
★ と ★★ は、4段階って微妙に切りが悪いなと思ったので無理やり分けました。

|評価|基準|
| --- | --- |
|★★★★★|致命的な問題の主因になりうる(エラーがあっても正常終了しちゃうので結果が間違っていてもわからない、改修難易度が爆上がりする、など)|
|★★★★☆|利用者に余計な手間がかかるかもしれない|
|★★★☆☆|ほかの開発者(将来の自分も含む)に余計な負荷を強いるかもしれない|
|★★☆☆☆|実害はないかもしれないが、好ましくない|
|★☆☆☆☆|実害はないかもしれないが、好ましくない。けど、VBA始めたての頃は仕方ないかもしれない|

# 以下、本題

## ★★★★★

### On Error Resume Next を処理全体に適用する
【概要】
これをやると、あらゆるエラーの発生時に、処理を止めることなく、エラーメッセージを出すことなく、次の文に処理を進めることができる。

【ありがち事例】
コードの不備によるエラーを、不備を解消することなく、これを使って回避する。しかも `On Error GoTo 0` で戻せばまだいいのにそれすらしない。

【弊害】
エラーを無視して進める時点で、その先で発生する副次的不具合の可能性が無限大である。
これを使ったコードが下手に稼働実績を得ると、`untatchable code` が爆誕してしまう。

【コメント】
「想定外があった時などは、結果が間違っていてもいいからとにかく止まらず完了してほしい」という要件があれば、使ってもいいのかもしれません。その場合は「改修が不可能になる可能性が高いので、その場合は新規で作り直す」という言質も取っておいたほうがいいと思います。

### On Error GoTo xxx によるエラーハンドルが中途半端

【概要】
On Error GoTo により、エラー発生時処理をすることができる。

【ありがち事例】
On Error GoTo で飛ばした先で、エラー内容ごとの処理を定義するが、そこに漏れがある。
具体的には、 `Select Case Err.Number` をやっておいて `Case Else` がない場合など。

【弊害】
漏れてしまうとエラーが起こったことがわからないので、折角のエラー処理が、逆に問題の迷宮入りを促してしまう。

## ★★★★☆

### 回避可能な参照設定
【概要】
VBAのコードの一部には、Excelの設定で追加設定しないと実行できないものがある。が、その一部は、コードの書き方によって、追加設定しなくても動くものがある。代表例は `FileSystemObject` 。

【ありがち事例】
設定したほうが便利なので普通に設定する

【弊害】
たまに利用者の環境によってエラーが起こることがある

【コメント】
参照設定したほうがコードは書きやすいわけですが、それを「配布時に、参照設定しなくても動くように戻す」というのは忘れがちというか面倒なんですよね。。。というわけで私は自分のPCでも参照設定してないです。

### 回避可能なCopyとPaste

【概要】
「コピー」と「ペースト」ができるので、自分が操作する感覚をコードに反映しやすい。

【ありがち事例】
コピーとペーストを駆使しまくる

【弊害】
コピーとペーストは実際にクリップボードを使っている。
そのため、処理時間のかかるマクロの場合、その間利用者がほかの作業でコピーペーストを行うと、マクロの動作と競合する。
自分がコピーしたものと違うものがペーストされることもあるし、もしかしたらマクロ側でも同じことが起こってるかもしれない。

【コメント】
クリップボードを使わなければできない処理というのも存在するようです。（知るところでは、他アプリへの貼り付けなど）
クリップボードを使うマクロの場合は、以下をしておきましょう。
・利用者に、動作中はクリップボードを使わないよう伝える
・それでも使われてしまうかもしれないので、コピーしたらできるだけすぐペーストするようにして、入れ替わりの可能性を下げる
（私の場合「今コピペだめ」って意識したとしても、その10秒後には「あ」とかなります。マクロ側の結果に影響したことは今のところないですが、自分の作業が壊れたことは何度かあります。。。）


## ★★★☆☆

### Option Explicitなし
【概要】
モジュール先頭でOption Explicit宣言をしなかった場合、宣言していない変数を使用することができる。

【ありがち事例】
コードを修正するなかで、変数宣言のタイミングがおかしくなってエラーになったりして、根本解決することなくOption Explicitを削除してしまう

【弊害】
値が入っていない変数を用いてしまうと、予測しない結果になってしまう。

### Workbook未指定のWorksheet指定、Wosksheet未指定のRange/Cells指定
【概要】
指定しなければ、暗黙にActiveworkbook,Activesheetが指定される。

【ありがち事例】
書いてるときはどれがアクティブかとか明確なので略してしまう

【弊害】
複数ブック・複数シートを跨ぐ処理の場合、あとから見た人にはどれがアクティブかが分かりづらい。
作ったマクロを「これを全シートにやるように拡張しよう」「これをフォルダ内の全ブックにやるように拡張しよう」みたいな話になったとき、拡張に手間取りやすい

【コメント】
「指定しないほうが速い」って聞いたことがある気がします。でも軽く試した限りでは、高速化テクニックとして検討できるほどの差は検出できませんでした。

## ★★☆☆☆

### 回避可能なvariant型宣言
【概要】
variant型は、どんな型も格納できる。そのほか、 `For Each xxx in Collection` や `多次元配列` など、variant型でないとだめな場面もある。

【ありがち事例】
variantでないとだめな場合以外でも、型を決めるのが面倒でvariantにしてしまう。

【弊害】
コードの可読性が落ちる(型が決まっているほうが誤解の可能性が減る)。また、型が分かれるなら本来は処理を分けるべきで、それをしないことで雑なコードになる。

【コメント】
variant絶対許さないマンになりたいのに、variantじゃないと駄目な場面があるのつらい

## ★☆☆☆☆

### マクロ記録で保存したコードをそのまま使う
【概要】
マクロ記録によって生成されたコードは、同じ結果を得るためにはお手軽な手段である。

【ありがち事例】
生成されたコードにはマクロとしては不要なコードも含まれているのだが、それを取捨選択することなく採用してしまう

【弊害】
あとからコードを見た人は、それが一括採用したコードなのか取捨選択の結果残ったコードなのかが判別しづらい。
余計なコードが大量に含まれるため、可読性が下がる。

【コメント】
そもそも初学者それ以降で、「記録」の用途が違うんだなとふと思いました。
初学者は「コードの原型を作る」なので、記録したものをそのままループに突っ込んだりするんだろうなと。うん自分もやってたかも。
そこそこ書けるようになってからは、「この機能はどう書けばいいのか」を調べるために記録をして、その先はリファレンス見ながら、っていう用途になるんじゃないかなと。

# あとがき

あとから思いついたら足します。