共用方式為


處理 Crystal 報表引擎的例外狀況

當您透過應用程式執行 Crystal Reports 時,有時候 Crystal 報表引擎可能會造成例外狀況。當例外狀況發生時,可能會出現錯誤對話方塊,或造成報表停止處理。以下是例外狀況的部份原因:

  • 報表引擎無法連接到資料庫。原因可能是資料庫位置或傳遞給報表引擎的登入參數不正確,也可能是因為其他的資料庫錯誤,例如別的使用者將資料表鎖定,資料庫引擎安裝不正確,或資料表已毀損。
  • 傳遞給參數的資料不正確。如果參數從程式碼或使用者輸入所接收的資料不正確,可能會造成報表停止執行。例如,將字串值傳遞給數值參數便會使報表停止執行。
  • 在 Crystal Reports 公式中發現錯誤。如果報表中有一個公式無法正常進行驗算,便會發生例外狀況。原因可能是公式中的語法不正確或是其他的程式設計錯誤,例如除以零的錯誤。
  • 報表引擎無法開啟報表。如果指定的檔案名稱或路徑不正確、選取的不是 Crystal Report,或報表已毀損,便會發生這個錯誤。

您可以選擇由 Crystal 報表引擎自行處理例外狀況並顯示自己的錯誤訊息,也可以由您自己來處理例外狀況。用程式設計的方法來處理例外狀況有以下這些優點:

  • 您可以自訂顯示給使用者看的錯誤訊息。例如,當報表無法連接到資料來源時,可以不要顯示「登入失敗」,而改為顯示更完整的訊息,例如「提供的登入參數不正確,無法連接到資料庫」。這麼做可為使用者提供較為詳細的資訊。
  • 您可以將事件寫入應用程式的記錄檔。您可以選擇將錯誤訊息、錯誤 ID、發生時間及其他相關資訊寫入記錄檔中。如此一來,便可稍後再追蹤及檢視錯誤。
  • 您可以使用自己的程式碼來處理例外狀況,讓報表繼續進行處理。您可以檢查錯誤的內容,再撰寫能處理該錯誤的程式碼,然後使用正確的資訊重新執行一次報表。

Crystal 報表引擎提供了自己的例外狀況類別,可讓您判斷發生的錯誤類型。例外狀況類別是從 System.ApplicationException 類別繼承而來,唯一的差別是例外狀況類別多提供了一個 ErrorID 屬性。ErrorID 是列舉型別,可讓您判斷發生的錯誤類型。以下表格會顯示不同的例外狀況類別和列舉值。

例外狀況類別

例外狀況類別 說明
DataSourceException EngineException 繼承而來。當資料來源有問題時,便會發生這個例外狀況。
EngineException System.ApplicationException 繼承而來。這是 Crystal 報表引擎的基底例外狀況類別。它會提供 ErrorID 屬性,以便判斷出錯誤類型。
ExportException EngineException 繼承而來。當匯出有問題時,便會發生這個例外狀況。
FormattingException EngineException 繼承而來。當設定報表格式有問題時,便會發生這個例外狀況。
FormulaException EngineException 繼承而來。當公式欄位發生錯誤時,便會發生這個例外狀況。
InternalException EngineException 繼承而來。當 Crystal 報表引擎內部發生錯誤時,便會發生這個例外狀況。
InvalidArgumentException EngineException 繼承而來。當使用的引數無效時,便會發生這個例外狀況。
LoadSaveReportException EngineException 繼承而來。如果開啟報表時發生錯誤,便會發生這個例外狀況。
LogOnException DataSourceException 繼承而來。如果登入資料來源時發生錯誤,便會發生這個例外狀況。
OutOfLicenseException EngineException 繼承而來。當同時使用權的數目超過時,便會發生這個例外狀況。
ParameterFieldCurrentValueException ParameterFieldException 繼承而來。如果尚未設定參數欄位目前的值,便會發生這個例外狀況。
ParameterFieldException EngineException 繼承而來。當參數欄位發生錯誤時,便會發生這個例外狀況。
PrintException EngineException 繼承而來。如果列印報表時發生錯誤,便會發生這個例外狀況。
SubreportException EngineException 繼承而來。如果開啟子報表時有問題,便會發生這個例外狀況。

