jueves, 8 de enero de 2015

VBA: Tratando con errores - el objeto Err.

Una de los recursos más útiles en programación es aprender a 'lidiar' con los errores generados...
Normalmente podemos salvarlos (que no arreglarlos) con las instrucciones:
On Error Resume Next
On Erro GoTo ...
y algunos otros.

Sin embargo, disponemos de otra herramienta igualmente útil para atrapar y, sobre todo, tratar los errores controlados en nuestros procedimientos, el objeto Err.
Este objeto Err tiene un par de métodos asociados:
.Clear
.Raise
y algunas propiedades interesantes:
.Number
.Description
junto a
.Source
.Helpfile
.HelpContext
.LastDLLError


Con este objeto podemos controlar cualquier tipo de Error que se pueda generar en nuestra aplicación Excel.
Un listado (no completo) de los diferentes códigos de error sería:




Error Significado
3 Return sin GoSub
5 Argumento o llamada a procedimiento no válida
6 Desbordamiento
7 Memoria insuficiente
9 Subíndice fuera del intervalo
10 Esta matriz es fija o se encuentra temporalmente bloqueada
11 División por cero
13 No coinciden los tipos
14 Espacio para cadenas insuficiente
16 Expresión demasiado compleja
17 No se puede realizar la operación solicitada
18 Se ha producido una interrupción por parte del usuario
20 Resume sin Error
28 Espacio de pila insuficiente
35 No se ha definido Sub o Function
47 Hay demasiados clientes de la aplicación DLL
48 Error al cargar biblioteca DLL
49 La convención de llamada a la DLL no es correcta
51 Error interno
52 Nombre o número de archivo incorrecto
53 Archivo no encontrado
54 Modo de archivo incorrecto
55 El archivo ya está abierto
57 Error de E/S de dispositivo
58 El archivo ya existe
59 Longitud de registro incorrecta
61 Disco lleno
62 Se sobrepasó el final del archivo
63 Número de registro incorrecto
67 Demasiados archivos
68 Dispositivo no disponible
70 Permiso denegado
71 Disco no preparado
74 No se puede cambiar el nombre con una unidad de disco diferente
75 Error de acceso a la ruta o el archivo
76 No se ha encontrado la ruta de acceso
91 Variable de objeto o bloque With no establecido
92 Bucle For no inicializado
93 La cadena modelo no es válida
94 Uso no válido de Null
96 No se puede recibir eventos de objeto porque el objeto ya está desencadenando el número máximo de eventos que admite
97 No se puede llamar a una función friend de un objeto que no sea una instancia de una clase
98 Una llamada a una propiedad o un método no puede incluir una referencia a un objeto privado como un argumento o un valor de retorno
321 El formato de archivo no es válido
322 No se puede crear un archivo temporal necesario
325 El formato del archivo de recursos no es válido
380 El valor de la propiedad no es válido
381 El índice de la matriz de propiedades no es válido
382 No se admite Set durante la ejecución
383 No se admite Set (propiedad de sólo lectura)
385 Se necesita un índice de matriz de propiedades
387 No está permitido Set
393 No se admite Get durante la ejecución
394 No se admite Get (propiedad de sólo escritura)
422 No se encontró la propiedad
423 No se encontró la propiedad o el método
424 Se requiere un objeto
429 El componente ActiveX no puede crear el objeto
430 Esta clase no admite Automatización o no admite la interfaz esperada
432 No se encontró el nombre del archivo o de la clase durante la operación de Automatización
438 El objeto no admite esta propiedad o método
440 Error de Automatización
442 Se ha perdido la conexión con la biblioteca de tipos o con la biblioteca de objetos para procesos remotos. Haga clic en 'Aceptar' para eliminar la referencia.
443 El objeto de Automatización no tiene un valor predeterminado
445 El objeto no admite esta acción
446 El objeto no admite argumentos con nombre
447 El objeto no admite la configuración regional actual
448 No se encontró el argumento con nombre
449 El argumento no es opcional
450 El número de argumentos es incorrecto o la asignación de propiedad no es válida
451 El procedimiento Let de la propiedad no está definido y el procedimiento Get no ha devuelto un objeto
452 El número ordinal no es válido
453 No se encontró la función en la DLL especificada
454 No se encontró el recurso de código
455 Error en el bloqueo de los recursos de código
457 Esta tecla ya está asociada con un elemento de esta colección
458 La variable utiliza un tipo de Automatización no admitido en Visual Basic
459 El objeto o la clase no admite el conjunto de eventos
460 El formato del Portapapeles no es válido
461 No se encontró el método o el dato miembro
462 El equipo servidor remoto no existe o no está disponible
463 La clase no está registrada en el equipo local
481 Imagen no válida
482 Error de impresora
735 No se puede guardar el archivo en TEMP
744 No se encontró el texto de búsqueda
746 Sustituciones demasiado largas
1004 Error definido por la aplicación o el objeto. Este es un mensaje 'cajón de sastre' de error muy común. Este error se produce cuando un error no se corresponde con un error definido por VBA. En otras palabras, el error se define por Excel (o algún otro objeto) y se propaga de nuevo a VBA.


