VBA技術解説
コーディングとデバッグ

ExcelマクロVBAの問題点と解決策、VBAの技術的解説
公開日:2013年5月以前 最終更新日:2019-10-05

コーディングとデバッグ


VBA開発での効率的なコーディングと、プログラム作成では避けて通れないデバッグについて説明します。
また、
陥りやすい間違い、よくやってしまう間違い等も説明しておきます。


効率的なコーディング

プロシージャーの移動
コール先のSubプロシージャーやFunctionプロシージャーに移りたい場合があります。
その場合は、
プロシージャー名を右クリックし「定義」
「表示」→「定義」(Shift+F2)
以上のいずれかで移動できます。

元に戻る場合は、
右クリックし「元の位置へ移動」
「表示」→「元の位置へ移動」(Ctrl+Shift+F2)
VBA 基礎

VBA 基礎

右上のプルダウンのモジュールを選択しても移動可能です。
VBA 基礎
Ctrl+↓で、1つ下のプロシージャーに移動します。
Ctrl+↑なら、1つ上のプロシージャーに移動します。

単語の選択
マクロVBAを書いていると頻繁にコピペします。
特に長い単語などは効率良くコピペします。

各単語となる、モジュール、オブジェクト、プロパティ、メソッド等をダブルクリックすると、全体が選択状態になります。
これをコピペします。

マウスを使用しない場合は、Shift+→等での選択となります。
うまく活用すれば、スペルミスを減らせます。

入力候補の表示方法1
「Ctrl+Space」で、その場所で入力可能な候補が表示されます。
矢印キーで選択し、「Tab」で、入力されます。
何も記述していない場所などでは、大量の候補が出ますが、
文字を入力していけば、その文字で始まる候補に絞られていきます。

入力候補の表示方法2
Range("A1").
と、「.」を入力した時点で、次の入力候補が表示されます。
後は方法1と同じです。

インデント・・・超重要
「ツール」→「オプション」でタブの量を設定できますが、初期値の4のままで使うことをお勧めします。
理由は、他の人と共有したときに同じ設定が良いからです。
もちろん、同じように変更している人の間ならそれで良いでしょう。

インデントは絶対に正しく行って下さい。
見た目の美しさだけでなく、バグの減少にも大いに貢献します。

For i = 1 To 10
If i = 1 Then
J = J + 1
Else
If J = 2 Then
K = 1
Else
K = 2
End If
End If
Next
For i = 1 To 10
  If i = 1 Then
    J = J + 1
  Else
    If J = 2 Then
      K = 1
    Else
      K = 2
    End If
  End If
Next

説明の必要がありませんね、どっちが良いか一目瞭然です。

インデントは「Tab」キーで行います。
Tabで右へ、Shift+Tabで左へ移動します。
この操作は、複数行を選択していれば、一気にインデントされます。

行の継続
「 _」、スペースに続けてアンダーバーを書くことで、行の継続が出来ます。
Cells(1, 1) = Cells(1, 1) & _
      "○○"
むやみにやるのは、かえって見づらくなりますので適宜改行します。
目安としては、横スクロールせずに全体が見えるようにしておく事を基本に考えれば良いでしょう。
画面解像度により1行に入る文字数が違いますので、文字数では一概にはいえませんが、
見やすくするために、適宜改行をいれるようにします。

その他
メニューにいろいろな機能があります。
自分で使いやすい、
マウス操作、ショートカットを見つける事が重要です。

そして最も重要な事は、コードの使い回しです。
これに勝るものはありません。
逆に言えば、使い回しができるコーディングをするように心がけるということになります。
最初は、苦労しますが、後にそれが財産となります。

デバッグ

メニューのデバッグ
VBA 基礎

どういうものがあるか一通りめを通しておきましょう。

VBAプロジェクトのコンパイル
一般には文法チェックと思われている事が多いのですが、正確には少し違うようです。
コンパイルによって、Pコード(説明省略)が作成される云々という話もありますが、気にする必要はないでしょう。

