Control de errores para aplicaciones robustas – 2 3. Los objetos Err y Error Hay diferentes formas de utilizar el objeto Err utilizado por Access y los objetos Error utilizados por el motor Jet, al igual que la instrucción Error. Para evitar confusiones es mejor examinarlos. Propiedad Descripcion Description Contiene la descripción del error, si existe la descripción HelpContext Guarda el Id de contexto para el archivo de ayuda VBA. HelpFile Guarda la ruta y el nombre del archivo de ayuda VBA. LastDllError Devuelve el último error en una llamada a una DLL. Number Contiene el número del error que ha sido establecido en el objeto Error. Esta es la propiedad predeterminada del objeto Err Source Refleja el sistema en el que este error ocurrió. Muchos errores de Access establecen la propiedad Source a MS Access. Cuando se utiliza la automatización, si otra aplicación (por ej., Excel ) causa el error, la propiedad Source se establece a ésta aplicación. El objeto Err tiene dos métodos: Clear y Raise. El método Clear permite eliminar el último error producido que se encuentra en el objeto Err. Con éste método se puede reintentar una acción en un bucle que puede causar un error. Después de que ocurra el error, podemos querer iniciar al principio del bucle y verificar el error de nuevo. Por tanto, se debe colocar la línea de código Err.clear en la parte final del bucle para establecer el objeto Err.Number a 0. El método Raise permite generar un error en tiempo de ejecución provocado. Esto es útil cuando se depura una aplicación o se crea un error personalizado. Otra finalidad del método Raise es generar errores definidos por el usuario para evitar la presentación de errores estandar y mostrar los personalizados. La colección Errors guarda las configuraciones más recientes de los errores múltiples que pueden suceder. Contiene un método Refresh y una propiedad Count, que cuenta el número de errores que contiene la colección Errors. Tratamiento de errores en procedimientos anidados Cuando se produce un error en un procedimiento anidado que no tiene activado el tratamiento de errores, Visual Basic retrocede buscando por la lista de llamadas un tratamiento de errores en otro procedimiento, en lugar de detener simplemente la ejecución. Esto proporciona al código la oportunidad de corregir el error dentro de otro procedimiento. Por ejemplo, supongamos que el Procedimiento A llama al Procedimiento B, y que el Procedimiento B llama al Procedimiento C. Si se produce un error en el Procedimiento C y éste no tiene activado el tratamiento de errores, Visual Basic comprueba el Procedimiento B, y luego el Procedimiento A, para ver si hay un tratamiento de errores activado. Si existe uno, la ejecución pasa al tratamiento de errores. Si no, se detiene la ejecución y se muestra un mensaje de error. Visual Basic también retrocede buscando por la lista de llamadas un tratamiento de errores cuando se produce un error dentro de un tratamiento de errores activo. Se puede forzar a que Visual Basic retroceda buscando por la lista de llamadas elevando un error del tratamiento de errores activo con el método Raise del objeto Err. Esto resulta útil para ocuparse en el tratamiento de errores de los errores que no anticipó. Si se produce un error no anticipado, y ese error se regenera dentro del tratamiento de errores, entonces la ejecución retrocede en la lista de llamadas para buscar otro tratamiento de errores, que puede haber sido establecido para tratar el error. Por ejemplo, supongamos que el Procedimiento C tiene activado un tratamiento de errores, pero que el tratamiento de errores no corrige el error que se ha producido. Una vez que el tratamiento de errores ha comprobado todos los errores que se anticiparon, puede regenerar el error original. La ejecución retrocede entonces por la lista de llamadas al tratamiento de errores del Procedimiento B, si es que existe, ofreciendo la oportunidad de que este tratamiento de errores corrija el error. Si no existiera tratamiento de errores en el Procedimiento B, o si no puede corregir el error y regenerarlo de nuevo, entonces la ejecución pasa al tratamiento de errores del Procedimiento A, suponiendo que exista uno. Para ilustrar este concepto de otra forma, supongamos que tenemos un procedimiento anidado que incluye el tratamiento de errores para un tipo de error de no coincidencia de tipos, un error que se había sido anticipado. En algún momento, en el Procedimiento C se produce un error de división por cero, que no se había anticipado. Si se ha incluido una instrucción que regenere el error original, entonces la ejecución pasa hacia atrás en la lista de llamadas a otro tratamiento de errores, si es que existe. Si en algún otro procedimiento de la lista de llamadas ha corregido un error de división por cero, entonces se corregirá el error. Si el código no regenera el error, entonces el procedimiento continúa la ejecución sin corregir el error de división por cero. Esto a su vez puede provocar otros errores dentro del conjunto de procedimientos anidados. En resumen, Visual Basic hace una búsqueda hacia atrás en la lista de llamadas de un tratamiento de errores activado si: Si se produce un error en un procedimiento que no incluye un tratamiento de errores activado. Se produce un error dentro de un tratamiento de errores activo. Si se utiliza el método Raise del objeto Err para elevar un error, puede forzar a que Visual Basic busque hacia atrás en la lista de llamadas un tratamiento de errores activado. Creación de errores definidos por el usuario. Utilizando las funciones CVErr() e IsErr() y el método Application.AccessError se pueden crear funciones propias que pueden devolver un valor tipo Error si sucede una situación de error en la función. La función CVError() convierte un valor a untito de datos Error, asignando este a una variable Variant. La función IsError() comprueba si una Variant es un tipo de datos Error. El método Application.AccessError proporciona una descripción de error sin el error en sí. Un ejemplo en el que se utilizan estas instrucciones es cuando queremos dividir dos números y la función recibe un valor de texto o un valor cero, en cuyos casos se produce un error. Veamos el código que controla ésta situación. Private Sub cmdTestCVErr_Click() Dim varReturnVal As Variant varReturnVal = ap_ShowErrorCVErr(InputBox("Introduzca el numerador:", "Numerador"), InputBox("Introduzca el denominador:", "Denominador")) If IsError(varReturnVal) Then '— Numero definido por el usuario If CInt(varReturnVal) = 2001 Then MsgBox "Introducir valores numéricos" '— Número de dividir por cero ElseIf CInt(varReturnVal) = 11 Then MsgBox Application.AccessError(11) End If Else MsgBox "La respuesta es: " & varReturnVal End If End Sub Con este control de errores se consigue: Si los datos introducidos no son numéricos, un número de error personalizado se le asigna al valor devuelto. Si el denominador es cero, se envía un error. Si todo es correcto, se envía la solución. Para que éste código funcione, necesitamos crear una función, en este caso llamada ap_ShowErrorCVErr. Veamos el código: Function ap_ShowErrorCVErr(varNumerator As Variant, varDenominator As Variant) As Variant '— Verifica y comprueba que el tipo de datos es correcto. If Not IsNumeric(varNumerator) Or Not IsNumeric(varDenominator) Then ap_ShowErrorCVErr = CVErr(2001) '— Comprueba que el denominador no es cero. ElseIf CDbl(varDenominator) = 0 Then ap_ShowErrorCVErr = CVErr(11) '—Si todo es correcto, realiza la acción. Else ap_ShowErrorCVErr = CDbl(varNumerator) / CDbl(varDenominator) End If End Function