Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(Windows 11 Home : Excel 2016)
エラー回避(2)
投稿日時: 23/12/10 22:22:53
投稿者: shimoichimabu

先ほど、「エラー回避」の返信を確認できました。
やはり、WinArrowさんでした。
回答ありがとうございます。
 
’@シート名の桁数で、絞り込みます。 
’この段階で「2018.3追加」は対象外になります。
’A数字だけのシート名で、絞り込みます。
’この段階で「マスター」は対象外になります。
これらも、すでに確認しました。
 
シートの名前のパターンはこれ位です。
 

投稿日時: 23/12/10 22:31:43
投稿者: shimoichimabu

追伸
 
On Error 〜 の注意点について、教えて頂きありがとうございました。
 
On error goto 〜 も使ったのですが、うまくいかず、ひょっとして1回しか実行できない?
今回のようなLOOPするようなケースでは、使えないのでしようか?

回答
投稿日時: 23/12/10 23:52:24
投稿者: WinArrow

最初の質問時のコードで、解説します。

引用:

For Each Sheet名 In Worksheets
On Error Resume Next
    If Sheet名.Name * 1 >= 2018 Then
        ・・・・・・・
        ・・・・・・・
    End If
On Error GoTo 0
Next

 
このコードでは、ループの中で
設定(Resume Next)し,
解除(Goto 0)していますよね?
 
でも、途中のどこかで、エラーが発生しても
それを判断するコードがありません。
従って、エラーが発生しても、何もなかったかのように終了してしまいます。
エラーがどこで発生したかを検知するためには、
エラーになりそうなところ(または、全てのステップ)にエラー検知のコードが必要になります。
 
このような事態を避けることから、(Resume Next)は、注意して使う必要があります。
 
(Resume Next)でhなく、ラベルを使って、そのラベルへ飛ばし、
そこで、エラー解析をして、戻るか/中止するか決めます。
致命的なエラーだったら、戻っても仕方がないので中止ですね・・・
 
 
 

投稿日時: 23/12/11 00:14:16
投稿者: shimoichimabu

WinArrowさん、回答ありがとうございます。
 
>ラベルを使って、そのラベルへ飛ばし、
>そこで、エラー解析をして、戻るか/中止するか決めます。
 
↓こういうコードですか?
 
For Each Sheet名 In Worksheets
On error goto エラー
    If Sheet名.Name * 1 >= 2018 Then ← 今回のケースではこの部分のみでエラーが発生する
        ・・・・・・・
        ・・・・・・・
    End If
Next
 
エラー:
 
ここで、エラー解析?
 
On Error GoTo 0
 
Resume Next

回答
投稿日時: 23/12/11 09:05:00
投稿者: WinArrow

>↓こういうコードですか?
 
イメージとしては、その通りです。
 
エラートラップを、デバッグツール(エラーの原因を把握し、バグをなくする)
として使用することは、問題がありません。
それにより開発者のスキルアップにもつながることにもつながります。
 
ですが、何のためにプログラムを作成しているのか?
という観点で考えると、
本番運用のプログラムにエラートラップが組み込んであるということは、
ユーザー(そのプログラムを使用して業務する人)にエラー対応を期待していることになります。
エラートラップを組み込んだから"安心"と考えてはいけません。
 
 
 

投稿日時: 23/12/12 12:03:56
投稿者: shimoichimabu

WinArrowさん、ご提言ありがとうございます。
 
最初の質問時のコードで、WinArrowさんがご提示された「ラベルを使って、そのラベルへ飛ばし、・・・」の方法で向学のために実際にTESTコードを書いてみました。
 
Dim N As Long
 
For N = 1 To Worksheets.Count
 
On Error GoTo エラー
 
    If Worksheets(N).Name * 1 >= 2023 Then
        MsgBox Worksheets(N).Name
    End If
 
err2:
 
    On Error GoTo 0 ← この位置の記述でOK?
 
Next
 
If N = Worksheets.Count + 1 Then Exit Sub
 
エラー:
 
Resume err2
 
End Sub
 
上記のコードを実行すると、とりあえずは問題なく終了しました。
WinArrowさんから見て、かなり強引・冗長と思われるコードと思われますが・・・。
WinArrowさんから提示されたNumeric、CLngを使った方法がわかりやすかったです。
 
On Error GoTo 0の使い方ですが、
「VBAの「On Error GoTo 0」の意味は、エラー処理を通常通りに戻すことです。
通常通りとは、エラーが発生すれば、エクセルでエラー発生ウィンドウを表示させることです。
エラー無視したい区間の終わりに、必ず、「On Error GoTo 0」を使用して下さい。」
と記載されていました。
いまいち、私は正確に理解できていませんが、On Error GoTo 0を記述する場所は上記の所でよろしいでしようか?

回答
投稿日時: 23/12/12 14:13:21
投稿者: WinArrow

「On Error 」を「エラーを無視する」と考えているとしたら、
少し違うと思います。
  
場合によっては、そのような場合もあります。
  
例1.シートを指定する処理において
@当該ブックに存在するシートをループして探す方法
   For Each sht In .Sheets
      If sht.Name = "○○" Then
 デメリット:シート数が多いと処理時間が掛かる。
  
A直接シートをしている場合
    On Error Resume Net
    Set Sht= ActiveWorkbook.SHeets("○○")
   On Error Goto 0
   If Sht Is Nothing then
    シートが存在しないときの処理
  
※Aは@のデメリットの代案として紹介しているWebページがあります。
 しかし、○○がプログラマのコーディングミス、
  メンテナンスで、○○シートを名前変更した、削除したかもしれない。
  どのような理由があっても業務が止まってしまいます。
  安易にOn Errorに逃げてはいけない。
  
プログラマの範疇で発生するエラーについては、逃げていけない。という考えです。
  
プログラマの範疇外のエラー
HDDが急に壊れた、通信ができなくなった・・・・というような事態を指します。    
 

回答
投稿日時: 23/12/12 14:43:53
投稿者: 半平太

>※Aは@のデメリットの代案として紹介しているWebページがあります。
 
別に捻り出した代案でもないし、逃げてもいない。
 
VBAの仕掛けを有効活用して、○○シートの有無を調べているだけです。
業務が止まる訳でもないです。
 
あと、On Error Resume Next の前に、
Set Sht = Nothing を入れて置く必要がある。
さもないと、それ以前に何かしら有効なWorksheetを参照していた場合、
それが維持されて、Nothing判定が無意味になる。

回答
投稿日時: 23/12/12 16:42:39
投稿者: WinArrow

引用:

あと、On Error Resume Next の前に、
Set Sht = Nothing を入れて置く必要がある。

半平太さん、ご指摘りがとうございました。
 
 

投稿日時: 23/12/12 19:15:39
投稿者: shimoichimabu

WinArrowさん、半平太さん、貴重なご意見ありがとうございます。
 
今回、色々なことが勉強になりました。
エラー対処について宿題として、もっと調べてみます。