• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:EnableEventsとOn Errorの違い)

EnableEventsとOn Errorの違い

このQ&Aのポイント
  • EnableEventsとOn Errorの違いについて教えてください。
  • EnableEventsとOn ErrorはVBAで使われるステートメントですが、役割としては異なります。
  • EnableEventsはイベントの発生を制御するものであり、エラーに対処するために使用されます。一方、On Errorはエラーハンドリングのためのステートメントです。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

>いずれも、エラーに対処するためのものであることはわかるのですが、役割の違いがわかりません。 違います。 EnableEventsは、エラーに対処する為の物ではありません。 「EnableEventsはエラーに対処する為の物」と言う勘違いをしているから http://okwave.jp/qa/q3037406.html の説明を読んでも理解できないのです。 Application.EnableEvents = False は「イベントプロシージャに飛ぶような事が起きても、イベントプロシージャに飛ぶな」です。 例えば、セルに値を入れて「Enter」を押すと Worksheet_Change のイベントが起きます。 ワークシートにイベントプロシージャが設定してあれば Private Sub Worksheet_Change(ByVal Target As Range) の所に飛んで来ます。 もし Private Sub Worksheet_Change(ByVal Target As Range) の中で、セルの値を書き換えると、そのイベントプロシージャの中から、自分自身が再帰的に呼ばれます。 再帰的に自分自身が呼ばれると、また、再帰的に自分自身を呼んで、の無限ループになって、最後は「メモリが足りなくて、もう呼び出せない」って言うエラーになります。 なので、セルを書き換えたら飛んでくるイベントプロシージャの中で、セルを書き換える必要が出たら Application.EnableEvents = False と指定して「もう呼ぶな」って指定してから、セルを書き換えます。 すると「セルの値が書き換わっても、イベントプロシージャに飛んでいかない」ので、セルの書き換えをしても、何も起きません。 そして、セルの書き換えが終わったら、イベントプロシージャから帰る前に Application.EnableEvents = True を行って「どこかでセルが書き換わったら、イベントプロシージャに飛んでもオッケーですよ」と、元の状態に戻すのです。

qazxcvfr4
質問者

お礼

詳しく、わかりやすい説明をありがとうございます。 ようやく理解できたと思います。

その他の回答 (2)

回答No.3

