C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

エラー処理について

[トピック内 12 記事 (1 - 12 表示)]  << 0 >>

■103695 / inTopicNo.1)  エラー処理について
  
□投稿者/ マクベス (1回)-(2025/05/28(Wed) 08:04:14)

分類:[.NET 全般] 

プログラム中にエラーが発生するとエラー処理を行うために
On Error GoTo ***
を追加します。
この後デバッグ中にエラーが出ると
エラーの行がわからないので
On Error GoTo 0
をエラー発生している箇所の前につけたのですが
エラーが発生している行で止まりません。

仕方がないので毎回
On Error GoTo ***
の行をコメントにしてデバッグをしています。
コメントの付け忘れや外し忘れなどをしたり
とても面倒です。

をエラー発生している箇所の前に
On Error GoTo ***
を元に戻すほうほうはありますか?

private sub 〜
 On Error Goto ERROR
call func1(**)
ERROR:
 MsgBox("エラー")
End Sub

private function func1(**) as Boolean
' これを追加してもエラー行で止まらず
' [エラー]のメッセージボックスが表示される
'   ↓
 On Error Goto 0   

 (ここでエラーが発生している) ←エラーが出ている箇所で止めたい

End Function

引用返信 編集キー/
■103696 / inTopicNo.2)  Re[1]: エラー処理について
□投稿者/ WebSurfer (2953回)-(2025/05/28(Wed) 09:49:11)
No103695 (マクベス さん) に返信

「.NET 全般」のタグが付いてますが、.NET アプリの話ではなく VBA の話ですか?

.NET アプリの例外処理の話なら try/catch/finally を利用するという話になるは
ずです。

例外の推奨事項
https://learn.microsoft.com/ja-jp/dotnet/standard/exceptions/best-practices-for-exceptions

引用返信 編集キー/
■103697 / inTopicNo.3)  Re[2]: エラー処理について
□投稿者/ マクベス (2回)-(2025/05/28(Wed) 09:56:17)
No103696 (WebSurfer さん) に返信
>
> 「.NET 全般」のタグが付いてますが、.NET アプリの話ではなく VBA の話ですか?

ごめんなさい。
タグのつけ間違いです。

OS:windows11
version:Excel2016
VBAマクロです。

引用返信 編集キー/
■103698 / inTopicNo.4)  Re[1]: エラー処理について
□投稿者/ 魔界の仮面弁士 (3848回)-(2025/05/28(Wed) 10:00:14)
2025/05/28(Wed) 10:05:45 編集(投稿者)

(書いているうちに No103696, No103697 が投稿されていたようで…)

No103695 (マクベス さん) に返信
> プログラム中にエラーが発生するとエラー処理を行うために
> On Error GoTo ***
> を追加します。

投稿時の分類が、
> 分類:[.NET 全般]
になっていますが、これは本当でしょうか?
[VB6 以前] や [Microsoft Office 全般] では無いのでしょうか?

VB6 や VBA であれば、On Error GoTo がしばしば利用されますが、
VB.NET においては本来、On Error GoTo は非推奨の構文です。


元質問のコードを見ると、
「MsgBox ("エラー")」 ← VBA 的な構文
ではなく、
「MsgBox("エラー")」 ← VB.NET 的な構文
と書かれていることから、VBA でははなく本当に VB.NET である可能性も捨てきれないですね。

とはいえ、「private function func1(**) as Boolean」という記述からすると、
これは単に掲示板に直書きしただけで、実際のコードと一致するものでは無いのでしょうけれども。


> この後デバッグ中にエラーが出ると
> エラーの行がわからないので
まず、VB.NET であるなら、On Error は使わず、Try - Catch による構造化例外処理を行うべきです。
これならば、例外時の Exception の StackTrace からエラー発生個所を調べることができます。

どうしても On Error を用いる場合、ソースに行番号を付与しておくと、
Erl 関数から「最後に通過した行番号」を得られます。(VBA でも VB.NET でも)
行番号が無い場合は 0 を返します。調査目的の機能なので、普段から使うようなものでは無いですが。

とはいえ On Error GoTo でジャンプしないということは、そもそものエラー発生個所が想定と違っていたか、
あるいは実行プログラムとソースコードのバージョン乖離という可能性もあるかと思います。


第三者が事象を再現可能な、最低限の短い実験用ソースコードを用意することはできますか?
頂いた情報だけでは、現在の状況が今一つ掴み切れずにいます。


> On Error GoTo 0
> をエラー発生している箇所の前につけたのですが
> エラーが発生している行で止まりません。
これは、ステップ実行した場合も同様なのでしょうか?

もしも VBA であるのなら、[ツール]-[オプション]設定の [全般]タブにて、
エラートラップモードを変更してみてください。
 ・エラー発生時に中断
 ・クラス モジュールで中断
 ・エラー処理対象外のエラーで中断


