none
CrystalReportsで「レポートのロードに失敗」のエラー RRS feed

  • 質問

  • お世話になります。

    VisualStudio2010

    NET.Framework4.0

    Windows7

    あるForm1からボタンクリックで、レポートプレビュー画面を3画面一度に表示させる仕組みがあります。

    レポート内容はすべて異なります。

    この処理を、Form1をCloseせずに、40回以上プレビューさせると「レポートのロードに失敗しました」とエラー表示されます。

    おそらくReportDocumentをCloseしていない事が原因と思われますが、そのCloseのタイミングに困っています。

    Form1にてボタンがクリックされるとサブモジュールにあるレポート生成処理が、3レポート分動きます。

    レポート1のビューを表示するための処理

     →サブモジュール内でCrxReport = New ReportDocument

     →サブモジュール内で、ビューワ用Form2を起動

      Dim NewForm As New Form2(CrxReport)

     →Form2内で

      Me.CRView.ReportSource = CrxReport

      ビューワ表示

    レポート2のビューを表示するための処理

     以下、レポート1と同様

    レポート3・・・以下略

    と、このような形のため、ボタンを1度クリックするだけでReportDocumentが3つ生成されるイメージを持っています。

    サブモジュール内でReportDocumentのCloseを考えましたが、ここでCloseすると、ビュー側は一見きちんと表示されているように見えますが、ページ送りをしようとすると「レポートのファイルパスが無効です」というメッセージが表示されます。

    上記のようなプログラム構成の場合、どこでCloseすべきでしょうか。

    ご助言頂ければ幸いです。


    2017年1月12日 9:53