Igualmente se puede ver en este link una explicación de alguno de estos.
O bien generar una lista en una hoja de cálculo con este sencillo procedimiento...

Sub ListaErrores()
Range("A1").Select
On Error Resume Next
For i = 1 To 1050
    Error i
    ActiveCell.Value = Err.Number & " - " & Err.Description
    ActiveCell.Offset(1, 0).Select
Next i
End Sub


Debemos saber que los números o códigos de error en VBA para Excel (tanto los definidos por Visual Basic como los definidos por el usuario) se encuentran entre 0 y 65535, y que de 0 a 512 está reservado para errores del sistema; el intervalo 513 a 65535 está disponible para los errores definidos por los usuarios.
Ojo, porque al establecer en la propiedad .Number nuestro propio código de error en un Módulo de clase, agregaremos el código de error a la constante vbObjectError (recomendado); por ejemplo, para generar el número de error 1313, asignaríamos vbObjectError +1313 a la propiedad .Number.


Y qué ocurre si quiere personalizar un error en mi procedimiento??. En ese caso utilizaremos los métodos que nos proporciona Err, en concreto .Raise.

Veamos el siguiente ejemplo:

Sub TestErrorPersonal()
Dim Entero As Integer
'controlamos un posible error en nuestro código
On Error GoTo TestErrorPersonal_Error
Entero = InputBox("Introduce un número entero", "Comprobación errores", 13)

If Entero > 10 Then
    'cuando se cumpla la condición
    'creamos un Error personalizado y su descripción
    Err.Raise Number:=1313, Description:="El valor " & Entero & " supera el límite establecido (10)..."
Else
  MsgBox "El entero dado es " & Entero
End If

Exit Sub
TestErrorPersonal_Error:
'Muestra un mensaje con nuestro Número de Error y su descripción
MsgBox "Error generado # " & Err.Number & " - " & Err.Description
'Borra todas las propiedades establecidas del objeto Err
Err.Clear
Exit Sub
End Sub



Como se aprecia rápidamente hemos creado nuestro propio Error (el número 1313), al que hemos añadido nuestra propia descripción.
En el procedimiento se pide al usuario introduzca un valor... se verifica si éste supera el valor establecido (10), en cuyo caso creamos un error personalizado.
Al estar controlado el error, con la instrucción (On Error GoTo TestErrorPersonal_Error), se ejecuta la parte final de macro, mostrando un mensaje construido empleando las propiedades .Err.Number y Err.Description.
Acabamos liberando nuestro Error.

VBA: Tratando con errores - el objeto Err.



En general, que debemos conocer de estos métodos del objeto Err:
método .Raise (.Raise number, source, description, helpfile, helpcontext): todos los argumentos son opcionales, excepto .Number. Sin embargo, si utilizamos .Raise sin especificar algunos de los argumentos, y los valores de las propiedades del objeto Err no se han borrado (con .Clear), dichos valores se conservarán para el error actual.

método .Clear (objeto.Clear): empleamos .Clear para borrar explícitamente el objeto Err después de controlar un error, por ejemplo, cuando hemos establecido el tratamiento diferido de un error con On Error Resume Next.


Algunas de las propiedades de Err:
propiedad .Number: Al devolver un error definido por el usuario desde un objeto, es recomendable establecer el Err.Number agregando el número que ha seleccionado como código de error a la constante vbObjectError.

propiedad .Description: La propiedad .Description contiene una breve descripción del error. necesaria para notificar al usuario el error generado. OJO, porque si no se rellena Description y el valor de Number corresponde a un error en tiempo de ejecución de Visual Basic, la cadena que devuelve la función Error se coloca en Description cuando se genera el error.

propiedad .Source: Con la propiedad .Source especificamos una expresión de cadena que representa al objeto que generó el error; la expresión es normalmente el nombre de clase o el identificador programático del objeto. Podemos utilizar .Source para proporcionar información al usuario cuando el código no pueda tratar un error generado en un objeto al que se ha tenido acceso.
Por ejemplo, si se tiene acceso a Microsoft Excel y éste genera un error División por cero, Microsoft Excel establecerá en Err.Number su código de error correspondiente y Excel.Application en Source.

No hay comentarios:

Publicar un comentario en la entrada