Manejo de excepciones del Motor de Crystal Report

Cuando ejecuta Crystal Reports mediante su aplicación, puede haber ocasiones en que el Motor de Crystal Report genere una excepción. Cuando se genera una excepción, puede aparecer un cuadro de diálogo de error o detenerse el procesamiento de los informes. A continuación se enumeran algunas causas de una excepción:

  • El motor de informes no puede establecer conexión con la base de datos. Esto puede deberse a que se han pasado al motor de informes unos parámetros incorrectos de inicio de sesión o de ubicación de la base de datos. También puede deberse a otros errores de la base de datos como, por ejemplo, el bloqueo de la tabla por parte de otro usuario, la instalación incorrecta del motor de la base de datos o el deterioro de la tabla.
  • Se han pasado datos incorrectos a un parámetro. Si un parámetro recibe datos incorrectos de código o de entrada de usuario, puede detenerse la ejecución del informe. Por ejemplo, si se pasa un valor de cadena a un parámetro numérico, se detendrá la ejecución del informe.
  • Se encuentra un error en una fórmula de Crystal Reports. Si una de las fórmulas del informe no se puede evaluar correctamente, se iniciará una excepción. Esto puede deberse a una sintaxis incorrecta de la fórmula o a otro error de programación, como un error de división por cero.
  • El motor de informes no ha podido abrir un informe. Esto puede suceder si se proporcionan una ruta de acceso o un nombre de archivo incorrectos, si se selecciona un informe que no es de Crystal o si el informe está dañado.

Puede dejar que el motor de informes de Crystal controle la excepción y muestre su mensaje de error, o bien controlar la excepción con sus propios medios. A continuación se enumeran algunas de las ventajas de controlar las excepciones mediante programación:

  • Se puede personalizar el mensaje de error mostrado al usuario. Por ejemplo, en lugar de mostrarse "La conexión no es posible" cuando el informe no puede establecer conexión con el origen de datos, se puede mostrar un mensaje más completo, como "No se puede conectar con la base de datos, los parámetros de inicio de sesión proporcionados son incorrectos". De este modo, el usuario dispondrá de información más detallada.
  • Se puede escribir un evento en el archivo de registro de la aplicación. Se puede escribir en el archivo de registro el mensaje de error, el identificador del error, el momento en que se produjo y otra información relevante. Esto permitirá el seguimiento y revisión posteriores de los errores.
  • Se puede controlar la excepción con el código propio para que pueda continuar el procesamiento del informe. Si se comprueba en qué consiste el error, se puede escribir código que lo controle y vuelva a ejecutar el informe con la información correcta.

El Motor de Crystal Report proporciona clases de excepción propias que permiten determinar el tipo de error que se ha producido. Las clases de excepción se heredan de la clase System.ApplicationException, con la única diferencia de que proporcionan una propiedad más denominada ErrorID. ErrorID es un tipo enumerado que permite determinar el tipo de error que se ha producido. Las tablas que aparecen a continuación muestran las diferentes clases de excepción y los distintos valores de enumeración.

Clases de excepción

Clase de excepción Descripción
DataSourceException Se hereda de EngineException. Esta excepción se inicia cuando surgen problemas con el origen de datos.
EngineException Se hereda de System.ApplicationException. Ésta es la clase de excepción base del Motor de Crystal Report. Proporciona la propiedad ErrorID para que se pueda determinar el tipo d error.
ExportException Se hereda de EngineException. Esta excepción se inicia cuando surgen problemas con la exportación.
FormattingException Se hereda de EngineException. Esta excepción se inicia cuando surgen problemas con el formato del informe.
FormulaException Se hereda de EngineException. Esta excepción se inicia cuando se produce un error en un campo de fórmula.
InternalException Se hereda de EngineException. Esta excepción se inicia cuando se produce un error interno en el Motor de Crystal Report.
InvalidArgumentException Se hereda de EngineException. Esta excepción se inicia cuando se utiliza un argumento no válido.
LoadSaveReportException Se hereda de EngineException. Esta excepción se inicia cuando se produce un error al abrirse un informe.
LogOnException Se hereda de DataSourceException. Esta excepción se inicia cuando se produce un error al establecerse la conexión con un origen de datos.
OutOfLicenseException Se hereda de EngineException. Esta excepción se inicia cuando se ha superado el número de licencias simultáneas.
ParameterFieldCurrentValueException Se hereda de ParameterFieldException. Esta excepción se inicia cuando no se ha establecido el valor actual de un campo de parámetro.
ParameterFieldException Se hereda de EngineException. Esta excepción se inicia cuando se produce un error en un campo de parámetro.
PrintException Se hereda de EngineException. Esta excepción se inicia cuando se produce un error al imprimirse un informe.
SubreportException Se hereda de EngineException. Esta excepción se inicia cuando surgen problemas al abrirse un subinforme.

