長年VBAを使い続けた結果、異世界転生した人が書いたVBA入門記事その6です。まずはVBAの基礎を身に付けて、Pythonにステップアップしましょう。→VBAユーザーのためのPython入門 ~xlwingsでExcelからPythonを呼び出す~
記事一覧
- Excel VBA入門 ~その1 Excel VBAとは~
- Excel VBA入門 ~その2 最初のプログラム~
- Excel VBA入門 ~その3 基礎1~
- Excel VBA入門 ~その4 基礎2~
- Excel VBA入門 ~その5 Tips~
- Excel VBA入門 ~その6 アンチパターン~
アンチパターンとは
良くないコードの書き方。これをやると後の人が困るのでやらないこと。
マクロの記録で作成したコードをそのまま使用
読みにくいコードが生成されるため、そのまま利用すると保守が辛くなる。行いたい操作を実現するための方法(オブジェクトやそのメンバーの使い方)の確認に留めるべき。
'アンチパターン
Sub Macro1()
Sheets("Sheet1").Select
Range("C4").Select
ActiveCell.FormulaR1C1 = "芦川先生"
ActiveCell.Characters(1, 2).PhoneticCharacters = "アシカワ"
ActiveCell.Characters(3, 2).PhoneticCharacters = "センセイ"
Range("C5").Select
End Sub
'修正例
Sub Macro1()
Sheets("Sheet1").Range("C4").FormulaR1C1 = "芦川先生"
End Sub
アクティブなブックやシートを前提
書かれているコード以外のものに、コードの動作が依存してしまうため。
'アンチパターン
'シートを追加し、追加されたシートの"A1"セルに値入力
Worksheets.Add
Range("A1").Value = "がんばれ元気"
'修正例
Dim newWS as Worksheet
set newWS = Thisworkbook.Worksheets.Add
newWS.Range("A1").Value = "がんばれ元気"
シートを番号で指定
シートに限らず、番号は何なのか分からなくなるので使わない。
'アンチパターン
Worksheets(1).Range("A1").Value = "シャーク堀口"
'修正例(シート名で)
Thisworkbook.Worksheets("登場人物").Range("A1").Value = "シャーク堀口"
'修正例(オブジェクト名で(プロパティ ウィンドウから事前に設定しておく))
wsChara.Range("A1").Value = "シャーク堀口"
クリップボードにコピー&ペースト
クリップボードはOSで共有しているため、タイミングが悪いとユーザー操作でExcel以外でコピーしたものが貼り付けられてしまう。オブジェクトのメンバーを適切に使えばクリップボードへのコピーは回避できることが多いため、極力避ける。
'アンチパターン
ws.Range("A1:C3").Copy
ws.Range("E1:G3").Select
Selection.Parent.Paste
'修正例
ws.Range("E1:G3").Value = ws.Range("A1:C3").value
モジュールレベル変数(グローバル変数)を使う
モジュールレベル変数とは、プロシージャーや関数の外で定義された変数。他の言語ではグローバル変数と言う。グローバル変数はほとんどの場合用いるべきではない(=害を多く生み出す)とされている。
使ってはいけない理由:
- プロシージャーや関数の入出力がわからなくなるため、コードが理解しづらくなる
- コードが理解しづらくなるため、保守が難しくなる
- 大量に使用した場合、メモリーがオーバーフローし、ブックを開くだけでExcelが落ちる
- その他はこちら
モジュールレベル定数なら使ってもOK:
Const 定数名 As データ型 = 値
関数や変数を使わず連続コピペ
少なくとも変数は使用して欲しい。
1回しか使わないのに変数を使う
1回しか使わないなら変数を使う意味がない。ただし、読みやすさのためならOK(例:関数の引数が大量にある場合、個々の引数を変数に格納した上で関数に渡す)
データ整形
データ整形用の機能が最初から備わっているPandasやPower Queryを使用する。
帳票作成
VBAで帳票の特定のセルにちまちま値を入力するのはNG。
Excelの関数と組み合わせるようにする。例えば、VBAは特定のシートの特定のテーブルに結果を出力するだけにしておいて、帳票はそのテーブルやそのテーブルを元にしたピボット テーブルからExcelの関数で取得するようにする。
参考
みんな苦労しているんだなぁ('A`)
- Excel VBA に対する防衛術
- なぜVBはC#と比べて駄目なのか(これはVBだけど)