アプリ版:「スタンプのみでお礼する」機能のリリースについて

次のスクリプトで”Select Case Workbooks(saki).Worksheets(z).Name”のところで変数zに存在しないワークシートのインデックスが入った時にはエラーが出るので、On Erroe Goto で回避しようと思うのですができません(そのままマクロが止まってしまう)。
なぜ回避できないのか教えてください。 また回避するいい方法があれば教えてください。



Private Sub UserForm_Activate()

moto = Cells(2, 5)
saki = Cells(1, 5)
For z = 1 To 50
On Error GoTo e0
Select Case Workbooks(moto).Worksheets(z).Name
Case "検索"
Case "結果"
Case "エフ"
Case "ツール"
Case "記憶"
Case Else
On Error GoTo e0
UserForm3.ComboBox1.AddItem Workbooks(moto).Worksheets(z).Name
End Select
Next

e0:
For z = 1 To 50
On Error GoTo e1
Select Case Workbooks(saki).Worksheets(z).Name    ’ここでエラーが出る(実行時エラー'9' インデックスが有効範囲にありません)
Case "検索"
Case "結果"
Case "エフ"
Case "ツール"
Case "記憶"
Case Else
On Error GoTo e1
UserForm3.ComboBox2.AddItem Workbooks(saki).Worksheets(z).Name
End Select
Next
e1:
End Sub

A 回答 (4件)

zの値が、有効範囲を超えないようにすれば良いと思います。



>For z = 1 To 50

For z = 1 To Workbooks(moto).Worksheets.Count

にしたらどうですか。

この回答への補足

早速やってみたらうまくいきました。Countプロパティと言うものがあったとは、気づきませんでした。
今までエラーが出そうなところは大体 On Errorで処理しようとしていましたが、言われるとおりエラーを回避する前にエラーを出さないようにすると言う手もありますね。
またひとつ勉強になりました。ありがとうございます。

問題は解決しましたが、なぜエラートラップできないのか疑問なので、引き続き質問を受付けます。

補足日時:2004/03/08 00:01
    • good
    • 0

#3 さんの回答で全てOKだと思いますが、せっかく書いたので、、、(^^;


ループ部分の処理は殆んど同じようなので、こんな書き方もありかな?

Private Sub UserForm_Initialize()
Dim wb1 As Workbook, wb2 As Workbook
 On Error Resume Next
 Set wb1 = Workbooks(ActiveSheet.Cells(2, 5).Value)
 If Not wb1 Is Nothing Then AddCombo wb1, Me.ComboBox1
 Set wb2 = Workbooks(ActiveSheet.Cells(1, 5).Value)
 If Not wb2 Is Nothing Then AddCombo wb2, Me.ComboBox2
End Sub

Private Sub AddCombo(wb As Workbook, cmb As ComboBox)
Dim ws As Worksheet
 For Each ws In wb.Worksheets
  Select Case ws.Name
  Case "検索", "結果", "エフ", "ツール", "記憶"
  Case Else
     cmb.AddItem ws.Name
  End Select
 Next ws
End Sub

> エラーを出さないようにすると言う手もありますね。

こちらの考えを優先するべきだと思います。

この回答への補足

こちらはちょっと高度なやり方ですか。
私のあまり使うことのないコードがあったりしますね。
VBA初心者の私ではいろいろと調べないと理解できないです。すみません。
回答ありがとうございました。

補足日時:2004/03/08 01:49
    • good
    • 0

>On Erroe Goto で回避しようと思うのですができません



質問のコードでは『e0』に飛んでいるだけですね。いわゆる『goto』の意味合いです。
ヘルプには、On Erroe Goto line は『引数 line に指定した行から始まるエラー処理ルーチンを有効にします』とあります。e0から始まるエラー処理ルーチンでエラーに対する処理を行わず、再度エラーが発生しトラップできなくなってます。

エラー処理としては、代表的にはResumeステートメントでしょうか。


●エラーが出なくなるように書き換えてみました。(重複部分を少し訂正しています)

Private Sub UserForm_Activate()
  Dim moto As String, saki As String
  Dim z As Integer

  moto = Cells(2, 5)
  saki = Cells(1, 5)

  On Error GoTo e0
  For z = 1 To 50
    Select Case Workbooks(moto).Worksheets(z).Name
      Case "検索", "結果", "エフ", "ツール", "記憶"
      Case Else
      UserForm3.ComboBox1.AddItem Workbooks(moto).Worksheets(z).Name
    End Select
  Next

