EnableEventsとOn Errorの違い

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

EnableEventsとOn Errorの違い

エクセル2010を使っている者ですが、VBAのことでお教えください。 Application.EnableEvents = False Application.EnableEvents = True といった、EnableEventsステートメントと、On Errorのステートメント (On Error Resume Next 等)は、役割としてどう違うのでしょうか。 いずれも、エラーに対処するためのものであることはわかるのですが、 役割の違いがわかりません。(特に、EnableEventsについては、以下の URLの回答を見ても理解できません) http://okwave.jp/qa/q3037406.html よろしくお願いいたします。

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

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8524/19375)
回答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

  • (少数点、第三位から切り捨て)をこのマクロにどう入力すればいいですか??

    四捨五入を切捨て(第三位)するにはどうしたらいいのでしょうか?? VBAをちゃんと理解できていないので、誰か分かる人助けてください!! ついでにROUNDDOWNとかの関数はVBAに入力するコードとしては、 まったく別物なんでしょうか??初心者が生意気言ってすいません・・・。 Private Sub Worksheet_Change(ByVal Target As Range) On Error Resume Next Application.EnableEvents = False If Range(Target.Address).Column = 2 And _ Range(Target.Address).Row >= 5 And _ Range(Target.Address).Row <= 10 Then Range(Target.Address).Value = _ Range(Target.Address).Value / 19 End If Application.EnableEvents = True End Sub よろしくおねがいします・・。 カテゴリー間違えて入れなおしました。すみません・・。

  • (少数点、第三位で切り捨て)をしたいんですが、このマクロに何を足せばいいですか??

    四捨五入を切捨て(第三位)するにはどうしたらいいのでしょうか?? VBAをちゃんと理解できていないので、誰か分かる人助けてください!! ついでにROUNDDOWNとかの関数はVBAに入力するコードとしては、 まったく別物なんでしょうか??初心者が生意気言ってすいません・・・。 Private Sub Worksheet_Change(ByVal Target As Range) On Error Resume Next Application.EnableEvents = False If Range(Target.Address).Column = 2 And _ Range(Target.Address).Row >= 5 And _ Range(Target.Address).Row <= 10 Then Range(Target.Address).Value = _ Range(Target.Address).Value / 19 End If Application.EnableEvents = True End Sub よろしくおねがいします。

  • EnableEventsの意味は

    VBAを勉強中の初心者です。 Excelでプロシージャの中に書かれている次の文は、どういう意味を持っているのですか。 Application.EnableEvents = False '処理命令文 Application.EnableEvents = True EnableEventsとは、何を可能にさせると言っているのでしょうか。 = Falseとは、何が違うと言っているのでしょうか。 割り込み禁止で、ここで処理が実行されている間は、他の余分なことは受け付けないと言っているのかと勝手な想像もしていますが、どうでしょうか。 教えて下さい。よろしくお願いします。

  • マクロのコードについて

    いつも大変お世話になっております。 https://okwave.jp/qa/q9884968.htmlにて、質問した者です。 回答してくださった方のとおりにやってみたのですが、背景の色が消えません。 Sub ボタン1_Click() If Application.Intersect(Selection, Range("A1:F3")) Is Nothing _ Or Selection.Count > 1 Then Exit Sub End If Application.EnableEvents = False Selection.Interior.Color = xlNone Application.EnableEvents = True End Sub 上記のように教えていただき、コピペしてやってみたのですが、背景の色は変わらなかったです。 私のやり方がだめでしょうか? マクロのボタンを作成し、コードを入力しました。 エラーも出たので、エラー検索し https://okwave.jp/qa/q9885232.html 上記も設定済です。 回答してくださった方々には大変失礼なことを聞いているのもわかっています。本当に申し訳ございません。

  • Onってなんでしょうか?

    私は現在、VB6を使用してプログラム開発を行っています。 「On Error」ステートメントに関して質問させていただきます。 私の管理下のソースに、   (1)「On Error Goto [行ラベル]」   (2)「On Err Goto [行ラベル]」 の2種類のステップがあり、 (2)に関しての動作が不明で困っています。 (要は「On [Object] Goto [行ラベル]」と記述した場合に、  どのように解釈されるのか分らないのですが・・・  (1)、(2)共にコンパイルは通りますが(2)の場合はエラーハンドリングはできません。) <質問> (1)「On Err Goto [行ラベル]」 と記述した場合、  どのような条件でGotoが実行されるのでしょうか?  (Errはエラーオブジェクトです) (2)「On」は   ・「On Error Goto [行ラベル]」   ・「On Error Resume Next」   ・「On Error Goto 0」  以外に使用する方法があるのでしょうか?

  • エラー処理

    環境:IIS,ASP(VBScript) サーバー Windows2000Server ASP超初心者です。 処理の途中でエラーになっても On Error Resume Next と If Err.Number then ........ を組み合わせればうまく逃げられるのはわかるの ですが、On Error Resume Nextを書いてもエラー が表示されて落ちます。 #include file の中についてはOn Error Resume Nextは無効なのでしょうか?

  • 【VBA】On Error をつけても「Match

    【VBA】On Error をつけても「Matchプロパティを取得できません」を回避できません。  今晩は、質問させていただきます。どうぞよろしくお願いいたします。 環境:エクセル2010でございます。  下のようにコーディングしておりますが、「Matchプロパティを取得できません」が出てコード実行が中断されてしまいます。 取得できなかった場合の対処は既に(更にその下に)コーディングしておりますので、Matchのエラーをスルーさせたいのですが。。。 On Error GoTo error1 line1 = (Application.WorksheetFunction.Match(strTime, WS_data.Range("G:G"), 0))          '↑この行でエラーになります。 error1: On Error GoTo 0  On Error GoTo error1をOn Error Resume Nextに変えても同じ症状になってしまいます。 もしお詳しい方がいらっしゃいましたらアドバイスいただけないでしょうか。  どうぞよろしくお願いいたします。

  • VBAの日付チェックでオーバーフローを回避したい。

    VBAの日付チェックでオーバーフローを回避したい。 ExcelのG列のセルに入力されたものが日付型であるかどうかのチェックかけたいと思います。 以下のコードだと、数字2958466以上の入力でオーバーフローが発生します。 これを回避する方法はありますか? セルを日付型に設定しているため、2958465(2999/12/31)までしか判別できないのでしょうが、 利用者が2958466以上を入力してしまう可能性はあります。 オーバーフローではなく、エラーメッセージが出せたら・・・と思います。 Private Sub Worksheet_Change(ByVal Target As Range) If Target.Column = 8 Then Application.EnableEvents = False If Target <> "" And Not IsDate(Target) Then MsgBox "日付型で入力してください。" & vbCrLf & "(例:2010/10/31)", vbCritical, "入力エラー" Target = "" Target.Select End If Application.EnableEvents = True End If End Sub こんなコードも試しましたが、結果は同じでした。 ↓ Private Sub Worksheet_Change(ByVal Target As Range) If Target.Column = 8 Then Application.EnableEvents = False If Target > 2958466 Then MsgBox "日付型で入力してください。" & vbCrLf & "(例:2010/10/31)", vbCritical, "入力エラー" Target = "" Target.Select Else If Target <> "" And Not IsDate(Target) Then MsgBox "日付型で入力してください。" & vbCrLf & "(例:2010/10/31)", vbCritical, "入力エラー" Target = "" Target.Select End If End If Application.EnableEvents = True End If End Sub On Error Resume Next や On Error GoTo ... での対処も考えましたが、同じ結果でした。 何か良い方法がありましたら、お願いいたします。

  • アクセス イベントの発生を停止させたい

    アクセスでイベントを発生しないようにしたいのですが エクセルで使用できる、Application.EnableEvents = Falseを使うと、 コンパイルエラーになります。 フォームを指定して、 .FilterOn = True を通ると、 該当のフォームのPrivate Sub Form_Current()イベントが発生してしまうので、 Application.EnableEvents = Falseのように、イベントの発生を停止させたいです。

  • Excelの三つのVBAを一つにまとめる。

     初めまして、よろしくお願いします。当方全くの素人でVBAの基礎もよくわからず、ネットから拾ってきていじった三つのVBAがあります。この三つ、一つ一つは個別に機能するのですが、VBAとして正しいのかさえよく解っていません。この三つを一つにまとめて、同時に機能するようにしたいと頭を抱えています。 Sub TEST() Application.ScreenUpdating = False Application.EnableEvents = False ActiveSheet.Calculate Range("b10:b20").Insert shift:=xlShiftToRight Range("b10:b20").Value = Range("a10:a20").Value Application.OnTime TimeValue("09:00:00"), "TEST" Application.ScreenUpdating = True Application.EnableEvents = True ActiveWorkbook.Save End Sub ________________________________________________________________ Sub TEST1() Application.ScreenUpdating = False Application.EnableEvents = False ActiveSheet.Calculate Dim myCnt As Long Range("c30:c40").Copy Range("d30:d40").PasteSpecial Paste:=xlPasteValues Range("b30:b40").Copy Range("c30:c40").PasteSpecial Paste:=xlPasteValues Range("a30:a40").Copy Range("b30:b40").PasteSpecial Paste:=xlPasteValues nextTime = Now() + TimeValue("01:00:00") Application.OnTime nextTime, "TEST1" Application.ScreenUpdating = True Application.EnableEvents = True ActiveSheet.Calculate ActiveWorkbook.Save End Sub ________________________________________________________________ Sub TEST2() Application.ScreenUpdating = False Application.EnableEvents = False ActiveSheet.Calculate Dim myCnt As Long Range("c50:c60").Copy Range("d50:d60").PasteSpecial Paste:=xlPasteValues Range("b50:b60").Copy Range("c50:c60").PasteSpecial Paste:=xlPasteValues Range("a50:a60").Copy Range("b50:b60").PasteSpecial Paste:=xlPasteValues nextTime = Now() + TimeValue("00:10:00") Application.OnTime nextTime, "TEST2" Application.ScreenUpdating = True Application.EnableEvents = True ActiveSheet.Calculate ActiveWorkbook.Save End Sub ________________________________________________________________  解る方、よろしくお願いします。

専門家に質問してみよう