コンパイルでは、VBA全体の文法チェックが行われます。
つまり、実行することがない仮に書いたプロシージャーもチェックされるということです。
それは、VBA全体をきれいにすることに役立ちます。
他人に渡す場合は、コンパイルしてきれいにしてから渡しましょう。
また、コンパイル後に何も変更していない場合は使用不可になっています。

ステップイン(F8)
プログラムを1ステップづつ進めます。
Call先のSubモジュールや、Functionの中にも入り、1ステップづつ進みます。
全てのステップを確認する場合に使用します。

ステップオーバー(Shift+F8)
Call先のSubモジュールや、Functionの中には入りません。
元のプロシージャーを1ステップづつ進みます。
今実行しているプロシージャーの動作のみ確認する場合に使用します。

ステップアウト(Ctrl+Shift+F8)
今実行しているプロシージャーを抜けて、呼び出し元に戻ります。
ステップインでモジュールに入った時に、急ぎ呼び出し元の次ステップに進みたい場合に使用します。

カーソル行の前まで実行(Ctrl+F8)
言葉通り、カーソル行の前まで実行一気に進みます。
ただし、ブレークポイントがあれば、そこで止まります。

ウォッチ式の追加
ウォッチ式の編集(Ctrl+W)
クイックウォッチ(Shift+F9)
ウォッチ式については、多くの機能があるので、ここでは簡単に説明します。

マクロ実行中に、変数やプロパティの内容を監視できます。
監視したい変数やプロパティを式として、ウォッチ式に追加します。
式には、以下のようなものが指定できます。
・変数
・プロパティ
・変数およびプロパティを使った式

使い方が少し面倒なので、必ずしも使う必要はありません。
まずは以下に記載した、イミィディエイト ウインドウをしっかりつかえるようになってください。
ただし、
ピンポイントで監視したい変数がある時はとても便利で強力な機能なので、
いずれは使えるようになってください。

ブレークポイントの設定/解除(F9)
コードウインドウの左のグレー部分をクリックでも設定出来ます。
押すことにより、設定⇔解除が繰り返されます。

VBA 基礎

この茶色(色はオプションで変更可能)の行が、ブレークポイントを設定した行になります。
変数定義などの行には設定できません。
マクロの実行が、ブレークポイントを設定したステップで中断します。

すべてのブレークポイント解除(Ctrl+Shift+F9)
文章そのままですね。

次のステートメントの設定(Ctrl+F9)
次のステートメントの表示
さすがに使う必要があるとは思えませんので説明を省きます。

プログラムが小さいうちは、全ステップをステップインで実行することも可能ですが、
プログラムが数千になった場合、実際の実行ステップはその数倍になり、
全てをステップインで実行することは、現実的に不可能になりますし、時間の無駄です。

プログラムだけを見ていても、最初は何が悪いのか分からないと思います。
特に、エラーにはならないが、結果が正しくないといった場合です。

そのような場合は、以下の方法を試みて下さい。

1.VBEのウインドウを小さくして、バックにエクセルの画面が見えるようにして下さい。
2.まずは入口となるモジュールの先頭ステップにブレークポイントを設定
3.そしてマクロを実行(F5)して下さい。
4.バックのエクセルの動きを良く見て下さい。
5.あっ、この辺だという所があるはずです。
6.問題のありそうなステップの少し前にブレークポイントを設定、2.のブレークポイントは解除
7.再度マクロを実行(F5)して下さい。
8.ブレークポイントで中断後は、まずはステップアウトで進む。
9.問題のステップを特定して下さい。
10.SubモジュールやFunctionの場合は、ここでステップインに変更。
11.また、ステップアウトで進みます。
12.4.以降を繰り返す。