e0_re:
  On Error GoTo e1
  For z = 1 To 50
    Select Case Workbooks(saki).Worksheets(z).Name
      Case "検索", "結果", "エフ", "ツール", "記憶"
      Case Else
      UserForm3.ComboBox2.AddItem Workbooks(saki).Worksheets(z).Name
    End Select
  Next

  Exit Sub

e0:
  Resume e0_re
e1:

End Sub


●このような処理の場合、『On Error Resume Next』の方が分かりやすいでしょう。

Private Sub UserForm_Activate()
  Dim moto As String, saki As String
  Dim z As Integer

  moto = Cells(2, 5)
  saki = Cells(1, 5)

  On Error Resume Next

  For z = 1 To 50
    Select Case Workbooks(moto).Worksheets(z).Name
      Case "検索", "結果", "エフ", "ツール", "記憶"
      Case Else
        UserForm3.ComboBox1.AddItem Workbooks(moto).Worksheets(z).Name
    End Select
  Next

  For z = 1 To 50
    Select Case Workbooks(saki).Worksheets(z).Name
      Case "検索", "結果", "エフ", "ツール", "記憶"
      Case Else
        UserForm3.ComboBox2.AddItem Workbooks(saki).Worksheets(z).Name
    End Select
  Next
End Sub


●エラー処理ルーチンは不要ですね。
 #1さんの Worksheets.Count や下のようにFor Each で書けます。
 個人的には UserForm_Activate よりは UserForm_Initialize を使っています。
 
Private Sub UserForm_Initialize()
  Dim moto As String, saki As String
    moto = Cells(2, 5)
    saki = Cells(1, 5)
    
  Dim ws As Worksheet

  For Each ws In Workbooks(moto).Worksheets
    Select Case ws.Name
      Case "検索", "結果", "エフ", "ツール", "記憶"
      Case Else
        UserForm3.ComboBox1.AddItem ws.Name
    End Select
  Next

  For Each ws In Workbooks(saki).Worksheets
    Select Case ws.Name
      Case "検索", "結果", "エフ", "ツール", "記憶"
      Case Else
        UserForm3.ComboBox2.AddItem ws.Name
    End Select
  Next
End Sub

コピーですむので長くなりました。

この回答への補足

いろいろなやり方ありがとうございます。
VAB入門とかいうような本では On Error GoTo でエラー処理するように書いてありますが、こういう場合は On Error Resume Next のほうがいいようですね(ヘルプを見てもそう載っていました)

補足日時:2004/03/08 02:03
    • good
    • 0

「エラー処理ルーチンの中で発生した実行時エラーは


当該のプロシージャでは救済されません。」

ご質問のコードでは、
上段のForループの中でエラーが発生した場合、
ラベルe0:の「エラー処理ルーチン」に飛んで下段のForループが
実行されますが、ここでいくら「On GoTo e1」を宣言しても
上記の理由で、e1:ラベルには飛んでくれません。
このプロシージャを抜けて呼び出し元で「実行時エラー」になります。

ちなみに上段のForループをすべてコメントアウトして実行すると
e1:ラベルがエラー処理してくれます。

ご質問のコードのままで対処するならば、#1さんの方法は正解だと思います。

(以後の文は私見ですので読み流してください)
ただ、このプロシージャの目的が2つのブックのシートを「必ず一度は検査する」
ことにあるようなので、そういったメインの処理をエラールーチンにいれるのは
問題があると思います。万一、別の事由のエラーが発生した場合も下段のForループが
実行されてしまい、そこでまたエラーが発生すればもう救済されませんし、
エラーが起こらなかったとしても、処理内容の整合性が疑われるかもしれません。

#1さんの方法を使えば、エラー処理を使わなくてもスッキリ記述できると思います。

この回答への補足

なるほど・・・ラベルへ飛んだ先ではその後すべてがエラー処理ルーチンとみなされてしまうのですね。それで2重にエラー処理はできないよという考え方ですね。分かりやすい回答でしたありがとうございます。

補足日時:2004/03/08 01:56
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!