Microsoft Access 掲示板

実行時エラー2501が出る。

10 コメント
views

お世話になります。


Private Sub Report_NoData(Cancel As Integer)

    Cancel = True
    
End Sub

上記のようなイベントを持つレポート(レポート名はR_Reportとします)を、
フォームに配置したボタンのクリック時イベントで開くと実行時エラーが出ます。


Private Sub btn_1_Click()

    DoCmd.OpenReport "R_Report", acViewPreview

End Sub

ボタンを押し、レポートが空ならメッセージもエラーも出さずに開かないようにしたいのですが、空データ時イベントやクリック時イベントにどのようなコードを記述するのがいいのでしょうか。

ACDC包囲網
作成: 2025/04/24 (木) 10:33:50
通報 ...
1

DoCmd.OpenReport でレポートを開くのに失敗するので実行時エラーが発生します。そういう仕様です。
エラー処理を追加しましょう。
メッセージも何も出さないのなら、

Private Sub btn_1_Click()
    On Error Resume Next
    DoCmd.OpenReport "R_Report", acViewPreview
    On Error GoTo 0
End Sub
2
ACDC包囲網 2025/04/24 (木) 11:01:43 修正 1e61d@44ebd >> 1

ボタンにこのコードを書く場合、レポートの空データ時イベントは不要ですか?
また、複数のレポートを開く場合、レポートの数だけこのエラー処理を書く必要がありますか?下記のような書き方をする必要がありますか?

Private Sub btn_1_Click()

    On Error Resume Next
    DoCmd.OpenReport "R_Report1", acViewPreview
    On Error GoTo 0

    On Error Resume Next
    DoCmd.OpenReport "R_Report2", acViewPreview
    On Error GoTo 0

    On Error Resume Next
    DoCmd.OpenReport "R_Report3", acViewPreview
    On Error GoTo 0
End Sub
3

ボタンにこのコードを書く場合、レポートの空データ時イベントは不要ですか?

必要です。ないと、空のレポートが開きます。

複数レポートの場合は、On Error Resume Next は最初に一つだけでもOKです。

Private Sub btn_1_Click()

    On Error Resume Next
    DoCmd.OpenReport "R_Report1", acViewPreview
    DoCmd.OpenReport "R_Report2", acViewPreview
    DoCmd.OpenReport "R_Report3", acViewPreview
    On Error GoTo 0
End Sub

ただ、いまさらですが、
On Error Resume Next にしてしまうと、どんなエラーでも無視してしまうので、
空データ以外のエラーが発生した場合、気がつかないので推奨しません。

コード例

Private Sub btn_1_Click()

    On Error GoTo ErrorHandler
    DoCmd.OpenReport "R_名簿", acViewPreview, , "ID=0"
    DoCmd.OpenReport "R_Report1", acViewPreview
    DoCmd.OpenReport "R_Report2", acViewPreview
    DoCmd.OpenReport "R_Report3", acViewPreview

    Exit Sub
ErrorHandler:
    Select Case Err.Number
    Case 2501 '空データエラー時
        '何もしない
    Case Else
       MsgBox "予期せぬエラーが発生しました" & vbCrLf & Err.Number & ":" & Err.Description
    End Select
End Sub
4
hiroton 2025/04/24 (木) 12:00:57 b2fe4@f966d

hiroton的にはそもそもエラーを出さないほうが好きですね
先にレポートに表示されるレコードの件数を調べて0ならレポートを開かなければいいので。VBAのエラー処理に悩まされるよりはよっぽど楽だと思います

5
ACDC包囲網 2025/04/24 (木) 12:51:42 1e61d@44ebd >> 4

わたしもできればそうしたいです。
使うのはDcountでしょうか?

6
hiroton 2025/04/24 (木) 13:11:59 b2fe4@f966d

もっとも単純な例であれば、レポートのレコードソースに指定しているクエリ(テーブル)からDcountでレコード数を取得すればいいですね

    Dim レコードカウント As Long
    レコードカウント = DCount("*", "Q出力")
    
    If レコードカウント <> 0 Then
        DoCmd.OpenReport "R_Report", acViewPreview
    End If

※レポートのレコードソースに「Q出力」を指定している場合

レポートのレコードソースの作り方によってはDAOでレコードソースを生成するなどの手法が必要になるかもしれません

7
ACDC包囲網 2025/04/24 (木) 14:11:38 1e61d@44ebd >> 6

ありがとうございます。

レポートのレコードソースはクエリビルダーで作成されているのですが、この場合はDAOというものを使う必要があるということでしょうか?

また、このパターンだと、レポートの空データ時イベントは不要になりますか?

8

エラーがでないように事前チェックするか、
エラー処理で対処するか、
どちらがいいかはその時次第でしょうね。
プログラマーの考え方にもよりますが。

空データ時でキャンセルした場合は、実行時エラー2501が出るいう仕様にMSがしたのなら、それをありがたく利用させもらうというのも選択肢の一つです。

レポートのレコードソースプロパティにSQLを設定している場合、DCountでは簡単に件数を取得できないので、
DAOで、SQLからレコードセットを生成してデータ有無を調べるという面倒なことになるので、エラー処理にするほうがシンプルでしょう。

私としては、
事前に件数を取得するためにレコードセットを開き(DCountにしろDAOにしろ)、その後、レポートでレコードセットを開くというのが2度手間という気がするので、空データ時でキャンセルするのを使うことが多いですね。

9
hiroton 2025/04/24 (木) 17:06:29 b2fe4@f966d

とりあえず回答例を載せておきます

    Dim reportName As String
    Dim rs As Recordset
    
    reportName = "R_Report"
    DoCmd.OpenReport reportName, acViewPreview, , , acHidden
    
    Set rs = CurrentDb.OpenRecordset(Reports(reportName).RecordSource, , acReadOnly)
    If rs.EOF Then
        DoCmd.Close acReport, reportName
    Else
        Reports(reportName).Visible = True
    End If
    rs.Close

※レポートの空データ時イベントは不要です

ここまでやるとなかなかめんどくさいですね。エラー処理がどういうものかきちんと理解できてるのであれば、空データ時イベント+エラー処理でもいいと思います


レポートのレコードソースをレポートとフォームのモジュール(VBA)2か所に記述することになると修正のときに困るので、結局レポートを一度開いてしまうことにしました
一度開いてしまうとレポートの表示が入るので最初は非表示で開いてから、データをチェックして表示するように

いろいろ考えてみると、いろいろ細かいことが多くてどこまで反映させるか悩みどころですね。「細かいこと」はバッサリカットです

10
ACDC包囲網 2025/04/30 (水) 08:35:34 1e61d@44ebd

お二方、ありがとうございました。
レコードソース用のクエリを作成し、Dcountでレコードがあるのか判定するのが最もシンプルに書けると思いましたので、こちらを採用しました。