こうして問題のステップを特定していきます。
もちろん、複数のSubモジュールの不整合によるバグも多いので、そうそうこんな単純には行きません。
ただ、お伝えしたいのは、「急がば回れ」ということです。
問題を特定せず、感を便りに適当に直したりすると、かえって状態を悪くします。
(経験を重ねれば、感で、多分ここだなというのも分かるようにはなってきますが)
ただし、
ステップ実行の途中でも、エクセルを触ることが出来てしまいます。
選択シートを変更したり、選択セルを変更してしまうと、
それが原因で、プログラムが正しく動作しなくなる場合があるので注意して下さい。
アクティブシート以外を見る為にシート選択を変更した場合は、元のシートに戻すようにして下さい。
ただし、アクティブシートに頼らないコーディングが望ましいのですが、完全にはなかなか難しいと思います。

イミディエイト ウインドウ(Ctrl+G)

「表示」→「イミィディエイト ウインドウ」
変更していなければ、VBEの画面の右下に表示されます。
他のウインドウも含めてフロー化が出来ますが、やめたほうが良いでしょう。

VBA 基礎

ステップ実行中に、このウインドウで変数等の値を見る事が出来ます。
(マクロを実行していなくても使えるのですが、それについては別途説明します。)

「?変数」と入力し、Enter すると、その下に値が表示されます。

セル等を指定しても構いません。
「?Cells(1, 1)」 アクティブなシートの指定セルの値が表示されます。

「?Worksheets(2).cells(3,3)」 このようにすれば、
アクティブではないセルの内容も確認出来ます。

「?Range("A1:B10")」 この指定はエラーとなります。
単純に言えば、(ただ一つの)値を表示出来ない指定はエラーとなります。

「?Functionプロシージャー名(引数)」
Functionの戻り値が単なる値であれば表示されます。
戻り値がオブジェクトの場合はプロパティを指定するか、値が1つだけの場合に限定されます。
つまり、Functionでも、戻り値が、(ただ一つの)値を持つなら表示可能です。

Debug.Print 対象
とVBAで書くことで、これが実行されると、
イミディエイトウインドウに、対象の値を表示できます。
対象は、上で説明したエラーとならない指定をしてください。

ローカル ウインドウ

現在のプロシージャ内で宣言されているすべての変数およびその値が自動的に表示されます。

ローカル ウィンドウが表示されている場合、
実行から中断モードに遷移したときには自動的に表示が更新されます。

詳しい機能や使い方については、以下を参考にしてください。

ローカルウィンドウの使い方
VBAのエディター、VBEにはいくつかのウィンドウがあります、その中で、ローカルウィンドウの使い方の説明です、これが使えないと、配列やオブジェクトを扱ったVBAのデバッグに困ることになります。サンプルコードは、以下の表を使っています。まずは、配列でのローカルウィンドウの使い方について。

「ツール」→「オプション」

前述したインデントのタブ間隔等は、このオプションで変更できます。
ただし、
特別な理由が無い限り標準で使用して下さい。
自分一人で全て完結するならまだしも、他の人と関わるなら特殊な設定はしない方が良いです。

「全般」タブにある、「エラートラップ」は、かなりVBAを習得してから変更してください。
必まずは、「エラー処理対象外のエラーで中断」にしておいて下さい。
これを変更すると、プログラム内でのエラートラップが正常に動作しなくなります。

陥りやすい間違い、よくやってしまう間違い

Dim i1, i2 As Integer
これですと、i1はVariantになってしまいます。

If A = 1 Or B = 1 And C = 1 Then
これは、どんな条件になるのでしょうか?
優先順は、And > Or が基本ですが、もしこの結果が正しいとしても、書いてはいけません。
必ず、()を付けて
If A = 1 Or (B = 1 And C = 1) Then
このように、優先順を明示して下さい。

If オブジェクト = ○○ Then
これは文法エラーです。
If オブジェクト Is ○○ Then
このようにIsを使います。

With Sheet(1)
  Cells(1, 1) = 1
End With
このCellsは、アクティブシートのセル参照になってしまいます。
かならず先頭に「.」を付けて、「.Cells」とします。