EngineExceptionErrorID 列舉值

ErrorID 說明
DataSourceError 存取資料來源時發生錯誤。
ExportingFailed 匯出報表時發生錯誤。
IndexOutOfBound 嘗試存取的值超出陣列界限。
InternalError Crystal 報表引擎內部發生錯誤。
InvalidArgument 使用無效的引數來設定值。
InvalidExportOptions 傳遞給報表引擎的匯出選項值不正確或遺漏資料。
InvalidFormula 處理公式欄位時發生錯誤。
InvalidParameterField 處理參數欄位時發生錯誤。
InvalidParameterValue 傳遞給參數欄位目前值的數值無效,因此發生錯誤。
InvalidPrintOptions 傳遞給報表引擎的列印選項值不正確或遺漏資料。
LoadingReportFailed 開啟報表時發生錯誤。
LogOnFailed 登入資料來源時發生錯誤。
MissingParameterFieldCurrentValue 參數欄位目前不包含任何值。
OpenSubreportFailed 開啟子報表時發生錯誤。
OutOfLicense 使用權的數目超過,因此發生錯誤。
PageFormattingFailed 設定報表格式時發生錯誤。
PrintingFailed 列印報表時發生錯誤。
SavingReport 儲存報表時發生錯誤。

使用程式碼處理例外狀況

根據您使用的是 ReportDocument 物件、Windows Form Viewer 或 Web Form Viewer,處理例外狀況的方式會略有不同。這兩種檢視器控制項有預先定義的 HandleException 事件,您可以在其中加入程式碼。ReportDocument 物件則必須透過 Try-Catch 陳述式來處理例外狀況。如果將報表傳遞給檢視器,然後發生錯誤,檢視器將可攔截到例外狀況。

使用檢視器控制項處理例外狀況

使用檢視器控制項處理例外狀況時,會使用檢視器的 HandleException 事件。在這個事件中,您可以將事件的 ExceptionEventArgs.Exception 參數型別轉換成 EngineException 類別。有了 EngineException 類別之後,您就可以檢查 ErrorID 屬性來判斷發生的錯誤類型。

以下範例將說明,如果登入資料庫或存取資料來源有問題時,要如何覆寫顯示的錯誤訊息。所有其他的錯誤訊息則交由 Crystal 報表引擎顯示。

[Visual Basic]

Private Sub CrystalReportViewer1_HandleException(ByVal source As Object, _ ByVal e As CrystalDecisions.Windows.Forms.ExceptionEventArgs) Handles CrystalReportViewer1.HandleException
   If TypeOf (e.Exception) Is EngineException Then
      Dim engEx As EngineException
      engEx = e.Exception
      If engEx.ErrorID = EngineExceptionErrorID.DataSourceError Then
         e.Handled = True
         MessageBox.Show _ 
         ("An error has occurred while connecting to the database.")
      ElseIf engEx.ErrorID = EngineExceptionErrorID.LogOnFailed Then
         e.Handled = True
         MessageBox.Show _ 
     ("Incorrect Logon Parameters. Check your user name and password.")
      End If
   End If
End Sub