すべての返信

  • モジュール内で表示されるというのがモーダルかモーダレスかにもよりますが、新しく表示されたFormを検出して、そのForm内にあるCrystalReportViewerを探して、そのReportSourceに対してFormが閉じられるタイミングで処理すればよいということでしょうか。

    Public Class MainForm
    #Region "モーダルの場合"
        Private prevForms As New List(Of Form)
    
        Private Sub ModalButton_Click(sender As Object, e As EventArgs) Handles Button1.Click
            prevForms.Clear()
            prevForms.AddRange(Application.OpenForms.OfType(Of Form)()) '表示される前に既に表示されているフォームの一覧を保持
    
            AddHandler Application.Idle, AddressOf app_Idle
    
            Module1.ShowReport_Modal()
    
            RemoveHandler Application.Idle, AddressOf app_Idle
        End Sub
    
        Private Sub app_Idle(sender As Object, e As EventArgs)
            'アイドル状態になる毎に新しいフォームがないか調べる
            For Each newForm As Form In Application.OpenForms.OfType(Of Form).Except(prevForms) 'LINQで差集合
                '新しく開かれたフォームが見つかったら閉じられる前に処理できるようにイベント登録
    
                AddHandler newForm.FormClosing, AddressOf newForm_FormClosing
                prevForms.Add(newForm)
            Next
        End Sub
    
    #End Region
    
        Private Sub ModelessButton_Click(sender As Object, e As EventArgs) Handles Button2.Click
            Dim prevForms As New List(Of Form)
            prevForms.AddRange(Application.OpenForms.OfType(Of Form)()) '表示される前に既に表示されているフォームの一覧を保持
    
            Module1.ShowReport_Modeless()
    
            '新しく表示されたフォームを探す
            For Each newForm As Form In Application.OpenForms.OfType(Of Form).Except(prevForms) 'LINQで差集合
                '新しく開かれたフォームが閉じられる前に処理できるようにイベント登録
                AddHandler newForm.FormClosing, AddressOf newForm_FormClosing
            Next
        End Sub
    
        Private Sub newForm_FormClosing(sender As Object, e As FormClosingEventArgs)
            Dim f As Form = CType(sender, Form)
            Dim crv As CrystalDecisions.Windows.Forms.CrystalReportViewer
            crv = FindCrystalReportViewer(f)
            If (crv IsNot Nothing) Then
                'CrystalReportViewerが含まれている
                Dim doc = TryCast(crv.ReportSource, CrystalDecisions.CrystalReports.Engine.ReportClass)
                If (doc IsNot Nothing) Then
                    'ドキュメントがあるなら閉じる
                    doc.Close()
    
                    MsgBox("レポートを閉じました")
                End If
            End If
    
    
            prevForms.Remove(f)
        End Sub
    
        Private Function FindCrystalReportViewer(ByVal ctl As Control) As CrystalDecisions.Windows.Forms.CrystalReportViewer
            Dim crv As CrystalDecisions.Windows.Forms.CrystalReportViewer = Nothing
            If (TypeOf ctl Is CrystalDecisions.Windows.Forms.CrystalReportViewer) Then
                crv = CType(ctl, CrystalDecisions.Windows.Forms.CrystalReportViewer)
            Else
                For Each child As Control In ctl.Controls
                    crv = FindCrystalReportViewer(child)
                    If (crv IsNot Nothing) Then
                        Exit For
                    End If
                Next
            End If
            Return crv
        End Function
    End Class
    
    
    Friend Module Module1
    
        Public Sub ShowReport_Modeless()
            Dim NewForm1 As New Form1
            Dim NewForm2 As New Form2
            Dim NewForm3 As New Form3
            NewForm1.Show()
            NewForm2.Show()
            NewForm3.Show()
        End Sub
    
        Public Sub ShowReport_Modal()
            Dim NewForm1 As New Form1
            NewForm1.ShowDialog()
        End Sub
    
    End Module

    個別に明示されていない限りgekkaがフォーラムに投稿したコードにはフォーラム使用条件に基づき「MICROSOFT LIMITED PUBLIC LICENSE」が適用されます。(かなり自由に使ってOK!)

    2017年1月12日 11:29
  • 返信ありがとうございます。

    ビュー用Formはモーダルではなく、メインFormもビューFormもどちらも使える状態です。

    ●ビュー画面1出力(MAINF)

     If Not (blnCRepo(plngReportOption, _
                  Trim$(ビュー用Form1に表示したいレポートファイル), _   'レポート名
                    Trim$(mstrRPT_TTL), _     'レポートタイトル
                     0, _
                     Trim$(mstrSTC_NAM), _
                     lngCounts)) Then
     End If

       

    ●サブモジュール(XZRCR2010M)

     Public Function blnCRepo(ByVal vlngDestination As Long, _
                                 ByVal vstrFileKey As String, _
                                 ByVal vstrReportTitle As String, _
                                 ByVal vlngFileType As Long, _
                                 ByVal vstrFileName As String, _
                                 Optional ByRef rlngCounts As Long = 0) As Boolean

            Dim blnRet As Boolean
            Dim strPrinterDriver As String ' プリンタドライバ名変数の宣言
            Dim strPrinterName As String   ' プリンタ名変数の宣言
            Dim strPrinterPort As String   ' ポート名変数の宣言
            Dim lngMarginTop As Long       ' 余白(上部)変数の宣言
            Dim lngMarginLeft As Long      ' 余白(左側)変数の宣言
            Dim lngMarginBottom As Long    ' 余白(下部)変数の宣言
            Dim lngMarginRight As Long     ' 余白(右側)変数の宣言

            Try
                ' クリスタルレポート初期設定

                ' 設定ファイル読み込み時のキーセクションの設定
                pstrFileLocation = vstrFileKey

                ' 出力先ファイル名の指定 ※ファイル出力時のみ フォルダ名含む[絶対パス・相対パス両方可]
                pstrExportFileName = vstrFileName

                ' タイトルの設定
                pstrFileName = vstrReportTitle

                ' プリンターへ印刷時出力先の指定
                ' クリレポで設定したプリンタを使用する場合は値を "" または コメント にして下さい
                strPrinterDriver = ""   ' プリンタドライバ名指定
                strPrinterName = ""     ' プリンタ名指定
                strPrinterPort = ""     ' ポート名指定

                ' プリンターの余白の設定
                ' 既定値使用の場合は全て 0またはマイナス
                lngMarginTop = 0
                lngMarginLeft = 0
                lngMarginBottom = 0
                lngMarginRight = 0

                blnRet = OpenReports(vlngDestination, 0, "")

            Catch ex As Exception
                blnRet = False
                MsgBox(Err.Description, vbOKOnly + vbCritical)
            Finally
                blnCRepo = blnRet
            End Try
        End Function

        Public Function OpenReports(ByVal method_mode As Long, _
                                    Optional ByVal fgDataRefresh As Long = 0, _
                                    Optional ByVal vstrPrinter As String = "") As Boolean
            ' @(f)
            '
            ' 機能  : レポートを開き、引数に基づき出力タイプを変えて出力
            '
            ' 引き数 : method_mode      :出力タイプ(REPORTS_OPTION 定数で設定)
            '           plngformula_count:レポートの引数の数を指定
            '           plngDDFPathCount :内部情報(部課ドライブ切り替えファイル数)

            Dim lngI As Long, lngJ As Long
            Dim lngPaperInfo As Long
            Dim CrxReport As ReportDocument

            OpenReports = False

            Try
                ' CR 個別レポートオープン
                CrxReport = New ReportDocument

                CrxReport.Load(pstrFileLocation, OpenReportMethod.OpenReportByTempCopy)

                If fgDataRefresh <> 1 Then
                    CrxReport.Refresh()
                End If

                ' レコード選択式設定
                If pstrSelectionFormula <> "" Then
                    CrxReport.DataDefinition.RecordSelectionFormula = pstrSelectionFormula
                End If

                ' グループ選択式設定
                If pstrGroupSelectionFormula <> "" Then
                    CrxReport.DataDefinition.GroupSelectionFormula = pstrGroupSelectionFormula
                End If

                lngPaperInfo = CrxReport.PrintOptions.PaperOrientation
                If vstrPrinter <> "" Then
                    CrxReport.PrintOptions.PrinterName = vstrPrinter
                    CrxReport.PrintOptions.PaperOrientation = lngPaperInfo
                End If

                ' パラメータ設定
                lngI = plngFormulaCount - 1
                For lngJ = 0 To lngI
                    If pary_strFormula(lngJ, 0) <> "" Then
                        CrxReport.DataDefinition.FormulaFields.Item(pary_strFormula(lngJ, 0).ToString).Text = _
                                                                    pary_strFormula(lngJ, 1)
                    End If
                Next

                'ログオン情報を適用
                For Each Table As CrystalDecisions.CrystalReports.Engine.Table In CrxReport.Database.Tables
                    Dim logOnInfo = Table.LogOnInfo
                    'logOnInfo.ConnectionInfo.DatabaseName = "データベース名"
                    logOnInfo.ConnectionInfo.ServerName = XZRXMLM.pstrHST_Name
                    logOnInfo.ConnectionInfo.UserID = XZRXMLM.pstrUSR_Name
                    logOnInfo.ConnectionInfo.Password = XZRXMLM.pstrPWD_Name

                    Table.ApplyLogOnInfo(logOnInfo)
                Next

                ' エクスポート時フォーマットタイプセット
                If pstrExportFormatType = 0 Then
                    pstrExportFormatType = ExportFormatType.CrystalReport
                End If

                ' モード別処理実行
                Select Case method_mode

         ※ここがビュー表示部分です

                    Case REPORTS_OPTION.OUTPUT_VIEWER
                        Dim NewForm As New XZRCR2010F(CrxReport)
                        With NewForm.CRView
                            .ShowCloseButton = pblnShowCloseBtn
                            .ShowCopyButton = pblnShowCopyButton
                            .ShowExportButton = pblnShowExportButton
                            .ShowGotoPageButton = pblnShowGotoPageButton
                            .ShowGroupTreeButton = pblnShowGroupTreeButton
                            .ShowPageNavigateButtons = pblnShowParameterPanelButton
                            .ShowParameterPanelButton = pblnShowParameterPanelButton
                            .ShowPrintButton = pblnShowPrintButton
                            .ShowRefreshButton = pblnShowRefreshButton
                            .ShowTextSearchButton = pblnShowTextSearchButton
                            .ShowZoomButton = pblnShowZoomButton
                            .Zoom(plngShowZoomSize)
                        End With

                        ' タイトル
                        NewForm.Text = pstrFileName
                        NewForm.Show()
                        NewForm.WindowState = FormWindowState.Maximized
                        OpenReports = NewForm.CRView.Visible
                        ' 件数取得
                        plngPageCount = NewForm.CRView.ViewCount

                    Case REPORTS_OPTION.OUTPUT_PRINTER
                        CrxReport.PrintToPrinter(1, True, 1, 2)
                        OpenReports = True

                    Case REPORTS_OPTION.OUTPUT_EXPORT
                        CrxReport.ExportToDisk(pstrExportFormatType, pstrExportFileName)
                        OpenReports = True

                End Select
            Finally
            End Try

            CrxReport.Close()
        End Function

    ●ビュー用Form(XZRCR2010F)をNewした際の処理

        Public Sub New(ByVal rpt As Object)

            InitializeComponent()
            Me.CRView.ReportSource = rpt

        End Sub

    上記を1つのくくりとして、3レポート分すべて別のビュー画面として表示しています。

    よって、3つのビュー用Formはすべて同一となります。

    XZRCR2010FがForm画面になるのですが、こちらが閉じる際に上記で言うところのCrxReportをClose出来ればいいと思うのですが、どのように参照したら良いかわからず・・・という状況です。

    2017年1月13日 1:41
  • >よって、3つのビュー用Formはすべて同一となります。

    掲載されたコードを見る限り、インスタンスは別物ですよね。

    >XZRCR2010FがForm画面になるのですが、こちらが閉じる際に上記で言うところのCrxReportをClose出来ればいいと思うのですが、どのように参照したら良いかわからず・・・という状況です。

    XZRCR2010FはCrxReportの参照を受け取っているので、XZRCR2010FのFormClosingイベントでCrxReportのCloseメソッドを実行することはできないのでしょうか?

    また、OpenReportsメソッドの最後でCrxReport.Close()を実行されていますが、これは必要ないように思いますが、いかがでしょうか?


    ★良い回答には回答済みマークを付けよう! MVP - .NET  http://d.hatena.ne.jp/trapemiya/

    2017年1月13日 7:27
    モデレータ