こんにちは。 実際に、マクロを書いてみて、目で見たほうが早いと思います。 1) >Application.EnableEvents = False 'イベントが発生しない、つまり入力で反応させない  ここの中で、入力をする >Application.EnableEvents = True これを入れないと、Excel のバージョンによって、かなりの回数を繰り返した覚えがあります。 たぶん時間のズレが起きるので、途中で止まるのですが、Excel 2010 では、以下のコートでは、1を入力すると97と出てきます。つまり、96回を繰り返したということです。昔のバージョンでは、リンク先のように、10,000回以上の繰り返したのかもしれません。 Private Sub Worksheet_Change(ByVal Target As Range) '■  If IsNumeric(Target.Value) Then  Target.Value = Target.Value + 1  End If End Sub ということになって、何度も何度も繰り返してしまうのです。 ■の場所に、デバッグの中のブレークポイントを置いてみれば分かります。 どっちかというと、エラー自体は、あまり発生はしないというか、VBAの保護機能なのか、途中でループが止まるようです。バージョンによって、ループの数が違うようです。もし、クラス・モジュールを使って、自分自身が複雑なイベントを作るようになると、何度も、イベントを繰り返して、手がつかなくなることもあります。イベントは、ブレークポイントを置いて、一度は再帰が起きていないか確認した方が良いと思います。再帰とは、一端、プロシージャを抜けて、再び、そこに戻ってくることを指します。 2) On Errorのステートメント (On Error Resume Next 等) こちらの話は、上級レベルになってしまうので、説明が難しくなります。ここの掲示板の回答者でも、正しく使えない人もいるようです。正しく使っている人は、少ないかもしれません。 基本的な使い方は、VBA全体に、エラーが発生して動かなくなってしまう時に使います。ユーザーにエラーが発生して、VBAが実行できなかったことを知らせたり、エラーを回避したりする時に使うもので、プログラマーとしては、そのエラー自体を把握していなければ、本来は、使うことはお勧めできないということです。また、エラーが発生した時に、どのような回避をするを考えなくてはなりません。 一般的には、「エラートラップ」と読んでいて、3つの使い方があります。 本格的なVBAを書くようになると、エラートラップは、最初から入れません。コーディングがほぼ完成し、エラーの対処の方針が決まってから、エラートラップを入れます。そうしないと、コーディングの最中では、原因と対処ができなくなってしまうからです。どんなエラーが、どこで発生しているかを把握します。それから、対処法を考えていきます。安易に入れるのは、好ましくありません。 a. On Error Goto ジャンプ先 On Error Goto 自体は、変数の型の宣言の次の行辺りに置き、全体を見渡すようにします。 そして、ジャンプ先は、主に最後の行に置きます。 ジャンプ先の名称は、一般的には、ErrorHandler という名称にしています。 主に、ActiveX や外部オブジェクトのエラーに用います。 例: Public Function IsClipboardFormat(ByVal iFormat As Long) As Boolean   Dim vFormats As Variant   Dim vFormat As Variant   IsClipboardFormat = False   On Error GoTo ErrorHandler '●   vFormats = Application.ClipboardFormats   For Each vFormat In vFormats     If vFormat = iFormat Then       IsClipboardFormat = True       Exit Function     End If   Next   Exit Function ErrorHandler: '●   Exit Function End Function 'Sub プロシージャでは、ErrorHandler の後に、MsgBox Err.Number & ":" & Err.Description を入れます。 b. On Error Resume Next 主に、Error の発生を無視させて次に進めるというものです。 基本的には、On Error GoTo 0 で、エラートラップを終わらせます。 あまりに長い範囲には用いません。例えば、図形などのオブジェクトをまとめて検索する時に、プロパティがないことがあります。その時に、それを飛び越えるために使ったりします。 例: Sub OpenLinksMacro()   Dim ar As Variant   Dim v As Variant   ar = ActiveWorkbook.LinkSources(xlExcelLinks)   If Not IsEmpty(ar) Then     On Error Resume Next '●     For Each v In ar       ActiveWorkbook.OpenLinks (v)     Next v     On Error GoTo 0 '●   End If End Sub c. Err.Raise を使ってユーザーエラーを発生させます。 上記、a. b. と同じなのですが、途中で、エラーを発生させます。 Const vbMyError As Integer = 513 で、ユーザーの任意の定数を指定します。(一般的には、513という数字だっという記憶です。既存のものとはぶつからないようにします。) Err.Raise vbMyError でエラーを発生させて、 On Error GoTo ErrorHandler の中で、 If Err.Number = vbMyError Then  MsgBox Err.Number & " " & "ユーザーエラーが発生しました。" End If などとします。 大雑把ですが、以上になります。

qazxcvfr4
質問者

お礼

On Errorのステートメントも含めて、詳しく解説していただきありがとうございました。 勉強させていただきました。

回答No.2

On Errorは、ご理解通りエラーに対処するものです。 「On Error ○○」なら「エラーが発生したら○○しなさい」ですね。 対して、EnableEventsは、イベントの発生を抑止するかどうかを切り替えるものです。 ご存じかと思いますが、Excelでは、操作やマクロ処理などにより、様々なイベントが発生します。 例えば、ExcelのBookを開くと、Workbook_Activateイベントが発生します。 イベントが発生しても、直接的に処理に影響することはないのですが、そのイベントの発生を条件に、 何かの処理を行うプロシージャなどを用意していた場合で、処理の都合上「今は処理してはいけない」と言う場合に使用します。 分かり易い簡単な例をあげてみます。 自動実行マクロ(Auto_Open)が記載されている、あるブック(以下、ブックA)があるとします。 この自動実行中マクロには「IDを入力してください」というメッセージを表示する処理が記述されています。 次に、別ブック(以下、ブックB)のマクロにおいて、ブックAを開く必要があるとします。 更に、その際「IDを入力してください」というメッセージは表示させたくないとします。 単純に、ブックBのマクロ内に、ブックAをopenする命令を記述すると、ブックAが開かれるとすぐに、Auto_Openマクロが実行され、 メッセージが表示されてしまいます。 そこで、EnableEvents = Falseとして、イベントの発生を抑止してから、ブックAを開くようにすると、 ブックAのOpenイベントが発生しなくなるため、Auto_Openマクロが実行されず、メッセージも表示されなくなります。 コードとしては、下記のような感じです。 Application.EnableEvents = False Workbooks.Open fileName:="xxx.xls" Application.EnableEvents = True

qazxcvfr4
質問者

お礼

丁寧で、わかりやすい説明をありがとうございます。 ようやく理解することができました。

関連するQ&A