[C#]

private void crystalReportViewer1_HandleException(object source, CrystalDecisions.Windows.Forms.ExceptionEventArgs e)
{
   if (e.Exception is EngineException)
   {
      EngineException engEx = (EngineException)e.Exception;
      if (engEx.ErrorID == EngineExceptionErrorID.DataSourceError)
      {
         e.Handled = true;
         MessageBox.Show _
         ("An error has occurred while connecting to the database.");
      }
      else if (engEx.ErrorID == EngineExceptionErrorID.LogOnFailed)
      {
         e.Handled = true;
         MessageBox.Show _
    ("Incorrect Logon Parameters. Check your user name and password.");
      }
   }
}

[C++]

void crystalReportViewer1_HandleException (Object* sender, CrystalDecisions::Windows::Forms::ExceptionEventArgs * e)
{
   try
   {
      EngineException* engEx; 
      engEx = __try_cast<EngineException*>(e->Exception);
      if (engEx->ErrorID == EngineExceptionErrorID::DataSourceError)
      {
         e->Handled = true;
         MessageBox::Show ("An error has occurred while connecting to the database.");
      }
      else if (engEx->ErrorID == EngineExceptionErrorID::LogOnFailed)
      {
         e->Handled = true;
         MessageBox::Show ("Incorrect Logon Parameters. Check your user name and password.");
      }
   }
   catch(System::InvalidCastException*)
   {
// 加入錯誤碼。
   }
};

[VJ#]

private void crystalReportViewer1_HandleException(System.Object source, CrystalDecisions.Windows.Forms.ExceptionEventArgs e)
{
   if (e.get_Exception() instanceof EngineException)
   {
      EngineException engEx = (EngineException)e.get_Exception();
      if (engEx.get_ErrorID() == EngineExceptionErrorID.DataSourceError)
      {
         e.set_Handled(true);
         MessageBox.Show
         ("An error has occurred while connecting to the database.");
      }
      else if (engEx.get_ErrorID() == EngineExceptionErrorID.LogOnFailed)
      {
         e.set_Handled(true);
         MessageBox.Show
    ("Incorrect Logon Parameters. Check your user name and password.");
      }
   }
}

使用 ReportDocument 物件處理例外狀況

使用 ReportDocument 物件處理例外狀況時,必須使用 Try-Catch 陳述式。在 Catch 中,您可以參考其中一個 Crystal 例外狀況類別。EngineException 是基底類別,可以攔截到 Crystal 報表引擎發生的所有例外狀況。其他的例外狀況類別則可用來判斷發生的錯誤類型。只要在 EngineException 類別和 ApplicationException 之前攔截到這些例外狀況類別,就可以知道發生的例外狀況類型。

以下範例將說明,如果登入資料庫或存取資料來源有問題時,要如何覆寫顯示的錯誤訊息。其他所有的例外狀況則會顯示原始的錯誤訊息。

[Visual Basic]

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As _ System.EventArgs) Handles Button1.Click
   Try
      Dim report As New ReportDocument()
      report.Load("c:\sample.rpt")
      report.PrintToPrinter(1, True, 1, 2)
   Catch engEx As LogOnException
      MessageBox.Show _
     ("Incorrect Logon Parameters. Check your user name and password.")
   Catch engEx As DataSourceException
      MessageBox.Show _
      ("An error has occurred while connecting to the database.")
   Catch engEx As EngineException
      MessageBox.Show(engEx.Message)
   End Try
End Sub

[C#]

private void button1_Click(object sender, System.EventArgs e)
{
   try
   {
      ReportDocument report = new ReportDocument();
      report.Load ("c:\\sample.rpt");
      report.PrintToPrinter (1,true,1,2);
   }
   catch (LogOnException engEx)
   {
      MessageBox.Show _
("Incorrect Logon Parameters. Check your user name and password.");
   }
   catch (DataSourceException engEx)
   {
   MessageBox.Show _
("An error has occurred while connecting to the database.");
   }
   catch (EngineException engEx)
   {
      MessageBox.Show (engEx.Message);
   }
}

[C++]

void ButtonClick(Object* sender, System::EventArgs * e)
{
   try
   {
      ReportDocument* report = new ReportDocument();
      report->Load ("c:\\sample.rpt");
      report->PrintToPrinter (1,true,1,2);
   }
   catch (LogOnException* engEx)
   {
      MessageBox::Show("Incorrect Logon Parameters. Check your user name and password.");
   }
   catch (DataSourceException* engEx)
   {
      MessageBox::Show("An error has occurred while connecting to the database.");
   }
   catch (EngineException* engEx)
   {
      MessageBox::Show (engEx->Message);
   }
};

[VJ#]

private void button1_Click(System.Object sender, System.EventArgs e)
{
   try
   {
      ReportDocument report = new ReportDocument();
      report.Load ("c:\\sample.rpt");
      report.PrintToPrinter (1,true,1,2);
   }
   catch (LogOnException engEx)
   {
      MessageBox.Show
("Incorrect Logon Parameters. Check your user name and password.");
   }
   catch (DataSourceException engEx)
   {
   MessageBox.Show
("An error has occurred while connecting to the database.");
   }
   catch (EngineException engEx)
   {
      MessageBox.Show (engEx.get_Message());
   }
}

請參閱

Crystal Reports 類別庫