> private function func1(**) as Boolean
> ' これを追加してもエラー行で止まらず
> ' [エラー]のメッセージボックスが表示される
> '   ↓
『[エラー]のメッセージボックス』を表示しているのは、
func1 の方では無く、Sub の方なのですよね?

エラー発生個所で止める以前の問題として、

call func1(**)
ERROR:
 MsgBox("エラー")

ではなく、

call func1(**)
Exit Sub
ERROR:
 MsgBox("エラー")

にしておくべきなのでは。
引用返信 編集キー/
■103699 / inTopicNo.5)  Re[1]: エラー処理について
□投稿者/ WebSurfer (2954回)-(2025/05/28(Wed) 10:03:29)
No103695 (マクベス さん) に返信

【追記】

VB.NET(Visual Basic .NET)でも、On Error Goto が使用できないわけではないそう
ですが、VB6 時代の前世紀の遺物的なものを使うのは止めて、Try〜Catch を使った処
理 (構造化例外処理) を行った方が良さそうです。

参考:

VB 6プログラマーのためのVB.NET入門 第14回 エラーと例外処理
https://atmarkit.itmedia.co.jp/fdotnet/vb6tonet/vb6tonet14/vb6tonet14_01.html

引用返信 編集キー/
■103700 / inTopicNo.6)  Re[3]: エラー処理について
□投稿者/ WebSurfer (2955回)-(2025/05/28(Wed) 10:07:54)
No103697 (マクベス さん) に返信

> OS:windows11
> version:Excel2016
> VBAマクロです。

レスが前後してしまいました。

VBA は全く分かりません。お役に立てずすみませんが、他の方の回答をお待ちください。
引用返信 編集キー/
■103701 / inTopicNo.7)  Re[3]: エラー処理について
□投稿者/ とくま (28回)-(2025/05/28(Wed) 13:45:26)
No103697 (マクベス さん) に返信
そもそもの考え方として、予想できるエラーには事前チェック処理を自分でプログラムして、エラーが発生するより
前に例外メッセージを表示させるから、エラー処理しなければいけないのは、完全に予想できなかったシステムエラー
くらいになって、場所は自ずと予測できるから必要ないのかも。
逆に、ダラダラ何の対策も考えずに、超絶長いソースコードが書かれた既存システムを担当させられた時は多少思ったかな。
でも大まかな処理ブロックごとにログ入れて、ある程度絞れたら、その処理ブロックの先頭からステップ実行しないと
前後関係も含めて分かり難いから、そこまで必要に思ったことが無いです。

https://excel-ubara.com/excelvba4/EXCEL_VBA_415.html
https://packpak.hatenablog.com/entry/2022/08/21/010717
やるとしても、すでに上がっているErl関数とかを使って、しっかりログを取るのが主流みたいですね。

引用返信 編集キー/
■103702 / inTopicNo.8)  Re[2]: エラー処理について
□投稿者/ マクベス (3回)-(2025/05/29(Thu) 07:52:39)
No103698 (魔界の仮面弁士 さん) に返信

>エラートラップモードを変更してみてください。
こういう設定があったんですね。

>エラー発生個所で止める以前の問題として
エクセルには try〜catch〜finaly がないので
正常な時も、異常な時も同じ後処理が必要な場合を
考えて同じコードを2か所に書きたくなかったので
以下のようなプログラム構造にしました。

private Sub 〜

     :
 Dim wbbok as Workbook
 Dim msg as string: errmsg = ""

 On Error GoTo ERROR
 msg = "処理が終了しました。"
     :
ERROR
 if errmsg = "" then
  ' エラー処理
  errmsg = "エラー"
 End If
 msgbox(msg)

' 何らかの影響で開かれたままのブックを閉じる
if wbook is null = false then wbook.Close

End Sub
引用返信 編集キー/
■103703 / inTopicNo.9)  Re[2]: エラー処理について
□投稿者/ マクベス (4回)-(2025/05/29(Thu) 08:00:17)
エラートラップモードが
 ・エラー処理対象外のエラーで中断
担っていたので
 ・エラー発生時に中断
に変更すると止まるようになりました。


解決済み
引用返信 編集キー/
■103704 / inTopicNo.10)  Re[3]: エラー処理について
□投稿者/ マクベス (5回)-(2025/05/29(Thu) 08:05:41)
エラートラップモードを
 ・エラー発生時に中断
に変更すると
止まってほしくない
On Error Resume Next
で止まってしまうんですね。

On Error Resume Next
Set ws = ThisWorkbook.Worksheets("Sheet1")
If Err.Number = 0 Then ws.Delete