Valores de enumeración EngineExceptionErrorID

ErrorID Descripción
DataSourceError Se ha producido un error durante el acceso al origen de datos.
ExportingFailed Se ha producido un error durante la exportación del informe.
IndexOutOfBound Se ha intentado el acceso a un valor que está fuera de los límites de una matriz.
InternalError Se ha producido un error interno en el motor de informes de Crystal.
InvalidArgument Se ha utilizado un argumento no válido para establecer un valor.
InvalidExportOptions Los valores de las opciones de exportación pasados al motor de informes son incorrectos o faltan datos.
InvalidFormula Se ha producido un error durante el procesamiento de un campo de fórmula.
InvalidParameterField Se ha producido un error durante el procesamiento de un campo de parámetro.
InvalidParameterValue Se ha producido un error porque se ha pasado un valor no válido al valor actual de un campo de parámetro.
InvalidPrintOptions Los valores de las opciones de impresión pasados al motor de informes son incorrectos o faltan datos.
LoadingReportFailed Se ha producido un error al abrirse un informe.
LogOnFailed Se ha producido un error al establecerse la conexión con un origen de datos.
MissingParameterFieldCurrentValue El campo de parámetro contiene valores que no son actuales.
OpenSubreportFailed Se ha producido un error al abrirse un subinforme.
OutOfLicense Se ha producido un error porque se ha superado el número de licencias.
PageFormattingFailed Se ha producido un error al aplicar formato al informe.
PrintingFailed Se ha producido un error al imprimirse un informe.
SavingReport Se ha producido un error al guardar el informe.

Controlar excepciones en código

Dependiendo de si se está utilizando el objeto Report Document, Windows Forms Viewer o Web Forms Viewer, la forma de controlar las excepciones variará ligeramente. Los dos controles Viewer tienen un evento HandleException predefinido al que se puede agregar código. El objeto Report Document necesita que las excepciones se controlen mediante un enunciado try-catch. Si el informe se pasa al visor y, en ese momento, se produce el error, el visor detectará la excepción.

Controlar excepciones con los controles Viewer

Cuando una excepción se controla con los controles Viewer, se utiliza el evento HandleException del visor. En este evento, se puede convertir el tipo del parámetro ExceptionEventArgs.Exception del evento a una clase EngineException. Cuando se tenga la clase EngineException, se podrá comprobar la propiedad ErrorID para determinar el tipo de error que se ha producido.

En el ejemplo siguiente se muestra cómo se anula el mensaje de error que se muestra cuando surgen problemas al establecerse la conexión con una base de datos o durante el acceso al origen de datos. La presentación de todos los demás mensajes de error correrá a cargo del Motor de Crystal Report.

[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*)
   {
      // Agregar código de error.
   }
};

[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.");
      }
   }
}

Controlar excepciones con el objeto ReportDocument

Cuando una excepción se controla con el objeto ReportDocument, es necesario utilizar un enunciado try-catch. En la detección se puede hacer referencia a una de las clases de excepción de Crystal. La clase EngineException es la clase base que detectará todas las excepciones iniciadas por el Motor de Crystal Report. Las demás clases de excepción se pueden utilizar para determinar el tipo de error que se ha producido. Al detectar estas clases de excepción antes que la clase EngineException y la clase ApplicationException, se podrá saber el tipo de excepción que se ha iniciado.

En el ejemplo siguiente se muestra cómo se anula el mensaje de error que se muestra cuando surgen problemas al establecerse la conexión con una base de datos o durante el acceso al origen de datos. Todas las demás excepciones mostrarán el mensaje de error original.

[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());
   }
}

Vea también

Biblioteca de clases de Crystal Reports