Excelでテーブルを循環しようとしています。この表の最初の3列にはテキスト見出しがあり、残りの列には見出しとして日付があります。これらの日付を日付型変数に順番に割り当て、日付に基づいていくつかの操作を実行したい
これを行うには、myTable.ListColumnsでforeachループを使用しています。最初の3つの列には日付ヘッダーがないため、ループを設定して、ヘッダー文字列を日付型変数に割り当てる際にエラーが発生した場合、ループが次の列に直接進むようにしました。
これは最初の列で機能するようです。ただし、2番目の列のヘッダーがdate-type変数に「割り当てられている」場合、マクロはエラー処理ブロック内にあるにもかかわらずエラーが発生します
Dim myCol As ListColumn
For Each myCol In myTable.ListColumns
On Error GoTo NextCol
Dim myDate As Date
myDate = CDate(myCol.Name)
On Error GoTo 0
'MORE CODE HERE
NextCol:
On Error GoTo 0
Next myCol
繰り返しになりますが、エラーはループの第2ラウンドのステートメントでスローされます
myDate = CDate(myCol.Name)
On Errorステートメントが機能しなくなる理由を説明できる人はいますか?
示されているコードでは、next
ステートメントを実行したときのエラー処理ルーチンはwithinであるとみなされています。
つまり、現在のエラーハンドラから再開するまで、後続のエラーハンドラは許可されません。
より良いアーキテクチャは次のとおりです。
Dim myCol As ListColumn
For Each myCol In myTable.ListColumns
On Error GoTo ErrCol
Dim myDate As Date
myDate = CDate(myCol.Name)
On Error GoTo 0
' MORE CODE HERE '
NextCol:
Next myCol
Exit Sub ' or something '
ErrCol:
Resume NextCol
これにより、通常のコードからのエラー処理が明確になり、別のハンドラーをセットアップする前に現在実行中のエラーハンドラーが終了することが保証されます。
このサイト には問題の説明があります:
エラー処理ブロックとエラー時Goto
エラーハンドラーとも呼ばれるエラー処理ブロックは、On Error Goto <label>:
ステートメントを介して実行が転送されるコードのセクションです。このコードは、問題を修正してメインコードブロックで実行を再開するか、プロシージャの実行を終了するように設計する必要があります。 On Error Goto <label>:
ステートメントは、行をスキップするだけでは使用できません。たとえば、次のコードは正しく機能しません。
On Error GoTo Err1:
Debug.Print 1 / 0
' more code
Err1:
On Error GoTo Err2:
Debug.Print 1 / 0
' more code
Err2:
最初のエラーが発生すると、実行はErr1:
に続く行に移動します。エラーハンドラーは、2番目のエラーが発生したときにまだアクティブであるため、2番目のエラーはOn Error
ステートメントによってトラップされません。
エラー処理が終わったことを示すために、エラー処理コードにある種のresume
を追加する必要があります。それ以外の場合、最初のエラーハンドラはまだアクティブであり、「解決」されることはありません。
http://www.cpearson.com/Excel/errorhandling.htm を参照してください(具体的には「エラー処理ブロックとエラー後処理」という見出しと次のセクション)
Paxdiabloの受け入れられた回答のフォローアップ。これは可能で、同じサブで2つのエラートラップを次々に許可します。
Public Sub test()
On Error GoTo Err1:
Debug.Print 1 / 0
' more code
Err1:
On Error GoTo -1 ' clears the active error handler
On Error GoTo Err2: ' .. so we can set up another
Debug.Print 1 / 0
' more code
Err2:
MsgBox "Got here safely"
End Sub
On Error GoTo -1
を使用すると、アクティブなエラーハンドラーがキャンセルされ、別のエラーハンドラーをセットアップできます(そしてerr.clear
はこれを行いません!)。これが良いアイデアであるかどうかは、読者の課題として残されていますが、うまくいきます!
Errオブジェクトのすべてのプロパティ設定をクリアすることは、エラーハンドラーをリセットすることとは異なります。
これを試して:
Sub TestErr()
Dim i As Integer
Dim x As Double
On Error GoTo NextLoop
For i = 1 To 2
10: x = i / 0
NextLoop:
If Err <> 0 Then
Err.Clear
Debug.Print "Cleared i=" & i
End If
Next
End Sub
OPと同じように、i =1
しかし、i = 2
、使用したのはErr.Clear