次に進まなくなる。
引用返信 編集キー/
■103705 / inTopicNo.11)  Re[4]: エラー処理について
□投稿者/ 魔界の仮面弁士 (3849回)-(2025/05/29(Thu) 10:04:57)
No103703 で解決済みになっていたフラグが
No103704 で解除されているようなので、
解決済みに戻しておきます。

No103702 (マクベス さん) に返信
>> エラー発生個所で止める以前の問題として
> エクセルには try〜catch〜finaly がないので

VBA でのエラー復帰は Resume ステートメントを使う設計なので、
エラー有無によらず実行させるような Finally 句に該当する構文は無いですね。

Try〜Catch〜Finally を VBA で無理矢理に真似ようとすると、こんな感じになってしまうかな…。


Sub Qux()
  Dim a As Variant
Try:
  On Error GoTo Catch
  a = [Sheet1!A1].Value / [Sheet1!A2].Value
  MsgBox a, vbInformation
  'Exit Sub
  GoTo Finally
Catch:
  MsgBox "Error: " & CStr(Err.Number) & "(0x" & Right(String(8, "0") & Hex(Err.Number), 8) & ") on [" _
   & Err.Source & "]" & vbCrLf & Err.Description, vbExclamation
Finally:
  MsgBox "終了しました"
End Sub



No103704 (マクベス さん) に返信
> エラートラップモードを
>  ・エラー発生時に中断
> に変更すると
> 止まってほしくない
> On Error Resume Next
> で止まってしまうんですね。

「エラー発生時に中断」を選択していた場合には、
On Error Resume Next でも
On Error Resume 行番号 でも
On Error Resume 行ラベル でも
すべて、一時停止状態になります。
あえて停止させるための『エラー発生時に中断』モードですからね。

このモードは、プロシージャー内でエラーが握りつぶされているなどしていて、
呼び出し元で発生していた本来のエラーを捉えられなくなっているような場合において
調査目的・改修目的で使われたりします。

通常は「クラス モジュールで中断」もしくは「エラー対象外のエラーで中断」で良いと思いますが、
デバッグ中にもエラー トラップ モードは変更できますので、その時々で使い分けてください。

ただ、Err オブジェクトの状態は更新されているはずなので、一時停止中に
インジケーターバーの 黄色矢印 を手動ドラッグして次の行に移動させることで、
On Error Resume Next 相当のステップ実行動作とみなすことはできるでしょう。

※インジケーターバーを非表示にしている場合は、[ツール]-[オプション]画面から
 [エディターの設定]タブの [インジケーター バー]の設定を on にしておきます。
解決済み
引用返信 編集キー/
■103706 / inTopicNo.12)  Re[3]: エラー処理について
□投稿者/ 魔界の仮面弁士 (3850回)-(2025/05/29(Thu) 11:01:36)
書き忘れ。

No103702 (マクベス さん) に返信
> Dim msg as string: errmsg = ""
「Dim msg As String: msg = ""」なのでは?

msg と errmsg が別変数であるというのだとしても、
msg 宣言行で errmsg を初期化するというのも、いささか不自然かと。


>  On Error GoTo ERROR
個人的には、行ラベルの名前を大文字 ERROR にすることはお奨めしません。

標準の VBA.Conversion モジュールに同名の「Error 関数」「Error$ 関数」があるため、
大文字 ERROR を定義してしまうと、これらを使った既存のコードが(他者が書いたものも含めて)、
Error ではなく ERROR 表記に補正されてしまい、見栄えが悪くなってしまうためです。

Error は予約語というわけでは無いですし、文法的には問題無いのですが…
殆どの場合、こうした大文字小文字は同一視されるとはいえ、
標準で用意されているものと同じ名前の物を定義するときは、気を使った方が良いと思います。


>  msg = "処理が終了しました。"
>      :
> ERROR
>  if errmsg = "" then
>   ' エラー処理
>   errmsg = "エラー"
>  End If
>  msgbox(msg)

行ラベルのコロンを書き漏らしているのはさておき、
エラー処理ルーチン部の前には、Exit ステートメントを置いておかないと、
エラーが無い時も、そのままパススルーで実行されてしまいますよ。

そもそも上記の場合、「MsgBox errmsg」ではなく「MsgBox msg」なわけで、
サンプルコードであるとしても、意図がさっぱり読み解けない…。

> ' 何らかの影響で開かれたままのブックを閉じる
> if wbook is null = false then wbook.Close

「If wbook Is Null = False Then」は、VBA の文法的にあり得ません。
Is 演算子に対しては、必ずオブジェクトを渡す必要があるからです。
Null は予約語であるため、null という名前のオブジェクト型変数を用意することもできないはず。

「If Not wbook Is Nothing Then」とか
「If Not IsNull(wbook) Then」なら分からなくも無いですが…。
解決済み
引用返信 編集キー/

このトピックをツリーで一括表示


トピック内ページ移動 / << 0 >>

このトピックに書きこむ