名前付引数
メソッド(引数1, 引数2, ・・・)
メソッド(名前1:=引数1, 名前2:=引数2, ・・・)
どちらでも通りますが、複数の引数がある場合は、名前付を使用するようにしましょう。
上では、引数の順序を全て正しくしていとなければなりません。
注意点は、「:=」とコロンを忘れずに。
Findメソッド
引数が多いので、省略できるものは省略して良いでしょう。
ただし省略した場合、前回時の指定が引き継がれます。
エクセルでの検索にも影響を受けるので、
複数個所で使用している場合は極力全て指定したほうが良いでしょう。
[Application.]WorksheetFunction.VLookup
Application.VLookup
どちらも、基本的には同じですが、下は古い書き方になります。
現在は、上を使用して下さい。
検索値が見つからない場合の動作に違いがあります。
上は、エラーで停止しますが、下なら戻り値を判定出来ます。
ですが、下を使ってのエラー対処は、どうかな?・・・と思うところもあります。
上でも、エラートラップすれば良いのです。

この他にも、
最終行の取得方法で、たまに間違いというか勘違いかなと思える時もあります。
この話は長くなりそうなので、また別の機会に。
その他いろいろありますが、
一度正しく書いたコードの使い回しをすれば、すこしずつ減ってくるはずです。

サイト内の関連ページ

ローカルウィンドウの使い方
VBAのエディター、VBEにはいくつかのウィンドウがあります、その中で、ローカルウィンドウの使い方の説明です、これが使えないと、配列やオブジェクトを扱ったVBAのデバッグに困ることになります。サンプルコードは、以下の表を使っています。まずは、配列でのローカルウィンドウの使い方について。

デバッグの基礎|MOS VBAエキスパート対策
・【ここでのポイント】 ・デバッグとは ・論理エラーと文法エラー ・イミディエイトウィンドウ ・ブレークポイント ・ステップ実行 ・その他のデバッグ用のウィンドウ ・【業務改善の実務】 ・【本サイト内の関連ページ】 ・VBAエキスパート公式テキスト



同じテーマ「マクロVBA技術解説」の記事

VBAとは、マクロとは
コーディングとデバッグ
ローカルウィンドウの使い方
WorksheetFunctionについて
RangeとCellsの深遠
Offset、Resizeを使いこなそう
値渡し(ByVal)、参照渡し(ByRef)について
最終行・最終列の取得方法(End,CurrentRegion,SpecialCells,UsedRange)
ユーザー定義関数の作り方
セルの値について(Value,Value2,Text)
Excelのバージョンを判断して「名前を付けて保存」


新着記事NEW ・・・新着記事一覧を見る

ブール型(Boolean)のis変数・フラグについて|VBA技術解説(2024-04-05)
テキストの内容によって図形を削除する|VBA技術解説(2024-04-02)
ExcelマクロVBA入門目次|エクセルの神髄(2024-03-20)
VBA10大躓きポイント(初心者が躓きやすいポイント)|VBA技術解説(2024-03-05)
テンキーのスクリーンキーボード作成|ユーザーフォーム入門(2024-02-26)
無効な前方参照か、コンパイルされていない種類への参照です。|エクセル雑感(2024-02-17)
初級脱出10問パック|VBA練習問題(2024-01-24)
累計を求める数式あれこれ|エクセル関数応用(2024-01-22)
複数の文字列を検索して置換するSUBSTITUTE|エクセル入門(2024-01-03)
いくつかの数式の計算中にリソース不足になりました。|エクセル雑感(2023-12-28)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
3.RangeとCellsの使い方|VBA入門
4.ひらがな⇔カタカナの変換|エクセル基本操作
5.繰り返し処理(For Next)|VBA入門
6.変数宣言のDimとデータ型|VBA入門
7.ブックを閉じる・保存(Close,Save,SaveAs)|VBA入門
8.並べ替え(Sort)|VBA入門
9.セルのクリア(Clear,ClearContents)|VBA入門
10.Findメソッド(Find,FindNext,FindPrevious)|VBA入門




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。


このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