Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Capítulo 1: Introducción
A. Introducción 14
A. Introducción 18
C. La interfaz 20
1. Los módulos 21
2. Los cuadros de diálogo personalizados 23
3. Las barras de herramientas 25
A. Introducción 28
B. ¿Qué es un objeto? 28
1. Propiedad de un objeto 28
2. Método de un objeto 28
C. Regla de codificación 29
1. Asociación de objetos 30
2. Asociación de propiedades o de métodos 30
D. Ayuda en línea 31
1. La celda 31
2. El rango de celdas 32
3. Las celdas nombradas 32
G. Los procedimientos 34
H. Las funciones 34
A. Introducción 38
B. La Grabadora de macros 38
C. Primer ejercicio 41
G. Síntesis 51
A. Introducción 54
C. El método MsgBox 55
1. Vista de un mensaje personalizado 55
2. Ver el resultado de una variable 56
3. Personalizar el mensaje 56
F. El método InputBox 68
A. Introducción 72
B. La instrucción If 72
1. Presentación 72
2. Ejemplo de aplicación 73
3. Explicación 74
4. Transformación del código 74
5. Abreviatura de escritura 75
6. Condición anidada 76
A. Introducción 88
Capítulo 8: Depuración
A. Presentación 106
1. La tecla 8 108
2. La combinación de teclas m 8 109
A. Introducción 166
A. Introducción 198
A. Introducción 216
A. Introducción 230
A. Introducción 244
A. Introducción 272
1. Presentación 280
2. Puesta en marcha 281
3. Insertar nuevos registros en Access 283
4. Actualizar una base Access desde Excel 285
A. Introducción 308
A. Introducción 322
1. Presentación 331
2. Manipular los datos de la lista 332
3. Alimentar una lista en el programa 335
I. Síntesis 339
A. Introducción 342
1. Ejemplo 1 343
2. Ejemplo 2 346
3. Ejemplo 3 346
Anexos
índice 359
Frédéric LE GUEN
Conferenciante y consultor en Sistemas de Información para empresas desde hace más de quince
años, Frédéric LE GUEN, reconocido Microsoft MVP (Most Valuable Professional) desde 2010, es
también el creador de la web francesa de formación www.excelexercice.com. Gracias a sus muchos
trabajos en empresas desarrolló varias aplicaciones con Excel; en este manual nos ofrece su
experiencia a través de abundantes y variados ejemplos elegidos por su valor pedagógico y
práctico.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Introducción
El objetivo de este libro es enseñarle, mediante prácticas, cómo diseñar macros con Microsoft Excel. Una macro es el
nombre que se le da a los programas que se escriben en un entorno de Office (Excel, Word, Access, PowerPoint).
Estas le permiten reproducir tareas un gran número de veces y sin error.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
¿A quién va dirigido este libro?
Ya sea usted estudiante, comerciante, jefe de proyectos, gestor, asesor, o simplemente utilice Excel a diario para la
gestión de sus cuentas o de una asociación, habrá constatado que a menudo tiene que realizar las mismas tareas y
le gustaría mejorar sus conocimientos de Excel para automatizar esas tareas.
Aunque nunca haya creado un programa, ni siquiera haya visto una línea de código en su vida, los ejemplos
siguientes le mostrarán, paso a paso, cómo crear macros mediante el lenguaje VBA.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
¿Qué es una macro?
Una macro es un conjunto de líneas de código que contienen instrucciones. Excel interpretará estas instrucciones
para realizar diversas tareas: operaciones matemáticas, operaciones en hojas de cálculo, operaciones en archivos,
etc. Estas instrucciones siempre se interpretarán del mismo modo y, además, el trabajo se hará mucho más rápido
que si tuviera que volver a hacer la misma tarea varias veces.
El lenguaje empleado para codificar estas instrucciones es el VBA (Visual Basic for Applications). La ventaja principal de
este lenguaje es que es muy comprensible puesto que las instrucciones se escriben (casi) como si fuese lenguaje
corriente.
Desde Excel 2007, Microsoft distingue entre guardar un libro sin macro (.xlsx) y guardar un libro con macro (.xlsm). Un
libro que contiene macros y que se ha guardado en formato xlsx no conservará sus líneas de código. Al mismo tiempo
es un mecanismo de seguridad para comprobar la existencia de un programa en un libro y una obligación a la hora de
guardarlo.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
¿Qué interés tiene hacer macros?
Diseñar una macro tiene muchas ventajas. En primer lugar, el programa hará y deshará las instrucciones siempre en
el mismo orden. Por lo tanto, una macro le garantiza la integridad de su trabajo. Además, un programa le hará ganar
tiempo a la hora de realizar sus tareas.
Imagine que tiene que trabajar en un archivo de un millar de datos. Para tratar este archivo manualmente, podría
necesitar tres o cuatro horas, mientras que si trabaja con una macro, bastarían tres o cuatro segundos para tratar
los datos.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Contenido del libro
Este libro está dividido en cuatro partes. La primera parte le presenta el entorno de trabajo empleado para el diseño
de macros. La segunda parte le explica los principios básicos de programación. En la tercera parte, encontrará las
principales funciones que tendrá que utilizar en su trabajo. Y en la cuarta parte, descubrirá las técnicas de
optimización que permiten mejorar la ejecución de sus programas así como las técnicas utilizadas para la creación de
cuadros de diálogo personalizados.
Sea cual sea la versión de Excel con la que trabaje, en el libro encontrará las respuestas a sus problemas. Desde
Excel 2003, el lenguaje VBA ha evolucionado muy poco, no obstante le señalaremos las pocas diferencias entre las
versiones.
Puede consultar este manual capítulo por capítulo, en función de sus necesidades, sin que tenga que respetar
necesariamente el índice de contenidos. Este libro es ante todo una ayuda para la creación de programas. Todos los
ejemplos presentados se pueden descargar gratuitamente desde la página Información.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Introducción
Para crear macros, no se trabaja con Excel sino con otro programa, el Editor Visual Basic, más comúnmente llamado
Visual Basic Editor o incluso VBE.
Como se muestra en la imagen anterior, Microsoft Excel y Visual Basic Editor son dos aplicaciones que aparecen por
separado en la barra de tareas de Windows. Sin embargo, aunque VBE sea una aplicación aparte, esta no puede
iniciarse si no es desde Excel.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
¿Cómo iniciar Visual Basic Editor?
El proceso difiere según la versión de Excel empleada.
1. Versión Excel 2003 (o anterior)
Para iniciar Visual Basic Editor, utilice el menú Herramientas Macro y haga clic en la opción Editor de
Visual Basic o pulse [Alt][F11].
2. Versión Excel 2007 (o posterior)
En las nuevas versiones de Excel, las herramientas que permiten crear macros están ocultas por defecto.
Para visualizar la pestaña reservada a las herramientas de programación, haga clic en la pestaña Archivo
y después en el botón Opciones. Seleccione la categoría Personalizar cinta de opciones. En la zona
Pestañas principales, active Desarrollador y después acepte.
Aparecerá la pestaña Programador.
En esta nueva pestaña, haga clic en el icono Visual Basic para iniciar VBE.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
En todas las versiones de Excel, puede iniciar VBE pulsando las teclas [Alt][F11].
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
La interfaz
Al inicio, la aplicación Visual Basic aparece como en la captura de pantalla siguiente:
La interfaz está compuesta por el Explorador de proyectos (1), la ventana de propiedades (2) y la zona de trabajo
(3).
Si el Explorador de proyectos no está visible, es posible visualizarlo usando el menú Vista Explorador de proyectos
(o el método abreviado [Ctrl] R). De la misma manera, si no está visible la ventana de propiedades, es posible
mostrarla mediante el menú Vista Ventana de propiedades (método abreviado [F4]).
1. Los módulos
Los módulos son el alma de la programación. Un módulo se presenta como una hoja en blanco en la que usted
escribirá sus líneas de código.
Para insertar un módulo, en el Explorador de proyectos, haga clic con el botón derecho del ratón en su
proyecto (o en su libro Excel) y seleccione el menú Insertar Módulo.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
También es posible insertar módulos mediante el menú Insertar Módulo o bien haciendo clic en la flecha situada a
la derecha del icono .
Ahora, la zona de trabajo contiene un módulo que se presenta como una hoja en blanco. Verá aparecer este
módulo en el Explorador de proyectos.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Por defecto, su nombre genérico es "Módulo1, 2, 3, …"
Para darle otro nombre, como por ejemplo Primer_Programa, escriba el nombre en la ventana de
propiedades en lugar de la palabra Módulo 1.
Se ha modificado el nombre de su módulo en el Explorador de proyectos.
2. Los cuadros de diálogo personalizados
Hacer macros también es crear sus propios cuadros de diálogo.
Para insertar un cuadro de diálogo, en el Explorador de proyectos, haga clic con el botón derecho del
ratón en el documento y seleccione el menú Insertar UserForm (que es la traducción de cuadro de
diálogo).
Aparecerá un cuadro de diálogo en blanco en la zona de trabajo:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
En los capítulos Los cuadros de diálogo personalizados y Los controles, veremos cómo rellenar un cuadro de diálogo
y también cómo recuperar la información introducida. Podemos observar que del mismo modo que aparecen los
módulos, aparece un icono UserForm1 en el árbol del Explorador de proyectos y que la ventana de propiedades
contiene muchos más elementos para un cuadro de diálogo que para un módulo.
3. Las barras de herramientas
Al inicio, solo está visible la barra de herramientas Estándar, pero una gran parte de las funciones que usará con
frecuencia no están en esta barra de herramientas. Se pueden mostrar otras dos barras de herramientas.
Aconsejamos que se añadan dos barras de iconos adicionales: la barra Edición y la barra Depuración.
Para visualizar las barras de herramientas que faltan, coloque el puntero del ratón en una zona vacía (sin
texto ni icono) de la barra de herramientas y haga clic con el botón derecho del ratón para que aparezca
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
el siguiente menú contextual.
En este ejemplo, solo está marcada la opción Estándar.
Marque las dos primeras opciones para que aparezcan la barra de Depuración y la barra de Edición.
Si estas barras de herramientas se muestran como una barra flotante y quiere colocarlas en la parte
superior de la ventana de la aplicación, haga clic en la barra de título de la barra de herramientas y
deslícela hacia las otras barras de herramientas. Cuando suelte el botón del ratón, la barra de
herramientas se colocará en el mismo nivel que las demás barras de herramientas.
Es importante señalar que las barras agregadas de esta forma aparecerán de nuevo cada vez que se inicie el editor;
el editor conserva las opciones de vista.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Introducción
La ventaja de Visual Basic, con respecto a otros lenguajes de programación, es su simplicidad de comprensión para
cualquier neófito; es un lenguaje orientado a objetos.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
¿Qué es un objeto?
En Visual Basic, un objeto corresponde a uno de los elementos de la aplicación Excel: un libro (Workbook), una hoja
de cálculo (Worksheet), una columna (Column), una fila (Row), un rango de celdas (Range), una celda (Cells), etc.
A esos objetos se les asociará ya sea una propiedad o un método.
1. Propiedad de un objeto
Una propiedad corresponde a las características de un objeto.
l Para una celda, las propiedades pueden ser su valor, su color, su tamaño, su fuente de carácter, etc.
l Para una hoja, las propiedades pueden ser su nombre, su visibilidad (oculta o no), su color de pestaña, etc.
Las propiedades que se aplican a un objeto son diferentes de un objeto a otro.
En el capítulo Depuración veremos de qué manera mostrar la lista de métodos y propiedades vinculadas a un
objeto.
2. Método de un objeto
Un método corresponde a una acción efectuada a un objeto.
l Una celda se puede copiar, pegar, borrar, etc.
l Una hoja se puede copiar, suprimir, renombrar, etc.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Regla de codificación
La codificación de los métodos y de las propiedades es muy sencilla: un objeto se asocia a un método o a una
propiedad separándolos por un punto:
Objeto.Método
O
Objeto.Propiedad
Por ejemplo, podemos escribir:
Cada objeto posee numerosas propiedades y métodos.
Para ayudarle a encontrar todas las propiedades relacionadas con un objeto, tras escribir un punto, aparecerá un
menú desplegable.
En ese menú, identificará las propiedades mediante el icono y los métodos mediante el icono .
Si después de escribir un punto no aparece el menú desplegable, puede hacerlo aparecer pulsando las teclas [Ctrl]
[Espacio].
Un poco más adelante en este capítulo veremos de qué manera mostrar la ayuda en línea específica de un término de
lenguaje VBA.
1. Asociación de objetos
Es posible hacer asociaciones de objetos entre sí.
Por ejemplo, para expresar que quiere copiar (Método) desde la hoja 2 (Objeto), la celda B5 (Objeto), escribirá la
línea siguiente:
Sheets("Hoja2").Cells(5,2).Copy
También puede especificar el nombre del libro cuando su macro necesite trabajar en varios archivos de Excel.
Workbooks("libro1.xlsx").Sheets("Hoja1").Cells(4, 5) = _
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Workbooks("libro2.xlsx").Sheets("Hoja1").Cells(1, 3)
Atención: respete el orden de los términos. Una celda está incluida en una hoja de cálculo. Por lo tanto debe
escribir el objeto Hoja antes que el objeto Celda. Las hojas de cálculo tienen extensiones .xlsm porque solo
las hojas de cálculo con esas extensiones guardan también el código VBA. Las hojas de cálculo xlsx están vacías de
código VBA.
2. Asociación de propiedades o de métodos
Del mismo modo, puede asociar a un objeto varias propiedades o métodos. Por ejemplo, si quiere contar el número
de filas no vacías desde la celda A1, puede escribir la instrucción siguiente:
Cells(1, 1).CurrentRegion.Rows.Count
Esta escritura puede traducirse del siguiente modo: a partir de la celda A1, seleccionamos el conjunto de celdas
adyacentes (tanto en filas como en columnas), después nos centramos en las filas que contamos.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Ayuda en línea
Ya hemos mencionado algunos términos importantes que permiten identificar celdas y filas. El cúmulo de términos,
propiedades y métodos puede llegar a confundirle, pero existe una manera muy simple de encontrar propiedades y
métodos vinculados a un objeto y es utilizando la ayuda en línea.
Para hacerlo bastará con:
l Seleccionar el término cuya ayuda quiere ver.
l Pulsar la tecla [F1] del teclado.
En su navegador aparecerá una ventana con el término seleccionado. Si la página web está vacía querrá decir que el
término seleccionado no existe o bien que la selección no es correcta.
Un truco para saber si los términos están correctamente escritos consiste en escribirlos siempre en
minúsculas. Si los términos forman parte de instrucciones reconocidas, VBE los pondrá siempre en
mayúsculas. Si las instrucciones permanecen en minúsculas, querrá decir que el lenguaje VBA no los
reconoce.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Codificación de las celdas y de los rangos de celdas
Todos sus programas van a utilizar, de una forma o de otra, el contenido de una celda o de un rango de celdas.
Llegados aquí es importante explicar cómo comunicar con una celda y/o una hoja mediante el código VBA.
1. La celda
Una celda se codifica del siguiente modo:
Siempre hay que escribir la palabra en plural. El número de fila y el número de columna son obligatoriamente
valores numéricos enteros positivos.
Observe que el número de fila se escribe en primer lugar, al contrario que en las referencias de celdas de Excel,
donde el número de fila aparece tras la letra de la columna: A1, D3, F34, etc.
2. El rango de celdas
Range(referencia)
Un rango de celdas se traduce por la instrucción Range. Esta instrucción puede utilizarse de tres maneras
diferentes.
Tomemos como ejemplo la selección de las celdas A1 a C5; podemos escribir:
Range("A1:C5").Select Las referencias de las celdas se escriben "literalmente" entre comillas. No se
pueden variar esas referencias, están congeladas.
[A1:C5].Select Aquí, reemplazamos la instrucción Range por unos corchetes, las referencias
están escritas sin comillas.
Range(Cells(1, 1), Cells(3, Esta escritura puede parecer más compleja, pero es el método que queremos
5)).Select destacar, ya que con este cada componente de las referencias de celda puede
gestionarse por una variable, como veremos a continuación.
3. Las celdas nombradas
Cuando se nombra una celda o un rango de celdas, puede recordar sus nombres en lugar de dar las referencias de
las celdas.
Por ejemplo, si la celda A1 se llama IVA, puede escribir simplemente:
[IVA].Select
De este modo, incluso si desplaza esta celda a otro lugar de su hoja de cálculo, la instrucción no se modificará en su
código. En el capítulo Optimización, sección Las celdas con nombre y las tablas, veremos las ventajas de tratar de
esta manera las celdas importantes de nuestro programa.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Significado del signo =
El signo = debe considerarse como un puente. La información que está a la derecha del signo = se traslada hacia el
elemento que está a la izquierda.
Por ejemplo, para asignar el valor 15 a la celda A1, escribimos:
Cells(1,1) = 15
Para colorear de rojo el fondo de la celda A1, escribimos:
Cells(1,1).Interior.Color = vbRed
También podemos invertir la escritura. Para conocer el código del color de la celda A1 y poner ese resultado en la
celda D1, vamos a escribir el código siguiente:
Cells(1,4) = Cells(1,1).Interior.Color
Por último, para reproducir el color de la celda A1 a la celda D1:
Cells(1,4).Interior.Color = Cells(1,1).Interior.Color
A continuación, si queremos efectuar un cálculo retomando el contenido de la celda A1 (que contiene el valor 7, por
ejemplo) para añadirle el valor 5 y que el resultado aparezca en B1, escribiremos la fórmula de la siguiente manera:
Cells(2, 1) = Cells(1, 1) + 5
Le resultado será 12 en la celda B1.
También podemos usar la misma celda como valor para usar en el cálculo y como celda para almacenar el
resultado. De esta forma, si queremos usar el contenido de la celda A1, agregarle una unidad complementaria y
transcribir el resultado también en A1, escribiremos:
Cells(1, 1) = Cells(1, 1) + 1
La consecuencia de esta línea de código será que el valor en A1 se modificará cada vez que el programa lea la línea.
Ahora quizá le parezca algo extraño, pero cuando estudiemos las variables y los bucles, esta escritura nos permitirá
avanzar de fila en fila al ejecutar el programa.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Los procedimientos
Todas las líneas de código deben escribirse en uno o varios procedimientos.
Un procedimiento se caracteriza por la escritura de la instrucción Sub (diminutivo de Subroutine que significa
Procedimiento en español) y de la instrucción End Sub que concluye el procedimiento.
Sub Cambiar_el_color()
Su programa
End Sub
Para iniciar este programa, puede o bien pulsar la tecla [F5] o bien hacer clic en el icono .
Para nombrar un procedimiento, se admiten todos los términos salvo las palabras reservadas (como For, Next,
While, Cells, Date, etc.). Las palabras reservadas son necesariamente palabras en inglés. Además, si nombra su
procedimiento con varias palabras, el único separador autorizado es _ (underscore o guión bajo). Los espacios y el
guión () están prohibidos ya que podrían impedir que el programa se ejecutara.
Si su proyecto se compone de varios procedimientos, (véase capítulo Estructura de un programa), cada procedimiento
deberá tener un nombre único.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Las funciones
Las funciones se diferencian de los procedimientos por el hecho de que estas devuelven un valor al final del
tratamiento. Son muy importantes para aislar acciones o test concretos. Por ejemplo, si queremos saber si un archivo
existe en un directorio, escribiremos una función personalizada que nos dirá si el archivo existe o no; la función
devolverá Sí o No (para ver todo el código de la función consulte el capítulo Trabajar con los archivos Encontrar un
archivo en un directorio).
Para escribir una función, hay que escribir el código entre las instrucciones Function y End Function.
Por ejemplo, vamos a crear una función personalizada que devolverá en una celda el nombre de su hoja activa.
Escribiremos esta función de la forma siguiente:
Function Nombre_Hoja()
Nombre_Hoja = ActiveSheet.Name
End Function
Aunque simple, este código muestra la diferencia fundamental existente entre una función y un procedimiento. En las
funciones, el nombre de la función (Nombre_Hoja) se utiliza a la vez como nombre de la función y como nombre para
el resultado del cálculo. Todas las funciones creadas pueden nombrarse en una hoja de cálculo.
Escriba el nombre de su función en una celda.
Observará que su función Nombre_Hoja aparece en el menú desplegable con el mismo título que las funciones
integradas de Excel.
Termine la escritura de su función (no olvide los paréntesis).
El resultado de la función se muestra en la celda:
En una hoja de cálculo, las funciones se interpretan directamente sin que usted tenga que iniciar el programa (como
para un procedimiento).
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Esta función se ha creado sin ningún parámetro, pero en el capítulo Estructura de un programa Parámetros de
llamada veremos cómo podemos transmitirle parámetros personalizados.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Introducción
Una vez vistos los principios básicos de la programación, podemos escribir nuestro primer programa. Para ello, vamos
a pedirle a Excel que nos ayude gracias a la Grabadora de macros.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
La Grabadora de macros
Esta herramienta grabará todas las acciones realizadas con Excel: selección de una celda, de un grupo de celdas, dar
formato, etc.
Muy a menudo, tendrá que eliminar algo de código para guardar solo lo esencial.
1. Versión Excel 2003 (o anterior)
Para iniciar la Grabadora, vaya al menú Herramientas Macro, y active la opción Grabar nueva macro.
Aparecerá un cuadro de diálogo que le pide que escoja un nombre para su macro.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Indique el nombre de la macro y haga clic en Aceptar.
A partir de ese momento, todas las acciones que realice se grabarán en el Visual Basic Editor.
herramientas flotante.
2. Versión Excel 2007 (o posterior)
En la esquina inferior izquierda de la ventana de Excel, en la barra de estado, verá al lado de la instrucción Listo, el
icono de la Grabadora de macros.
En la versión de Excel 2007, el icono solo puede verse si se ha activado la pestaña Desarrollador en la cinta de
opciones. Para ver la pestaña Desarrollador, remítase al capítulo El editor de Visual Basic Cómo iniciar Visual
Basic Editor.
Para iniciar la grabación, basta con hacer clic en este icono:
Aparecerá un cuadro de diálogo que le pide que escoja un nombre para su macro.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Indique el nombre de la macro y haga clic en Aceptar.
A partir de ese momento, todas las acciones que realice se grabarán en el Visual Basic Editor.
Para detener la grabación, haga clic en el mismo sitio (el icono habrá cambiado de apariencia):
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Primer ejercicio
Para nuestro primer programa, vamos a trabajar con el libro (Ejemplo 4C) que podrá descargar desde la página
Información.
El objetivo de nuestro trabajo es combinar los nombres de la columna A cuando estos sean idénticos para alcanzar el
resultado siguiente:
Como comprobará, el número de líneas que se van a combinar, varía. Por lo tanto, no es posible utilizar la
herramienta Copiar formato ya que esta herramienta respeta no solo el formato, sino también el número de
líneas afectadas. Así que debemos crear una macro para realizar esta tarea automáticamente.
En un primer momento, vamos a utilizar la Grabadora de macros para codificar la primera combinación de celda. Es
importante que respete los pasos siguientes para que pueda llegar exactamente al mismo código que el que figura a
continuación.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Inicie la Grabadora.
Conserve el nombre Macro1 y haga clic en Aceptar.
Seleccione las celdas A2 a A5.
Abra el cuadro de diálogo Formato de celdas (Formato Celda en Excel 2003 o, en Excel 2007, 2010, 2013
y 2016, haga clic en el icono de cuadro de diálogo del grupo Alineación en la pestaña Inicio).
Aparecerá el siguiente cuadro de diálogo:
Ventana de configuración de alineación de una celda
Marque la opción Combinar celdas.
Escoja la alineación Horizontal: Izquierda (sangría).
Escoja la alineación Vertical: Centrar.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Pulse Aceptar.
Aparecerá un mensaje de error que le indica que la combinación hará desaparecer valores, pero no le
haga caso: haga clic en Aceptar.
El resultado en la pantalla será el siguiente:
Detenga la grabación haciendo clic en el botón Stop .
A continuación acceda a Visual Basic Editor: en el Módulo1 encontrará un programa similar a este:
Sub Macro1()
’
’ Macro1 by.................
’
Range("A2:A5").Select
With Selection
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlCenter
.WrapText = False
.Orientation = 0
.AddIndent = False
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
End Sub
Encontrará ese código en el archivo del Ejemplo 4B2.
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Examen del código
El código comienza por líneas escritas en verde precedidas de un apóstrofo: estas líneas son comentarios. Una línea
precedida de un apóstrofo no se interpreta como código.
La primera línea que se interpretará corresponde a la selección del rango de celdas A2 a A5:
Range("A2:A5").Select
A continuación, visualizará el conjunto de datos reunidos en un bloque With/End
With. Un bloque de datos
With/End With permite asociar varias propiedades a un solo objeto. Aquí, para el objeto Selection, las líneas
corresponden a nueve propiedades del cuadro de diálogo Formato Celda pestaña Alineación:
HorizontalAlignment, VerticalAlignment, WrapText, etc.
Es uno de los principales defectos de la Grabadora de macros: cuando activa un cuadro de diálogo de Excel
(Formato de celdas, Configurar página, etc.) la Grabadora codifica todos los elementos de este cuadro de diálogo,
aunque no los haya modificado.
No dude en suprimir las líneas de código inútiles.
En nuestro ejemplo, como solo hemos cambiado tres parámetros en el cuadro de diálogo, solo podemos
conservar las siguientes líneas:
Sub Macro1()
Range("A2:A5").Select
With Selection
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlCenter
.MergeCells = True
End With
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Ejecución del código
Ahora vamos a utilizar el código para dar formato a las demás celdas del libro.
Inicie su programa, haciendo clic en el icono o pulsando la tecla [F5].
¡No ve ningún cambio en su hoja de cálculo! De hecho, la primera línea de código indica que ha seleccionado las
celdas A2 a A5, el programa solo se aplicará en esta selección (debido a la instrucción With Selection).
Para que este programa se aplique a cualquier selección de celdas, debe eliminar la línea de código Range
("A2:A5").Select o, mejor incluso, ponerla como comentario precediéndola de un apóstrofo.
El código pasa a ser:
Sub Macro1()
’Range("A2:A5").Select
With Selection
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlCenter
.MergeCells = True
End With
End Sub
Ahora comprobemos la buena ejecución del programa.
Seleccione las celdas A6:A12 e inicie su programa.
Las celdas A6 a A12 se han combinado.
Seleccione las celdas A13:A14 e inicie su programa.
Para cada selección realizada, el programa combina las celdas y alinea el texto en las celdas combinadas. Cada vez
que lo ejecute, aparecerá un mensaje de alerta de la combinación. En el capítulo Trabajar en un libro Excel, verá cómo
evitar estos mensajes con la propiedad DisplayAlerts.
En el capítulo sobre los bucles veremos cómo automatizar el programa para combinar todas las celdas sin necesidad
de seleccionarlas previamente.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Otras técnicas para mejorar el código
Cuando use la Grabadora de macros, puede reescribir fácilmente algunas acciones para mejorar la ejecución y la
lectura del código.
1. Grabar acciones con dos hojas de cálculo
Ilustraremos este punto con un ejemplo muy simple.
Realice las siguientes operaciones:
En un nuevo libro, introduzca una palabra o una cifra en la celda A1.
Inicie la Grabadora de macros.
Inserte una nueva hoja.
Vuelva a la Hoja1.
Copie el contenido de la celda A1 en B4.
Copie el contenido de la celda B4.
Seleccione la celda Hoja2 del libro.
Pegue el contenido del Portapapeles en la celda C2.
Cambie el formato de la celda C2 (fuente, color).
Vuelva a la hoja Hoja1.
Elimine el contenido de la celda A1.
Detenga la grabación.
El código generado debería ser similar a esto:
Sub Macro1()
Sheets.Add After:=ActiveSheet
Sheets("Hoja1").Select
Range("A1").Select
Selection.Copy
Range("B4").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Selection.Copy
Sheets("Hoja2").Select
Range("C2").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Selection.Font.Bold = True
Selection.Font.Underline = xlUnderlineStyleSingle
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
End With
Sheets("Hoja1").Select
Range("A1").Select
Selection.ClearContents
End Sub
Observe que cada etapa (seleccionar, copiar, pegar, eliminar) se ha codificado en el orden especificado. Veamos a
continuación cómo reducir el código sin que el resultado varíe.
2. La instrucción Select
Un análisis rápido del código muestra que la instrucción Select está presente prácticamente en todas las líneas.
Cuando tenga una línea que termine por Select y el siguiente empiece por Selection, podrá eliminar los dos
términos y escribir una sola línea de código :
Range("A1").Select
Selection.Copy
Pasará a :
Range("A1").Copy
Al eliminar todas esas repeticiones en Select, limpiará el código y reducirá sensiblemente el número de líneas de
código generado por la Grabadora.
3. La instrucción Copy
La grabadora de macros traduce la operación Copiar/Pegar en cuatro líneas de código:
Range("A1").Select
Selection.Copy
Range("B4").Select
ActiveSheet.Paste
Es posible escribir todas esas instrucciones en una sola línea de código. El método Copy posee una serie de
opciones entre las que se encuentra una llamada Destination. Con esta opción podrá copiar el contenido de una
celda y pegarlo en otra dentro de la misma instrucción.
Range("A1").Copy Destination:=Range("B4")
Como veremos en la siguiente sección, el método Copy puede reemplazarse muy bien por otro método, siempre y
cuando solo debamos copiar el contenido de una celda. Por el contrario, si lo que debemos copiar es un rango de
celdas Range("A1:C3"), deberá usarse el método Copy, que es sumamente sencillo de usar.
4. Transferencia de datos
Cuando tenga que copiar el contenido de una sola celda en otra, no será preciso usar el método Copy, bastará con
transferir el valor de una celda a la otra.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Range("B4") = Range("A1") ’Copia el contenido de A1 en B4
Cells(2, 4) = Cells(1, 1) ’Misma acción
Esto es también válido para copiar el contenido de celdas entre hojas de cálculo. En ese caso habrá que especificar
el nombre de las hojas en la instrucción:
Sheets("Hoja2").Range("C2") = Sheets("Hoja1").Range("B4")
Sheets("Hoja2").Cells(3, 2) = Sheets("Hoja1").Cells(2, 4)
5. El bloque de datos With ... End With
With Sheets("Hoja2").Range("C2")
.Font.Bold = True
.Font.Underline = xlUnderlineStyleSingle
.Interior.Pattern = xlSolid
.Interior.Color = 65535
End With
O también
With Sheets("Hoja2").Range("C2")
.Font.Bold = True
.Font.Underline = xlUnderlineStyleSingle
With .Interior
.Pattern = xlSolid
.Color = 65535
End With
End With
6. El código optimizado
En definitiva, si aplicamos los diferentes métodos enumerados arriba, podremos escribir el código en pocas líneas:
Sub Macro1()
Sheets.Add After:=ActiveSheet
Sheets("Hoja1").Select
Range("B4") = Range("A1")
Sheets("Hoja2").Range("C2") = Sheets("Hoja1").Range("B4")
With Sheets("Hoja2").Range("C2")
.Font.Bold = True
.Font.Underline = xlUnderlineStyleSingle
.Interior.Pattern = xlSolid
.Interior.Color = 65535
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
End With
Sheets("Hoja1").Range("A1").ClearContents
End Sub
Escrito de esta forma, el código es más fácil de leer ya que una línea de código corresponde a una acción y la
ejecución se ve sensiblemente mejorada.
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Síntesis
Utilizar la Grabadora de macros tiene ventajas, pero también inconvenientes:
Ventajas Inconvenientes
Permite recuperar el código de objetos, de propiedades, La Grabadora de macros escribe muchos código inútil.
de métodos, así como los parámetros de formato Todas las referencias de celdas se graban
(color, bordes, orientación, casillas de formulario, etc.). "literalmente" (se transcriben con sus coordenadas, sin
posibilidad de cambiarlas).
Todas las acciones se escriben a medida que se van
realizando, sin posibilidad de repetición (véase Los
bucles).
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Introducción
Como vimos en el capítulo Primer programa, la Grabadora de macros convierte cada una de las selecciones de celda,
de rango de celdas, en referencias fijas:
Range("A3:B5").Select
Range("C8").Select
Columns("D").Select
Este tipo de escritura del código tiende a desaparecer ya que las referencias serán invariablemente las mismas. Es
decir, el interés de hacer un programa es aplicar una instrucción a un elemento (una celda, una hoja de cálculo, un
libro, un gráfico, etc.) y después reproducir esta instrucción en otros elementos.
Este es el motivo por el que no deben escribirse las referencias de una celda directamente en el código, sino que
deberá usarse una variable que, como su propio nombre indica, permitirá hacer variar las coordenadas de la celda.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
¿Qué es una variable?
Las variables pueden verse como cajas en las que se almacenan una serie de informaciones: cifras, fechas, texto, etc.
Por supuesto que no se trata de una caja en el sentido literal, sino de un espacio reservado en la memoria del
ordenador. Como el ordenador administra este espacio en la memoria, la cuestión no está ahí. Lo que debemos
recordar es que creando una variable (una caja) con un nombre propio, el VBA sabrá siempre en qué caja deberá leer
o recuperar los datos. De hecho, bastará con declarar un nombre de variable y atribuirle un tipo de datos para que
Visual Basic se ocupe del resto.
Realmente no hay reglas para el nombre que le da a sus variables; puede escoger cualquier palabra con la condición
de que no sea una de las palabras reservadas (palabras clave) de VBA (como Sheets, Cells, Worksheets, Columns,
Rows, etc.).
Una variable puede estar compuesta por una o varias palabras, pero estas no deben estar separadas por un espacio
o por un guion (). El único carácter de separación autorizado es el guion bajo (_).
Para lograr mayor eficacia en la gestión de las variables es preferible optar por nombres comprensibles (Núm_Fila,
Nombre_Libro, Nombre_Hoja, etc.), en lugar de elegir nombres compuestos de una sola letra (i, j, k, etc.).
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
El método MsgBox
El método MsgBox es una función importante para comprender programas en Visual Basic ya que permite mostrar en
todo momento mensajes personalizados. Pero MsgBox no solo muestra mensajes personalizados, sino que también
bloquea la ejecución del resto del código.
1. Vista de un mensaje personalizado
Escriba, por ejemplo, el programa siguiente:
Sub Test_Vista()
MsgBox "Mensaje personalizado"
End Sub
este programa muestra el siguiente cuadro de diálogo:
Como podrá observar, la instrucción para mostrar un mensaje es muy sencilla, pero lo que es importante
comprender es que mientras no pulse el botón Aceptar, la ejecución del código permanece bloqueada en la línea
MsgBox.
Ahora podrá mostrar más de un mensaje personalizado y también reagrupar texto personalizado con el contenido
de una variable al mismo tiempo.
2. Ver el resultado de una variable
Todos los textos introducidos entre comillas aparecerán tal cual en el cuadro de diálogo, pero las variables no deben
escribirse nunca entre comillas. De hacerlo, el cuadro de diálogo mostraría el nombre usado en el programa para
calificar la variable y no su contenido.
Mientras que la siguiente instrucción mostrará el valor de la variable en el cuadro de diálogo.
Según el contenido de la variable (texto, número, fecha, etc.), la instrucción precedente mostrará a la vez el texto
escrito entre comillas y el contenido de la variable. Por ejemplo, podemos escribir los siguientes mensajes:
l Mi_Variable tiene como valor 35
l Mi_Variable tiene como valor París
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
l Mi_Variable tiene como valor 25/12/2017
En el apartado siguiente veremos los diferentes tipos de variables que se pueden utilizar.
Fíjese en el símbolo & entre el texto entrecomillado y el nombre de la variable. En el capítulo Administrar las listas de
caracteres veremos con más detalle técnicas propias para cadenas de caracteres (hay muchísimas), pero de
momento sepa que el símbolo & permite vincular el texto personalizado con el contenido de una variable.
3. Personalizar el mensaje
Puede personalizar la configuración del cuadro de diálogo MsgBox, el título de la ventana, el número de botones,
los iconos, etc. De esta forma los usuarios tendrán la impresión de que el mensaje es propio del programa y no un
mensaje de Excel.
El método MsgBox, además del mensaje que se quiere comunicar, posee las siguientes opciones:
La opción Botón permite cambiar el nombre de los botones que aparecen (Cancelar, Sí, No, etc.) y también cambiar
el icono que aparece a la izquierda del cuadro de diálogo. Para ello, es necesario seleccionar una de las constantes
que aparecen después de escribir una coma tras el mensaje personalizado.
El tercer parámetro permite escribir títulos personalizados.
Si escribimos la siguiente línea:
Obtendremos este mensaje:
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
será ligeramente distinto ya que hay que indicar que la respuesta del usuario (Sí o No) se incluirá en una variable.
Sub Macro1()
Dim LaRespuesta As Long
LaRespuesta = MsgBox("¿Estás contento?", vbYesNo)
End Sub
Más adelante, en el capítulo Las condiciones, estudiaremos cómo tratar las respuestas y cómo conocer el valor de la
respuesta en el capítulo Depuración.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Declaración de una variable
1. ¿Declaración obligatoria o no?
Visual Basic permite trabajar con variables sin declararlas. Sin embargo, un lenguaje informático cualquiera no
puede trabajar al mismo tiempo con datos numéricos y datos textuales. En efecto, si trata de agregar cifras y texto,
su programa se detendrá y se quedará colgado, es decir, el programa se detendrá por completo sin terminar el
tratamiento.
Declarar sus variables prevendrá un error de manipulación de los datos de un programa.
En todos los ejemplos que se muestran a continuación, las variables se declaran sistemáticamente.
Por otro lado, al declarar las variables, es muy fácil recordar sus nombres haciendo uso de la combinación de teclas
[Ctrl][Espacio] .
Basta con introducir los primeros caracteres del nombre de una variable declarada y usar el método abreviado [Ctrl]
[Espacio] para que el nombre de la variable se complete al instante.
Podrá hacer obligatoria la introducción de variables modificando una opción de la configuración de Visual Basic
Editor.
Abra el menú Herramientas Opciones.
En la pestaña Editor, marque la opción Requerir declaración de variables.
Haga clic Aceptar.
La adición de un nuevo módulo empezará sistemáticamente por la instrucción, que impone la declaración de todas
las variables, Option Explicit.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
2. Comprobación de las declaraciones
Cuando se encuentra en modo Explicit, es decir que declara todas variables, no podrá iniciar el programa si una
sola variable no ha sido declarada. El programa será incapaz de comprender de qué manera interpretar la
información.
Esto podría parecer un obstáculo, pero existe una manera muy sencilla de comprobar que todas las variables han
sido declaradas antes de iniciar el programa. Bastará con activar el menú Depuración, y el submenú Compilar
VBAProject.
La herramienta recorrerá todo el proyecto (todos los procedimientos y funciones) y si detecta que alguna variable se
usa sin haber sido declarada, lo señala mediante un mensaje de error.
3. Tipo de variable
El Visual Basic le propone una docena de tipos de variables distintas para declarar sus variables (véase Anexos
Tipos de variables). Sin embargo, no necesitará utilizarlas todas ya que normalmente solo empleará cuatro o cinco.
En todos los ejemplos de este párrafo, se usará el mismo nombre para la variable ( Mi_Variable), pero el tipo de
declaración será diferente. De esta forma le resultará más fácil comprender que es el tipo de declaración de la
variable lo que prima sobre su nombre mismo. El nombre es solo un medio nemotécnico que le permitirá saber si una
variable contiene una dirección (por ejemplo Dirección_Cliente), un código postal (CP_Cliente) o un
número de fila (Num_Fila).
a. Declaración de texto
Cuando una variable contenga texto, tendrá que declararse obligatoriamente en String.
Sub Test_Variable()
Dim Mi_Variable As String
Mi_Variable = "Hola" ’La variable Mi_Variable vale "Hola"
MsgBox "Valor de la variable : " & Mi_Variable ’Vista
Mi_Variable = 10 ’El programa convierte la cifra 10 en
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
texto "10" y ningún cálculo será posible con ese dato.
End Sub
Si trabaja con cadenas de caracteres de longitud fija, se puede especificar la longitud que se espera. Por ejemplo,
si tiene una variable para almacenar un código postal (longitud siempre igual a cinco caracteres), puede hacerlo de
la siguiente manera:
Sub Test_Variable()
Dim Mi_Variable * 5 As String
Mi_Variable = "12345" ’La variable Mi_Variable vale "12345"
MsgBox "Valor de la variable: " & Mi_Variable ’Vista
Mi_Variable = "1234567" ’La variable Mi_Variable vale "12345"
MsgBox "Valor de la variable: " & Mi_Variable ’Vista
Mi_Variable = "11" ’La variable Mi_Variable vale "11 "
’(3 vacíos después de la cadena de caracteres)
MsgBox "Valor de la variable: " & Mi_Variable ’Vista End Sub
Encontrará otro ejemplo de la aplicación de variables String con una longitud definida en el primer párrafo del
capítulo Administrar las listas de caracteres.
b. Declaración de números
En VBA, un número con decimales y un número entero son dos elementos diferentes, y por lo tanto, no se declaran
del mismo modo. Para los números decimales, debe declararlos en Double y para los números enteros, ha de
declararlos en Long.
Sub Test_Variable()
Dim Mi_Variable As Long
Mi_Variable = "Hola" ’El programa se detiene porque el tipo transmitido
’ no es el que se esperaba.
Mi_Variable = 10 ’Mi_Variable vale 10
MsgBox "Valor de la variable: " & Mi_Variable ’Vista
Mi_Variable = 10,54 ’Mi_Variable vale 10 (no hay decimal en Long)
MsgBox "Valor de la variable: " & Mi_Variable ’Vista
End Sub
Si declara una variable en Long y le transmite un número decimal no se produce error, pero solo se conserva la
parte entera.
Sub Test_Variable()
Dim Mi_Variable As Double
Mi_Variable = 20 ’Mi_Variable vale 20
MsgBox "Valor de la variable: " & Mi_Variable ’Vista
Mi_Variable = 20,88 ’Mi_Variable vale 20,88
MsgBox "Valor de la variable: " & Mi_Variable ’Vista
End Sub
Existen otros tipos de declaración de los números como Integer, Byte, Single, etc. Hace ya unos veinte años,
era muy importante la optimización de la memoria y, por tanto, declarar muy bien las variables. Hoy en día, dado el
rendimiento de los ordenadores ya no es necesario tener eso en cuenta.
El Visual Basic 7 (que salió con Office 2010) convierte sistemáticamente las declaraciones de tipo Byte, Integer
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
en tipo Long y Single en Double al ejecutar un programa.
Por lo tanto, para los números trabaje únicamente con los tipos Double para los decimales y
Long para los enteros.
Desde que salió Office 2010, el Visual Basic trabaja con ordenadores con una arquitectura de 64 bits. Si aumenta
el tamaño de la memoria, puede realizar cálculos en 8 bytes. Para definir una variable con 8 bytes, le tiene que
designar el tipo LongLong. Esto solo funciona para las versiones de Office de 64 bits. Veremos más
detalladamente este aspecto concreto de las variables de 64 bits en el capítulo Optimización El entorno de
64 bits.
c. Declaración fechas
Las fechas son números particulares porque las manipulaciones vinculadas a fechas son específicas (día, mes,
año). Si desea almacenar fechas dentro de variables, deberá declararlas como tipo Date (es lógico).
Las horas deberán también declararse como tipo Date.
El tipo de declaración Date se hace cargo tanto de fechas como de horas. Si envía un número entero a una
variable de tipo Date, el valor se convertirá en número de días desde el 01/01/1900 (primera fecha en Excel) y si
transmite un variable decimal, la parte entera se convertirá en fecha y la parte decimal en hora.
d. Declaración de objetos
El término objetos puede resultar confuso, pero hay que comprender que una hoja de cálculo, un libro, una
columna, una celda, etc. son, de hecho, objetos y varias propiedades están vinculadas a ellos.
En la imagen siguiente, por ejemplo, puede ver una parte de las propiedades vinculadas al objeto Hoja de
cálculo. En el capítulo Depuración veremos cómo hacer que aparezca la lista de propiedades vinculadas a objetos.
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Información obtenida gracias a las Inspecciones de la depuradora.
Las variables Object se declaran siempre precedidas de la instrucción Set.
e. Declaración booleana
Las variables booleanas ( Boolean) solo aceptan dos valores: Verdadero o Falso. Son las variables más
elementales, ya que son las que ocupan menos memoria.
Este tipo de variables resulta muy útil para declarar el resultado de test como que:
l una celda esté o no vacía,
l las opciones de un cuadro de diálogo estén marcadas o no,
l haya o no una hoja de cálculo,
l etc.
Cuando comprueba el valor de variables booleanas, puede comprobar que los valores sean Verdadero ( True) o
Falso (False) o bien, todavía más simple 1 (True) o 0 (False).
f. Declaración en Variant, declaración cajón de sastre
Al contrario que las funciones booleanas que solo usan un bit, existe una declaración que usa todo el espacio en
memoria que VBA autoriza, es decir, 16 bytes. Esta variable se conoce como Variant y es posible almacenar en
ella cualquier tipo de datos (texto, números, fechas, booleanos) sin que el programa se interrumpa debido a
incompatibilidades en el tipo de datos.
De hecho, las variables en Variant pueden recibir múltiples tipos de datos durante de la ejecución del programa.
Resultan muy prácticas en el caso de declarar algunos tipos de tablas en memoria (vea el último apartado de este
capítulo) o para usar la función InputBox que permite transmitir datos en un programa (véase el párrafo
siguiente) ya que, una vez más, se desconoce el tipo de datos que introducirá el usuario. Pero el mayor riesgo de
declarar todo como Variant es realizar manipulaciones de variables (cálculo o concatenación) en los distintos
tipos. Por lo tanto, aprenda a usarlos bien pronto para evitar el abuso de este tipo de declaración.
4. Alcance de las variables
a. La instrucción Dim
La instrucción Dim (diminutivo de Dimension) permite definir un nombre como si fuese una variable y asignarle un
espacio de almacenamiento.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
DIM Nombre_de_la_variable AS Tipo de variable
Una variable se declara siempre al principio de un procedimiento. Al declarar una variable dentro de un
procedimiento, esta solo se reconocerá (o será visible) para este único procedimiento.
La declaración de una variable con la instrucción Dim inicializa la variable.
Una variable declarada en uno de los formatos numéricos tendrá como valor 0, una variable declarada de tipo
String estará vacía (no confundir con una cadena de caracteres que contiene espacios).
Esto implica que si vuelve a referirse a este procedimiento en el transcurso del programa, no conservará el último
valor almacenado en las variables como lo veremos en el capítulo Estructura de un programa.
En el capítulo Estructura de un programa, veremos que es posible escribir una variable Dim al principio de un
módulo.
b. La instrucción Static
La instrucción Static se declara también en un procedimiento pero, a diferencia de la instrucción Dim que
inicializa las variables desde la entrada a este procedimiento, una variable declarada en Static conserva su
valor en la memoria; este valor se conserva mientras Excel esté abierto. O dicho de otra forma, si vuelve a iniciar
su programa, su código se ejecutará utilizando el último valor de sus variables declaradas en Static.
Por ejemplo, si inicia varias veces el siguiente código:
Sub Variable_Static()
Static Núm_Fila as Long
Núm_Fila = Núm_Fila +1
Cells(Núm_Fila , 1) = Núm_Fila
End Sub
Observará que para cada nueva ejecución, el programa escribe el resultado en una nueva línea. Como la variable
se ha declarado en Static, cada nueva ejecución reutilizará el anterior valor calculado.
Si ahora utiliza el mismo programa pero con la variable declarada en Dim, el valor de la variable seguirá siendo
igual a 1, ya que Dim reinicializa sistemáticamente las variables.
Sub Variable_Static()
Dim Núm_Fila as Long
Núm_Fila = Núm_Fila +1
Cells(Núm_Fila , 1) = Núm_Fila
End Sub
- 6- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Debemos señalar que la instrucción Static casi nunca se usa en programación. Si desea conservar el contenido
de una variable durante toda la ejecución del programa, es preferible que declares las variables en Public.
c. La instrucción Public
Si desea que una variable sea visible en todos los módulos para todos los procedimientos de un proyecto (es
decir, en todos los Sub), deberá declararla al principio de un módulo y, sobre todo, no hacerlo en procedimientos
en modo Public de la siguiente forma:
Como para una variable Static, el valor se conservará en la memoria mientras Excel esté abierto y todos los
procedimientos o funciones de su proyecto reconocerán la variable.
Generalmente, los nombres de archivos, las rutas de acceso o los nombres de hoja de cálculo se
declaran en variable Public ya que esa información a menudo la vuelven a usar todos los
procedimientos.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 7-
Caso práctico de utilización de una variable
Queremos hacer un programa que mostrará un número de fila, sumar este número de fila a sí mismo y multiplicarlo
por sí mismo. Podemos escribir el código de la siguiente forma:
Sub Cálculo()
Cells(1, 1) = 1
Cells(1, 2) = 1 + 1
Cells(1, 3) = 1 * 1
End Sub
El resultado es el siguiente:
Si iniciamos varias veces este programa, obtendremos siempre el mismo resultado. Es lógico, ya que siempre
llamamos a los mismos valores.
Para hacer más dinámico este programa, vamos a reemplazar todos los valores 1 por una variable.
El código pasa a ser:
Sub Cálculo()
Dim Val_Data As Long
Val_Data = 1
Cells(1, 1) = Val_Data
Cells(1, 2) = Val_Data + Val_Data
Cells(1, 3) = Val_Data * Val_Data
End Sub
Si iniciamos varias veces este programa, el resultado seguirá invariable ya que la ejecución se hará siempre con el
valor 1.
Ahora, si le damos el valor 2 a la variable Val_Data, obtendremos el siguiente resultado:
Por descontado, cambiar a mano el valor de la variable es una herejía, pero en el capítulo Los bucles veremos cómo
automatizar la actualización del valor de nuestra variable. También podemos utilizar el método InputBox como
veremos en el siguiente párrafo.
La variable Val_Data también puede usarse como parámetro del número de fila en la instrucción Cells.
El código pasa a ser:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Sub Cálculo()
Dim Val_Data As Long
Val_Data = 1
Cells(Val_Data, 1) = Val_Data
Cells(Val_Data, 2) = Val_Data + Val_Data
Cells(Val_Data, 3) = Val_Data * Val_Data
End Sub
Inicie tres veces seguidas el programa con los valores para la variable Val_Data: 1, 2 y 3.
El resultado figura en su hoja de cálculo en las filas 1, 2 y 3:
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
El método InputBox
En el ejemplo precedente, para cambiar el valor de la variable, no tenemos otra opción que modificar el programa
cambiando manualmente el valor de la variable Val_Data. Coincidirá con nosotros en que esa no es una solución
demasiado práctica.
Para evitar tener que cambiar a mano el valor de algunas variables en el programa, es posible transmitir el valor de
una variable en un programa en curso de ejecución. Esto puede hacerse gracias al método InputBox.
El método InputBox se construye en parte como el método MsgBox pero además, hay que prever una variable que
recibirá el valor que se quiere transmitir al programa.
Cuando el programa llegue a la instrucción, aparecerá en pantalla el siguiente cuadro de diálogo:
Para continuar ejecutando el programa, deberá introducir alguna información (texto, número, fecha) en el cuadro de
texto y confirmar haciendo clic en el botón Aceptar.
En este ejemplo queremos recibir un número entero (Long) que corresponde al valor de la fila, pero para prevenir
cualquier error de tecleo, es preferible que declaremos la variable como Variant. Nuestro programa anterior puede
entonces escribirse:
En adelante, cada vez que se inicie el programa, un cuadro de diálogo le preguntará en qué fila desea que aparezca
el resultado y, una vez que pulse el botón Aceptar, Excel mostrará el resultado en la hoja de cálculo.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Las tablas en memoria
1. Presentación
En programación, puede designar a una sola variable varios valores ordenándolos unos tras otros mediante una
tabla.
Trabajar con tablas en memoria no es demasiado complicado; es exactamente como trabajar con informaciones
ordenadas dentro de una columna de su hoja de cálculo.
Suponiendo que tiene un programa que utiliza todos los días de la semana, en lugar de crear una variable para
cada día de la semana, puede crear una tabla que se llamará Día_Semana y que contendrá todos los días de la
semana: lunes, martes...
Para devolver los elementos ordenados en una tabla, basta con precisar la posición (el índice) en la tabla.
Por ejemplo:
Día_Semana(0) = Lunes
Día _ Semana (2) = Martes
Día _ Semana (6) = Domingo
El primer elemento ordenado en una tabla empieza en el índice 0.
2. Las ventajas de trabajar con tablas
Llegados a este punto de nuestro manual, no es preciso abundar en más detalles sobre el trabajo con tablas en
memoria. Sepa, no obstante, que existen funciones propias de las tablas que hacen ganar muchísimo tiempo, tanto
en lo que se refiere a la escritura del código como a la ejecución del programa.
Por ejemplo, puede conocerse al instante el número de elementos ordenados en la tabla mediante la instrucción
UBound. Del mismo modo, si desea borrar todos los valores de una tabla en memoria, bastará con usar la
instrucción Erase.
Encontrará numerosos ejemplos de aplicaciones e instrucciones propias de las tablas en el capítulo Optimización,
dentro de la sección Las tablas en memoria.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Introducción
Un programa informático lleva a cabo tests constantemente: qué valor es mayor, qué celdas están vacías, etc. En
función del resultado obtenido, el programa efectúa o no un tratamiento específico.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
La instrucción If
IF condición THEN
[Instrucciones si Verdadero]
[ELSE]
[Instrucciones si Falso]
END IF
1. Presentación
La instrucción IF es muy simple de entender. Se realiza un test (o condición) que sea o bien verificado (Verdadero) o
bien no verificado (Falso).
Por ejemplo, puede comprobar:
l el valor de los números de fila,
l si una celda está o no vacía,
l la diferencia de valor entre dos celdas,
l la presencia de una hoja en un libro,
l ...
Una condición solo devuelve dos datos: el test es Verdadero o Falso (y nada más).
En el caso de que el test sea Verdadero, el programa ejecuta las instrucciones que se encuentran después de THEN
(traducción de Entonces).
Si el resultado de la condición es Falso, el programa realiza las instrucciones que se encuentran después de ELSE
(traducción de Si no).
Caso concreto: si desea comprobar que una variable tiene el valor True, no es necesario que lo especifique en el
test.
Las siguientes escrituras son similares.
o
If Mi_Variable Then
En el capítulo Las funciones básicas veremos cómo integrar operadores de comparación u operadores lógicos ( And,
Or) para enriquecer nuestros tests.
2. Ejemplo de aplicación
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
La siguiente hoja de cálculo muestra el resultado de los encuentros entre 6 equipos. En la columna A aparece el
nombre de los equipos, en la B el número de puntos en la clasificación y en la C, el resultado de la última jornada
(ganado = 1, perdido = 0).
Cuando se ha ganado un partido, el equipo se apunta 3 puntos, si no, el equipo se apunta 1 punto. Queremos
añadir +3 al valor de la columna B cuando el resultado de la columna C sea igual a 1; cuando el valor sea igual a 0,
añadiremos +1.
En VBA, se traduce del siguiente modo:
Sub Resultado_Partido()
If Cells(2, 3) = 1 Then
Cells(2, 2) = Cells(2, 2) + 3
Else
Cells(2, 2) = Cells(2, 2) + 1
End If
End Sub
3. Explicación
La parte de la derecha del signo = utiliza el valor de la celda B2 en la operación. Es decir, 35 + 3. Aquí la celda B2 se
lee y su contenido se utiliza en un cálculo.
La parte de la izquierda del signo = indica dónde guardamos el resultado. Por lo tanto, reutilizamos la celda B2 que
aquí se utilizará como lugar de almacenamiento.
En resumen:
l antes de la ejecución de la línea de comando, la celda B2 tiene el valor 35;
l en la instrucción, este valor se utiliza en el cálculo;
l al final, la celda B2 vale 38.
4. Transformación del código
Para permitir a nuestro programa que se ejecute en todas las líneas, vamos a sustituir en cada instrucción Cells,
el índice de la fila por una variable.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Sub Resultado_Partido()
Dim Núm_Fila as Long
Núm_Fila = 2
If Cells(Núm_Fila , 3) = 1 Then
Cells(Núm_Fila , 2) = Cells(Núm_Fila , 2) + 3
Else
Cells(Núm_Fila , 2) = Cells(Núm_Fila , 2) + 1
End If
End Sub
Ahora, basta con que cambie el número de línea para aplicar este código a todos los equipos:
Inicie su programa para Núm_Fila = 3.
Inicie su programa para Núm_Fila = 4.
Inicie su programa para Núm_Fila = 5.
Inicie su programa para Núm_Fila = 6.
Inicie su programa para Núm_Fila = 7.
En el capítulo Los bucles veremos cómo hacer para que los valores de las variables se modifiquen automáticamente.
Y el resultado en la pantalla pasa a ser:
5. Abreviatura de escritura
Como la instrucción IF es una de las funciones más utilizadas en programación, existen otras formas de escribirla.
Retomando el mismo ejemplo, si el resultado es una derrota sin ningún punto, ya no necesitamos la instrucción
Else. Añadir 0 al resultado anterior obviamente no tiene sentido. Por lo tanto, nuestro test se escribiría:
If Cells(2, 3) = 1 Then
Cells(2, 3) = Cells(2, 3) + 3
End If
Pero en ese caso, también podríamos haber escrito toda la instrucción en una sola línea, colocando el resultado de
la condición justo después de la instrucción THEN:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Una instrucción IF con Else también puede escribirse en una sola línea. En ese caso, hay que utilizar la instrucción
lif que respeta la misma sintaxis que la función SI en Excel:
El resultado de esta función se copia en una celda o en una variable.
Aplicado a nuestro programa, el test pasa a ser:
Sub Resultado_Partido()
Dim Núm_Fila as Long
Núm_Fila = 2
Cells(Núm_Fila , 2) = Iif(Cells(Núm_Fila , 3) = 1, _
Cells(Núm_Fila , 2) + 3, Cells(Núm_Fila , 2) + 1)
End Sub
6. Condición anidada
Como ya sabe, un partido puede ganarse o perderse, pero también puede haber un empate. Por tanto, debemos
modificar nuestra condición para tener en cuenta este tercer elemento.
Una función IF solo puede tratar dos resultados, Verdadero o Falso. Entonces, para integrar a nuestra condición IF
un tercer resultado, debemos crear otra instrucción IF en la parte Else de la primera condición. Es lo que se
conoce como imbricación de las condiciones (o Si imbricado).
En caso de partido empatado, un equipo gana dos puntos. La nueva tabla de resultados es la siguiente:
En lo que respecta al código, vamos a retomar el programa anterior y vamos a añadir una nueva condición. Vamos a
reemplazar el caso en que el test sea Falso, por un nuevo test en el que trataremos los dos últimos casos. El código
será el siguiente:
Sub Resultado_Partido()
Dim Núm_Fila as Long
Núm_Fila = 2
If Cells(Núm_Fila , 3) = 1 Then
Cells(Núm_Fila , 2) = Cells(Núm_Fila , 2) + 3
Else
If Cells(Núm_Fila, 3) = 0 Then
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Cells(Núm_Fila , 2) = Cells(Núm_Fila , 2) + 1
Else
Cells(Núm_Fila , 2) = Cells(Núm_Fila , 2) + 2
End If
End If
End Sub
Tenemos nuestras tres posibilidades de resultados.
Como el número de casos que tratamos es importante, el número de funciones IF que combinamos entre sí,
también lo será y el programa corre el riesgo de ser ilegible para usted, y más aún para las personas que vayan a
leerlo. Si un caso así llega a producirse, es preferible optar por el método con la instrucción SELECT CASE.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
La instrucción SELECT CASE
1. Presentación
La instrucción Select Case (traducción de ’Según el caso’) comprobará un valor.
A diferencia de la instrucción If que solo permite tratar dos casos (Verdadero o Falso), la instrucción Select Case
le permite precisar todos los valores posibles. Los diferentes casos que va a enumerar se llaman conexiones.
La conexión Case Else se escribe siempre al final de la instrucción y se efectúa cuando el valor que va a
comprobar no se encuentra en ninguna conexión anterior.
2. Ejemplo de utilización
a. Test a un solo valor
Es el caso más simple. Puede crear una conexión para cada valor unitario posible.
Imaginemos que desea mostrar la cantidad de artículos que hay en ese momento en stock. En A1 puede ver el
nombre del artículo y desea que en B1 aparezca la cantidad en stock relativa a ese producto. Para ello
escribiremos el siguiente programa:
Sub Cantidad_en_stock ()
Select Case Cells(1, 1)
Case "Producto 1"
Cells(1, 2) = 25
Case "Producto 2"
Cells(1, 2) = 18
Case "Producto 3"
Cells(1, 2) = 36
Case "Producto 4"
Cells(1, 2) = 51
Case Else
Cells(1, 2) = "El producto no se conoce"
End Select
End Sub
En nuestro test, el contenido de la celda A1 se lee al principio de la instrucción y, según sea su valor, devolvemos
la cantidad en stock relativa a la conexión. Si el contenido de A1 es igual a Producto 3, la celda B1 mostrará 36 y
así para todos los productos.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Si el valor de A1 no se encuentra en las diferentes conexiones, como por ejemplo ’Producto 10’, la que se ejecute
será la instrucción Case Else.
b. Test en varios valores no contiguos
En un Select Case también puede especificar en una misma conexión, todos los valores no contiguos posibles
que puede tomar el valor verificado. Para ello, basta con separar cada uno de ellos con una coma.
Por ejemplo, quiere crear un test que muestre la palabra "Número primo" en B1 en función del valor contenido en
A1.
Sub Es_Primo()
Select Case Cells(1, 1)
Case 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
Cells(1, 2) = "Número primo"
Case Else
Cells(1, 2) = "No es un número primo"
End Select
End Sub
c. Test en valores contiguos
Puede indicar que una conexión Case debe ejecutarse para todos los valores comprendidos en un intervalo
mediante la instrucción To. Por ejemplo, si realiza un test que devuelva la calificación en función del valor
contenido en A1. Su test se escribirá de la siguiente forma:
Sub Resultado_Examen()
Select Case Cells(1, 1)
Case 0 To 4.99
Cells(1, 2) = "No aprobado"
Case 5 To 5.99
Cells(1, 2) = "Aprobado"
Case 6 To 6.99
Cells(1, 2) = "Aprobado. Bien"
Case 7 To 8.99
Cells(1, 2) = "Aprobado. Notable"
Case Else
Cells(1, 2) = "Aprobado. Sobresaliente"
End Select
End Sub
Observe que las diferentes conexiones no se solapan. Sin embargo, si se diese el caso, el programa no habría
detectado la anomalía y habría devuelto el primer caso respondiendo al criterio de selección.
3. Reversibilidad
Hasta ahora, hemos realizado tests en el valor de una celda o de una variable. Pero a la inversa también es posible.
La instrucción Select Case permite verificar un valor y encontrar en qué caso se ha verificado ese test.
A modo de ejemplo, cojamos el siguiente libro (Ejemplo 6C3):
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Queremos aplicar un porcentaje de descuento en función del estado civil de un individuo.
Para ello, creamos una función personalizada llamada Estado_Civil.
Vamos a utilizar la instrucción Select Case para verificar que una celda es igual a 1 o bien Verdadero (True).
Function Estado_Civil
Select Case True
Case Cells(1, 2)
Estado_Civil = 5
Case Cells(2, 2)
Estado_Civil = 0
Case Cells(3, 2)
Estado_Civil = 10
Case Cells(4, 2)
Estado_Civil = 15
Case Else
Estado_Civil = ”Imposible”
End Select
End Function
En la celda B6, escriba =Estado_Civil().
Observe que en caso de que tenga que verificar el valor 1 o 0, también puede verificar en valores True (Verdadero)
o False (Falso).
Esta técnica de programación es muy útil para hacer tests en cuadros de diálogo y saber qué casillas de verificación
se han marcado y cuáles no.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
¿IF o SELECT CASE?
Hace algunos años, la instrucción Select Case desapareció de los programas ya que requería demasiada memoria.
Después cambiaron las cosas y el problema de la memoria se volvió obsoleto. Sin embargo, las ideas arraigadas son
difíciles de cambiar y la instrucción Select Case no es muy popular entre los programadores.
Lejos de estas consideraciones, es más coherente utilizar la función IF cuando solo hay una, dos o incluso tres
posibilidades. A partir de ahí, es preferible utilizar la función Select Case.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Ejemplo de uso de dos instrucciones
Tomemos el siguiente ejemplo donde queremos extraer datos de una hoja de cálculo para copiarlos en otra. Sabemos
que este trabajo puede hacerse a través la herramienta Filtro de Excel, sin embargo, si debemos llevar a cabo la
operación a menudo, el hecho de crear un programa nos hará ganar mucho tiempo. Para ello escribiremos un test que
usará la instrucción IF y la instrucción Select Case.
1. Crear un test en función de los parámetros
Desea crear un programa que extraerá una serie de información a partir de un rango de datos y quiere que los
propios usuarios escojan ellos mismos la columna de filtrado y el valor que desean filtrar.
En tales casos, muchos desarrolladores de Excel usarían la Grabadora de macros para recuperar el código generado
por Excel. Esta solución funciona, por supuesto, pero genera un bloqueo porque obliga a conservar en el código el
valor de la columna que queremos filtrar, el criterio de filtrado (mayor, menor, diferente, etc.) y el valor a partir del
cual se hará el filtro.
Ahora bien, lo que nosotros queremos es que el usuario pueda elegir libremente esos tres elementos: la columna a
filtrar, el criterio de filtrado y el valor para realizar el filtro.
Supongamos que tenemos el siguiente documento, en el que hay fechas, nombres de los clientes, artículos,
cantidades y valores. Podrá descargar este ejemplo, llamado Ejemplo 6E1.xlsx, desde la página Información.
2. Crear los parámetros
Para que los usuarios seleccionen los parámetros de filtrado, crearemos en tres celdas los parámetros para la
selección de la columna, el criterio de filtrado y el valor que deseamos probar.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Para crear un menú desplegable con las elecciones autorizadas, haga clic en la pestaña Datos grupo
Herramientas de datos Validación de los datos. Seleccione la opción Lista y a continuación, en la zona
Origen, introduzca los parámetros permitidos.
3. Crear un test en el programa
El principio del programa es muy simple, basta con reunir e introducir en variables los valores introducidos por el
usuario.
No obstante, y esto es específico de Excel, es preciso convertir las letras introducidas por el usuario en valores
numéricos. Esto puede hacerse muy fácilmente con esta línea de código:
A continuación, debemos escribir todos los casos posibles con ayuda de la función SELECT CASE.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Test1 = Cells(Num_ Fila, Num_Columna) <> Val_Filter
Case "Contiene"
Test1 = Cells(Num_ Fila, Num_Columna) Like "*" &
Val_Filter & "*"
Case "No contiene"
Test1 = Not (Cells(Num_ Fila, Num_Columna) Like "*" &
Val_Filter & "*")
End Select
Estudiaremos la instrucción Like en el capítulo dedicado a cadenas de caracteres.
El programa lleva a cabo una búsqueda mediante la instrucción Select Case, a partir del signo introducido por el
usuario (Val_Sign). Según el valor introducido por el usuario, buscaremos la escritura del test correspondiente y la
almacenaremos en la variable Test1. Como esta variable solo puede autorizar dos únicos valores (Verdadero o
Falso), deberemos declararla como booleano (Dim Test1 As Boolean).
Independientemente del signo seleccionado por el usuario, nosotros compararemos los dos mismos elementos:
l La celda en que se basa el test Cells(Num_Fila, Num_Columna), donde Num_Fila corresponde a la fila tratada y
Num_Columna corresponde a la columna introducida en los parámetros.
l El valor que debe comprobarse y que el usuario ha dado en la tabla de parámetros.
Al concluir este primer bloque de líneas de código que nos ha permitido traducir el test del usuario en lenguaje VBA,
deberemos usar el test para seleccionar o no los datos. El test se escribe de la siguiente manera:
If Test1 Then
Instruction
End if
Donde Instruction corresponde a las instrucciones de extracción que va a ejecutar. Podrá encontrar este
ejemplo en el archivo Ejemplo 6E2.xlsm.
No es necesario escribir Test1 = True ya que en las funciones If, el valor True se busca por defecto.
4. Programa completo
Para terminar el programa, solo quedará repetir este test tantas veces como filas haya en la hoja de cálculo. Es lo
que se conoce como hacer un bucle. Estudiaremos la administración de los bucles en el capítulo Los bucles.
El programa completo Ejemplo 6E2.xlsm puede descargarse desde la página Información.
Para comprender cómo funciona este programa, cambie los parámetros de filtrado escribiendo, por
ejemplo:
C No contiene Santo
C Contiene Castelblanco
B = Paul
A >= 01/04/2014
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
D <= 75
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Introducción
Los programas que hemos realizado hasta ahora solo pueden ejecutarse una vez con un único valor para las
variables. Para evitar tener que iniciar varias veces el mismo programa cambiando manualmente los valores de las
variables, vamos a estudiar ahora los bucles, que se encargarán de cambiar el valor de las variables en nuestro lugar
y de ejecutar así las instrucciones varias veces.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
La instrucción For ... Next
Con:
l Índice: corresponde a la variable. Su valor evolucionará durante el bucle;
l Principio: valor con el que empezará el bucle;
l Fin: valor con el que acabará el bucle;
l Paso: incremento del valor del bucle. Este valor es facultativo; por defecto, el valor del Paso es igual a 1.
Un bucle FOR ... NEXT se comprende muy fácilmente: el bucle empieza con el valor Principio y se termina cuando el
Índice alcance el valor Fin. Los bucles FOR ... NEXT se utilizan para un número conocido de repeticiones.
1. Etapas de un bucle For ... Next
Al principio, la variable Index se inicia con el valor indicado. Si escribimos For
Index = 1, la variable Index valdrá
1, si escribimos For Index = 50, la variable Index valdrá 50, y así sucesivamente.
A continuación, el programa interpretará las líneas de código correspondientes a su Instruction usando el valor
de la variable Index.
Por último, cada vez que se alcance la instrucción Next, la variable Index se incrementará. El incremento estará en
función del valor del Paso (si se omite el Paso, el incremento será de una unidad).
Todas las etapas del bloque Instruction se repetirán hasta que la variable Index alcance el valor límite definido
por la instrucción To.
2. Primer ejemplo de bucle
Vamos a retomar el ejemplo del método InputBox realizado en el capítulo Las variables pero vamos a remplazar la
instrucción InputBox por un bucle para que el programa ejecute 10 veces los cálculos. El programa pasa a ser:
Sub Programa_Principal()
Dim Val_Data As Long
For Val_Data = 1 To 10
Cells(Val_Data, 1) = Val_Data
Cells(Val_Data, 2) = Val_Data + Val_Data
Cells(Val_Data, 3) = Val_Data * Val_Data
Next Val_Data
End Sub
3. Explicación del código
Al iniciar el bucle, la variable Val_Data toma el valor 1.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
A continuación, el programa accede al bloque de instrucciones que se repetirá; la variable Val_Data se utiliza en
los parámetros de cálculo y para escribir el resultado. En nuestro primer pasaje, el resultado se inscribirá en la
primera fila de la hoja de cálculo. El programa escribirá en la celda A1 el valor 1, en A2, el resultado 1 + 1 es decir, 2
y en A3, el resultado 1 * 1 es decir, 1.
A continuación, el programa llega a la instrucción Next que aumentará (o incrementará) la variable Val_Data en una
unidad. Al mismo tiempo, se realiza un test para verificar que la variable Val_Data no ha alcanzado el valor máximo
situado después de To, es decir, 10 en nuestro ejemplo. Como en este momento, Val_Data vale 2, el programa
volverá a la instrucción For. Y así sucesivamente, hasta que la variable Val_Data alcance el último valor del bucle, es
decir, 10.
Al final del proceso, el resultado será el siguiente en nuestra hoja de cálculo:
Llegados aquí podrá poner como valor máximo del bucle un valor diferente de 10. Reinicie el programa cambiando el
valor máximo para que el nuevo resultado aparezca en la hoja de cálculo.
A título de ejemplo, ponga 1000 como valor máximo y observe cuánto tiempo emplea su ordenador en hacer los
cálculos.
4. Ejemplo de bucle con dos variables
Hasta ahora, hemos utilizado una sola variable para modificar la referencia de las filas de una celda. Pero como ya
sabe, la instrucción Cells se compone de la referencia de una fila y de una columna. También es posible crear un
programa que haga variar el índice de las filas y el índice de las columnas.
En el ejemplo siguiente vamos a crear una tabla de multiplicación 15x15. Y para que entienda bien la lógica de la
construcción del programa, vamos a desgranar cada etapa.
a. Etapa nº 1
Para su primer programa, no trate de diseñar el problema entero. Empiece siempre su programa calculando una
sola celda. A continuación, agregue los bucles y variables que permitan reproducir este cálculo en las demás celdas
de la hoja.
Empecemos, pues, por el cálculo de la primera celda:
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Sub Tabla_Multiplicación()
Cells(1, 1) = 1 * 1
End Sub
b. Etapa nº 2
Ahora introduzca el primer bucle que permita el incremento de filas. Reemplazaremos el índice de las filas por una
variable que servirá también en nuestro cálculo. El código pasa a ser:
Sub Tabla_Multiplicación()
Dim Núm_Fila as Long
For Núm_Fila = 1 To 15
Cells(Núm_Fila, 1) = Núm_Fila * 1
Next
End Sub
Este programa completará las quince primeras filas de la columna A dando los valores de 1x1 a 15x1.
c. Etapa nº 3
Para finalizar, vamos a construir un segundo bucle que permita hacer variar el índice de las columnas:
Sub Tabla_Multiplicación()
Dim Núm_Fila as Long
Dim Núm_Col as Long
For Núm_Col = 1 To 15
For Núm_Fila = 1 To 15
Cells(Núm_Fila, Núm_Col) = Núm_Fila * Núm_Col
Next
Next
End Sub
d. Síntesis
El encadenamiento de tareas es muy sencillo. El programa ejecuta, en primer lugar, el bucle de las columnas y
después, el de las filas que se realiza quince veces.
Cuando termina el bucle de las filas, incrementamos en una unidad la variable de las columnas para rellenar la
columna B. Y después, volvemos a empezar el bucle de las filas partiendo del valor 1 (iniciando siempre la variable
al principio del bucle). Esta vez los resultados se introducirán en la columna B (ya que el índice de la columna vale
2) para los valores que van de 2x1 a 2x15. Y así sucesivamente, hasta que el bucle de las columnas llegue al
último valor, 15.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Bucle según condición
WHILE condición
[Instrucción]
WEND
a. Principio
A diferencia de un bucle FOR ... NEXT en el que se impone especificar el número de veces que se ejecutará el
bucle, un bucle WHILE ... WEND se para cuando se verifica un test (ver capítulo Las condiciones).
Por ejemplo, es posible realizar un bucle hasta que el programa alcance la primera celda conocida. Así, sea cual
sea el número de celdas no vacías de una columna, el bucle se detendrá cuando el programa alcance la primera
celda vacía.
b. Ejemplo de aplicación
Vamos a escribir un programa que recorrerá todas las filas de la columna A hasta que lleguemos a la última celda.
Por cada celda no vacía, escribiremos el número de fila de la columna B.
Obtendremos el siguiente código, pero así escrito, no puede funcionar:
Sub Programa_Principal()
Dim Fila_Leída As Long
While Cells(Fila_Leída, 1) <> ""
Cells(Núm_Fila, 2) = Núm_Fila
Wend
End Sub
c. Obligación
A diferencia de un bucle FOR ... NEXT, un bucle WHILE impone inicializar el primer valor de la variable e
incrementar la variable en el programa.
El código pasa a ser:
Sub Programa_Principal()
Dim Fila_Leída As Long
Fila_Leída = 2 ’Inicialización de la variable
While Cells(Fila_Leída, 1) <> ""
Cells(Fila_Leída, 2) = Fila_Leída
Fila_Leída = Fila_Leída + 1 ’Incremento
Wend
End Sub
Por desgracia, frecuentemente olvidamos incrementar la variable del bucle, y como consecuencia, se bloquea el
programa. Para salir de esta situación, pulse las teclas [Ctrl][Pausa] y podrá volver a tener el control de su
programa.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
2. Ejemplo de código
Vamos a retomar el ejemplo del capítulo Primer programa Primer ejercicio, que combina las celdas de un mismo
cliente a partir del archivo Ejemplo 4C. Recordemos que habíamos creado el siguiente código:
Sub Macro1()
With Selection
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlCenter
.MergeCells = True
End With
End Sub
Para que este código se pueda utilizar en todo el documento, hay que seleccionar un rango de celdas antes de
iniciar el programa. Gracias a los bucles, vamos a adaptar este código para que funcione en todos los casos,
independientemente del número de filas que queramos combinar.
Para poder seleccionar el rango de celdas correspondiente a un mismo cliente, debemos crear un programa con dos
variables:
l una primera variable correspondiente a la fila de principio del rango de celdas (Núm_Fila).
l una segunda variable correspondiente al número de fila de fin del rango de celdas de la selección (Fila_Fin).
La variable de los números de fila servirá, al mismo tiempo, para determinar la fila de partida de la combinación y
para encontrar la última fila de nuestros valores para detener el bucle.
Por lo tanto, debemos hacer dos bucles:
l El primero para recorrer el conjunto de filas de la columna A (hasta que encontremos una fila vacía).
l El segundo se utilizará para encontrar la última fila del rango antes de cambiar el nombre del cliente.
El primer bucle es clásico. Hay que leer en secuencia las celdas de la columna A hasta que se encuentre una celda
no conocida y así, acabar el programa.
Sub Macro1()
Dim Núm_Fila As Long
Núm_Fila = 2
While Cells(Núm_Fila, 1) <> ""
INSTRUCCIONES
Núm_Fila = Fila_Fin + 1
Wend
End Sub
El segundo bucle determina el rango de celdas que será objeto de la combinación. Para ello, debemos realizar un
bucle que verifique la igualdad entre los nombres de dos celdas contiguas.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
En una primera variable, guardaremos la primera fila en la que haya igualdad de nombres. Hacemos bucles en los
nombres tantas veces como haya nombres iguales y cuando detectemos dos nombres distintos, recuperamos el
valor de la última fila leída. Así, tendremos la primera y la última celda que corresponde a un mismo cliente.
Sub Macro1()
Dim Núm_Fila As Long
Núm_Fila = 2
’ Test sobre la celda vacía para detener el programa
While Cells(Núm_Fila, 1) <> ""
Fila_Fin = Núm_Fila
’ Test sobre la similitud del nombre de un cliente
While Cells(Fila_Fin, 1) = Cells(Fila_Fin + 1, 1)
Fila_Fin = Fila_Fin + 1
Wend
’INSTRUCCIONES DE FUSIÓN
Núm_Fila = Fila_Fin + 1
Wend
End Sub
Así, cuando ya no se verifica el test sobre la similitud de los nombres (y por tanto el test es Falso) tenemos en la
variable Núm_Fila el valor de la primera celda del rango y, en la variable Fila_Fin, el valor de la última celda del
rango.
El rango de datos que queremos fusionar se conoce, por tanto, solo nos faltaría copiar el código del formato
después de este segundo bucle.
Fila_Fin = Núm_Fila
’ Test sobre similitud de un nombre de cliente
While Cells(Fila_Fin, 1) = Cells(Fila_Fin + 1, 1)
Fila_Fin = Fila_Fin + 1
Wend
Núm_Fila = Fila_Fin + 1
Wend
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
En este programa, no es posible gestionar los bucles con un FOR ... NEXT, ya que no conocemos de antemano el
número de filas que formarán parte del rango que vamos a combinar.
Para evitar la aparición del mensaje de alerta en el momento de la combinación, vamos a indicar a Excel que no
debe mostrar ningún mensaje durante la ejecución del programa. Ahora agregamos la instrucción
Application.DisplayAlerts = False al principio del programa y después, justo antes de dejar la macro, volvemos a
poner el parámetro en True para que Excel vuelva a mostrar los mensajes de error (cf. capítulo Trabajar en un libro
Excel El objeto Application).
Este es el código final que realiza las operaciones de combinación para todo el documento:
Sub Macro1()
Dim Núm_Fila As Long
Núm_Fila = 2
Application.DisplayAlerts = False
While Cells(Núm_Fila, 1) <> ""
Fila_Fin = Núm_Fila
While Cells(Fila_Fin, 1) = Cells(Fila_Fin + 1, 1)
Fila_Fin = Fila_Fin + 1
Wend
With Range(Cells(Núm_Fila, 1), Cells(Fila_Fin, 1))
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlCenter
.MergeCells = True
End With
Núm_Fila = Fila_Fin + 1
Wend
Application.DisplayAlerts = True
End Sub
Encontrará el código correspondiente en el archivo Ejemplo 7C2.
3. Do ... Loop
O:
DO
Instrucción
LOOP {while | Until} condición
a. Presentación
Los bucles DO ... LOOP son similares a los bucles WHILE ... WEND: hay que inicializar la variable utilizada por el
bucle antes de entrar en la celda y, a continuación, incrementar dicha variable dentro del bucle.
Es posible hacer el test con While (traducción de Mientras) pero también con Until (traducción de Hasta).
Además, es posible hacer un test al principio del bucle o al final de este.
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
b. Ejemplo de aplicación
El siguiente documento es una hoja de ausencias que se compone de dos columnas: la primera contiene las
fechas y la segunda, los nombres de los ausentes. El archivo correspondiente se llama Ejemplo 7C3b.
Como habrá comprobado, para la misma fecha, puede haber uno o varios nombres. Para mejorar la legibilidad de
este documento, quiere organizar su tabla presentando en la misma fila, una fecha y todos los nombres
correspondientes a esa fecha.
Para realizar esta permutación, hemos escrito el siguiente programa:
Sub Main()
Dim Núm_Fila As Long
Dim Col_Escritura As Long, Fil_Escritura As Long
Fil_Escritura = 1
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Col_Escritura = 5
Do
Cells(Fil_Escritura, 4) = Cells(Núm_Fila, 1)
Cells(Fil_Escritura, Col_Escritura) = Cells(Núm_Fila, 2)
Col_Escritura = Col_Escritura + 1
Núm_Fila = Núm_Fila + 1
Loop While Cells(Núm_Fila - 1, 1) = Cells(Núm_Fila, 1)
Fil_Escritura = Fil_Escritura + 1
Wend
End Sub
c. Explicación del código
Empezamos inicializando la variable que leerá las celdas de la columna A Núm_Fila y la que se utilizará para
escribir el resultado final (Fil_Escritura).
A continuación, escribimos el bucle que leerá todas las celdas hasta la última celda no vacía (bucle realizado con la
instrucción WHILE ... WEND).
Justo después de iniciar el bucle, inicializamos la variable de la columna de escritura Col_Escritura. La
inicialización se hace dentro del primer bucle ya que debemos volver a colocarnos en la columna D cuando
hayamos tratado todos los nombres asociados a la misma fecha (para una explicación más detallada, consulte el
capítulo siguiente sobre la depuración).
En cada bucle, incrementamos la variable de la fila que se va a leer, pero no la de la fila para escribir. La variable
Fil_Escritura solo debe incrementarse después del segundo bucle (cuando ya no haya igualdad de fechas).
El test del segundo bucle se realiza al final del bucle. De este modo, el bucle se detendrá justo después de haber
incrementado la variable de lectura de la columna A.
d. Mejora del código
Habrá observado que en este programa reescribimos la fecha cada vez que el programa trata una fila. Sería más
sensato escribir la fecha una sola vez por fila de escritura haciendo un test para evitar tener que reescribir este
dato si ya se ha presentado. Hay distintos modos de hacer este test:
l comprobar que la celda de la columna 5 está vacía,
l comprobar que la variable Col_Escritura = 5.
El programa pasa a ser:
Sub Main()
Dim Núm_Fila As Long
Dim Col_Escritura As Long
Dim Fil_Ecritura As Long
- 6- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Fil_Escritura = 1
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Col_Escritura = 5
Do
If Col_Escritura = 5 Then
Cells(Fil_Escritura, 4) = Cells(Núm_Fila, 1)
End If
Cells(Fil_Escritura, Col_Escritura) = Cells(Núm_Fila, 2)
Col_Escritura = Col_Escritura + 1
Núm_Fila = Núm_Fila + 1
Loop While Cells(Núm_Fila - 1, 1) = Cells(Núm_Fila, 1)
Fil_Escritura = Fil_Escritura + 1
Wend
End Sub
Otra técnica: habría sido posible escribir la fecha al salir del segundo bucle, y así evitamos realizar un test:
Sub Main()
Dim Núm_Fila As Long
Dim Col_Escritura As Long
Dim Fil_Escritura As Long
Fil_Escritura = 1
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Col_Escritura = 5
Do
Cells(Fil_Escritura, Col_Escritura) = Cells(Núm_Fila, 2)
Col_Escritura = Col_Escritura + 1
Núm_Fila = Núm_Fila + 1
Loop While Cells(Núm_Fila - 1, 1) = Cells(Núm_Fila, 1)
Cells(Fil_Escritura, 4) = Cells(Núm_Fila - 1, 1)
Fil_Escritura = Fil_Escritura + 1
Wend
End Sub
En ese caso particular, es necesario devolver el valor de la fecha de la fila anterior. En efecto, en este momento
acabamos de terminar el test de igualdad de la fecha y, por tanto, al salir del bucle, el valor de la fila leída señala
la fecha siguiente. Vamos a escribir la fecha de la penúltima fila leída, es decir Núm_Fila - 1.
Encontrará el código correspondiente en el archivo del Ejemplo 7C3d.
e. Trabajar con dos hojas
Seguimos queriendo leer los datos de hoja1, pero el resultado debe copiarse en hoja2 en la columna A. La tarea
puede parecer compleja, pero, de hecho, es muy sencillo de codificar.
Partiendo del código anterior, vamos a agregar a cada objeto Cells, el objeto Sheets.
Para las celdas leídas, agregamos el objeto Sheets("Hoja1") y para las celdas en las que vamos a escribir,
agregamos el objeto Sheets("Hoja2").
El código pasa a ser:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 7-
Sub Main()
Dim Núm_Fila As Long
Dim Col_Escritura As Long
Dim Fil_Escritura As Long
Fil_Escritura = 1
Núm_Fila = 1
While Sheets("Hoja1").Cells(Núm_Fila, 1) <> ""
Col_Escritura = 2
Do
Sheets("Hoja2").Cells(Fil_Escritura, Col_Escritura) =
Sheets("Hoja1").Cells(Núm_Fila, 2)
Col_Escritura = Col_Escritura + 1
Núm_Fila = Núm_Fila + 1
Loop While
Sheets("Hoja1").Cells(Núm_Fila - 1, 1) =
Sheets("Hoja1").Cells(Núm_Fila, 1)
Sheets("Hoja2").Cells(Fil_Escritura, 1) =
Sheets("Hoja1").Cells(Núm_Fila - 1, 1)
Fil_Escritura = Fil_Escritura + 1
Wend
End Sub
Encontrará el código completo en el archivo Ejemplo 7C3e.
- 8- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Bucle en objetos Excel
1. Presentación
Este nuevo bucle es una de las funciones más interesantes de Excel. Gracias a ella, se pueden realizar bucles en
colecciones de objetos (como las hojas, los libros, los gráficos, etc.).
En la sección Colección de objetos del Anexo de este manual, encontrará las colecciones de objetos más usuales de
Excel.
A diferencia de los bucles anteriores, en los que las variables contenían valores numéricos que era preciso
incrementar, aquí la variable contiene el conjunto de propiedades del objeto.
La variable que se utilizará debe estar asociada a una propiedad o a un método para poder explotarla.
Por ejemplo, desea extraer el nombre de todas las hojas de un libro para escribir el resultado en la columna A de la
hoja Hoja1. El código es el siguiente:
Sub Bucle_Hoja()
Dim Objeto_Hoja As Object
Dim Escrit_Fila As Long
Escrit_Fila = 1
For Each Objeto_Hoja In Worksheets
Sheets("Hoja1").Cells(Escrit_Fila, 1) = Objeto_Hoja.Name
Escrit_Fila = Escrit_Fila + 1
Next
End Sub
2. Explicación del código
Mucha información está en la línea FOR EACH: el término WorkSheets indica que el bucle se va a aplicar a la
colección de objetos Hoja: vamos a centrarnos en el objeto "Hoja de cálculo" de nuestro libro y recorrer cada una de
ellas.
La línea FOR EACH puede traducirse del siguiente modo: "Para cada hoja del libro, vamos a trasladar la totalidad de
propiedades de la hoja seleccionada a la variable Objeto_Hoja".
Por lo tanto, la variable Objeto_Hoja no contendrá un valor, sino la totalidad de propiedades de la hoja sobre la
que se coloque el bucle. La siguiente imagen, que proviene de un depurador, muestra una parte de las propiedades
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
relacionadas con la hoja en la que se coloca el bucle:
En el capítulo siguiente sobre las depuraciones veremos cómo visualizar el conjunto de propiedades de un objeto.
Al final, el programa se interpretará de la siguiente forma: "Para cada hoja de nuestro libro, escribimos su nombre
(propriedad Name del objeto) en una nueva celda.
Desde la página Información, encontrará el archivo Ejemplo 7D que extrae el nombre de todas las hojas del libro y
que genera un reenvío con vínculos hipertexto gracias a la instrucción Hyperlinks.
Sub Navigation()
Dim Mi hoja As Object
Dim Num_Fila As Long
Num_ Fila = 1
For Each Mi hoja In Worksheets
If Mi hoja.Name <> "Sumario" Then
’ Index en el sumario
Sheets("Sumario").Cells(Num_Fila, 1) =Mi hoja.Name
Sheets("Sumario").Hyperlinks.Add _
Anchor:=Sheets("Sumario").Cells(Num_Fila, 1), Address:="", _
SubAddress:=Mi hoja.Name & "!A1", TextToDisplay:=Mi hoja.Name
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Presentación
Cuando un programa topa con una anomalía al ejecutarse como, por ejemplo, hacer operaciones con texto, abrir un
archivo sin nombre (variable vacía) o intentar llegar a una celda con referencias que contienen valores decimales, el
programa se detiene de inmediato y muestra un cuadro de dialogo.
En el siguiente ejemplo realizamos un código que multiplica por diez los valores de la columna A e inscribe el resultado
en la misma fila de la columna B. Puede descargar el ejemplo desde la página Información.
Sub Bucle_Simple ()
Dim Núm_Fila As Long
For Núm_Fila = 1 To 7
Cells(Num_ Fila, 2) = Cells(Num_ Fila, 1) * 10
Next
End Sub
Solo que, como el contenido de la celda A4 es texto y no un número, el programa es incapaz de efectuar la operación
y eso provoca que aparezca el cuadro de diálogo siguiente:
Llegados aquí, es importante saber dos cosas:
Tómese siempre el tiempo de leer el origen del error (en este caso la incompatibilidad de tipo).
No pulse nunca, nunca, NUNCA, el botón Fin. Haga clic siempre en Depurar.
Al hacer clic en el botón Depurar, abrirá Visual Basic Editor y verá la línea de código que ha hecho que el programa se
parase. En nuestro ejemplo, nos hemos detenido en la línea que efectúa el cálculo.
La línea de error puede identificarse fácilmente porque aparece siempre subrayada en amarillo.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Pero cuidado, el programa no se ha detenido. Simplemente está en modo pausa.
Si el programa se detiene, no será posible estudiar el valor de las variables o los tests. Si quiere de veras detener la
ejecución, bastará con hacer clic en el icono .
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Buenas prácticas
Hasta ahora hemos iniciado siempre los programas pulsando el icono de Visual Basic Editor o bien usando el
método abreviado [F5]. Solo que, si el programa es largo y se produce un error inesperado, no será posible detener
la ejecución del programa.
Imagine por un momento que lleva a cabo un programa que cambia el nombre de los archivos y que, en lugar de
hacerlo en su ordenador, lo elabora en el servidor de su empresa ya que no indica la ruta de acceso. Como en VBA la
instrucción "Anular" ([Ctrl] Z) es inoperante, no le costará imaginarse los problemas que su programa puede causar.
Por ese motivo recomendamos siempre iniciar programas en modo Paso a paso ([F8]) durante toda la fase de diseño
del programa.
Solo iniciará programas con [F5] una vez que haya controlado todas las etapas y no se produzca ningún error de
ejecución. Yo mismo, tras veinte años de experiencia en programación con VBA, sigo iniciando mis programas con la
tecla [F8].
En los ejemplos que se irán sucediendo a continuación, procure siempre iniciar los programas en modo Paso a paso.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Lectura "Paso a paso"
La herramienta de depuración presenta dos intereses principales:
l controlar la ejecución del programa paso a paso,
l visualizar el contenido de las variables y de las condiciones durante la ejecución.
1. La tecla [F8]
Para explotar la herramienta de depuración, vamos a retomar el código que hemos utilizado en el capítulo sobre los
bucles para reorganizar una lista de nombres por fecha. El siguiente programa contiene voluntariamente dos
errores que vamos a encontrar gracias a la herramienta de depuración:
Sub Organización_Nombre()
Dim Núm_Fila As Long
Dim Col_Escrit As Long
Dim Fil_Escrit As Long
Fil_Escrit = 1
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Col_Escrit = 5
Do
Cells(Fil_Escrit, Col_Escrit) = Cells(Núm_Fila, 2)
Col_Escrit = Col_Escrit + 1
Núm_Fila = Núm_Fila + 1
Loop While Cells(Núm_Fila - 1, 1) = Cells(Núm_Fila, 1)
Cells(Fil_Escrit, 4) = Cells(Núm_Fila, 1)
Fil_Escrit = Fil_Escrit + 1
Wend
End Sub
El código correspondiente se encuentra en el archivo Ejemplo 8C.
Sitúe el cursor en el procedimiento que desea iniciar.
Inicie el programa en modo Paso a paso pulsando la tecla [F8]. Inmediatamente verá aparecer una línea
amarilla al principio de su procedimiento.
La línea amarilla indica la instrucción que se va a ejecutar.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Para hacer avanzar paso a paso el programa, basta con pulsar la tecla [F8]: cada vez que pulse la tecla
[F8], la línea de código en amarillo se ejecuta y pasa a la línea siguiente.
2. La combinación de teclas [Mayús][F8]
Si trabaja en un programa que comporta varios procedimientos y funciones, existe un truco muy interesante que
permite ejecutar íntegramente procedimientos o funciones sin tener que pasar Paso a paso por el procedimiento.
En el capítulo siguiente, Estructura de un programa, veremos cómo construir programas con varios procedimientos,
pero aquí solo nos centraremos en el uso del depurador en estos casos.
Imagine que tiene un programa donde hay un procedimiento que lo único que hace es buscar un valor en una tabla
de memoria. Utilizar la depuradora para limpiar fila a fila toda la tabla en memoria es una tarea sumamente
fastidiosa que además no le enseñará nada sobre el desarrollo del programa.
De hecho, cuando se encuentra en la línea de llamada de un procedimiento (Call) o una función, al pulsar
simultáneamente las teclas [Mayús][F8], ejecutará el contenido del procedimiento al que se ha llamado sin tener
que pasar todas las líneas del procedimiento en modo Paso a paso.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Inspeccionar las variables
Ahora que sabe controlar el desarrollo del programa, vamos a visualizar el contenido de las variables durante la
ejecución.
Hasta ahora, para leer el contenido de las variables, hemos visto que podíamos usar el método MsgBox como vimos
en el capítulo sobre las variables, pero este método es desventajoso ya que bloquea la ejecución del programa cada
vez que aparece el cuadro de diálogo personalizado. Por ese motivo, es mucho más eficaz usar la herramienta de
inspección para ver el contenido de las variables sin bloquear la ejecución.
Seleccione la variable que desea observar mediante un clic de arrastre y active el menú Depuración
Inspección rápida...
También puede activar la Inspección rápida mediante la combinación de teclas [Mayús][F9] o haciendo clic
en el icono .
Es necesario que la variable que va a inspeccionar esté previamente seleccionada.
Aparecerá el siguiente cuadro de diálogo:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Haga clic en el botón Agregar, la variable inspeccionada aparece en una nueva ventana llamada
Inspecciones.
La ventana Inspecciones aparece bajo el código
Observe que, en este estadio, el valor de la variable es igual a 0. Esto se debe a que el programa aún no ha leído la
línea amarilla. La leerá la próxima vez que pulse la tecla [F8].
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
La ventana Inspecciones
La ventana Inspecciones le permite visualizar todas las variables que ha seleccionado.
En esa ventana, verá para cada variable:
l su nombre,
l su valor,
l su tipo,
l su procedimiento de aplicación.
También puede seleccionar varios datos, como una operación matemática o un test.
Del mismo modo, también puede seleccionar un objeto (como una hoja de cálculo, etc.); en ese caso, la ventana
Inspecciones no muestra directamente la información.
Haga clic en el símbolo situado a la izquierda del nombre del objeto para desplegar todas las
propiedades relacionadas con ese objeto:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Lo mismo ocurre con las tablas en la memoria. Al seleccionar el nombre de la tabla no verá aparecer
ningún valor, sin embargo, si pulsa sobre el icono situado a la izquierda del nombre de la tabla,
aparecerá todo el contenido de la misma.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
La ventana de variables locales
Si trabaja en proyectos grandes en los que se administra un gran número de variables, puede resultar muy fastidioso
tener que seleccionarlas unas tras otras para ver su contenido en la ventana Inspecciones.
Para ganar tiempo, puede mostrar todas las variables del procedimiento en curso de ejecución seleccionando en la
barra de herramientas el menú Ver y, a continuación, el submenú Ventana Locales.
De esta manera, bajo las líneas de código aparecerá la ventana Locales.
Vista de todas las variables locales y procedimientos en curso
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
En este ejemplo podemos ver todas las variables del Módulo1 del procedimiento Main_Pgm (primera información que
aparece justo antes de la ventana).
Si trabaja en un proyecto que contiene varias Sub o Functions, al llamar a una nueva, solo serán visibles las variables
contenidas en el nuevo procedimiento o función y lo mismo ocurrirá para todo el programa.
Las variables locales ya no son las mismas porque el programa está ahora dentro de otra función
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
El punto de interrupción
Para evitar pasar por todo su código en modo Paso a paso, puede colocar un punto de interrupción. El principio es
leer el código de forma normal hasta que el programa alcance el punto de interrupción; a continuación, usted retoma
el control en modo Paso a paso.
Acceda a la línea en la que desea marcar una parada. A continuación, haga clic en el icono o pulse la
tecla [F9].
Ahora, toda la línea de código aparece resaltada en rojo.
También puede utilizar el ratón para hacer clic en el margen gris para mostrar/quitar un punto de interrupción.
Inicie su programa con [F5]. La ejecución se detendrá en el punto de interrupción y la línea amarilla (modo
paso a paso) se superpondrá a la línea roja (punto de interrupción):
Para continuar la ejecución, puede pulsar la tecla [F8] para leer el programa Paso a paso o pulsar la tecla
[F5] para leer el programa de forma continua hasta el próximo punto de interrupción. Si el punto de
interrupción está colocado en un bucle, el programa se detendrá en cada iteración del bucle.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
La instrucción Debug.Print
Cuando tiene un programa que repite varios cientos de veces el mismo bucle, resulta fastidioso tener que pulsar la
tecla [F5] para que el programa continúe después del punto de interrupción.
Para evitar esto, se pueden posicionar "marcadores" que ayudarán a proseguir la ejecución del programa. Al acabar,
bastará con releer los diferentes marcadores para analizar el programa y ver dónde está el error.
Para añadir un marcador al programa es preciso añadir la instrucción Debug.Print seguida del nombre de la
variable que se quiere analizar.
Retomaremos el primer ejemplo de este capítulo y vamos a añadirle la instrucción para seguir el valor de la variable y
también el resultado obtenido.
Sub Bucle_Simple()
Dim Núm_Fila As Long
For Num_ Fila = 1 To 7
Cells(Núm_Fila, 2) = Cells(Num_ Fila, 1) * 10
Debug.Print "Valor de la fila : " & Num_ Fila
Debug.Print "Resultado del cálculo : " & Cells(Num_ Fila, 1) * 10
Next
End Sub
El error de la celda A4 se ha corregido reemplazando "Hola" por el valor 4.
Al acabar de ejecutar el programa, para ver el seguimiento de la instrucción Debug.Print, seleccione la opción
Ventana Inmediato en la barra de menú (o utilice el método abreviado de teclado [Ctrl] G).
Por debajo de las líneas de código verá aparecer sus líneas personalizadas con los diferentes valores de variables y
cálculos.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Interrupción según condición
En modo depuración también puede detener la ejecución de un programa cuando una variable alcance un valor. De
esta manera, los bucles se ejecutarán normalmente hasta el momento en que la variable de referencia alcance el
valor deseado.
Imaginemos un documento Excel que contiene 100 celdas conocidas; queremos detener la ejecución del programa
cuando este llegue a la fila 98 (para visualizar la ejecución del código hasta su término).
Vamos a modificar la inspección de la variable Núm_Fila para que el programa se detenga cuando se alcance el
valor 98.
En la ventana Inspecciones, seleccione la variable Núm_Fila.
Haga clic con el botón derecho y señale la opción Modificar inspección.
Aparecerá una ventana.
En la zona Expresión, indique el valor que debe alcanzar la variable para detener el programa (aquí 98).
En la zona Tipo de inspección, active la opción Interrupción cuando el valor sea verdadero.
Después de confirmar, la ventana Inspecciones ya no muestra en la primera columna el icono sino el icono
para indicar que se trata de una variable de tipo Interrupción.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Inicie su programa pulsando la tecla [F5], el programa se detendrá cuando la variable Núm_Fila alcance
el valor 98.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Intervenir durante la ejecución del código
En modo Paso a paso, es posible modificar una línea de código ya ejecutada y después volver atrás situándose sobre
ella para interpretarla de nuevo. También es posible modificar el valor de las variables manualmente para actuar
sobre el comportamiento del programa.
1. Vuelta atrás
Imaginemos que tenemos un programa idéntico al primer código de este capítulo, pero con la instrucción
While ... Wend.
Sub Bucle_Simple()
Dim Núm_Fila As Long
Núm_ Fila = 1
While Cells(Núm_ Fila, 1) <> ""
Cells(Núm_ Fila, 2) = Cells(Núm_ Fila, 1) * 10
Núm_ Fila = Núm_ Fila + 1
Wend
End Sub
Inicie el programa.
Efectúe 2 o 3 pasos en el bucle.
Ahora supongamos que desea escribir el resultado, no en la columna B, sino en la columna C. En lugar de detener el
programa, cambiar el valor de la columna y volver a iniciar el programa, es posible intervenir en algunos parámetros
del código sin detener la ejecución.
Cambie el valor de la columna 2 por 3 en el código.
Desplace la línea de ejecución (la línea amarilla) para situarla antes del bucle (justo al principio de la
variable).
Continúe con su programa en modo Paso a paso para iniciar de nuevo el bucle con la nueva columna y
escribir el resultado en la columna C.
En VBA hay elementos que no se pueden modificar cuando el programa se está ejecutando como, por ejemplo,
cambiar el nombre a una variable, modificar el tipo de una variable o cambiar el tamaño de una tabla en memoria.
2. Cambiar manualmente el valor de las variables
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Abrir la ventana Inmediato (menú Ver, y Ventana Inmediato).
Escribir el nombre de la variable seguido del valor que quiere dársele.
Num_Fila = 1
En la siguiente imagen, he recorrido 5 veces el bucle y mi variable, por tanto, tiene el valor 5 (visible en la ventana
Inspecciones).
La variable Num_Fila es igual a 5
Ahora cambio el valor de la variable usando la ventana Inmediato y confirmo pulsando [Entrée]. Observe que el
valor de la variable en la ventana Inspecciones es ahora igual a 1.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Después del cambio, la variable Num_Fila es igual a 1
El programa se reiniciará desde el valor 1 de la variable, se reiniciará, por tanto, desde el principio del bucle.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Ejemplo de aplicación de la depuradora
Retomemos el código del principio del capítulo. La ejecución del procedimiento Main da el siguiente resultado en su
hoja de cálculo.
1. Resolución del primer error
El programa no muestra el primer nombre en la columna E (excepto en la primera fila). Vamos a observar el
comportamiento de la variable Col_Escrit en modo paso a paso; también vamos a observar la variable
Fil_Escrit.
Cada vez que se carga una fecha, la variable Col_Escrit debería tomar el valor 5. Ahora bien, como no se da el
caso, vamos a analizar el comportamiento de las dos variables en la ventana Inspecciones.
Añada una inspección para cada una de las dos variables Fil_Escrit y Col_Escrit.
Inicie el programa en modo Paso a paso (tecla [F8]) y siga la ejecución hasta que la variable
Fil_Escrit alcance el valor 2.
En este paso, acabamos de terminar la escritura de la primera fila y el resultado en nuestra hoja de cálculo es el
esperado:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Pulse una vez más la tecla [F8] para volver al principio del bucle.
En este paso, la variable Col_Escrit debería volver a 5, pero no es así, esta no se inicializa. De hecho, esta
instrucción está fuera del bucle principal (el programa no volverá a pasar por esta instrucción hasta el final).
Para corregir este problema, basta con desplazar la instrucción Col_Escrit = 5 debajo de la línea
While para que la variable Col_Escrit se inicialice después de cada ciclo del bucle While.
Inicie su programa pulsando la tecla [F5].
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
El resultado parece correcto, pero si observamos con atención las fechas encontraremos un nuevo problema:
tenemos un desfase entre los nombres y las fechas.
2. Resolución del segundo error
Vamos a utilizar una vez más la herramienta de depuración para inspeccionar el comportamiento de la instrucción
que escribe la fecha. Vaya al segundo procedimiento Organización_Nombre.
Cree un punto de interrupción en la línea de escritura de la fecha:
Cells(Fil_Escrit, 4) = Cells(Núm_Fila, 1)
Cree una inspección para la variable Núm_Fila.
Inicie su programa pulsando la tecla [F5].
El programa se detiene justo antes de la escritura de la fecha en la hoja Excel, pero en este estadio, el valor
Núm_Fila es igual a 3.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
El programa recuperará el valor de la celda A3 (13/04/2010) para copiarla en la celda D1.
Para copiar en D1 la fecha esperada (el 12/04/2010), hay que recuperar el valor de la fila anterior. Basta con restar
1 a la variable Núm_Fila.
El código pasa a ser:
Sub Organización_Nombre()
Dim Núm_Fila As Long
Dim Col_Escrit As Long
Dim Fil_Escrit As Long
Fil_Escrit = 1
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Col_Escrit = 5
Do
Cells(Fil_Escrit, Col_Escrit) = Cells(Núm_Fila, 2)
Col_Escrit = Col_Escrit + 1
Núm_Fila = Núm_Fila + 1
Loop While Cells(Núm_Fila - 1, 1) = Cells(Núm_Fila, 1)
Cells(Fil_Escrit, 4) = Cells(Núm_Fila - 1, 1)
Fil_Escrit = Fil_Escrit + 1
Wend
End Sub
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Dividir un programa en varios procedimientos
Hasta el momento, hemos creado cada programa en un solo procedimiento. Pero el interés de VBA es poder construir
un programa con varios procedimientos o varias funciones que puedan ejecutarse varias veces a lo largo de la
ejecución.
1. Código inicial
La carpeta Ejemplo 9A contiene dos libros: Cliente.xlsx y Ejemplo 9A.xlsm.
El objetivo del programa es abrir el segundo libro (Cliente.xlsx) y llevar a cabo una selección a partir de la fecha de
nacimiento de los clientes. Con la Grabadora de macros, obtenemos el código que se muestra a continuación. En su
caso la ruta de acceso será diferente, pero enseguida lo corregiremos.
Sub Macro1()
Workbooks.Open Filename:="C:/MisDocumentos/Excel/Cliente.xlsx"
Range("H1").Select
Selection.CurrentRegion.Select
ActiveWorkbook.Worksheets("Hoja1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Hoja1").Sort.SortFields.Add _
Key:=Range("H2:H201") _
, SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Hoja1").Sort
.SetRange Range("A1:J201")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
La primera instrucción corresponde a la apertura del archivo y las demás a las filas de comandos para efectuar la
selección. Vamos a aislar estas dos partes en dos procedimientos distintos.
2. División del código
Sub Procedimiento_Principal
Call Abrir_Archivo
Call Selección_Datos
End Sub
Sub Abrir_Archivo ()
Workbooks.Open Filename:="C:/MisDocumentos/Excel/Cliente.xlsx"
End Sub
Sub Selección_Datos ()
Range("H1").Select
Selection.CurrentRegion.Select
ActiveWorkbook.Worksheets("Hoja1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Hoja1").Sort.SortFields.Add _
Key:=Range("H2:H201") _
, SortOn:=xlSortOnValues, Order:=xlAscending, _
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Hoja1").Sort
.SetRange Range("A1:J201")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
.Apply
End With
End Sub
Los dos programas son rigurosamente los mismos, hemos escrito la instrucción de apertura del libro en un
procedimiento aparte y hemos hecho lo mismo en lo que respecta a la selección. Para continuar ejecutando el
programa como antes, hemos creado un procedimiento (Procedimiento_Principal) que solo contiene dos
instrucciones: las instrucciones de llamada a otros dos procedimientos con la instrucción Call.
Para iniciar el programa completo, es preciso que el cursor esté en el procedimiento principal y que pulse la tecla
[F5]. O bien, si el cursor está fuera de todos los procedimientos, un cuadro de diálogo le preguntará qué
procedimiento desea iniciar.
3. La instrucción Call
La instrucción Call no es obligatoria para llamar a otro procedimiento, pero aconsejamos vivamente usarla.
Podríamos haber escrito perfectamente el procedimiento principal de la manera siguiente y el programa habría
funcionado igual.
Sub Procedimiento_Principal
Abrir_Archivo
Selección_Datos
End Sub
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Pero conservar la instrucción Call ofrece tres ventajas:
Es fácil localizar todas las llamadas hechas por el proyecto realizando una búsqueda ( [Ctrl] F) con la
palabra clave Call.
En caso de tener que releer un programa, es más sencillo comprender las filas de llamada.
El paso de parámetros es más legible usando la instrucción Call gracias a la aparición de una etiqueta
informativa que indica los parámetros que se esperan.
4. El interés de dividir en varios procedimientos
Mientras el programa sea relativamente pequeño, puede escribir el código en un solo procedimiento. Pero en cuanto
tenga que gestionar un programa mayor, con varios tests y varios bucles, si escribe todo el código en un solo
procedimiento, el programa se hará ilegible enseguida.
La idea de la programación modular es aislar una parte específica del programa (por ejemplo, una condición) en un
procedimiento o en una función. Desde el procedimiento principal, usted hace llamadas a esos procedimientos o
funciones tantas veces como precise usarlos.
Ni que decir tiene que no es obligatorio crear programas con varios procedimientos, pero haciéndolo resulta más
fácil aislar etapas en procedimientos separados y, sobre todo, protege de errores.
En efecto, si se conserva todo el código en un solo procedimiento, modificar un bucle, una variable o un test puede
tener repercusiones sobre todo el procedimiento. Al aislar tareas en procedimientos específicos, nos aseguramos de
conservar el código y el riesgo de errores de ejecución es mucho más limitado.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Alcance de las variables
Partiendo del caso que nos ha servido de ejemplo al principio de este capítulo, hemos conseguido dividir nuestro
programa inicial en tres procedimientos (uno que administra las llamadas y otros dos que ejecutan las acciones de
apertura de archivos y de selección) sin que ello ocasione el menor error de ejecución.
De hecho, el trabajo de división ha sido sencillo de realizar, ya que no hemos tenido que gestionar el paso de variable
de un procedimiento a otro porque no había ningún parámetro en el programa inicial. Ahora, para hacer el programa
más flexible, vamos a transformar la ruta de acceso y la columna de selección en variable y vamos a ver que la
gestión de llamadas de un procedimiento es más compleja.
1. Vuelta a la declaración de las variables
a. Dim dentro de un procedimiento
Como ya hemos indicado en el capítulo Las variables, una variable declarada en Dim dentro de un procedimiento
solo es visible en el procedimiento donde se ha declarado.
En el ejemplo de arriba, el procedimiento 2 no es capaz de interpretar la variable Mi_Variable ya que no se ha
declarado en el mismo procedimiento. En esos casos el programa detectará un error y se interrumpirá la ejecución.
b. Dim al principio del Módulo
Si declara una variable con la instrucción Dim al principio del módulo, todos los procedimientos y todas las
funciones de ese módulo podrán verla.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
En este caso, el procedimiento 2 puede interpretar el contenido de la variable ya que se ha declarado a nivel del
módulo y los dos procedimientos están en el mismo módulo.
Por el contrario, en el caso siguiente, la variable Mi_Variable no puede interpretarse porque el procedimiento 2 está
en otro módulo.
c. Declaración en Public
Por último, si declara una variable en Public, esta será visible para todos los procedimientos y en todos los
módulos, independientemente del módulo en el que se haya declarado.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Cuando se declara en Public, la variable es visible para todos los procedimientos y en todos los módulos
2. Dim o Public
Tal y como lo acabamos de presentar, sería tentador declarar todas nuestras variables en Public para que todos
los procedimientos puedan verlas. Es indudable que resultaría más fácil de administrar, pero contradice los principios
de un programa bien organizado.
En efecto, los procedimientos corresponden a funcionalidades concretas como la apertura de un archivo, por
ejemplo. Esencialmente, en ese caso solo necesitamos dos variables: el nombre del archivo y su ruta de acceso.
Ahora, si en el mismo proyecto tenemos un procedimiento que efectúa una selección dentro de una hoja de cálculo,
¿qué interés hay en que este procedimiento tenga la posibilidad de leer las variables que han servido para abrir el
archivo? Está claro que ninguno.
Por ese motivo, es recomendable declarar las variables de manera que solo sean visibles para los procedimientos
donde desempeñan una verdadera función. Con la práctica verá que las variables Public, en general, no son muy
numerosas en los programas.
Pero entonces, ¿cómo transmitir el contenido de una variable Dim declarada en local (es decir, en un procedimiento)
a otros procedimientos o funciones?
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Parámetros de llamada
1. Principio de transmisión de variables locales
Para poder transmitir en el momento de la llamada variables declaradas en local (es decir, generalmente visibles por
un único procedimiento), es preciso pasar las variables como parámetro.
Para transmitir el contenido de variables declaradas en Dim a otro procedimiento es preciso:
l Indicar que el procedimiento llamado espera un parámetro o más de uno, para funcionar.
l Especificar en el momento de la llamada que transmitimos los parámetros que se esperan.
Si se quiere indicar que un procedimiento llamado necesita parámetros para funcionar, es preciso indicar el nombre
de las variables que se esperan entre los paréntesis situados tras el nombre del procedimiento (o de la función).
Retomando nuestro ejemplo, quiero que la ruta de acceso de mi libro Cliente.xlsx sea un parámetro en el momento
de la llamada. El procedimiento Abrir_Archivo se escribe ahora de la manera siguiente:
La modificación de código es fácil de entender. Hemos reemplazado la ruta de acceso inicial por una variable y el
valor de esta variable se transmitirá cuando se llame al procedimiento.
Ahora, para indicar el valor de la variable en el momento de la llamada, añadiremos esta información mediante
paréntesis.
Sub Procedimiento_Principal
Call Abrir_Archivo ("C:/MisDocumentos/Excel/")
Call Seleccionar_Datos
End Sub
a. Respeto del tipo de variable
En el ejemplo precedente, hemos transmitido el valor de la ruta de acceso directamente a los parámetros de
llamada. Hubiéramos podido hacerlo también a través de una variable. En esos casos es imperativo respetar los
tipos de variables entre el procedimiento llamado y el que ha hecho la llamada.
Sustituyo la ruta de acceso por una variable en el procedimiento de llamada y escribo el siguiente código:
Sub Procedimiento_Principal
Dim Rep_Trabajo As String
Rep_Trabajo = "C:/MisDocumentos/Excel/"
Call Abrir_Archivo(Rep_Trabajo)
Call Seleccionar_Datos
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
He creado una nueva variable en la que indico el valor del directorio actual y utilizo esta variable como parámetro
al hacer la llamada.
¿Usted qué cree?, ¿esta escritura funciona, sabiendo que la variable de llamada es Rep_Trabajo y la variable
esperada tiene el nombre de Ruta_Acceso?
Sí, por supuesto. Si el nombre de las variables difiere entre el procedimiento que hace la llamada y
el llamado, no se producen problemas de interpretación.
Por el contrario, en el programa siguiente, los nombres de las variables son estrictamente los mismos, pero los
tipos de declaración son diferentes (una es un Variant y la otra un String), el programa es incapaz de
interpretar los datos transmitidos durante la llamada y ocasionará un error de ejecución.
Sub Procedimiento_Principal
Dim Ruta_Acceso As Variant
Ruta_Acceso = "C:/MisDocumentos/Excel/"
Call Abrir_Archivo(Ruta_Acceso)
Call Seleccionar_Datos
End Sub
Cuando se llama a procedimientos o funciones, poco importa transmitir referencias de celda, valores, fórmulas o
variables. Lo que cuenta es que el tipo de variable enviado sea estrictamente el mismo que el que se espera.
2. Ayuda en la escritura y en la navegación
a. Uso de las etiquetas informativas
En esta fase de aprendizaje, puede que le inquieten las informaciones que deben transmitirse a otros
procedimientos:
l ¿Cuántos parámetros debo transmitir?
l ¿Qué tipo de declaración de variables se espera?
Pues bien, no es preciso que se plantee todas esas preguntas porque VBA facilita la ayuda necesaria mediante
etiquetas informativas.
Retomando nuestro ejemplo, hemos empezado añadiendo un parámetro a nuestro procedimiento
Abrir_Archivo. En lo sucesivo, cuando llame a ese procedimiento, en el momento en que abre un paréntesis,
una etiqueta informativa le indicará el número de variables que debe introducir y el tipo que se espera.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Aquí sabemos al instante que debemos transmitir una sola variable de tipo String correspondiente a la ruta de
acceso de nuestro archivo.
b. Navegación simplificada
Cuando trabaja con proyectos que contienen numerosos módulos que, a su vez, cuentan con numerosas
funciones, podría parecer difícil alcanzar procedimientos llamados entre todas esas filas de código, pero dos trucos
lo hacen muy simple, de hecho.
Para encontrar sin problemas procedimientos llamados, coloque el puntero del ratón sobre el nombre del
procedimiento/función, haga clic con el botón derecho del ratón y después haga clic en Definición.
El editor de código le conduce de inmediato al principio del procedimiento llamado, también cuando el
procedimiento no está en el mismo módulo que la llamada.
También puede seleccionar el procedimiento al que quiere llegar desde la lista desplegable situada
encima del módulo, a la derecha:
También puede mostrar únicamente el procedimiento seleccionado, utilizando las opciones de la parte inferior de
Visual Basic Editor.
Todos los procedimientos del módulo están visibles de forma predeterminada.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Para ver solo el procedimiento seleccionado, active la vista Ver procedimiento haciendo clic en el icono
: solo se mostrará en la pantalla el procedimiento o la función seleccionados en el menú
desplegable.
3. Flexibilidad de programación
En el ejemplo precedente, para ilustrar la llamada a procedimientos, habíamos transmitido la ruta permanente de
acceso al procedimiento para abrir el archivo. Incluso si el código es exacto desde un punto de vista sintáctico,
carece mucho de flexibilidad.
Si mañana usted cambiara la ruta de su directorio de trabajo, se vería obligado a modificar el código en el programa
para reflejar la nueva ruta.
Para evitar esto, vamos a agregar una función antes de la llamada que determine por sí misma la ruta de acceso.
Como el libro que contiene el código Ejemplo 9A.xlsm, y el libro, Cliente.xlsx, se encuentran en el mismo directorio,
usaremos una funcionalidad de VBA que nos permitirá recuperar la ruta de acceso del libro activo, es decir
ActiveWorkbook.Path .
Trasladado al código, tenemos:
Sub Procedimiento_Principal()
Dim Rep_Trabajo As String
Rep_Trabajo = ActiveWorkbook.Path
Call Abrir_Archivo(Rep_Trabajo)
Call Seleccionar_Datos
End Sub
No hemos cambiado la llamada al procedimiento ni el código del procedimiento para abrir el libro y aun así sigue
funcionando, independientemente del directorio de trabajo. Ahí reside el interés principal de escribir un programa
con varios procedimientos elementales (que solo efectúan una o dos tareas). Nos basta con modificar los valores de
llamada para cambiar el resultado del programa sin tener que recurrir a pesadas reescrituras del código.
Para ser del todo completo, el código precedente no puede funcionar ya que falta un carácter en la cadena de
caracteres de la ruta de acceso. La instrucción ActiveWorkbook.Path no indica el último "/" de la ruta de
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
acceso. No es grave porque podemos corregirlo de la siguiente forma:
Sub Procedimiento_Principal()
Dim Rep_Trabajo As String
Rep_Trabajo = ActiveWorkbook.Path & "/"
Call Abrir_Archivo(Rep_Trabajo)
Call Seleccionar_Datos
End Sub
En el capítulo Trabajar con los archivos veremos otras técnicas para recuperar información de los archivos (tamaño,
hora de modificación, etc.).
a. Finalizar el programa
Para acabar de escribir adecuadamente el programa completo, vamos a pasar como parámetro la columna que se
escogerá al llamar al procedimiento Seleccionar_Datos.
En la celda A1 del libro Ejemplo 9 A.xslm, crearemos una lista desplegable igual que habíamos hecho en el
último ejemplo del capítulo Las condiciones. Esta lista mostrará las letras de la A a la J. Recuperaremos la letra
correspondiente a la columna de selección en la llamada de la función.
A continuación, bastará con reemplazar la referencia a la columna de selección por la letra trasmitida por
parámetro en todo el código inicial. El código completo es el que se muestra a continuación y puede encontrarse
en el libro Ejemplo 9C.xlsm:
Sub Procedimiento_Principal()
Dim Rep_Trabajo As String
Dim Columna_Letra As String
’ Variables de trabajo
Rep_Trabajo = ActiveWorkbook.Path & "/"
Columna_Letra = Cells(1, 1)
’ Llamada de los procedimientos
Call Abrir_Archivo(Rep_Trabajo)
Call Seleccionar_Datos(Columna_Letra)
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
.Apply
End With
End Sub
¿Por qué tenemos que recuperar la letra de la columna antes de abrir el segundo archivo? Porque después de
abrir el libro Cliente.xlsx, ese es el libro que estará activo y, por tanto, la celda A1 tendrá como valor "Género" (el
título de la columna A del libro Cliente.xlsx) y no el valor de la letra de selección.
b. Procedimientos invisibles
Encontrará el programa completo en el archivo Ejemplo 9C. Este programa contiene en efecto los tres
procedimientos estudiados, pero cuando se inicia el programa desde la hoja de cálculo pulsando a la vez las teclas
[Alt][F8] desde Excel (y no desde Visual Basic Editor), solo aparecerá un procedimiento.
Solo vemos un procedimiento
De hecho, cuando construimos un procedimiento con al menos un parámetro, es lógico que sea llamado por otro
procedimiento en algún momento del programa. Por lo tanto, solo los procedimientos sin parámetros
(independientes) están accesibles para iniciar un programa, todos los demás procedimientos están invisibles.
- 6- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Las llamadas a funciones
Al final del capítulo sobre la programación en Visual Basic ya mencionamos la diferencia entre procedimientos y
funciones. A modo de recordatorio diremos que las funciones devuelven resultados exactamente igual que lo hacen
las funciones de Excel, mientras que los procedimientos ejecutan tareas específicas.
El ejemplo que habíamos dado era una función sin parámetro a la que se llamaba desde una hoja de cálculo y que
devolvía en su celda el nombre de la hoja activa.
Ahora vamos a ver cómo podemos integrar en los programas funciones personalizadas para efectuar cálculos
personalizados. Si quiere llevar a cabo investigaciones sobre el tema más pormenorizadas en webs anglosajonas,
utilice la palabra clave UDF (User Defined Function).
1. Crear una función personalizada con parámetros
Partiremos de un archivo Excel que presenta la media de temperaturas en grados Celsius.
Escribiremos un programa que nos permitirá convertir las temperaturas en grados Celsius de la columna B en
grados Fahrenheit en la columna C. Es un programa muy sencillo.
Sub Convertir_Grados()
Dim Núm_Fila As Long
Núm_Fila = 2
While Cells(Núm_Fila, 1) <> ""
Cells(Núm_Fila, 3) = Cells(Núm_Fila, 2) * 9 / 5 + 32
Núm_Fila = Núm_Fila + 1
Wend
End Sub
Ahora vamos a transformar el código para aislar la fórmula de conversión de los Celsius en Fahrenheit en una
función aparte.
Si más adelante en el programa debemos recurrir nuevamente a esta fórmula de conversión resulta más sencillo
llamar a la función que se encarga de efectuar el cálculo que escribir la misma fórmula en varias partes del
programa.
La escritura de la función se deduce muy fácilmente del programa precedente poniendo la fila de cálculo en una
función personalizada.
Function Fahrenheit()
Fahrenheit = Cells(Núm_Fila, 2) * 9 / 5 + 32
End Function
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Por supuesto, esta función no podrá funcionar así ya que la instrucción Cells(Núm_Fila, 2) no podrá
interpretar la función. Por tanto, la idea es transmitir como parámetro el valor en grados directamente.
2. Llamada a la función personalizada
Ahora vamos a transformar nuestro procedimiento inicial para que llame a la función personalizada. Simplemente,
remplazaremos la fila de código que efectuaba el cálculo por el nombre de la función personalizada que hemos
creado dándole como parámetro el contenido de la celda. De esta manera:
Sub Convertir_Grados()
Dim Núm_Fila As Long
Núm_Fila = 2
While Cells(Núm_Fila, 1) <> ""
Cells(Núm_Fila, 3) = Fahrenheit(Cells(Núm_Fila, 2))
Núm_Fila = Núm_Fila + 1
Wend
End Sub
3. Afectar un tipo a la función personalizada
Como las funciones personalizadas devuelven un valor, está perfectamente autorizado precisar el tipo de datos que
devolverá la función (aunque no es obligatorio). En nuestro ejemplo podíamos haber escrito:
El tipo de datos que devuelve la función será de tipo Double. Si nuestra función devuelve el resultado de un test,
como la presencia o no de un archivo en un directorio (tal y como veremos en el capítulo Trabajar con los archivos),
nuestra función se declarará como Boolean.
Podrá encontrar todo el código en el archivo Ejemplo 9D3.x
4. Transmitir un rango de celdas
Hasta ahora solo habíamos transmitido variables unitarias a nuestros procesos o a nuestras funciones
personalizadas, pero también es posible transmitir conjuntos de valores usando tablas en memoria.
Lo más simple para ilustrar este punto es crear una función Suma que sumará 10 celdas que se transmitirán en
forma de rango de datos.
Transmitir un rango de datos equivale a transmitir una tabla como argumento. En el ejemplo de abajo, efectuamos
la llamada a la función Mi_Suma transmitiéndole un rango de datos.
Sub Llamada_Función()
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Cells(12, 1) = Mi_Suma(Range("A1:A10"))
End Sub
En el capítulo Las variables ya hablamos del funcionamiento de las tablas. En el capítulo Optimización también
encontrará consejos para mejorar el rendimiento de las tablas mediante la instrucción UBound que devuelve el
tamaño de una tabla.
En nuestro ejemplo resulta muy práctico, ya que sea cual sea el número de celdas que se transmiten como
parámetros, siempre podremos efectuar un bucle entre el primer elemento y el último de la tabla en memoria.
En nuestro ejemplo hacemos un bucle con los valores transmitidos en argumento, pero debemos notar aquí una
diferencia. El primer elemento está en posición 1 (y no 0 como en el caso con la tabla).
La particularidad de transmitir un rango de celdas como argumento es que no se transmiten los valores contenidos
en las celdas, sino un montón de información: el ancho de las columnas, la altura de las filas, los bordes, los
nombres de las celdas, etc. Este es el motivo por el que estamos obligados a declarar el rango de celdas como
Object o Variant.
Es también por esta razón por lo que estamos obligados a precisar que durante el test hecho con la instrucción
UBound nos centramos solo en los valores (Value). Si hubiéramos escrito el nombre del parámetro solo, el
programa no habría podido interpretar nuestros datos.
Por lo tanto, realizaremos un bucle en cada uno de los elementos de la tabla donde hacemos la suma acumulativa
de los valores en la variable Mi_Suma que es también el nombre dado a la función personalizada.
Encontrará el Ejemplo 9D4 con su código desde la página Información.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Ejemplo de aplicación
Uno de los indicadores de análisis bursátil son los medios móviles. El principio es hacer la media de los x últimos días
de las bolsas para encontrar una tendencia. Eso es lo que haremos tomando respectivamente la media de los últimos
10, 20 y 30 días.
Dicho de esta forma podríamos pensar que será preciso escribir largas líneas de código. No obstante, al escribir
programas divididos en tareas unitarias escribiremos, de hecho, códigos muy cortos. Es posible obtener el libro con
los datos brutos desde la página Información, Ejemplo 9E.xlsx.
1. Etapa 1: creación del código para la primera celda
En primer lugar, concentrémonos en el cálculo de la primera media. Como debemos realizar el cálculo de los diez
últimos días, nuestra primera media se calculará en la celda D11.
Ahora construimos un bucle que recuperará los diez primeros valores, los irá sumando y después, dividirá el
resultado obtenido entre 10.
Escriba el siguiente código:
Sub Pgm_Principal()
Dim i_Fil As Long
Dim Resultado_Sum as Double
For i_Fil = 1 To 10
Resultado_Sum = Resultado_Sum + Cells(i_Fil + 1, 3)
Next
Cells(11, 4 = Resultado_Sum/10
End Sub
2. Etapa 2: extracción del cálculo de la suma en una función
Vamos a aislar el bucle que calcula la suma en una función pasando como parámetro las diez primeras cotizaciones
en bolsa en una tabla tal y como hemos visto en el párrafo precedente.
Escriba el siguiente código:
Sub Pgm_Principal()
Cells(11,4) = La_Suma(Range("C2:C11")) / 10
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Dim indice_Tab As Long
For indice_Tab = 1 To Ubound(Tab_Valor.Value)
La_Suma = La_Suma + Tab_Valor(indice_Tab)
Next
End Function
La escritura de la función se comprende con bastante facilidad. Hemos trasmitido el contenido de diez celdas a la
función, lo que se traduce por la transmisión de una tabla como parámetro.
A continuación, recorreremos toda la tabla con la variable indice_Tab hasta llegar al último valor de la tabla dado
por la instrucción UBound.
Esta instrucción es muy práctica, ya que sin conocer exactamente el número de elementos que la tabla contiene,
sabemos que leeremos siempre todos los valores de la tabla en memoria. Estamos obligados a especificar .Value
ya que nos centramos solo en los valores transmitidos en la tabla y no en las demás propiedades.
En el bucle principal, el resultado que la función devuelve se divide entre 10.
3. Etapa 3: creación de la función Media
Podemos detallar aún más nuestro código separando el cálculo de la suma y el cálculo de la media, metiendo cada
uno en una función.
Como el cálculo de la media depende del cálculo de la suma (que es en sí misma una función), vamos a utilizar como
parámetro de la función Media, el resultado de la función Suma.
Modifique el código de la siguiente forma:
Sub Pgm_Principal()
Cells(11,4) = La_Media(Range("C2:C11"))
End Sub
Por sí mismo verá que las funciones de cálculo de la suma y de la media utilizan a la vez la tabla transmitida para
sumar los valores y el tamaño de la tabla (el número de elementos contenido en su interior) para efectuar la
división.
Estas dos funciones se codifican de manera que funcionarán independientemente del número de celdas
transmitidas. Dado que estas dos funciones funcionan en todos los casos, vamos a ponerlas aparte, es decir, en un
módulo separado y no volveremos más a ellas.
Ahora vamos a concentrarnos solo en los bucles que nos permitirán recorrer todas las celdas donde van a calcularse
las diferentes medias.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
4. Etapa 4: creación del bucle para las filas y explicación del código
Ahora vamos a diseñar el bucle para calcular las medias móviles de todas las celdas de la columna D. Sabemos que
el primer cálculo debe mostrarse en la fila 11 (para contabilizar los 10 datos anteriores). Aquí vamos a utilizar el
valor de la celda D1 para determinar el número de celdas que se debe transmitir a la función.
a. El código
Elaboraremos un bucle While que se detendrá cuando el programa llegue a la última celda no vacía de la columna
A y cuando hayamos recorrido 10 filas (test con la función If), transmitiremos el rango de celdas a la función.
Escriba el bucle de la siguiente forma, sustituyendo el código creado en la etapa 1:
Sub Pgm_Principal()
Dim NúmFil As Long
Dim EncabCol As Long
NúmFil = 2
EncabCol = Cells(1, 4) ’Valor en celda D1
While Cells(NúmFil, 1) <> ""
If NúmFil > EncabCol Then
Cells(NúmFil, 4) = _
La_Media(Range(Cells(NúmFil - EncabCol + 1,3),Cells(NúmFil,3)))
End If
NúmFil = NúmFil + 1
Wend
End Sub
b. Explicación del código
Al inicio del programa, en la variable EncabCol recuperamos el valor del encabezamiento (el valor 10 en D1).
Dentro del bucle, llevamos a cabo un test para saber si el valor de la fila leída (NúmFil) es mayor que el valor del
encabezado de la columna. De esta forma sabremos cuándo tendremos al menos 10 celdas que debemos pasar
como parámetros a las funciones. Por ejemplo, si la variable NúmFil vale 8, habremos leído menos valores de lo
esperado y, por tanto, no llamaremos a la función personalizada para efectuar los cálculos.
Cuando hayamos leído al menos 10 celdas, llamaremos a la función La_Media pasándole como parámetro el
rango de celdas de las 10 celdas leídas anteriormente.
Para escribir esto, vamos a usar la función Range y usaremos como parámetro las coordenadas de la primera
celda Cells(NúmFil - EncabCol + 1, 3) y la última celda del rango Cells(NúmFil, 3). En el caso de
que la variable NúmFil valga 11, tomaremos las coordenadas de la celda Cells(11-10+1, 3) y de la celda
Cells(11, 3).
5. Etapa 5: creación del bucle para las columnas
Para hacer el cálculo de la media de las tres columnas D, E y F, basta con reemplazar el parámetro de la columna en
la instrucción Cells por una variable y crear un nuevo bucle, solo para hacerla variar el valor de las columnas.
Para realizar este último bucle, podemos utilizar la instrucción FOR ... NEXT ya que sabemos que debemos
hacer el bucle 3 veces, para los valores 10, 20 y 30.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Ya solo quedaría reemplazar las referencias que se hacen en la columna 4 por la variable NúmCol.
Modifique el código de la siguiente forma:
Sub Pgm_Principal()
Dim NúmFil As Long
Dim NúmCol As Long
Dim EncabCol As Long
For NúmCol = 4 To 6
NúmFil = 2
EncabCol = Cells(1, NúmCol) ’Valor de los encabezados
While Cells(NúmFil, 1) <> ""
If NúmFil > EncabCol Then
Cells(NúmFil, NúmCol) = _
La_Media(Range(Cells(NúmFil - EncabCol + 1, 3),_
Cells(NúmFil, 3)))
End If
NúmFil = NúmFil + 1
Wend
Next
End Sub
6. Conclusión
Al final tenemos un único procedimiento que efectúa un bucle en las filas y otro en las columnas. También tenemos
dos funciones de cálculo: la primera para el cálculo de la suma y la otra, para el cálculo de la media. El código final
es:
Sub Pgm_Principal()
Dim NúmFil As Long
Dim NúmCol As Long
Dim EncabCol As Long
For NúmCol = 4 To 6
NúmFil = 2
EncabCol = Cells(1, NúmCol) ’Valor encabezados
While Cells(NúmFil, 1) <> ""
If NúmFil > EncabCol Then
Cells(NúmFil, NúmCol) = _
La_Media (Range(Cells(NúmFil - EncabCol + 1, 3),_
Cells(NúmFil, 3)))
End If
NúmFil = NúmFil + 1
Wend
Next
End Sub
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Function La_Media(Tab_Valor As Variant) As Double
La_Media = La_Suma(Tab_Valor) / UBound(Tab_Valor.Value)
End Function
El código completo se encuentra en el archivo Ejemplo 9E5.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Parámetros opcionales
Cuando se elaboran procedimientos o funciones a partir de parámetros, es obligatorio informar de todos los
parámetros en el momento de hacer la llamada. De no ser así, el programa se detendrá inmediatamente en caso de
detectar que el número de parámetros que se direccionan no se corresponde con el número de parámetros que se
esperan.
Existen situaciones en las que elaborar dos funciones prácticamente iguales exceptuando uno o dos parámetros no
es demasiado oportuno, sobre todo para mantener el código.
Para evitar esto, en el momento de crear procedimientos o funciones, podemos indicar que algunos parámetros son o
no obligatorios.
Tomemos el ejemplo de un libro que contiene cantidades y precios unitarios de bienes producidos y también una
columna con el país emisor de la factura.
Deseamos crear una función que calcule el precio sin impuestos en todos los países, pero también queremos que esa
misma función calcule el importe con IVA cuando se trata de España. Para los demás países no es preciso editar el IVA
ya que no será posible recuperarlo.
Nuestro programa de llamada y la función para el cálculo sin IVA se escribe de la siguiente simple manera:
Sub Pgm_Principal()
Dim NúmFil As Long
NúmFil = 2
While Cells(NúmFil, 1) <> ""
Cells(NúmFil, 5) = Precio _ SinIVA _ ConIVA (Cells(NúmFil, 4),
Cells(NúmFil, 3))
NúmFil = NúmFil + 1
Wend
End Sub
Ahora modificaremos la función de llamada para gestionar el cálculo del IVA, pero para ello necesitamos dos
informaciones más: el país y la tasa de IVA. Como esta información no es útil para calcular el precio sin IVA,
indicaremos que esos parámetros son opcionales.
Para indicar parámetros opcionales, es necesario precederlos de la instrucción Optional y es imperativo situarlos
al final de los parámetros.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Para que se tenga en cuenta que la función puede funcionar con parámetros opcionales, escribiremos el programa de
la siguiente manera:
Sub Pgm_Principal()
Dim NúmFil As Long
NúmFil = 2
While Cells(NúmFil, 1) <> ""
Cells(NúmFil, 5) = Precio_SinIVA_ConIVA(Cells(NúmFil, 4),
Cells(NúmFil, 3))
Cells(NúmFil, 6) = Precio_SinIVA_ConIVA(Cells(NúmFil, 4),
Cells(NúmFil, 3),_ Cells(NúmFil, 2), 0.2)
NúmFil = NúmFil + 1
Wend
End Sub
Si no el parámetro País no está indicado al hacer la llamada, entonces se recibe como vacío en la función, de ahí que
llevemos a cabo un test sobre ese parámetro para saber si debemos considerar o no ese valor en la función.
En el procedimiento principal, llamamos en dos ocasiones a esta función:
l Una vez en la columna E para calcular el precio sin IVA.
l Una vez en la columna F para calcular el con IVA solo en España.
Puede encontrar el programa completo en el archivo Ejemplo 9F.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Los operadores
Uno de los aspectos clave de la programación es realizar comparaciones entre datos y, en función del resultado de
esta comparación, efectuar un tratamiento específico.
Este capítulo le presentará la lista completa de los operadores que están a su disposición para efectuar tests entre
variables.
1. Los operadores aritméticos
La siguiente tabla presenta la lista de los operadores y su significado:
Operador Resultado
a + b Suma los valores a y b.
a b Resta el valor b del valor a.
Atención, a b no da el mismo resultado que b a.
a * b Multiplica los valores a y b.
a / b Divide el valor a entre el valor b.
a ˆ b Eleva una variable a a la potencia b.
a Mod b Devuelve el resto de la división de a entre b (Mod significa Módulo).
Los operadores aritméticos respetan el orden de prioridades matemáticas.
Si una operación utiliza varios operadores aritméticos, las potencias se calcularán siempre antes que la
multiplicación y la división, que a su vez, se calcularán antes que la resta y la suma.
Para modificar el orden de prioridad de los cálculos, puede emplear los paréntesis.
Por ejemplo:
l 4*4ˆ21/4 = 63,75
l 4*4ˆ(21)/4 = 4
l 4*4ˆ((21)/4) = 5.65
l (4*4)ˆ((21)/4) = 2
Los módulos son operadores poco conocidos, pero son muy útiles para saber si un número es múltiplo de otro.
Por ejemplo, para saber si el número de la celda A1 es un número par, puede escribir el siguiente código:
Para realizar un test a una celda para saber si su valor es un múltiplo de 12, puede escribir el siguiente código:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Msgbox "La celda A1 es un múltiplo de 12"
Else
Msgbox " La celda A1 no es un múltiplo de 12"
End If
2. Los operadores de comparación
Los operadores de comparación en VBA son idénticos a los símbolos matemáticos. La tabla siguiente le resume el
conjunto de comparaciones que puede realizar.
Operador Resultado
a = b Verifica si a y b son iguales.
a < b Verifica si a es menor (estrictamente) que b.
a <= b Verifica si a es menor o igual que b.
a > b Verifica si a es mayor (estrictamente) que b.
a >= b Verifica si a es mayor o igual que b.
a <> b Verifica si a y b son diferentes.
3. Los operadores lógicos (o booleanos)
Existen cuatro operadores lógicos: Or, And, Xor y Eqv. Cada uno de ellos verifica una expresión A y una expresión
B; según el operador lógico escogido, la expresión devolverá el resultado Verdadero (True) o Falso (False):
l El operador Or devuelve True cuando una de las dos expresiones o las dos, son verdaderas.
l El operador And devuelve True solo si las dos expresiones son verdaderas.
l El operador Xor (o O Exclusivo) devuelve True si una sola de las dos expresiones es verdadera (pero no las dos).
A continuación, le mostramos cuatro ejemplos para ilustrar cada uno de los casos:
l Para ganar en las carreras de caballos, puede apostar o en orden, o sin orden, pero en los dos casos, usted gana.
Para saber cuáles son los jugadores que ganan, hay que utilizar el operador Or.
l Para que admitan a un estudiante, tiene que tener una media de 5 y ninguna nota inferior a 2,5. Aquí, utilizaremos el
operador And.
l Para contratar a un candidato, el perfil ideal ha de tener, al menos, cuatro años de estudios, o, al menos, cinco años
de experiencia, pero no los dos criterios. Por tanto, utilizará el criterio Xor.
l En caso de contaminación, los coches con matrículas pares tienen derecho a circular los días pares (y viceversa). En
este caso, hay que utilizar el operador Eqv (parpar/imparimpar).
Existe otro operador lógico que invierte el valor de la expresión. Se trata del operador Not.
4. Simplificación de la escritura de los tests
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Puede escribir las condiciones de dos formas distintas:
o
También puede incluir paréntesis para dar prioridad al orden de sus tests. Por ejemplo, en caso de que desee
realizar un test a sus clientes. En la columna A, puede indicar Hombre o Mujer y en la columna B, la información de
su estado civil (casado, soltero, viudo, etc.). Si quiere hacer un test de las mujeres solteras o viudas, escribirá el
test de la siguiente manera:
Si prueba el valor Verdadero, no es necesario escribirlo en una condición IF, ya que, por defecto, es lo que la
función va a buscar:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Conversión de variable
Muchas empresas trabajan con archivos de texto procedentes de exportaciones de bases de datos. Por ese motivo,
los datos contenidos en esos archivos suelen ser de tipo String, incluidos los valores numéricos. Como no es posible
hacer cálculos con los datos textuales (String), deberá convertir el tipo de sus variables en uno de los tipos de datos
numéricos existentes.
1. Funciones de conversión
La siguiente tabla le presenta el conjunto de funciones de conversión de Visual Basic:
Función Resultado
CDbl (variable) Convierte la variable en tipo Double.
CLng (variable) Convierte la variable en tipo Long.
CStr (variable) Convierte la variable en tipo String.
CDate (variable) Convierte la variable en tipo Date.
Pero atención, la conversión de una variable en un cálculo no transforma su tipo permanentemente para el resto del
programa. La conversión solo se aplica para la instrucción o el cálculo en el que se utiliza la variable.
2. Probar una variable
La utilización de una cadena de caracteres en un cálculo provoca la detención del programa. Si tiene dudas sobre el
contenido de una variable, es preferible efectuar un test sobre el tipo.
Se pueden probar dos tipos de datos: los datos que utilizan la función IsDate y los datos numéricos con
IsNumeric.
Por ejemplo, puede realizar el test siguiente para comprobar el tipo de datos contenidos en la celda A1.
Sub Test_Dato()
If IsNumeric(Cells(1,1)) Then
MsgBox "La celda A1 contiene un valor numérico"
Else
MsgBox "La celda A1 no contiene cifras"
End If
End Sub
La instrucción IsNumeric devuelve Verdadero o Falso; según el valor contenido en la celda A1, se mostrará uno de
los dos mensajes.
En este ejemplo, podemos omitir precisar el test = True, ya que es, por defecto, el valor probado con If. Puede
agregar = True para más claridad, esto no cambiará en absoluto el resultado del test:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Funciones matemáticas
1. Funciones usuales
Además de los operadores aritméticos descritos anteriormente, el lenguaje VBA posee un gran número de funciones
matemáticas. En la siguiente tabla le mostramos las más usuales.
Función Resultado
Abs(x) Devuelve el valor absoluto del número x.
Int(x) Devuelve la parte entera del número x.
Sqr(x) Devuelve la raíz cuadrada del número x.
Rnd() Devuelve un número aleatorio comprendido entre 0 y 1. Esta instrucción no requiere un parámetro,
sin embargo es aconsejable preceder una función Rnd por la función Randomize para reiniciar el
algoritmo aleatorio.
Round(x,n) Redondea la cifra x con n decimales.
2. Las funciones Excel
También puede integrar funciones Excel en un programa VBA. Tomemos por ejemplo el cálculo de la desviación típica
de las celdas A1 a A5.
En un procedimiento, utilice el objeto Application y asóciele la propiedad WorksheetFunction. Si escribe un punto
en la expresión, aparecerá un menú desplegable con la lista completa de las funciones de cálculo de Excel:
Los nombres de las funciones están en inglés; para calcular la desviación típica, vamos a buscar la función StDev
(diminutivo de Standard Deviation o desviación típica en español). Los parámetros de esta función corresponden al
rango de celdas A1:A5. La escritura pasa a ser:
Application.WorksheetFunction.StDev(Range("A1:A5"))
Para recuperar el resultado en una variable, escriba:
Sub Función_Mate()
Dim Resultado As Double
Resultado = Application.WorksheetFunction.StDev(Range("A1:A5"))
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Introducción
En VBA, encontrará todas las funciones de Texto de Excel, e incluso, algunas más. Empezaremos presentando todas
las funciones y su uso en casos concretos y después veremos cómo recuperar los datos desde un archivo de texto y
cómo crear un archivo de texto mediante un programa VBA.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Funciones básicas
1. El operador &
a. Utilización en un programa
Antes que nada, es indispensable conocer el operador & y su utilización. Este operador permite relacionar dos
elementos juntos (texto, variable, contenido de celdas, etc.) para hacer solo uno. La utilización de este operador
es realmente primordial en programación y los ejemplos de utilización son infinitos.
b. Ejemplo de uso para cambiar el nombre a una hoja
Abra el archivo Ejemplo 11B1b. En este archivo, aparece una lista de apellidos en la columna A y una lista de
nombres en la columna B. Para cada una de las líneas del libro, va a crear una hoja que se denominará el Apellido
+ el Nombre.
Comience utilizando la Grabadora de macros para agregar una nueva hoja llamada Nuevo Apellido.
Obtendrá un código similar a este:
Sheets.Add After:=ActiveSheet(1)
Sheets("Hoja2").Select
Sheets("Hoja2").Name = "Nuevo Apellido"
A continuación, integre ese código en un bucle, con ruptura en los apellidos de la columna A de la Hoja 1.
Sub Adición_Hoja()
Dim Núm_Fila As Long
Núm_Fila = 2
While Sheets("Hoja1").Cells(Núm_Fila, 1) <> ""
Sheets("Hoja1").Select
Sheets.Add After:=Sheets(1)
Sheets("Hoja2").Select
Sheets("Hoja2").Name = "Nuevo Apellido"
Núm_Fila = Núm_Fila + 1
Wend
End Sub
A continuación, reemplace "Nuevo Apellido" por la concatenación de las celdas de la columna A y B del
siguiente modo:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
El operador & se utiliza dos veces en este ejemplo ya que ponemos un espacio " " entre el apellido y el nombre.
Sin este, el apellido y el nombre se unirían uno al otro. Si desea separar el apellido del nombre por un guion,
escriba el código de la siguiente forma:
c. Entrar en bucle con todos los nombres
Para acabar su programa, reemplace la cifra 1 de la instrucción Sheets.Add que indica después de
qué hoja añade una nueva hoja, por la expresión Sheets.Count que devolverá el número de hojas
de su libro. El código final es el siguiente:
Sub Adición_Hoja()
Dim Núm_Fila As Long
Núm_Fila = 2
While Sheets("Hoja1").Cells(Núm_Fila, 1) <> ""
Sheets.Add After:=Sheets(Sheets.Count)
ActiveSheet.Name = Sheets("Hoja1").Cells(Núm_Fila, 1) & " " &
Sheets("Hoja1").Cells(Núm_Fila, 2)
Núm_Fila = Núm_Fila + 1
Wend
End Sub
El resultado corresponde a la imagen siguiente:
Encontrará el código completo en el archivo del Ejemplo 11B1c.
Atención: muy a menudo, VBA agrega automáticamente espacios entre las instrucciones, pero raramente con el
símbolo &. Con el símbolo & es usted el que tiene que poner los espacios entre cada elemento de una línea de
código para no generar errores de ejecución.
Ejemplo de error al crear un nombre de archivo:
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
2. Las tres instrucciones habituales
a. La instrucción Left
La instrucción Left permite extraer los n caracteres de la izquierda de una cadena de caracteres.
Left(texto; n caracteres)
b. La instrucción Right
La instrucción Right permite extraer los n caracteres de la derecha de una cadena de caracteres.
Right(texto; n caracteres)
c. La instrucción Len
La instrucción Len devuelve el número de caracteres contenidos en una cadena de caracteres.
d. Ejemplo de uso de instrucciones de texto
Len(texto)
La utilización de estas tres instrucciones Left, Right y Len le permitirá hacer selecciones determinadas.
Por ejemplo, deseamos recuperar del siguiente documento el número de cada habitación:
El número de la habitación puede tener una longitud de 1 o 2 unidades. Por tanto, debemos adaptar el parámetro
longitud de la instrucción Right para devolver cada número.
Como la primera parte de la celda (la palabra Habitación) siempre tiene la misma longitud, utilizando la longitud
total de la celda (con la instrucción Len), menos la longitud de la palabra Habitación (añadiéndole también el
espacio después de la palabra, es decir, 11 caracteres en este ejemplo), obtendremos exactamente la longitud
que debemos seleccionar.
Por lo tanto, el código será:
Sub Bucle_Principal()
Dim Núm_Fila As Long
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Cells(Núm_Fila, 2) = Right(Cells(Núm_Fila, 1), _
Len(Cells(Núm_Fila, 1)) - 11)
Núm_Fila = Núm_Fila + 1
Wend
End Sub
e. Extracción de una parte de una celda
Mid(Texto,Posición de partida,Longitud)
Esta instrucción devuelve una parte de una cadena de caracteres dentro de esta. Por ejemplo, tiene la siguiente
lista de datos:
Cada nombre está compuesto por la palabra Informe, por una fecha y un estado. Para extraer la fecha de cada
línea, hay que recuperar una cadena de caracteres de una longitud de 7 caracteres a partir del 11º carácter (el
término "Informe " cuenta con 10 caracteres con los espacios y el guion).
Escriba un programa como este para extraer la fecha de cada una de las celdas:
Sub Bucle_Principal()
Dim Núm_Fila As Long
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Cells(Núm_Fila, 2) = Mid(Cells(Núm_Fila, 1), 11, 7)
Núm_Fila = Núm_Fila + 1
Wend
End Sub
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
3. Sustitución
a. Función Mid
La función Mid tiene un segundo uso: también permite reemplazar una parte de los caracteres de una cadena por
otros en un lugar concreto.
Tomando el ejemplo anterior, deseamos reemplazar el carácter "" por el carácter "/".
Modifique el código del siguiente modo:
Sub Bucle_Principal()
Dim Núm_Fila As Long
Dim Cadena_a_tratar As String
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Cadena_a_tratar = Cells(Núm_Fila, 1)
Mid(Cadena_a_tratar, 9, 1) = "/"
Cells(Núm_Fila, 1) = Cadena_a_tratar
Núm_Fila = Núm_Fila + 1
Wend
End Sub
Atención: la substitución se hace en la memoria. No es posible hacer la modificación y, al mismo tiempo, mostrar el
resultado en la hoja de cálculo.
Ese es el motivo por el cual el contenido de la celda se almacena en la variable Cadena_a_tratar, la sustitución
se hará desde esta variable y el contenido de esta variable se copiará en la misma celda que la celda de origen.
b. Función Replace
La función Replace es más completa que la función Mid. Cuando Mid impone el reemplazo de un carácter por otro
en un lugar concreto, la función Replace, reemplaza 1 o n caracteres en su cadena inicial por otro, y no importa
dónde se encuentren estos caracteres en la cadena. Esta función, por defecto, tiene en cuenta la caja (diferencia
entre las mayúsculas y las minúsculas).
Si, por ejemplo, tiene la palabra "Abracadabra" en la celda A1, la instrucción siguiente tendrá como resultado
"Abricidibri":
La primera A, que está en mayúscula, no se ha reemplazado.
4. Posicionamiento de un carácter
a. La instrucción InStr
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
InStr([Posición de partida], Texto, Texto buscado, [Opción de comparación])
La instrucción InStr (diminutivo de In String, traducido por En la Cadena), devuelve la posición de un carácter o
de un grupo de caracteres en una cadena de caracteres. Si la cadena que busca no está presente, la función InStr
devolverá 0.
La función InStr a menudo se emplea en tests para conocer, o no, la presencia de caracteres.
No es necesario especificar la posición de partida si comienza por el principio de la cadena de caracteres (por
defecto, la posición de partida es igual a 1).
Escriba el siguiente código:
Sub Test_Instr()
Dim Valor_Test As String
Dim Resultado As Long
Valor_Test = "El monstruo de las galletas :)"
’Ningún valor para la posición de partida
Resultado = InStr(Valor_Test, "E")
Cells(1,1) = Resultado
End Sub
El valor devuelto en A1 es 1.
Pruebe la instrucción modificando sucesivamente el código:
La función tiene en cuenta la caja como muestra el resultado de los dos primeros tests con la letra ”e”.
b. La instrucción InstrRev
Por el contrario, si lo que quiere es encontrar la posición de un carácter o de una palabra desde el final de la
cadena de caracteres, la instrucción InstrRev es la más adecuada.
Si se omite la posición de partida, la búsqueda comienza desde el último carácter (valor implícito 1). Por el
contrario, si introduce un valor (por ejemplo 10), la búsqueda invertida comenzará a partir del décimo carácter
partiendo del principio de la cadena de caracteres (partiendo de la izquierda y no de la derecha, como la
instrucción habría podido hacernos pensar).
Tomemos el siguiente ejemplo: desea obtener el nombre del último directorio contenido en la cadena de
caracteres.
- 6- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
En primer lugar, haremos un test simple para saber si el último carácter de la cadena es el símbolo \ (en cuyo caso
no lo tendremos en cuenta), a continuación, recuperamos la posición del carácter \ y extraemos el nombre del
último directorio.
Sub Último_Directorio()
Dim Ruta As String
Dim Último_Dir As String
Ruta = "C:\Mis Documentos\Usuario\Excel\Proyecto001\"
’Test para saber si el último carácter es \, si sí, se eliminará
If Right(Ruta,1) = "\" Then
Toda la cadena se conserva exceptuando el último carácter
Ruta = Left(Ruta, Len(Ruta) - 1)
End If
5. Cortar una cadena
Split(Texto, separador)
La función Split le permite cortar una cadena de caracteres según un separador (coma, punto y coma, guion, etc.).
Esta función extraerá automáticamente cada parte de su cadena en una tabla en memoria. No es necesario que
gestione el tamaño de esta tabla, la misma función es la que realiza el trabajo.
En la sección Corte según un carácter de separación de este capítulo, encontrará un ejemplo completo de utilización
de esta función.
6. Supresión de los espacios
Trim(Texto)
Esta función permite "limpiar" toda una cadena de caracteres de los espacios indeseado colocados al principio y al
final.
Si solo desea sustituir los espacios del principio de las cadenas, puede utilizar la función LTrim(Texto) y, al
contrario, si desea borrar solo los espacios de la derecha, utilizará la función RTrim(Texto).
7. Mayúsculas y minúsculas
a. Todos los caracteres en mayúsculas
Ucase(Texto)
La función Ucase (Upper Case) permite poner en mayúsculas todos los caracteres de una cadena. También puede
utilizar la función StrConv con la siguiente fórmula:
StrConv(Texto, vbUpperCase)
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 7-
b. Todos los caracteres en minúsculas
Lcase(Texto)
La función Lcase (Lower Case) permite poner en minúsculas todos los caracteres de una cadena.
También puede utilizar la función StrConv con la siguiente fórmula:
StrConv(Texto, vbLowerCase)
c. Primera letra en mayúscula
Para tener, en una cadena de caracteres, sistemáticamente la primera letra en mayúsculas y el resto en
minúsculas, debe utilizar la función StrConv escrita de la siguiente forma:
StrConv(Texto, vbProperCase)
Esta función es muy útil para los nombres compuestos o los archivos musicales (mp3, por ejemplo).
8. Invertir las letras
StrReverse(Texto)
Esta función invierte todos los caracteres de su cadena inicial, incluido el orden de las palabras. Se utiliza para
encontrar palíndromos (palabras que se escriben del mismo modo en los dos sentidos como Radar, Kayak,
Reconocer) o también para realizar algoritmos de codificación.
La siguiente imagen le muestra el resultado de una misma cadena con las cuatro funciones de transformación de
una cadena de caracteres.
9. Comparación de cadenas
a. Función StrComp
- 8- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
StrComp(Texto_1, Texto_2, Tipo de comparación)
La función StrComp le permite comparar dos cadenas entre sí.
El tercer argumento de la función le permite tener en cuenta la caja (vbBinaryCompare), o no
(vbTextCompare).
El resultado devuelto por la función es:
1 Si Texto_1 es inferior a Texto_2
0 Si Texto_1 es idéntico a Texto_2
1 Si Texto_1 es superior a Texto_2
Escriba el siguiente código:
Sub Comparar_Cadenas()
Dim Comparación As Long
Dim Texto_1, Texto_2 As String
Texto_1 = "ABCD": Texto_2 = "abcd"
Comparación = StrComp(Texto_1, Texto_2, vbBinaryCompare) ’ =-1
Cells (1,1) = Comparación
End Sub
El resultado que aparecerá en A1 es 1.
Modifique el código para comprobar la instrucción:
b. Función Like
En su forma básica, la función Like le permite comparar dos cadenas entre sí y reenviar True o False según el
resultado.
Pero la función Like también permite el uso de metacaracteres en los criterios de comparación.
La siguiente tabla le muestra los metacaracteres que puede utilizar:
Metacaracteres Correspondencia en su cadena
? Cualquier carácter único
* Cero o más caracteres
# Cualquier cifra (09)
[ listacaracteres ] Cualquier carácter presente en listacaracteres
[! listacaracteresc] Cualquier carácter ausente en listacaracteres
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 9-
Para comprobar que tiene una dirección de correo electrónico en una celda, puede escribir:
Para comprobar que tiene una dirección de correo electrónico que termina por .es, puede escribir:
Para comprobar que tiene un número de teléfono móvil, puede escribir:
10. Los caracteres ASCII
a. La instrucción Asc
En un ordenador, cada signo corresponde a una cifra en la clasificación ASCII (American Standard Code for
Information Interchange). El código 65 está asociado con el carácter A y el código 97 está asociado al carácter a
(discriminación mayúsculas/minúsculas).
Para conocer la cifra asociada a un signo cualquiera, utilice la función Asc. El ejemplo siguiente devuelve el valor
65.
Si diseña un programa en el que los usuarios puedan especificar la letra de la columna a partir de la cual se inicia
el tratamiento, podrá escribir el siguiente código:
Si el usuario indica la columna D por ejemplo, Asc ("D") envía el valor 68. A continuación, 6864 envía el valor 4.
Sabrá que el usuario quiere comenzar el tratamiento en la columna 4. Se trata de una técnica diferente a la que
vimos con la instrucción Column.
b. La instrucción Chr
Pero, con los caracteres ASCII, es sobre todo interesante la utilización de un número como carácter. Por ejemplo,
la instrucción Chr permite usar caracteres no imprimibles en el código, como los saltos de línea, por ejemplo. Así, si
quiere ver un mensaje con la función MsgBox en dos filas, tendrá que escribir:
- 10 - © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Chr(13) corresponde a un retorno de carro en la clasificación ASCII. En el anexo E, encontrará la lista de los 32
caracteres ASCII no imprimibles.
Esta función también puede emplearse en los tests del carácter comillas. Como una cadena de caracteres tiene
que ir entre comillas, no podrá escribir """ (tres comillas) para escribir su test. Sin embargo, puede escribir el
código siguiente para comprobar si el primer carácter de su cadena son unas comillas.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 11 -
Leer un archivo de texto
El lenguaje VBA permite acceder a un archivo de texto (.txt, .xml, .bat, .asc, etc.) directamente en la memoria, sin
tener que abrirlo en una hoja de Excel. De este modo, puede recorrer todo un archivo y seleccionar solo los
elementos que desea recuperar en ese archivo.
Vamos a ver en las siguientes secciones cómo abrir, leer, extraer y cerrar un archivo de texto. Después pondremos en
práctica estas técnicas en un caso real de importación de datos.
1. Abrir el archivo de texto
La apertura de un archivo de texto en la memoria requiere especificar:
l la ruta o el nombre del archivo,
l el tipo de acceso,
l el número de atribución.
a. La ruta o el nombre del archivo
Es necesario que el archivo exista y que la ruta de acceso sea correcta. Puede o bien poner la ruta completa entre
comillas o utilizar variables.
Muy a menudo, el carácter \ que separa la ruta de acceso y el nombre del archivo se omite: ¡no lo olvide, o no
podrá abrir el archivo!
b. El tipo de acceso
Es absolutamente necesario que especifique si accede a un archivo de lectura (Input) o de escritura (Output). Sin
este parámetro, su archivo no se podrá abrir nunca.
c. Número de archivo
Para cada archivo que abra, tendrá que concretar un número de orden que permitirá identificar sus archivos
durante el tratamiento. Puede gestionar usted mismo los números (1, 2, 3,...) o pedirle a VBA que gestione esos
números mediante la instrucción FreeFile.
Para nuestro ejemplo, podemos escribir la siguiente instrucción que abrirá nuestro archivo de texto:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
2. Leer una línea
La línea leída se transmitirá a la variable que figura tras la coma, aquí la variable Cadena_Leída.
3. La instrucción EOF
EOF(Número de archivo)
A diferencia de un bucle While, que comprueba si una celda está o no vacía para detenerse, no es posible detectar
el final de un archivo de texto de otra forma que mediante la instrucción EOF, (End Of File).
Esta instrucción reenviará Verdadero si se alcanza el final del archivo. El test se realiza en el número de archivo en el
parámetro. Al integrar esta instrucción en un bucle con condición, podemos detectar si se alcanza el final del bucle o
no.
While EOF(1)
Instrucción
Wend
4. Cerrar un archivo
Después de abrir un archivo, nunca debemos olvidar cerrarlo para liberar el número del archivo de la memoria.
Para las instrucciones Open y Close, el símbolo # no es obligatorio, pero sí aconsejado.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Crear un archivo de texto
El VBA también permite crear archivos de texto. Esta función es muy útil cuando se tienen que enviar datos de la hoja
de cálculo a una base de datos o bien diseñar un archivo de eventos (archivo log).
1. Crear un archivo
Crear un archivo consiste en usar la instrucción Open, pero definiendo el acceso como Output (salida). Después de
leer esta línea de código, VBA crea un archivo vacío con el nombre especificado.
Atención: si en su ordenador ya hubiera un archivo con el mismo nombre, este sería remplazado por el nuevo sin
mediar mensaje de aviso previo.
2. Escribir una línea
Para escribir datos en un archivo en salida, utilice la instrucción Print seguida del número de archivo
correspondiente al número de orden atribuido en el momento de abrirlo.
Para guardar una línea en el archivo, bastará con que ponga todos los datos en una sola variable.
3. Declarar variables
Para crear archivos de texto deberá declarar todas las variables de tipo String (lo que no deja de ser lógico, ya
que estamos diseñando un archivo de Texto). Las variables declaradas en String pueden tener una longitud fija.
Todos los elementos copiados en la variable tendrán entonces la misma longitud (definida por la cifra que sigue al
símbolo *).
4. Ejemplo de aplicación
Tiene un libro con:
l en la columna A, códigos postales,
l en la columna B, nombres de ciudades,
l en la columna C, referencia del cliente,
l en la columna D, apellidos,
l en la columna E, nombres.
El archivo correspondiente se llama Ejemplo 11D4.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Tiene que transmitir estos datos a una base de datos que le impone una estructura fija para cada campo:
l los códigos postales tienen que tener una longitud de 5.
l Los nombres de ciudad tienen que tener una longitud de 30.
l Las referencias de cliente tienen que tener una longitud de 9.
l Los apellidos de cliente tienen que tener una longitud de 25.
l Los nombres tienen que tener una longitud de 15.
Deberá crear, por tanto, un archivo de texto que respetará la longitud dada. El código será así:
Sub Crear_Archivo_Texto()
Dim Ruta As String
Dim Archivo As String
Dim i_Fil As Long
Dim CP As String * 5
Dim Ciudad As String * 30
Dim Ref As String * 9
Dim Apell As String * 25
Dim Nombre As String * 15
Sustituya "C:\Su_Ruta" por la ruta de acceso al lugar en que deberá guardarse el archivo conservando las
comillas.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Encontrará el código de este ejercicio en el archivo Ejemplo 11D4.
5. Ejercicios de aplicaciones
a. Nueva herramienta : Power Query
Antes de presentar los dos ejercicios de aplicaciones que vienen a continuación y que no son simples , es
importante hacer un paréntesis para presentar una nueva herramienta: Power Query.
Power Query es una herramienta que ha sido desarrollada para facilitar la importación de datos, no solo para
archivos de texto, y la manipulación de datos (separación en columnas, eliminación de líneas concretas, cambio de
un documento en columnas a un documento en filas, reagrupación de datos, fusión de columnas, etc.).
Power Query se usa de la misma forma que la Grabadora de macros: todas las manipulaciones efectuadas son
guardadas con el fin de repetirlas. Y, contrariamente a VBA, no es en absoluto necesario entrar en el código para
personalizar la importación. El uso del lenguaje de programación de Power Query lenguaje M se reserva a
casos muy específicos.
Por tanto, si los elementos que necesita automatizar conciernen a importaciones de archivos y las manipulaciones
de datos, puede ser más oportuno trabajar con Power Query que usar la Grabadora de macros. Esto le permitirá
ganar mucho tiempo y, sobre todo, mantener el proceso de importación será mucho más fácil con Power Query que
con VBA.
b. Ejercicio: Extraer los datos de un archivo de texto
Descargue desde la página Información el documento Ejemplo 11D5.txt que contiene información
extraída de una base de datos. Desea incorporar esta información en un libro de Excel.
Desafortunadamente, en este ejemplo (procedente de un caso real de empresa), no hay delimitador de columnas
como tabulaciones o puntos y coma. Deberemos basarnos en la línea de títulos y en los espacios entre los
encabezamientos de columna para determinar los elementos que vamos a extraer.
Abrir y leer el archivo
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Para abrir, leer, hacer un bucle y cerrar un archivo, hay que escribir un código similar a este. Todas las
instrucciones usadas aquí ya han sido vistas en los apartados precedentes.
Sub Leer_Archivo()
Dim Cadena_Leída As String
Close #1
End Sub
Cada vez que se vuelve a pasar por el bucle, leemos una nueva fila del archivo. El incremento de filas se gestiona
automáticamente por la instrucción Line Input.
Corte en columna
El código que cortará nuestro archivo de texto inicial en columna se puede escribir en el mismo procedimiento justo
después de la instrucción Line Input o bien en un nuevo procedimiento para separar bien las tareas en el
programa:
Última_Fil = Cells(Rows.Count,1).End(xlUp).Row
Última_Fil = IIf(Cells(1, 1) = "", 1, Última_Fil + 1)
Cells(Última_Fil, 1) = Trim(Mid(Texto_A_Tratar, 1, 9))
Cells(Última_Fil, 2) = Trim(Mid(Texto_A_Tratar, 10, 11))
Cells(Última_Fil, 3) = Trim(Mid(Texto_A_Tratar, 22, 32))
Cells(Última_Fil, 4) = Trim(Mid(Texto_A_Tratar, 55, 8))
End Sub
El código está disponible en el Ejemplo 11D5b1.
Explicación del código
En este procedimiento empezamos recuperando el número de la última fila conocida en la hoja de cálculo gracias a
la instrucción Cells(Rows.Count,1).End(xlUp).Row. Habríamos podido poner simplemente el valor 1 y así
empezar siempre la importación en la fila 1. Solo que si construimos así el programa, no podemos encadenar las
importaciones de archivos sin amontonar los datos anteriormente importados.
La instrucción se comprende de la siguiente manera: nos colocamos ficticiamente en la última celda de la columna
A de nuestra hoja de datos Cells(Rows.Count,1) y volvemos a subir hacia arriba hasta la última celda no
vacía que encontremos End(xlUp). Así Excel se colocará en la última celda conocida de la columna A y devolverá
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
el número de la fila (Row).
Solo debemos tener en cuenta un caso adicional, el caso en que la columna A está completamente vacía. En ese
caso, si la celda A1 está vacía empezaremos el programa en la fila 1, si no nos situaremos justo después de la
última celda no vacía. Este test se escribe usando simplemente la función Iif.
Por último, cortamos nuestro archivo en cuatro trozos de longitud conocida y colocamos el resultado en cuatro
columnas de la hoja de cálculo. Para escribir el resultado sin ningún espacio inútil, limpiamos los datos de la
extracción con la función Trim.
Habríamos podido sustituir el primer Mid por un Left, pero para la continuación del tratamiento, es preferible
utilizar Mid en cada corte.
Escrito con estos dos procedimientos, nuestro programa ya funciona perfectamente, pero se puede perfeccionar
ya que esto implica que nuestro archivo de entrada tenga una estructura siempre idéntica y un número de
columnas siempre igual a 4.
Si de entrada tenemos varios archivos con un número de columnas diferente, deberemos hacer el programa más
flexible adaptándonos a la estructura del archivo de entrada.
Determinar la estructura del archivo
No cabe duda de que diseñar un programa que se adapte a la estructura de cualquier archivo en entrada lo hace
más complejo. No se desanime si no comprende las explicaciones a la primera lectura. Tómese el tiempo de
analizar el código del archivo y volver más tarde a las explicaciones de cada línea de código.
Usaremos también numerosas funcionalidades vinculadas a la tabla en memoria, así que si no está muy
familiarizado con el uso de tablas en memoria, le aconsejamos que lea las detalladas y sencillas explicaciones del
capítulo Optimización Las tablas en memoria.
Para determinar la estructura del archivo en entrada, se deben tener en cuenta dos elementos:
l el número de columnas;
l el número de caracteres que constituye cada columna.
Para obtener este resultado, vamos a basarnos, no solo en los espacios del encabezamiento de las columnas,
sino también en el primer carácter inmediatamente después de una serie de espacios.
Por tanto, en cada ruptura, tendremos:
l la posición del principio de una columna,
l al final del tratamiento, el número de columnas de nuestro archivo, correspondiente al número de pasadas del bucle.
Vamos a hacer un bucle en cada uno de los caracteres de la primera fila hasta alcanzar el último carácter. Para
cada columna detectada, vamos a guardar en una tabla en memoria el número de caracteres de la columna.
Como la estructura del archivo de texto es un elemento central del programa, debemos declarar la tabla, no en un
procedimiento como hemos hecho en cada ejemplo, sino en la parte superior de hoja Módulo para que los datos
de la tabla sean visibles por los procedimientos. Por ese motivo la tabla se declara fuera de todos los
procedimientos en Public, pero sin precisar su dimensión.
Efectivamente, no conocemos el número de columnas presentes en el archivo de texto, vamos a abrir y cerrar un
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
paréntesis sin valor. Sin embargo, en el programa, estaremos obligados a redimensionar la tabla antes de añadir
una nueva columna.
El código completo para obtener la estructura del archivo está descrito a continuación y podrá encontrar el ejemplo
completo en el archivo Ejemplo 11D5b2.
Option Explicit
’ -----------------------------------------------------------------------------
’ Procedimiento de detección de la posición de las columnas
’ -----------------------------------------------------------------------------
Sub Estructura Archivo()
Dim t_col() As Long ’Tabla determinar el valor del inicio de cada columna
Dim i_car As Long ’Indice para los caracteres
Dim i_tab As Long ’Indice el tamaño de la tabla
Dim Línea_A_Tratar As String
Se deben colocar obligatoriamente dos valores en particular en la tabla:
l El primero, obligatoriamente igual a 1 (la primera columna empieza en la posición 1).
l El último, obligatoriamente igual a la longitud de la cadena de caracteres.
- 6- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
En la siguiente figura, aparece el resultado contenido en la tabla en la memoria gracias al depurador.
Este resultado se interpreta de la siguiente manera:
l La primera columna empieza en la posición 1
l La segunda columna empieza en la posición 10
l La tercera columna empieza en la posición 22
l La cuarta columna empieza en la posición 55
l Fin de línea en posición 63
Escribir el resultado en Excel
Ahora que hemos construido un programa capaz de detectar de manera precisa el número de columnas y el
número de caracteres que componen cada columna, nos queda transformar nuestro procedimiento
Separación_Columna para que tenga en cuenta esos datos. Para ello retomaremos las informaciones que
habíamos almacenado en la tabla t_col.
Para determinar el número de caracteres que vamos a extraer, simplemente leeremos en la tabla dos valores
contiguos (i_tab e i_tab+1), y realizaremos la sustracción.
’ -----------------------------------------------------------------------------------
’ Procedimiento de cumplimentado de la hoja Excel utilizando la estructura de columnas
’ -----------------------------------------------------------------------------------
Sub Separación_Columna(Texto As String)
Dim i_tab As Long
Dim Última Fila As Long
El índice que usamos para recorrer la tabla se utiliza también para determinar la columna de escritura.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 7-
Gestión de las llamadas de los procedimientos
Acabamos de escribir dos nuevos procedimientos, uno para detectar la estructura de las columnas y otro para
dividir nuestro archivo en columnas. En el primer módulo, justo después de leer una línea del archivo de texto,
deberemos llamar a estos dos nuevos procedimientos.
Para recuperar una sola vez la estructura del archivo de texto durante la lectura de la primera línea del archivo,
aconsejamos añadir un test gracias al uso de una variable booleana (Verdadero o Falso):
Sub Leer_Archivo()
Dim Cadena_Leída As String
Dim Encabezamiento As Boolean
Close #1
End Sub
Puede encontrar el código en el archivo Ejemplo 11D5b3.
El código completo puede parecerle complejo pero, de hecho, es mucho mejor programar a través de varios
módulos que con un solo módulo en el que define una estructura estática.
El hecho de haber escrito el programa en tres procedimientos tiene como ventaja aislar cada componente:
l acceso al archivo,
l detección de la estructura del archivo,
l escritura del resultado.
Así, en caso de modificación de su código, es más fácil modificar un solo procedimiento que un programa completo.
c. Corte según un carácter de separación
Al igual que el comando Convertir de la pestaña Datos de Excel, que le permite sementar el texto en varias
columnas basándose en un carácter de separación, puede hacer el mismo trabajo en VBA gracias a la función
Split.
- 8- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
El archivo Billar.txt contiene las coordenadas GPS de las salas de billar de España. Como podrá comprobar en la
siguiente imagen, el archivo no está estructurado con columnas de ancho idéntico.
Observamos, sin embargo, que la coma hace las veces de separador de las columnas. Vamos a realizar la
extracción basándonos en este símbolo.
Además, queremos seleccionar únicamente las filas que contengan la información [Billar] y excluir aquellas que
contengan [Billar nv].
Recuperación de las filas deseadas
Vamos a construir un test que comprobará si la cadena de caracteres [Billar] (incluyendo los corchetes) existe en
la fila leída del archivo de texto. La adición de los corchetes es importante para marcar la diferencia con las filas
que contienen el término [Billar nv]. El test consistirá en comprobar que la cadena [Billar] existe mediante la
instrucción InStr:
Si el término [Billar] se encuentra en la variable Extract, la instrucción InStr devolverá una cifra equivalente a
su posición en la cadena leída. Por el contrario, si no se encuentra el término, InStr devolverá 0. Por lo tanto,
podemos hacer un test que verifique que InStr es mayor que 0, lo que significará que se ha encontrado la
cadena buscada.
A continuación vamos a gestionar la extracción de los datos de la tabla con la función Split.
Nuestro procedimiento, se escribirá:
El programa completo se escribe de la siguiente manera:
Sub Leer_Archivo_Coma()
Dim Extract As String
Dim Tabla_Extracción As Variant
Dim Ruta As String
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 9-
’Apertura del archivo
Open Ruta & "Billar.txt" For Input As #1
Line Input #1, Extract ’Lectura primera fila del archivo
End Sub
En una sola instrucción hemos almacenado toda la fila leída en la tabla con tantas dimensiones como caracteres de
separación existían.
Contenido de la tabla tras la instrucción Split
Segmentación en el carácter coma
Para escribir los datos de la tabla en una hoja de cálculo, podemos escribir un segundo procedimiento, usando
como parámetro la tabla que vamos a tratar.
Recordemos que el nombre de la variable empleada como parámetro puede ser distinto entre los dos
procedimientos, pero el tipo de variable debe ser obligatoriamente el mismo entre el procedimiento de llamada y el
procedimiento llamado.
i_tab = 0
Do
ActiveSheet.Cells(Última_Fil, i_tab + 1) =_
Trim(Tabla_Extracción(i_tab))
i_tab = i_tab + 1
Loop While i_tab <= Ubound(Tabla_Extracción)
End Sub
- 10 - © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Como podrá comprobar, el procedimiento es casi el mismo que el que se usa en el ejemplo anterior para la
extracción de columnas. Esto prueba que un código totalmente codificado con parámetros puede reutilizarse muy
fácilmente en otros programas.
El resultado se puede ver en la imagen siguiente:
Obtenemos el resultado esperado, pero, ahora deseamos segmentar los datos de la columna C por el carácter
”espacio”.
Segmentación por el carácter espacio
Para segmentar la información de la columna C, vamos a volver a usar la función Split. Podemos escribir:
Sub Tratamiento_Columna_C()
Dim Núm_Fil As Long
Dim i_tab As Long
Dim Tabla_Extracción As Variant
Núm_Fil = 1
While Cells(Núm_Fil, 3) <> ""
Tabla_Extracción = Split(Cells(Núm_Fil, 3), "")
i_tab = 0
Do
ActiveSheet.Cells(Núm_Fil, i_tab + 4) =
Trim(Tabla_Extracción(i_tab))
i_tab = i_tab + 1
Loop While i_tab <= Ubound(Tabla_Extracción)
Núm_Fil = Núm_Fil + 1
Wend
End Sub
Esta vez, no recorremos todo el archivo de texto sino solo la columna C desde la fila 1. Para cada celda leída,
utilizamos la función Split para almacenar en la memoria cada subcadena. El resultado se inscribe en la columna D
(en el programa, la columna D se traduce por el valor i_tab + 4).
El resultado no siempre es satisfactorio ya que para los números de provincias inferiores a 10, perdemos el 0 del
principio. A continuación, para el nombre de las ciudades compuesto por varias palabras tenemos la información
escrita en varias columnas como vemos en la imagen siguiente:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 11 -
Concatenación de las ciudades
Solo queremos conservar el número de la provincia y el nombre de las ciudades.
Para ello, tendremos que crear toda una serie de condiciones muy complejas para tratar todos los casos posibles:
En efecto, la información contenida en la columna C no está nada estructurada. Tras el nombre de la ciudad, puede
haber:
l ninguna otra información;
l el nombre de la sala de billar;
l información sobre los billares;
l el número de teléfono.
Por lo tanto es absolutamente necesario realizar tests para cada caso, lo que supone un código enormemente
pesado.
Como verá, es preferible trabajar con archivos bien estructurados para evitar tener que tratar un gran número de
casos de test y cargar inútilmente sus programas.
Por último, también hay que realizar un test para gestionar la extracción de las ciudades compuestas por una o
varias palabras.
El código completo es el que presentamos a continuación.
Sub Tratamiento_Columna_C()
Dim Núm_Fil As Long
Dim i_tab As Long
Dim Tabla_Extracción As Variant
Dim Nombre_Ciudad As String
Dim Max_Dim_Tabla As Long
Dim Test_Fin_Bucle As Boolean ’Variable que le servirá para dejar
de recorrer la tabla en la memoria.
Núm_Fil = 1
While Cells(Núm_Fil, 3) <> ""
Tabla_Extracción = Split(Cells(Núm_Fil, 3), "")
’Tratamiento de la provincia
If i_tab = 1 Then
- 12 - © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
ActiveSheet.Cells(Núm_Línea, 4) = " ’ " &
Trim(Tabla_Extracción(i_tab))
Else
Encontrará en la página Información el archivo Ejemplo 11D45c con el código completo.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 13 -
Introducción
La utilización de las fechas en un programa no es siempre cosa fácil ya que estas responden a un cierto número de
reglas que deben tenerse en cuenta cuando desea explotar:
l El número de días de un mes difiere (28, 29, 30 o 31).
l El número de días de un año puede ser de 365 o 366 (año bisiesto).
l Los días como el sábado o el domingo pueden no contabilizarse (cálculo de días laborables).
La mayor parte de las funciones de Fecha integradas en Excel se presentan en lenguaje VBA. Vamos a ver, con
ejemplos concretos, cómo adaptar las diferentes funciones para manipular las fechas y después veremos a través de
funciones personales cómo diseñar una función que permita devolver el día de Pascua (sea cual sea el año) o cómo
calcular el número de la semana.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Introducción a las fechas
Antes que nada, es importante recordar que para utilizar las funciones de Fecha (en Excel o en VBA), el contenido de
las celdas debe estar en formato Fecha; este formato se define, no con Excel, sino con los parámetros de
configuración del sistema operativo instalado en su ordenador (Windows).
1. Configurar las fechas
En Windows, encontrará estos parámetros en el menú Configuración Hora e idioma.
En la pestaña Fecha y hora, elija el país correspondiente al formato de fecha.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Es posible personalizar aún más la configuración de la Fecha seleccionando el menú Cambiar formatos
de fecha y hora para especificar la vista y el formato de las fechas.
2. ¿Mi celda contiene una fecha?
Para comprobar si el contenido de una celda es una fecha (o un dato numérico), este dato debe estar alineado a la
derecha de la celda; el texto está alineado por defecto a la izquierda de la celda.
En la mayoría de países, los dos separadores de fecha admitidos son los símbolos / y . Pero en ciertos países como
Alemania, por ejemplo, el símbolo empleado es el punto (.) : si usted recibe un archivo que se ha generado desde
un ordenador configurado con parámetros alemanes, lo más probable es que tenga una fecha con formato
31.12.2016. Al importar a un ordenador español, este dato no se reconocerá como fecha sino como texto.
En otros países, el orden de los elementos que constituyen la fecha no es el mismo que en España. Por ejemplo, en
Estados Unidos, el mes precede a los días: el 31 de diciembre de 2016 escrito en versión americana sería
12/31/2016. Incluso en este caso, un ordenador con configuración española no podrá interpretar esta fecha como
formato fecha.
Puede incluso darse el caso de que trabaje con fechas con formato AAAAMMDD (20161231). Este formato de fecha
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
se usa en las grandes bases de datos ya que, en una clasificación en orden decreciente, la fecha más reciente
estará siempre en primera posición. Pero cuidado, al estar escrito de esta manera, es muy probable que Excel
interprete esta información como si fuera un número (20161231 = veinte millones ciento sesenta y un mil doscientos
treinta y uno) y no una fecha.
Una manera sencilla de saber si el dato que va a manipular es una fecha o no, consiste en hacer un test mediante la
instrucción:
IsDate(Dato)
Esta instrucción devolverá Verdadero si el dato es una fecha y Falso en el caso contrario:
If IsDate(Cells(1, 1) Then
MsgBox "La celda A1 contiene una fecha"
Else
MsgBox "No hay fecha en A1"
End If
3. Dar formato a una fecha
Del mismo modo que con Excel, con VBA puede escribir una fecha de varias maneras definiendo el formato mediante
la instrucción FORMAT:
El argumento del formato corresponde a todos los tipos de formato de número que Excel recoge. La única diferencia
entre Excel y VBA es que los parámetros de las fechas deben escribirse en inglés. Por ejemplo, el parámetro para el
año no se expresará mediante una a, sino mediante una y (inicial de year en inglés).
Por ejemplo, para la fecha del 05/07/2017 podemos tener como parámetro de fecha, los siguientes argumentos:
Formato Resultado
d 5
dd 05
ddd miér
dddd miércoles
m 7
mm 07
mmm Jul
mmmm Julio
y 17
yy 17
yyy 2017
yyyy 2017
Y evidentemente, combinándolas todas juntas, podemos visualizar una fecha de diferentes formas:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Formato Resultado
d mmm yy 5 Jul 17
dddd dd/mm/yy Miércoles 05/07/17
Puede utilizar como separador de fecha, los espacios, los guiones o las barras oblicuas. En todos los casos, debe
escribir el argumento del formato entre comillas.
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Las funciones básicas
Hay cuatro funciones que devuelven la fecha y la hora del sistema de su ordenador. Es frecuente recurrir a estas
funciones para realizar tests entre una fecha cualquiera y la fecha de su ordenador, por ejemplo:
l Test entre la fecha actual y una fecha de entrega en caso de superación de un plazo,
l Test entre la fecha actual y una fecha de cumpleaños en caso de igualdad del mes y del día,
l Test entre la hora actual y una hora de partida para cálculos de superación horaria (trabajo, alquiler, etc.).
Ninguna de las funciones siguientes necesita parámetros.
DATE
Esta función devuelve la fecha del sistema de su ordenador según el formato definido en su ordenador (generalmente
DD/MM/AAAA). Se comporta como la función HOY en Excel.
TIME
Esta función devuelve la hora de su ordenador en formato estándar HH:MM:SS.
TIMER
Esta función devuelve el número de segundos transcurridos desde la medianoche con una precisión del orden de la
fracción. Es la única instrucción en VBA que devuelve las fracciones de segundo.
NOW
Esta función devuelve la fecha y la hora actual de su ordenador exactamente como la función AHORA de Excel.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Las funciones de extracción
Existen funciones que permiten extraer cada elemento de una fecha y de una hora. Estas funciones son muy
sencillas, pero es importante conocerlas para poder hacer manipulaciones en las fechas y así diseñar fechas
dinámicas.
1. Extracción de las fechas
Las fechas se componen de un día, un mes y un año. Cada parte puede extraerse mediante tres instrucciones:
Day (Date)
Esta función extrae el día de una fecha.
Month (Date)
Esta función extrae el mes de una fecha.
Year (Date)
Esta función extrae el año de una fecha.
2. Extracción de las horas
Del mismo modo, las horas se componen de horas, minutos y segundos. Cada parte puede extraerse mediante tres
funciones:
Hour (Time)
Esta función extrae la hora de una variable de tiempo.
Minute (Time)
Esta función extrae los minutos de una variable de tiempo.
Second (Time)
Esta función extrae los segundos de una variable de tiempo.
En VBA no es posible extraer una fracción de hora inferior al segundo. Es bastante penalizador cuando se trata de
determinar la velocidad de ejecución de un programa, ya que, en este caso particular, es necesario conocer las
décimas, las centésimas y las milésimas. En el capítulo Optimización veremos cómo resolver este problema.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
La instrucción DateSerial
DateSerial(Año,Mes,Día)
Esta instrucción es muy útil para hacer manipulaciones, cálculos en las fechas y para convertir números en fechas.
1. Convertir un número en fecha
Supongamos, por ejemplo, que la celda A1 contiene el valor 20121231 y que desea convertir este valor en fecha.
En primer lugar, va a recortar el contenido de la celda A1 mediante las funciones Left, Right y Mid, y después va
a utilizar la instrucción DateSerial para efectuar la conversión:
De esta forma, el dato de la celda B1 será una fecha y no un número. Observe que las barras oblicuas (/) se añaden
automáticamente en la conversión.
2. Realizar operaciones con las fechas
La instrucción DateSerial permite hacer toda clase de cálculos en los elementos de una fecha. Por ejemplo, a
partir de la fecha 31/12/2012 contenida en la celda A1, deseamos realizar cálculos para obtener otras fechas:
l Añadir 32 días:
Da como resultado 01/02/2013. En ese caso, la fecha se ha aumentado en 2 meses.
l Añadir 2 meses:
Da como resultado 03/03/2013. Normalmente, tendríamos que haber tenido como resultado 28/02/2013, pero como
el parámetro de los días es de 31, la función añade 3 días.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
3. Manipulación de las fechas
Ahora, ¿cómo hacemos para obtener como resultado la fecha del 01/10/2012 a partir del 31/12/2012? Lógicamente,
deberíamos restar 3 meses y añadir 1 día. Ahora bien, el resultado devuelto es 02/10/2012.
¿Cómo se explica este resultado? Con los parámetros que hemos escrito, la fecha calculada es el 32/09/2012; como
esta fecha no puede existir y el mes de septiembre solo tiene 30 días, la función añade 2 días al mes siguiente para
dar como resultado el 02/10/2012. Entonces, ¿cómo lo hacemos?
Para devolver fechas específicas (como el primero o el último día de un mes) debemos utilizar otro método. Basta
con reemplazar el parámetro de los días por el valor 1 para devolver el primer día de cualquier fecha.
DateSerial(Year(Date); Month(Date); 1)
De esta manera, sea cual sea la fecha del sistema, esta instrucción devolverá siempre el primer día del mes.
Del mismo modo, es fácil encontrar el primer día del mes siguiente:
DateSerial(Year(Date); Month(Date) + 1; 1)
Ahora, para encontrar el último día de un mes, es necesario recordar la regla básica de las fechas en VBA: el valor 1
equivale a un día.
Así, sea cual sea la Fecha, esta instrucción devolverá siempre el último día del mes:
DateSerial(Year(Date); Month(Date) + 1; 1) - 1
4. Meses en letras
La instrucción MonthName permite convertir un número en un mes escrito con letras. Por ejemplo, si tiene el valor
9, la siguiente escritura le dará la indicación Sept o Septiembre.
De igual modo, la función WeekDayName devuelve el día en letras a partir de números del 1 al 7.
Tomemos el siguiente ejemplo, abra el archivo Ejemplo 12E4:
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Tiene un documento que representa las notas de los gastos para el mes de enero. Para evitar volver a copiar once
veces la hoja Enero y después cambiar manualmente el nombre de las hojas, puede construir una macro:
Utilice la Grabadora de macros para crear una copia de la hoja Enero y cambiar el nombre. El código
obtenido es:
Sheets("Enero").Select
Sheets("Enero").Copy After:=Sheets(1)
Sheets("Enero (2)").Select
Sheets("Enero (2)").Name = "test"
Podemos reducir la escritura de las dos últimas líneas en una sola, ya que cuando se agrega una nueva hoja, esta
pasa a ser automáticamente la hoja activa. Podemos escribir:
Sheets("Enero").Copy After:=Sheets(1)
ActiveSheet.Name = "test"
Ahora vamos a crear un bucle que irá del mes de febrero al mes de diciembre. Por lo tanto, el bucle empezará por 2
y acabará por 12.
Sub Añadir_Hoja()
Dim Mi_Mes As Long
For Mi_Mes = 2 To 12
Sheets("Enero").Copy After:=Sheets(1)
ActiveSheet.Name = MonthName(Mi_Mes, False)
Next
End Sub
Nos falta resolver un problema en este programa, ya que la adición de hojas no respeta el orden de los meses. Para
que la nueva hoja se agregue en última posición, y así conservar el orden natural de los meses, vamos a sustituir la
cifra 1 del parámetro After:=Sheets(1) por la variable Mi_Mes. De esta forma, cada nueva hoja se agregará en
última posición.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Y, para que la primera letra de cada mes esté en mayúscula, vamos a poner la función StrConv:
Sub Adición_Hoja()
Dim Mi_Mes As Long
For Mi_Mes = 2 To 12
Sheets("Enero").Copy After:=Sheets(Mi_Mes - 1)
ActiveSheet.Name = StrConv(MonthName(Mi_Mes, False), _
vbProperCase)
Next
End Sub
Puede descargar el código completo de este ejemplo, el archivo correspondiente se llama Ejemplo 12E4b.
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Calcular la diferencia entre dos fechas
Una de las principales dificultades de los cálculos en las fechas es la resta de dos fechas ya que hay que tener en
cuenta la fecha no a partir del primer día del mes, sino a partir del día indicado. Por ejemplo, entre el 31/12/2012 y el
01/01/2013 solo hay un día de diferencia y, sin embargo, ha cambiado el valor del mes así como el del año.
Afortunadamente, existe una función que soluciona este problema. En Excel, se trata de la función SIFECHA y en VBA,
de la función Datediff (en español en Excel y en inglés en VBA), y un funcionamiento diferente para las dos
instrucciones.
1. La función SIFECHA en Excel
SIFECHA(Fecha1;Fecha2;parámetro)
La función SIFECHA requiere dos fechas (Fecha1 anterior a Fecha2) y un parámetro que concretará el tipo de
diferencia que queremos devolver entre las dos fechas.
Los diferentes valores posibles son:
Parámetro Resultado
"y" diferencia en años
"m" diferencia en meses
"d" diferencia en días
"ym" diferencia en meses, una vez restados los años
"yd" diferencia en días, una vez restados los años
"md" diferencia en días, una vez restados los años y los meses
Ejemplo: si Fecha1 = 15/08/2009 y Fecha2 = 07/04/2011, obtenemos los siguientes resultados:
Parámetro Resultado
"y" 1
"m" 19
"d" 600
"ym" 7
"yd" 235
"md" 23
2. La función DATEDIFF en VBA
En la función de VBA, el parámetro se coloca antes de la fecha y en este caso, la Fecha1 no tiene porqué ser
anterior a la Fecha2. El número de parámetros es mucho más importante como muestra la tabla siguiente, pero los
resultados entre las dos funciones son totalmente diferentes:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Parámetro Resultado
yyyy Año
q Trimestre
m Mes
y Día del año
d Día
w Día de la semana
h Hora
n Minuto
s Segundo
Esta función no sabe gestionar rupturas de meses y de fechas. Por ejemplo, la diferencia en número de años entre
el 31/12/2012 y el 01/01/2013 es igual a 1 (lo cual es obviamente falso).
Por lo tanto, lo ideal es integrar la función de Excel en VBA.
3. Integración de la función SIFECHA de Excel en VBA
Como la función SIFECHA de Excel es una función oculta, no es posible llamarla con la instrucción
Application.WorksheetFunction. La solución reside en la utilización de la instrucción Evaluate.
Evaluate(Texto)
La instrucción Evaluate permite integrar una función de Excel en VBA, esta función debe escribirse entre comillas.
Por consiguiente, podemos integrar la función SIFECHA de este modo:
Cells(1, 3) = Evaluate("=sifecha(A1,B1,""ym"")")
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Funciones de semanas
A diferencia de Excel, existen muy pocas funciones relacionadas con las semanas en VBA. De hecho, solo hay una.
1. ¿Qué día de la semana?
WEEKDAY(Fecha, parámetros)
La función WEEKDAY devuelve un valor entre 1 y 7 correspondiente al día de la semana. El parámetro permite
concretar cuál es el primer día de la semana. Por defecto, el primer día de la semana es el domingo, pero puede
forzar el día con uno de los otros seis días de la semana.
Para que el lunes se considere el primer día de la semana, agregue el parámetro vbMonday.
2. Número de días laborables en la semana
No existe ninguna función interna para devolver el número de días laborables entre dos fechas. Sin embargo, puede
crear usted mismo esta función utilizando la función WEEKDAY.
Basta con contar el número de días entre dos fechas excluyendo del contador los sábados y los domingos. Como
una fecha es un número, es posible integrar directamente las fechas en la instrucción FOR ... NEXT.
La función se escribirá, por tanto:
3. Número de semana
Del mismo modo, no existe una función que devuelva el número de semana de una fecha. Podría verse tentado a
crear una función que divida el número de días entre 7, pero las cosas no son tan sencillas...
Existe una diferencia en la contabilización de los números de las semanas entre Europa y Norteamérica. En
Norteamérica (Estados Unidos y Canadá), la semana 1 empieza en el primer día del año, aunque sea domingo. En
Europa, la numeración de las semanas se rige por la norma ISO 8601. La regla de numeración es más compleja,
pero en la mayoría de los casos, la semana n°1 contiene al menos 4 días. Si el mes de enero empieza un viernes, un
sábado o un domingo, esta semana no se considerará la semana 1.
La siguiente función devuelve el número de semana respetando esta regla:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
D = Int(D)
NºSEM = DateSerial(Year(D + (8 - WeekDay(D)) Mod 7 - 3), 1, 1)
NºSEM = ((D - NºSEM - 3 + (WeekDay(NºSEM) + 1) Mod 7)) \ 7 + 1
End Function
Encontrará el código de esta función en el archivo Ejemplo 12G3.
4. Días festivos
Los días festivos son siempre días particulares en los cálculos de fechas. Estos son o bien fijos (como el 1 de enero,
el 25 de diciembre, etc.) o bien variables (como el domingo de Pascua); del domingo de Pascua depende el día de la
Ascensión (Pascua + 39) y el Pentecostés (Pascua + 49). Por lo tanto, es necesario determinar el "domingo de
Pascua" que corresponde al primer domingo siguiente (o cae el mismo día que) el día de la primera luna llena tras el
equinoccio de primavera (el 21 de marzo).
A partir de ahí, mediante el siguiente test puede determinar si la fecha que pasa como parámetro de la función es
un día festivo o no.
También puede incluir esta función en la función del número de días laborables, para descontar también de su bucle
los días festivos.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Next
End Function
El código correspondiente se encuentra en el archivo Ejemplo 12G4.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Introducción
El soporte de su programa es un libro de Excel. Puede recuperar la información o copiar datos contenidos en este. Un
libro también está compuesto por hojas de cálculo que puede manipular, borrar, renombrar, etc.
En los capítulos anteriores hemos explotado los elementos más importantes de un libro: las celdas (Cells), los
rangos de celdas ( Range), las hojas (Sheets) y los libros (Workbooks).
En este capítulo vamos a ver cómo manipular los libros, abrirlos, cerrarlos, guardarlos y también cómo modificar las
propiedades de un libro (Nombre, Título, Comentario, etc.).
También veremos cómo utilizar VBA para trabajar directamente en Excel para evitar los mensajes de alerta, bloquear
la actualización de una hoja, etc. Las posibilidades son múltiples.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Manipulación de los libros
Desde un programa VBA, puede realizar todas las manipulaciones comunes en los archivos como abrir, cerrar,
guardar. Todos estos comandos son propiedades del objeto Workbooks.
1. Diferencia entre Workbooks y ActiveWorkbook
ActiveWorkbook .Propiedades
ActiveWorkbook representa el libro activo. Cuando un programa abre varios libros, el libro activo es el último que
se ha abierto. Si desea trabajar en un libro específico, es aconsejable utilizar el objeto Workbooks (nombre
del archivo) para evitar que su programa se ejecute en el libro equivocado.
Con la instrucción Workbooks, el nombre del archivo debe tener obligatoriamente una extensión (xlsx, xlsm, etc.).
Atención: si utiliza el objeto Workbooks (nombre del archivo), su archivo deberá estar ya abierto o corre el
riesgo de generar una anomalía.
2. Abrir un libro
Para abrir un libro, basta con que añada el método Open al objeto Workbooks y que especifique la ruta de acceso
y el nombre del archivo (con su extensión). Puede escribir la información "literalmente" o con variables.
Workbooks.Open "C:\Documentos\Mi_archivo.xlsx"
’o
Workbooks.Open Ruta & Archivo
Si trabaja con variables, preste atención a no olvidar el carácter "\" entre la ruta de acceso y el nombre del archivo.
Utilice la depuración para verificar si la escritura Ruta + Archivo es en efecto una ruta de acceso existente.
Tras la instrucción Open, el libro que se acaba de abrir se convierte en el libro activo.
3. Cerrar un libro
Workbooks("Libro1.xlsx").Close
’o
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Workbooks(Nombre_Libro).Close ’ Aquí Nombre_Libro = "Libro1.xlsx"
’o
Workbooks(Nombre_Libro & ".xlsx").Close ’ Aquí Nombre_Libro="Libro1"
Al igual que al abrirlo, al cerrar un libro específico es obligatorio precisar la instrucción (xlsx, xlsm, etc.)
Si el archivo se ha modificado durante la ejecución del programa, automáticamente aparecerá un cuadro de diálogo
que le invita a guardar su documento, a menos que haya especificado mediante el parámetro SaveChanges si las
modificaciones deben guardarse (True) o no (False).
Workbooks("Libro1.xlsx").Close SaveChanges:=True
4. Guardar un libro
El método Save guarda su documento sin que usted tenga que confirmarlo.
Workbooks("Libro1.xlsx").Save
’o
ActiveWorkbook.Save ’Guardar el libro activo
5. Guardar un libro con un nombre nuevo
El método SaveAs guarda su documento con un nuevo nombre.
Workbooks("Libro1.xls").SaveAs Filename:="España.xlsx"
’o
ActiveWorkbook.SaveAs "España.xlsx"
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Las propiedades de un libro
Muy a menudo, las propiedades de un libro contienen información recogida al guardarlo anteriormente (Autor, Fecha
de modificación, Nombre de la empresa, etc.).
Puede cambiar esas propiedades seleccionando el menú Archivo Propiedades (Excel 2003) o el Botón Office
Preparar Propiedades (en la versión 2007), o en la pestaña Archivo Información Mostrar todas las
propiedades (desde la versión Excel 2010).
La siguiente ventana presenta las propiedades de su libro:
En un programa, el objeto Workbooks (o el objeto ActiveWorkbook) posee la propiedad
BuiltinDocumentProperties que retoma todas las propiedades de un libro.
Por ejemplo, puede manipular las siguientes propiedades en su libro, concretando cada vez el nombre de las
propiedades:
With ActiveWorkbook
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
.BuiltinDocumentProperties("Title") = Mi_nombre
.BuiltinDocumentProperties("Subject") = "Test_propiedades"
.BuiltinDocumentProperties("Author") = Mi_nombre
.BuiltinDocumentProperties("Keywords") = Variable_4
.BuiltinDocumentProperties("Comments") = Variable_5
.BuiltinDocumentProperties("Template") = Variable_6
.BuiltinDocumentProperties("Last author") = Variable_7
.BuiltinDocumentProperties("Company") = Variable_8
End With
Pero no es necesario concretar el nombre de las propiedades. Puede construir un bucle mediante la instrucción For
Each para recorrer todas las propiedades de un libro utilizando la colección de objetos
BuiltinDocumentProperties.
El siguiente código le permite recuperar todas las propiedades de su libro y mostrar cada una de ellas en una celda:
Sub Recuperación_de_las_propiedades()
Dim i_var As Long
Dim Prop As Object
On Error Resume Next
i_var = 1
For Each Prop In ActiveWorkbook.BuiltinDocumentProperties
Cells(i_var, 1) = Prop.Name
Cells(i_var, 2) = Prop.Value
i_var = i_var + 1
Next
End Sub
Estamos obligados a añadir la instrucción On Error Resume Next (ver el capítulo Gestión de errores) para no
detener el programa en el caso de que una propiedad no tuviera valor.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Interactuar con la aplicación Excel
DoEvents
Cuando un programa se está ejecutando, ya no se puede actuar en su aplicación hasta que el programa acabe. Sin
embargo, puede pedir a Excel que "transfiera la ejecución" al sistema de explotación gracias a la instrucción
DoEvents.
Cada vez que el programa pase por esta instrucción, le indica a su ordenador que es prioritario con respecto a la
ejecución del programa. Así, puede, por ejemplo, volver a Excel y manipular el libro durante la ejecución de la macro
(copiando una celda, por ejemplo).
Calculate
La instrucción Calculate es importante ya que permite forzar el recálculo de una hoja de cálculo. Es muy útil si
necesita mostrar un cronómetro, por ejemplo, y gestionar la actualización (véase el ejemplo que se propone en el
capítulo Iniciar un programa de varias maneras Inicio mediante un botón u otro objeto) o incluso para comprobar
que se han actualizado todas las fórmulas del libro.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
El objeto Application
Excel es en sí mismo un objeto, como una celda o una hoja de cálculo, con sus propiedades y sus métodos. El objeto
Application tiene vinculadas no menos de 305 propiedades, métodos y eventos. Solo estudiaremos las principales,
pero si desea conocer todas las propiedades de este objeto, puede consultar la siguiente dirección:
https://msdn.microsoft.com/eses/library/office/ff198091.aspx
Si trabaja con Excel 2003 o inferior, algunas de esas funcionalidades no estarán disponibles.
1. ScreenUpdating
Esta propiedad permite bloquear la actualización de Excel durante la ejecución de un programa. Al utilizar esta
propiedad, ganará mucho tiempo en el tratamiento de su programa ya que bloquea la actualización de Excel. No
olvide reubicar el valor de esta propiedad a True antes de abandonar el programa.
2. DisplayAlerts
Esta propiedad impide que se muestren los mensajes de alerta (valor False), como por ejemplo la ventana de alerta
que le invita a guardar un libro o la que aparece cuando elimina una hoja.
Mensaje de alerta cada vez que suprime una hoja de cálculo.
Al final del programa, es imprescindible que vuelva a poner el valor en True para que Excel continúe mostrando los
mensajes de alerta de forma normal.
3. StatusBar/DisplayStatusBar
Estas dos propiedades van de la mano:
l DisplayStatusBar muestra u oculta la barra de estado de Excel.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
l StatusBar gestiona los mensajes en la barra de estado.
La propiedad StatusBar le permite visualizar los mensajes en la barra de estado. Así, puede, por ejemplo, seguir el
desarrollo de su programa escribiendo el último número de fila tratada. La propiedad StatusBar es preferible a
MsgBox ya que la visualización de un mensaje con la instrucción MsgBox bloquea la ejecución de programa.
Para borrar sus mensajes personales en la barra de estado, debe colocar el valor False en la propiedad StatusBar:
4. Llamada a funciones de cálculo de Excel
a. Cómo usar las funciones de cálculo de Excel
Excel cuenta con más de 400 funciones de cálculo; 471 en la versión Office 365 de Excel para ser precisos. Algunas
de ellas han sido objeto de desarrollos optimizados por parte de universidades especializadas en estadística como
para los cálculos de desviaciones estándar y de varianza, entre otros.
De igual modo, es muy recomendable usar las funciones de cálculo de Excel en sus programas y recuperar
fácilmente el resultado en una variable antes que tener reescribir usted mismo las funciones de cálculo.
La llamada a funciones de cálculo se obtiene con la propiedad WorksheetFunction seguida del nombre de la
función en inglés. Si lo escribe en español, el VBA no será capaz de interpretarlo. A continuación, deberá pasar los
parámetros que su función espera, exactamente de la misma manera que si usara la función en una hoja de
cálculo.
Por ejemplo, si desea calcular la suma de los valores de su rango de celdas A1:A5 escribirá lo siguiente:
Sub Fonction_Cálculo()
Dim Result_Suma As Double
Result_ Suma = Application.WorksheetFunction.Sum(Range("A1:A5"))
End Sub
Pero algunas funciones pueden llamarse directamente. Es el caso de la función Match (equivalente de la función
de cálculo EQUIV) y de la función Index.
b. La función Match
La función Match permite recuperar el valor de la fila donde se sitúa el valor buscado. Por ejemplo, en el ejemplo
siguiente, se desea conocer el número de fila donde se encuentra el valor FFF.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Sub Fonction_Cálculo()
Dim Núm_Fila As Long
Núm_Fila = Application.Match("FFF", Range("A1:A10"), 0)
MsgBox "El número de la fila es: " & Núm_Fila
End Sub
c. La función Index
Por último, la función Index puede también escribirse directamente después de la instrucción Application. La
función Index permite encontrar el valor de una celda que se encuentra en la intersección entre una fila y una
columna.
Pero otro uso de la función Index permite permutar los datos de las columnas de una tabla en una sola
instrucción.
Por ejemplo, en su hoja de cálculo tiene los siguientes datos.
Y desea permutar las columnas entre ellas. En lugar de hacer una sucesión de operaciones de copiar/pegar, la
siguiente función permite llevar a cabo las manipulaciones de reordenación de acuerdo con las posiciones inscritas
en la tabla al final (Array).
Atención, para usar este procedimiento, deberá seleccionar los datos previamente a partir de la instrucción
UsedRange.
Sub Rearrange()
With ActiveSheet.UsedRange
.Value = Application.Index(.Value, .Worksheet.Evaluate("ROW(" & _
.Columns(1).Address & ")"), Array(7, 2, 4, 1, 6, 5, 3))
End With
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Y el resultado de la permutación pasa a ser:
Encontrará este código en el libro Ejemplo 13E.xlsm, desde la página Información.
5. Añadir un tiempo de latencia
Es posible solicitar a un programa que «espere» unos instantes antes de ejecutar la siguiente acción. Esto podría
ocurrir para acceder a datos en la Web o en un servidor remoto para los cuales el tiempo de espera es variable. Por
tanto, para evitar que una instrucción se ejecute antes de haber recibido datos, es posible imponer al programa que
espere durante un plazo de tiempo que se fijará usando la propiedad Wait.
Pero tenga cuidado, la propiedad Wait esperará recibir un valor en el futuro. Si desea que el programa se detenga
durante diez segundos, tendrá que decirle que volverá a arrancar diez segundos después del tiempo actual. Esto se
escribe de la manera siguiente:
Sub Test_Wait()
Nueva_Hora = Hour(Now())
Nuevo_Minuto = Minuto(Now())
Nuevo_Segundo = Second(Now()) + 10
Tiempo_Espera = TimeSerial(Nueva_Hora, Nuevo_Minuto , _
Nuevo_ Segundo)
Application.Wait Tiempo_Espera
End Sub
También puede escribir la hora exacta en que el programa se pondrá de nuevo en marcha de la siguiente manera:
Application.Wait ("20:20:00")
6. El cuadro de diálogo Abrir
La propiedad GetOpenFilename permite mostrar el cuadro de diálogo Abrir. La utilizará para permitir a los usuarios
escoger el archivo que desean abrir.
Pero esta propiedad no abre el archivo, solo recupera la ruta de acceso y el nombre del archivo seleccionado. A
continuación, tiene que utilizar el método Open para abrir el archivo.
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Puede añadir a esta propiedad el tipo de archivo. De este modo, solo los archivos que tengan esta extensión
aparecerán en el cuadro de diálogo.
7. El cuadro de diálogo Guardar como
Del mismo modo, con la propiedad GetSaveAsFilename puede mostrar el cuadro de diálogo Guardar como para
recuperar el nombre del archivo que el usuario ha elegido. Empleará esta propiedad para localizar el nombre con el
que se guardará el libro y después, guardará el libro con el método SaveAs.
Para imponer un formato al archivo, puede indicar como parámetro el tipo de extensión con la que se guardará el
archivo:
Nombre_Archivo = Application.GetSaveAsFilename( _
fileFilter:="Archivo Excel (*.xls), *.xls")
ActiveWorkbook.SaveAs Nombre_Archivo
8. Suspender la comunicación con la impresora
Si define una zona de impresión específica al ejecutar el programa, el tratamiento se verá enormemente ralentizado.
Para evitarlo, hay que cortar la conexión con la impresora durante el tiempo en que se define la configuración de la
página (PageSetup).
9. Modo copiarpegar suspendido
Cuando lleva a cabo una operación de copiarpagar en Excel, una vez efectuado el pegado, la celda de origen
aparece siempre rodeada de una línea de puntos que indica que la acción de pegado se encuentra todavía activa.
En programación ocurre lo mismo.
Al final de la operación de pegado, para indicar que la celda de origen debe perder su carácter de elemento
potencialmente reutilizable para ser pegada de nuevo, escriba la siguiente instrucción:
Application.CutCopyMode = False
La línea de puntos en torno a ella desaparecerá inmediatamente después de la instrucción.
10. Llamada a una macro externa
Durante la ejecución de un programa es posible hacer una llamada al código contenido en otro libro de Excel. Si
tiene un libro con un código muy específico como para diseñar un gráfico, por ejemplo, antes de importar el código al
libro activo, es posible llamarlo usando esta instrucción:
Application.Run "C:\MisDocumentos\MiLibro.xlsm!Modulo1.Sub_Llamada"
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Al igual que para abrir libros, es preciso indicar la ruta y el nombre del libro con su extensión, pero también hay que
añadir un signo de exclamación seguido del nombre del Módulo en el que se encuentra el procedimiento que va a
ejecutar.
11. Hacer que el ordenador hable
Es posible hacer que el ordenador hable con la siguiente instrucción:
- 6- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Introducción
En el capítulo Trabajar en un libro Excel, hemos visto cómo abrir, cerrar y guardar libros. Ahora vamos a ver otras
funciones para trabajar con archivos, pero desde una carpeta (renombrar, copiar, suprimir archivos, etc.). Veremos
cómo recorrer todos los archivos de un directorio y cómo filtrarlos según su extensión.
También veremos cómo recuperar el contenido de una celda sin abrir el libro correspondiente y cómo visualizar un
Explorador de carpetas.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Operación con archivos
Las siguientes funciones permitirán hacer operaciones con todo tipo de archivos. Por consiguiente, podrá utilizar un
programa VBA como Explorador de carpetas Windows para hacer todo tipo de operaciones en los archivos de su
ordenador.
1. Copiar un archivo
Puede copiar un archivo de un directorio a otro, sea cual sea su extensión (texto, imagen, sonido, vídeo, etc.)
utilizando la instrucción FileCopy.
Archivo1 = "C:\Dir_1\Documento.txt"
Archivo2 = "C:\Dir_2\Documento.txt"
FileCopy Archivo1, Archivo2
El archivo que se va a copiar no debe estar abierto.
2. Cambiar el nombre de un archivo
Con esta función, podrá cambiar el nombre de un archivo en una carpeta.
Esta instrucción no realiza ningún control en el nuevo nombre. Es importante que conserve el mismo tipo de
extensión entre el antiguo nombre y el nuevo. Además, si olvida precisar la extensión, el archivo será ilegible.
3. Mover un archivo
También puede usar la función Name para mover un archivo de un directorio a otro. Para hacerlo, bastará con
indicar, además del código anterior, el nombre de la ruta de inicio y el nombre de la ruta final sin cambiar esta vez el
nombre del archivo.
Por ejemplo, para mover el archivo test.xlsx desde el escritorio hasta una subcarpeta, escribirá:
SubDesplazamiento_Archivo()
Dim Ruta_Inicio As String
Dim Ruta_Final As String
Ruta_Inicio = "C:\Users\Escritorio\"
Ruta_Final = "C:\Users\ Escritorio\Nueva Carpeta\"
Name Ruta_Inicio & "test.xlsx" As Ruta_Final & "test.xlsx"
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Si cambia también el nombre del archivo, no solo desplazará el archivo, sino que también le cambiará el nombre en
la misma línea de código.
4. Eliminar un archivo
Último punto esencial, la supresión. Aquí, no hay objeto que deba especificarse ni método que se deba aplicar, sino
solo una instrucción a la que llamar, Kill.
Kill "C:\Documentos\Libro4.xlsx"
’o
Kill Ruta & Archivo
Esta instrucción elimina definitivamente un archivo de su disco.
Atención: no hay mensaje de confirmación.
5. Recuperar la hora y la fecha de un archivo
FileDateTime(Ruta&Archivo)
La instrucción FileDateTime devuelve la fecha y la hora de la creación o de la última modificación de un archivo
(devolverá la fecha más reciente).
Para recuperar la fecha o la hora, puede utilizar las funciones de texto para realizar un recorte:
El recorte de la fecha se interpretará como una cadena de caracteres y no como un dato de tipo fecha. El resultado
en la celda A1 se alineará a la izquierda de la celda, señal de que se trata de texto y no de un dato numérico. Para
convertir este resultado en fecha, hay que emplear la instrucción CDate.
6. Averiguar el tamaño de un archivo
FileLen(Ruta&Archivo)
La instrucción FileLen recupera el tamaño de un archivo en bytes.
Para convertir el resultado en kilobytes, debe dividir el resultado entre 1024. La siguiente tabla presenta el valor del
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
divisor para obtener la conversión en las distintas unidades de medida:
Kilobyte (KB) 1024 bytes
Megabyte (MB) 1024 KB 1024 2 = 1 048 576 bytes
Gigabyte (GB) 1024 MB 1024 3 = 1 073 741 824 bytes
Terabyte (TB) 1024 GB 1024 4 = 1 099 511 627 776 bytes
Pentabyte (PB) 1024 TB 1024 5 = 1 125 899 906 842 624 bytes
7. Encontrar un archivo en un directorio
Dir(Ruta)
La instrucción Dir devuelve un nombre que representa el nombre del archivo. Sin otro parámetro que la ruta, Dir
devuelve el primer archivo encontrado sea cual sea su extensión. Para restringir su búsqueda, puede especificar,
además de la ruta, el tipo de archivo que busca:
Del mismo modo, puede precisar una parte del nombre para filtrar más su búsqueda.
Atención, la instrucción Dir recupera los nombres de los archivos sin ningún orden predefinido.
Podrá entonces verificar si el archivo existe en el directorio haciendo este simple test:
Puede escribir el mismo test, pero dentro de una función. De esta forma podrá llamar al test desde cualquier parte
del código.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Existe_ Archivo = True
End If
End Function
La función se declara como Boolean, ya que solo puede devolver dos valores Verdadero o Falso (el archive existe o
no).
Para llamar a esta función, basta con escribir el nombre de la función en el procedimiento de llamada (la función
espera dos parámetros, por tanto se deberá llamar a la función transmitiendo los dos parámetros esperados).
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Operaciones con los directorios
También puede realizar tareas a nivel de directorios, renombrarlos o duplicarlos, por ejemplo. También puede recorrer
uno a uno todos los archivos de un directorio.
1. Definir un directorio de trabajo
ChDir Ruta
Como hemos comprobado a menudo, para la apertura o escritura de archivos, es importante precisar la ruta de
acceso. Pero si siempre trabaja en el mismo directorio, puede especificar a su programa la ruta que debe seguir
durante toda la ejecución del programa.
Así, no estará obligado a recordar la ruta de acceso al directorio en las instrucciones de apertura, guardado, etc.
ChDir "C:\Nuevo_Directorio\"
Workbooks.Open "Mi_archivo.xlsx"
ActiveWorkbook.SaveAs "Nuevo_Archivo.xlsx"
2. Crear un directorio
MkDir Nuevo_Directorio
Esta instrucción crea un nuevo directorio en el directorio actual. Pero también puede especificar toda o parte de la
ruta de acceso:
MkDir "Archivo"
’o
MkDir "C:\Documentos\Archivo"
3. Eliminar un directorio
RmDir Nombre_Directorio
Esta instrucción elimina un directorio. Es absolutamente necesario que el directorio esté vacío de todo archivo para
poder suprimirlo.
RmDir "Archivo"
’o
RmDir "C:\Documentos\Archivo"
4. Test para saber si un directorio existe
Antes de crear un directorio es indispensable comprobar si el nombre de ese nuevo directorio existe previamente.
Por otro lado, no se puede eliminar un directorio inexistente. Por esto es por lo que se recomienda utilizar la función
siguiente para comprobar si un directorio está o no presente en una carpeta.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Function ArchivoDirExiste(Ruta_A_Probar As String) As Boolean
On Error GoTo SalidaPgm
ArchivoDirExiste = False
If Not Dir(Ruta_A_Probar, vbDirectory) = vbNullString Then
ArchivoDirExiste = True
End If
SalidaPgm:
On Error GoTo 0
End Function
Para llamar a esta función y verificar la existencia de un directorio, bastará con comprobar si la función devuelve
Verdadero o Falso. Por ejemplo, es posible escribir:
Sub TestDirExiste()
If ArchivoDirExiste ("C:\Mis Documentos") Then
MsgBox "El directorio existe"
Else
MsgBox "El directorio no existe"
End If
End Sub
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
"Barrer" un directorio
1. Bucles con los archivos
La instrucción Dir también permite hacer un bucle para hacer una lista de todos los archivos de un directorio. Para
ello, la instrucción Dir se emplea de dos formas:
l la primera, para definir el tipo de archivo buscado,
l la segunda, sin ningún parámetro, para hacer un bucle.
Por ejemplo, en una carpeta determinada, deseamos añadir al principio de todos los nombres de archivos Excel la
palabra "Informe ".
Sub Bucle_Archivo
Dim Nombre_Archivo As String
Nombre_Archivo = Dir("C:\Mis Documentos\*.xlsx")
While Nombre_Archivo <> ""
Name Nombre_Archivo As "Informe - " & Nombre_Archivo
Nombre_Archivo = Dir
Wend
End Sub
2. Bucles con los directorios
Si solo desea recuperar los nombres de subdirectorios del nivel inferior, puede añadir un parámetro a la instrucción
Dir:
Dir(Ruta, parámetro)
Los posibles valores del parámetro son:
vbNormal (Predeterminado) Especifica los archivos sin atributos.
vbReadOnly Especifica los archivos accesibles solo en modo lectura, así como los archivos sin atributos.
vbHidden Especifica los archivos ocultos, así como los archivos sin atributos.
vbSystem Especifica los archivos del sistema, así como los archivos sin atributos.
vbVolume Especifica el nombre de volumen; si se especifica otro atributo, la constante vbVolume se
ignora.
vbDirectory Especifica las carpetas, así como los archivos sin atributos.
Para recuperar los nombres de los directorios, hay que utilizar el parámetro vbDirectory. Pero atención,
recuperará los nombres de los directorios, pero también los nombres de los archivos.
También recuperará los indicadores del directorio actual (simbolizado por un punto) y del directorio superior
(simbolizado por dos puntos). Es interesante hacer un test para evitar tratar estos dos casos en su programa:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
If Nombre_Archivo <> "." And Nombre_Archivo <> ".." Then
Instrucciones
End If
También puede crear un procedimiento que almacene en una tabla todos los subdirectorios de una carpeta
cualquiera. El siguiente código puede aplicarse a cualquier carpeta ya que la ruta del directorio analizado (Mypath)
se transmite como parámetro del procedimiento.
End If
End If
MyName = Dir
Loop
End Sub
3. Barrer todos los subdirectorios
Hemos visto que la función Dir recorre todos los archivos del directorio y también los directorios de un solo nivel
inferior, pero nada más. Para poder leer todos los subdirectorios sin restricciones, es preciso hacer un bucle
recursivo.
Un bucle recursivo es un bucle o procedimiento que se llama a sí mismo. El riesgo de los bucles de ese tipo es que el
procedimiento se llama hasta el infinito sin detenerse por lo que será indispensable prever una condición de salida
para el bucle.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
A modo de recordatorio, si se da el caso de que su programa entre en bucle hasta el infinito, es posible interrumpir
la ejecución pulsando las teclas [Ctrl][Pausa].
Pero creando bucles recursivos podrá crear programas que ofrezcan nuevas posibilidades de programación.
Por ejemplo, para barrer todos los subdirectorios de una carpeta determinada, puede usar el código que se basa en
la misma funcionalidad que la utilizada para buscar archivos Windows, el objeto FileSearchObject. Cada vez
que se encuentra una carpeta, la ruta se almacena en una tabla en la memoria y también en la primera columna del
libro. Encontrará el mismo código en el archivo Ejemplo 14D.
’Declaration
Public oFSO, oFld, oSubFolder
Public Tab_Dir() As String ’Tabla en memoria donde se almacenarán los
nombres de los archivos
Public i As Long
’====================================================================
’Función recursiva para encontrar todos los subdirectorios
’con el objeto FileSystemObject
’====================================================================
Sub RecorridoDirT()
’ Llamada al objeto FileSystemObject
Set oFSO = CreateObject("Scripting.FileSystemObject")
i = 0
’ Llamada a la función recursiva
Call RecorridoDir("C:\Users")
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
End If
End If
Exit Sub
Tratamiento error:
Debug.Print Err.Number & " " & Err.Description
Resume Next
End Sub
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Recuperar los datos sin abrir un libro
Si realiza un programa que abra y cierre libros para recuperar valores, comprobará que este tipo de tratamiento es
lento ya que estas operaciones son muy costosas en términos de memoria.
Para evitar saturar la memoria de su ordenador por esas múltiples operaciones de apertura y cierre de archivos,
usaremos astutamente la posibilidad que ofrece Excel de leer el contenido de una celda de un libro cerrado.
En una hoja de cálculo, tiene una celda que apunta a la celda B10 de un libro que está cerrado. Como fórmula tendrá
algo similar a esto: =’C:\Users\MisDocumentos\[Libro1.xlsx]Hoja1’!$B$10
Ahora, en programación trasladaremos esta escritura teniendo cuidado de respetar todos los símbolos esperados por
la fórmula.
Para asegurarnos de no cometer ningún error de sintaxis, pondremos cada uno de los elementos esperados (ruta,
nombre del libro, nombre de la hoja y dirección de la celda) en distintas variables. De esta manera resultará más fácil
cambiar cualquiera de las variables en función de las necesidades del programa.
La escritura de la fórmula en VBA da algo así:
Sub Enlace_Externo()
Dim Ruta As String
im MiLibro As String
Dim MiHoja As String
Dim MiCel As String
Dim MiFórmula As String
Ruta = "C:\Users\MisDocumentos\"
MiLibro = "Libro1.xlsx"
MiHoja = "Hoja1"
MiCel = Cel(2, 10).Address
MiFórmula= "=’" & Ruta & "[" & MiLibro & "]" & MiHoja & _
"’!" & MiCel
Range("A1") = MiFórmula
End Sub
La instrucción Address es obligatoria ya que es la referencia de la celda que vamos a recuperar y no el contenido de
la celda.
A continuación, es fundamental conservar todos los símbolos de la fórmula como pueden ser los corchetes, que
expresan el nombre del archivo, el signo de exclamación que separa el nombre del archivo de la dirección de la celda y
los apóstrofos que abren y cierran la ruta de acceso, el nombre del archivo y el nombre de la hoja de cálculo.
Como todos los componentes son variables, ahora resultará sencillo efectuar bucles tanto sobre el nombre de los
archivos (con la instrucción Dir), como sobre el nombre de las hojas (For Each) o incluso sobre las filas o columnas
de las celdas.
Al final del código que ha construido las referencias externas, se puede no conservar el enlace y conservar solo los
valores copiando y pegando la selección.
Cells(5, 4).Copy
Cells(5, 4).PasteSpecial xlPasteValues
Application.CutCopyMode = False
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Seleccionar un directorioI
Para poder seleccionar un directorio de trabajo mientras el programa se está ejecutando deberá utilizar la función
FileDialog, pero esta función no puede usarse sola. Es preciso asociarla a la función Application para poder
llamarla.
Sub Abrir_Cuadro_Dialogo()
Application.FileDialog(msoFileDialogFolderPicker).Show
End Sub
Pero mostrar el cuadro de diálogo para seleccionar un directorio no es suficiente, después es preciso recuperar el
nombre del directorio seleccionado. Para ello será preciso escribir la siguiente línea de código:
Sub Dir_Selection ()
Dim Dir As String
Application.FileDialog(msoFileDialogFolderPicker).Show
Dir = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1)
MsgBox Dir
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Seleccionar un archivo
Continuando con la instrucción FileDialog, también es posible seleccionar uno o varios archivos. Para ello deberá
modificarse el parámetro entre paréntesis. Por ejemplo, para seleccionar un archivo, escribirá:
Sub Selection_Un_Archivo()
Application.FileDialog(msoFileDialogFilePicker).AllowMultiSelect = False
Application.FileDialog(msoFileDialogFilePicker).Show
MsgBox Application.FileDialog(msoFileDialogFilePicker).SelectedItems(1)
End Sub
Para seleccionar varios archivos dentro del mismo directorio, deberá posicionar el indicador de multiselección en True y
después hacer un bucle para recuperar los nombres de los archivos seleccionados.
Después, lo más sencillo para tratar todos los archivos es almacenar sus nombres en una tabla en memoria (vea el
capítulo Optimización Las tablas en memoria para comprender cómo trabajar con tablas en memoria).
Sub Selection_X_Archivos()
Dim Tab_Nombre_Archivo() As String
Dim Index_ Archivo As Long
Application.FileDialog(msoFileDialogFilePicker).AllowMultiSelect = True
Application.FileDialog(msoFileDialogFilePicker).Show
For Index_Archivo = 1 To Application.FileDialog(msoFileDialogFilePicker). _
SelectedItems.Count
ReDim Preserve Tab_Nombre_ Archivo (Index_ Archivo - 1)
Tab_Nombre_ Archivo (Index_ Archivo - 1) = _
Application.FileDialog(msoFileDialogFilePicker).SelectedItems(Index_ Archivo)
Next
End Sub
Encontrará ese código en el archivo Ejemplo 14G.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Introducción
La optimización de un programa significa que vamos a mejorar la velocidad de ejecución del código, evidentemente,
sin cambiar el resultado final.
Este aspecto de la programación es muy importante. Trabajando como asesor, he tenido que reescribir por completo
programas que se ejecutaban en más de cuarenta minutos y he conseguido reducir el tiempo a apenas unos
segundos (quince, para ser exactos).
A continuación, encontrará muchas técnicas que permiten mejorar la rapidez de ejecución del código.
En los capítulos anteriores, ya hemos visto algunas técnicas de optimización:
l Cómo devolver en una sola instrucción el número de líneas de una columna sin tener que crear un bucle para
contabilizar todas las filas.
l La utilización de tablas para trabajar con datos almacenados en la memoria. En este capítulo profundizaremos en esta
técnica y presentaremos funciones específicas del uso de las tablas.
l El bloqueo de la actualización de la pantalla durante la ejecución del programa.
Todas estas técnicas permiten reducir significativamente el tiempo de tratamiento. Pero también hay otros medios
para mejorar la velocidad de ejecución, como la búsqueda de elementos en una hoja de cálculo sin pasar por bucles.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Instrucciones de búsqueda
Es posible realizar una búsqueda en un rango de celdas sin tener que recorrer las líneas una por una con un bucle
hasta encontrar el elemento buscado. Así conseguimos ganar muchísimo tiempo.
1. El método FIND
Range.FIND(Elemento buscado)
Los objetos Range, Rows y Columns disponen del método FIND que permite buscar un valor. Por ejemplo, el
archivo Ejemplo 15B1 contiene una lista de nombres en la columna A; buscamos el apellido SMITH.
En un procedimiento, puede escribir el siguiente código:
El resultado de un método FIND no es una variable, sino un Objeto. Por eso hay que definir la variable que
devolverá el resultado de una búsqueda con la instrucción Set.
2. Resultado de una búsqueda
Como el resultado es un objeto, hay un gran número de propiedades vinculadas al resultado de la búsqueda. Con la
herramienta Inspección, puede ver el conjunto de estas propiedades:
El valor del objeto no tiene realmente importancia ya que este será necesariamente igual al elemento buscado. Por
el contrario, puede recuperar las propiedades Row y Column para conocer el número de fila y el número de
columna en la que se ha encontrado el elemento buscado de la siguiente manera:
En caso de búsqueda infructuosa, la variable devolverá Nothing. Puede hacer un test con la instrucción Is Nothing
para saber si la búsqueda ha llegado al resultado o no:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
If Nombre_ok Is Nothing Then
Instrucción si no encontrado
Else
Instrucción si sí encontrado
End If
3. Búsqueda del elemento siguiente
Range.FindNext(Objeto)
Cuando la búsqueda haya llegado al resultado y desee buscar el mismo valor en el mismo rango de datos, puede
utilizar el método FindNext en un bucle. Este método debe tener como parámetro el nombre del objeto para poder
continuar la búsqueda.
Sin embargo, el método FindNext es incapaz de determinar el final de su lista de búsqueda: la búsqueda volverá al
principio y así, hasta el infinito. Para poder parar la búsqueda, antes de hacer el bucle, hay que recuperar el número
de la primera fila o la dirección de la primera celda que corresponda al elemento buscado. Cuando el valor de la fila
sea otra vez igual al valor de la primera fila de búsqueda, el bucle se detendrá.
En VBA, se puede traducir del siguiente modo:
Desde la página Información encontrará el código que encuentra todos los valores Smith en el archivo Ejemplo 15
B3.
De la misma forma, puede realizar una búsqueda en elementos anteriores utilizando el método FindPrevious.
4. Opciones de búsqueda
El método FIND corresponde en Excel al cuadro de diálogo Buscar. En VBA, todas las opciones de este cuadro de
diálogo se pueden configurar mediante las opciones del método FIND.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Puede añadir a su búsqueda las siguientes opciones:
l After: precisa la celda tras la cual usted desea empezar la búsqueda. Esta corresponde a la posición de la celda
activa cuando una búsqueda se realiza a partir de la interfaz del usuario.
l LookAt: indica si la búsqueda debe realizarse en toda la celda (xlWhole) o en una parte (xlPart).
l SearchOrder: indica el sentido de la búsqueda: por fila (xlByRows) o por columna (xlByColumns).
l SearchDirection: indica el sentido de la búsqueda: (xlNext) o (xlPrevious). Esta opción es rara ya que es un
duplicado de las instrucciones FindNext y FindPrevious.
l MatchCase: indica si la búsqueda respeta (True) o no (False) la coincidencia de mayúsculas y minúsculas.
l MatchByte: si ha instalado fuentes de caracteres codificados en 2 bytes (escritura vietnamita, china, etc.). Debe
colocar esta variable en True; False es el valor predeterminado.
Por ejemplo, para realizar una búsqueda en una parte de la celda, puede escribir la instrucción siguiente:
Por el contrario, una sola opción presente en el cuadro de diálogo no existe en parámetros en VBA: es la opción de
búsqueda en una sola hoja o en todo el libro.
Esta observación es importante ya que la búsqueda Find se hará siempre en función de la opción del cuadro de
diálogo. Si la opción está posicionada en el libro, la ejecución del código se hará sobre todo el libro, incluso si solo
quiere examinar una hoja.
5. Encontrar el número de la fila
Efectuar una búsqueda en una hoja de cálculo sirve a menudo para encontrar el número de la fila en que se
encuentra el valor buscado. Para devolver el número de fila, existen varios métodos:
El primero consiste en asociar la propiedad Row al resultado de la búsqueda. En este ejemplo, ponemos el código
para recuperar el número de fila en una función. De esta manera, si tuviera que buscar varias veces el número de la
fila en el programa, bastará con llamar a la función en lugar reescribir varias veces la misma instrucción de
búsqueda.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Sub Programa()
MsgBox Encuentra_Fila("CCC")
End Sub
La segunda técnica para encontrar el número de fila del valor buscado no utiliza la función Find sino una propiedad
de la instrucción Application; la función Match.
Sub Find_Match()
Dim Encuentra_Núm_Fila As Long
Encuentra_Num_Fila = Application.Match("CCC", Columns("A"), 0)
MsgBox Encuentra_Num_Fila
End Sub
La propiedad Match se comporta exactamente como la función EQUIV de Excel. Los parámetros que se esperan son:
l El valor buscado
l El rango de búsqueda
l Verdadero o 1 (Valor semejante); Falso o 0 (Valor exacto)
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Las tablas en memoria
1. Utilidad de trabajar con tablas en memoria
Trabajar con tablas siempre es un enfoque de programación que desconcierta. Muchos usuarios imaginan que los
datos están en alguna parte dentro del ordenador, invisibles, y que en caso de error será muy fácil encontrarlos. De
hecho, no es así.
Almacenar datos en la memoria es como almacenarlos en una hoja de cálculo.
Para los usuarios principiantes resulta muy tentador escribir parámetros temporales en una hoja de cálculo para
leerlos y reutilizarlos más tarde, ya que la actualización de los datos en la hoja de cálculo se puede visualizar
fácilmente.
Esta técnica está lejos de resultar óptima, ya que cada vez que escribe un valor temporal en la celda de una hoja de
cálculo, también está recurriendo a la interfaz gráfica de Excel. Y usted sabe que la vista de filas, columnas y hojas
requiere mucha memoria.
Por tanto, para mejorar la ejecución de los programas, aconsejamos vivamente que almacene sus datos en tablas
en memoria durante el tiempo de ejecución del programa.
2. Tablas de una o dos dimensiones
a. Tabla de una dimensión
Una tabla de una dimensión es exactamente como si tuviera los datos en una sola columna del libro.
En una tabla en memoria eso se representa de la forma siguiente:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Vista de una tabla en memoria desde la depuradora
Para encontrar un valor desde una hoja de cálculo deberá indicar los valores, la fila y la columna. Por ejemplo, si
desea encontrar el valor número cuatro, escribirá:
Valor_Celda = Cells(4, 1)
Ahora, si interroga a una tabla en memoria, bastará con precisar el rango. La única diferencia con respecto a las
columnas es que es necesario quitar una unidad ya que las tablas almacenan los datos a partir del valor 0.
Valor_Tabla=Día_Sem(3)
En los bucles, para encontrar el valor "Sábado", es posible escribir la siguiente instrucción:
Dim i as Long i = 1
While Cells(i, 1) <> "Sábado"
Instructions
i = i + 1
Wend
Y el mismo bucle para leer una tabla en memoria, daría:
i = 0
While Tab_Memoria(i)<> "Sábado"
Instructions
i = i + 1
Wend
b. Tabla de dos dimensiones
Una vez más, esta noción parece compleja al principio, pero es muy simple de visualizar. Una tabla de dos
dimensiones es exactamente igual que la cuadrícula de una hoja de cálculo de Excel; consta de filas y columnas.
Y en una tabla en memoria, los datos se ordenan de la siguiente manera:
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Es cierto que imaginarse una tabla de dos dimensiones es desconcertante al principio, pero, de hecho, resulta muy
fácil recuperar las notas de un alumno haciendo variar el segundo índice de la tabla dentro de un bucle:
For i = 0 To 3
MsgBox " Valor de la nota " & i & " " & Notas_Alumnos(0, i)
Next
También es posible recuperar igual de fácilmente todas las notas de la segunda materia haciendo variar esta vez
el primer índice de la tabla:
For i = 0 To 5
MsgBox " Valor de la nota nota " & i & " " & Notas_Alumnos (i, 1)
Next
3. Insertar datos en una tabla en memoria
Introducción unitaria de valores
Para insertar datos en memoria, es posible escribirlos de la siguiente manera:
Pero también es posible introducir datos con la instrucción Array. Bastará con que escriba todos los datos que
desee separándolos con una coma.
Mi_Tabla = Array(" Lunes ", " Martes ", " Miércoles ")
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Esta técnica obliga a declarar la tabla como Variant.
Caso práctico: escribir todos los encabezados de columna en una sola línea de código
La instrucción Array permite también transferir diferentes valores a un rango de celdas. Por ejemplo, si tiene un
documento que empieza por las mismas descripciones de columnas, simplemente escribirá:
Range(" A1:D1 ") = Array(" Fecha ", " Cliente ", " Precio ", " Cantidad ")
Obtendrá el siguiente resultado en la hoja de cálculo:
Cargar una tabla de dos dimensiones
También es posible cargar una tabla de dos dimensiones en memoria usando el símbolo de punto y coma para
cambiar de dimensión. Por ejemplo, si tenemos una tabla de cuatro filas y dos columnas, podemos cargar la tabla de
la siguiente manera:
Sub Carga_2_Dimensiones()
Dim MiTabla As Variant
MiTabla = [{2,6;3,8;10,14;5,-1}]
End Sub
Carga desde una hoja de cálculo
Muy a menudo, los datos que se quieren cargar en la tabla ya están recogidos en la hoja de cálculo. No obstante,
en lugar de elaborar un bucle para recoger los valores uno por uno en una tabla en memoria, un truco de Excel
permite transferir todo el rango de datos a una tabla.
Por ejemplo, tenemos los días de la semana en la columna A de la hoja de cálculo.
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
La inserción de esos datos en una tabla se hace con una sola instrucción:
Sub Inserción_Tabla()
Dim Mi_Tabla As Variant
Mi_Tabla = Range(" A1:A7 ")
End Sub
Y en la depuradora verá las siguientes informaciones:
Tres observaciones importantes:
l La declaración de la variable se hace sin especificar el tamaño (sin paréntesis) y siempre como Variant.
l El resultado de esta técnica copia el contenido de la columna en una tabla de dos dimensiones (siempre).
l La tabla tampoco empieza en el valor 0 como hemos visto hasta ahora, sino en el valor 1.
Es posible transferir el contenido de un rango de celdas de varias filas y columnas a una tabla en memoria de la
misma manera:
Sub Inserción_Tabla ()
Dim Mi_Tabla As Variant
Mi_Tabla = Range(" A1:E7 ")
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Este es el resultado:
4. Borrar una tabla
Cuando trabaja con tablas de una o dos dimensiones, puede borrar fácilmente todos los datos sin necesidad de
bucles gracias a la instrucción Erase.
Erase Mi_Tabla
Como podrá comprobar, los parámetros que definen el tamaño de la tabla no se mencionan. De hecho, el inicio se
realiza en el conjunto de la tabla.
5. Cambiar el tamaño de una tabla
Cuando se trabaja con tablas se debe especificar su tamaño en las declaraciones. Por ejemplo:
Pero esto obliga a conocer previamente el tamaño máximo de las tablas y no siempre es así. Sin embargo, es
posible cambiar el tamaño de las tablas a una dimensión durante el tratamiento.
Esto no puede hacerse con las tablas de más de una dimensión.
- 6- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Para redefinir el tamaño de una tabla de una dimensión se puede usar la instrucción ReDim.
Queremos, por ejemplo, crear una tabla que se corresponda con el número de filas no vacías. Recuperaremos el
número de filas con contenido de la columna A y usaremos este valor para establecer el tamaño de la tabla:
El valor 1 es necesario aquí para respetar que las tablas empiezan siempre en la posición 0.
Se puede, sin embargo, especificar que una tabla empieza en la posición 1 escribiendo al principio del módulo la
siguiente instrucción:
Option Base 1
Atención, el uso de la instrucción ReDim sola inicia obligatoriamente todos los datos almacenados previamente en la
tabla.
Para conservar los datos previamente grabados, deberá hacer que a la instrucción ReDim le siga la instrucción
Preserve.
De esta manera, podrá variar el tamaño de la tabla a lo largo del programa a medida que vaya agregándole datos
sin perder por ello los datos almacenados previamente.
6. Tamaño de una tabla
Al usar una tabla, puede conocer fácilmente su tamaño gracias a las instrucciones LBound (posición del primer
elemento) y UBound (posición del último elemento).
LBound(Tabla, dimensión)
UBound(Tabla, dimensión)
Así, para realizar un bucle en una tabla cuya dimensión no conoce, basta con escribir esta instrucción para hacer un
bucle desde el primer elemento hasta el último. Este código funciona en todos los ejemplos de tablas de una
dimensión.
Si la tabla tiene varios tamaños, deberá concretar mediante el argumento Dimension, en qué dimensión desea
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 7-
devolver el elemento por el que empieza su tabla.
Por ejemplo:
Ubound(Mi_Tabla, 1) Recupera el tamaño de la primera dimensión de la tabla
Ubound(Mi_Tabla, 2) Recupera el tamaño de la segunda dimensión de la tabla
Ubound(Mi_Tabla, 3) Recupera el tamaño de la tercera dimensión de la tabla
... ...
7. Buscar en una tabla
Cuando crea una tabla en la memoria, puede realizar fácilmente una búsqueda en los elementos que contiene sin
tener que hacer un bucle en cada elemento uno por uno. Para realizar esta búsqueda, debe utilizar la función
Filter.
l Su tabla debe tener obligatoriamente una dimensión.
l El argumento include precisa si su búsqueda debe contener (True) o no contener (False) el elemento de
búsqueda.
l El argumento compare precisa si su búsqueda debe respetar la caja (vbBinaryCompare) o no
(vbTextCompare).
El resultado devuelto por la función es en sí mismo una tabla. En ese caso, tendrá que crear un bucle para hacer
aparecer todos los resultados encontrados.
Para declarar una tabla cuya dimensión no conoce previamente, deberá hacer seguir el nombre de su variable por
parámetros abiertos y cerrados sin valor.
Por ejemplo, buscamos en nuestra tabla, la letra "a".
Sub Búsqueda_En_Tabla()
Dim Mi_Tabla(3) As String
Dim Tab_Resultado() As String
Dim i As Long
Mi_Tabla(0) = "uno"
Mi_Tabla(1) = "dos"
Mi_Tabla(2) = "tres"
Mi_Tabla(3) = "cuatro"
El resultado es la palabra "cuatro" en la celda A1.
- 8- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Ahora, si buscamos el valor "s", el programa devolverá en A1 "dos" y en A2, "tres".
Al revés, si buscamos los términos que no contienen "d", escribiremos.
Sub Búsqueda_En_Tabla()
Dim Mi_Tabla(3) As String
Dim Tab_Resultado() As String
Dim i As Long
Mi_Tabla(0) = "uno"
Mi_Tabla(1) = "dos"
Mi_Tabla(2) = "tres"
Mi_Tabla(3) = "cuatro"
Tab_Resultado = Filter(Mi_Tabla, "d", False)
El resultado es solo la palabra "dos" en la celda A1.
Para llevar a cabo la búsqueda de una palabra exacta deberemos añadir un test con el fin de evitar que nos
devuelva palabras compuestas. Por ejemplo, en la siguiente tabla queremos encontrar el número de palabras
iguales a gris:
Sub Búsqueda_En_Tabla()
Dim Mi_Tabla(3) As String
Dim Tab_Resultado() As String
Dim i As Long
Dim Palabra_Buscada As String
El resultado muestra un solo cuadro de diálogo con la palabra ”gris”. Los demás términos que contienen ”gris” no se
tienen en cuenta gracias al test.
a. Transferir el contenido de una tabla a un rango de datos
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 9-
Antes hemos visto cómo transferir el contenido de un rango de datos a una tabla en la memoria. El procedimiento
inverso también funciona.
El único problema aquí es indicar correctamente el tamaño del rango de celdas que hay que seleccionar para
copiar en él el contenido de la tabla en la memoria. Utilizando las instrucciones del tamaño de la tabla con la
instrucción ReSize, podemos definir fácilmente el rango de celdas. Debemos considerar, sin embargo, los casos
de tablas de una y dos dimensiones.
Tabla de dos dimensiones
Hemos visto que transfiriendo el contenido de un rango de celdas de una columna o varias a una tabla (sección
Carga desde una hoja de cálculo de este capítulo), la tabla en la memoria debía tener necesariamente dos
dimensiones: una para las filas y otra para las columnas.
Por tanto, para volver a copiar el contenido de una tabla de dos dimensiones sin conocer exactamente su tamaño,
podemos escribir la siguiente instrucción, que se adaptará exactamente al tamaño de la tabla:
’Option Base 1
Range("A1").Resize(UBound(MiTabla), UBound(MiTabla, 2)) = MiTabla
’Option Base 0
Range("A1").Resize(UBound(MiTabla)+1, UBound(MiTabla, 2)+1) = MiTabla
Tabla de una dimensión
Curiosamente, hacer que el contenido de una tabla sea de una dimensión no es tan sencillo. ¿Hay que devolver la
tabla horizontal o verticalmente? Si queremos devolverla horizontalmente, que es el caso más simple, podemos
usar una de estas sintaxis.
Sub Test_Tabla()
Dim MiTabla As Variant
’ Carga de la tabla en memoria
MiTabla= Array(1, 2, 3, 4)
’ Descarga en la hoja de cálculo
Range("A1:D1") = MiTabla
’ O también
Range("A1").Resize(1, UBound(MiTabla)+1) = MiTabla
End Sub
Para copiar de nuevo el contenido de una tabla de una dimensión verticalmente, no basta con invertir los
parámetros de la instrucción Resize. De hacerlo, solo el primer elemento de la tabla se repetirá tantas veces
como elementos contenga la tabla.
El único modo de volver los datos verticalmente es usando la instrucción Transpose.
Sub Test_Tabla()
Dim MiTabla As Variant
’ Carga de la tabla en memoria
- 10 - © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
MiTabla= Array(1, 2, 3, 4)
’ Descarga en la hoja de cálculo
Range("A1:A4") = Application.Transpose(MiTabla)
’ O también
Range("A1").Resize(1, UBound(MiTabla)+1) = _
Application.Transpose(MiTabla)
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 11 -
Las celdas con nombre y las tablas
1. Presentación
En Excel es posible atribuir un nombre específico a una celda o un rango de celdas. Resulta muy práctico para
personalizar las fórmulas, pero también proteje las referencias de las celdas y este es el tipo de seguridad que
buscamos en nuestros programas.
Partimos de un caso muy simple de tabla (Ejemplo 15D1) en la que tenemos una celda con la tasa de IVA. Pero la
referencia de la celda no es solo C1, también le hemos atribuido el nombre de Mi_IVA.
Para atribuir ese nombre existen dos maneras:
Método 1
Sitúese en C1.
Cambie el nombre directamente en el cuadro Nombre (como en la imagen).
Método 2
Sitúese en C1.
Vaya a la pestaña Fórmulas y haga clic en Asignar un nombre.
Ahora, en lo referente a fórmulas, podemos escribir el resultado de la siguiente manera:
2. Función dentro de un programa
En lo que respecta a los programas, ¿cómo podemos integrar celdas con nombre? Pues bien, basta simplemente con
indicar el nombre en un método Range o escribirlo entre corchetes para recuperar el contenido de la celda.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Dim Tasa_IVA As Double
Tasa _ IVA = Range("Mi_IVA") ’Primera escritura
Tasa _ IVA = [Mi_IVA] ’Segunda escritura
En ocasiones ocurre que alguna de estas dos sintaxis hace que el programa se detenga ya que el VBA tiene dudas
sobre qué información debe recuperar. En esos casos, basta con añadir la propiedad Value después de la
instrucción y ya no se produce el bloqueo.
La gran ventaja de utilizar celdas con nombre en programación es que siempre se podrá recuperar el contenido de la
celda, incluso cuando la posición de las celdas cambia a raíz de los cambios en el libro.
Con frecuencia, en efecto, se añaden o eliminan columnas en los libros y, por tanto, las coordenadas de las celdas
se modifican. Si construye los programas con referencias de tipo Cells(4,2), se verá obligado a corregirlos, pero
con celdas con nombre no será preciso tocarlos.
3. Coordenadas de las celdas con nombre
Otra de las grandes ventajas de usar celdas con nombre es la posibilidad de detectar inmediatamente la posición de
la celda con nombre o del rango con nombre mediante las propiedades Row y Column.
Por ejemplo, si trabaja en un libro que contiene una celda llamada Fecha_de_Factura, y sabe que debe indicar
exactamente cuatro filas por debajo del importe de la factura, podrá poner el valor de la fila de la celda en una
variable y usarla de nuevo de la forma siguiente:
Pero también podemos reducir la escritura a una sola línea de código de la siguiente manera:
Por tanto, si trabaja en libros bien estructurados, le resultará fácil navegar cómodamente en su interior basándose
en las celdas con nombre sin tener que borrar el contenido de toda una hoja hasta encontrar la celda buscada.
La lista de propiedades y métodos vinculados a una celda con nombre es muy importante. Bastará con recurrir a la
depuradora para que esa lista aparezca en la ventana Inspecciones.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Del mismo modo, es posible recuperar el nombre de la hoja de cálculo donde está posicionada la celda activa
escribiendo la siguiente línea de código:
Hoja_Celda = [Mi_Celda].Worksheet.Name
4. Uso de las tablas
Las tablas, que no se deben confundir con las tablas en la memoria, son herramientas muy potentes de Excel, pero
todavía son bastante poco usadas por los usuarios. Es todavía raro encontrar libros con tablas incorporadas.
A modo de recordatorio diremos que las tablas son los objetos que se obtienen activando el menú Insertar Tabla.
Al igual que las celdas con nombre, las tablas se identifican con nombres únicos y columnas con nombre. No solo es
posible trabajar en rangos de datos con un nombre único el nombre de la tabla sino también navegar dentro de
la tabla entre las columnas de ese objeto Tabla.
a. El objeto ListObject
En programación las tablas son ListObject.
Para encontrar todas las tablas dentro de un libro, basta con hacer un bucle con la instrucción For Each. A
continuación, solo deberá añadir la propiedad Name para obtener los nombres de las tablas.
ActiveSheet.ListObjects("Tabla_Ejemplo").ShowTotals = True
Para simplificar la escritura, aconsejamos que ponga el objeto Tabla dentro una variable personal y trabaje con
esa variable de la siguiente manera:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Dim Mi_Tabla As Object
Set Mi_Tabla = ActiveSheet.ListObjects("Tabla_Ejemplo")
Mi_Tabla.ShowTotals = True
Cuando se trabaja con tablas existe un gran número de propiedades específicas que es importante detallar.
b. Propiedades específicas de las tablas
Bucle de los encabezados de las columnas
Los encabezados de las tablas son muy importantes ya que su nombre se corresponde también con el de las
columnas como objeto VBA.
Sin tabla deberíamos encontrar en la programación la posición del encabezado de las columnas y también efectuar
un test para determinar la última columna para detener el bucle. En este ejemplo, todos esos controles no son
necesarios ya que nos basamos en los nombres de los objetos (Tablas y Columnas) cuyos tamaños y posiciones
conocemos.
Insertar una columna
Para insertar una columna entre otras dos dentro una tabla (después de la columna Nombre, por ejemplo),
deberemos primero encontrar la posición de la columna en la tabla de la siguiente manera:
A continuación, bastará con usar ese dato para indicar que vamos a añadir una columna después de esa.
Mi_Tabla.ListColumns.Add Position:=(Col_Nombre + 1)
En este ejemplo no se han usado bucles para encontrar la posición o insertar la columna, hecho que hace ganar
mucho tiempo cuando se trabaja con tablas de gran tamaño.
Cargar en la memoria el contenido de una sola columna
En este capítulo hemos visto cómo cargar fácilmente el contenido de un rango de celdas dentro de una tabla en la
memoria de la siguiente forma Mi_Tabla = Range("A1:A10").
Para ello será preciso que conozcamos previamente el rango que vamos a insertar en nuestra tabla en la
memoria, mientras que, trabajando con una tabla, podemos cargar toda una columna sin necesidad de conocer las
referencias de las celdas.
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Dim Mi_Columna As Variant
Set Mi_Tabla = ActiveSheet.ListObjects("Tabla_Ejemplo")
Set Mi_Columna = Mi_Tabla.ListColumns("Nom").DataBodyRange
La instrucción DataBodyRange se encarga de recuperar los datos contenidos en la columna.
c. Problemas vinculados con la tabla
Cuando se trabaja con tablas no se pueden producir restricciones imprevistas.
Recálculos sistemáticos
Debe saber que todas las fórmulas presentes en las tablas se vuelven a calcular sistemáticamente cada vez que
se produce una modificación. Si añade una columna, toda la tabla vuelve a calcularse; si elimina un valor, toda la
tabla vuelve a calcularse; si añade una nueva fila, toda la tabla vuelve a calcularse, etc. Resulta muy frustrante.
Para evitar que el programa se ralentice inútilmente debido a esta especificidad, es posible indicar que desea
bloquear los cálculos automáticos al inicio del programa usando la siguiente instrucción:
Application.Calculation = xlManual
Por supuesto, si durante el programa fuera preciso añadir una fórmula será imperativo que ponga en marcha de
nuevo el cálculo automático justo antes de la instrucción de cálculo.
Application.Calculation = xlAutomatic
Detectar la última fila
A lo largo del manual, hemos detectado la última fila de un documento de las siguientes formas:
Ahora bien, en una tabla estas instrucciones no funcionarán, ya que ambas instrucciones devolverán siempre la
última fila declarada de la tabla, sin tener en cuenta si está o no vacía.
Al programar, las tablas deben verse como globos en medio de la hoja de cálculo. Las tablas tienen sus propias
reglas y usan sus propios términos.
Por ejemplo, el siguiente código redimensiona la tabla exactamente a los datos contenidos en el documento.
Podrá encontrar el código en el archivo Ejemplo 15D4 desde la página Información.
Sub Cambio_tamaño_Tabla()
Dim Mi_Tabla As Object, ObjColumna As Object
Dim NumFilas As Long, ColNombre As Long
Dim UltimFila As Long, PrincFilaAs Long
Dim RangoActual As Variant
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Set Mi_Tabla = ActiveSheet.ListObjects("Tabla_Ejemplo")
’Encontrar el rango de la tabla (con encabezado)
RangoActual= Range("Tabla_Ejemplo[#All]").Address
’Supresión de las filas de fin (cadena de caracteres)
RangoActual= Left(RangoActual, InStrRev(RangoActual, "$"))
’Primera fila de la tabla (encabezado)
PrincFila= Range("Tabla_Ejemplo[#All]").Row
’Posición de la primera columna
ColNombre = Range("Tabla_Ejemplo").Column
’Número de filas en las tablas
NumFilas= Mi_Tabla.ListRows.Count
’Carga de la primera columna en la memoria
Set ObjColumna = Mi_Tabla.ListColumns(1).DataBodyRange
’Detección de la última fila con info
UltimaFila= Application.CountA(ObjColumna) + PrincFila
’ Cambio tamaño de la tabla
Mi_Tabla.Resize Range(RangoActual& ÚltimaFila)
End Sub
- 6- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Una API para los milisegundos
Para poder medir la velocidad de ejecución de un programa, las funciones internas de fechas y horas de VBA no son
suficientes, ya que es necesario realizar cálculos del orden de la centésima o milésima. Por lo tanto, vamos a utilizar
una API que será capaz de realizar este cálculo.
Tras haber declarado tres funciones que llaman a las otras tres a la misma dll, vamos a colocar en el programa las
cuatro líneas siguientes para iniciar su contador de tiempo y después, al final del programa, para detener el contador
y escribir el resultado en una celda.
Sub Pgm_Principal()
’ Colocar al principio del programa
timeBeginPeriod 1
t_start = timeGetTime()
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
El entorno de 64 bits
Los nuevos ordenadores están diseñados con procesadores de 64 bits para gestionar mejor los datos y asumir más
de 6 Gb de memoria. Microsoft ha secundado esta innovación proponiendo versiones desde Office 2010 de 64 bits
que vienen con la versión 7 de VBA. Esta evolución no es desdeñable en los programas que llaman a las API.
La gran mayoría de API llamadas en VBA son Kernel32.dll, shell32.dll, user32.dll. Como sus propios nombres indican,
estos archivos están diseñados para funcionar en un entorno de 32 bits, de ahí los problemas en la migración de
macros desde una versión de 32 bits hacia una plataforma de 64 bits.
1. La instrucción PtrSafe
Para permitir la ejecución de las API en un entorno de 64 bits, basta con indicar tras su Declare la instrucción
PtrSafe para que la llamada de la API sea segura. Por ejemplo, puede tener:
2. Las variables de 64 bits
Pero la instrucción PtrSafe no es suficiente para hacer segura la llamada. En efecto, y como ya hemos visto en el
capítulo Las variables con presentación de los tipos de variables, la arquitectura de 64 bits impone dos nuevos tipos
de variables: LongLong y LongPtr.
El tipo LongPtr es capaz de gestionar por igual las variables de 32 o 64 bits en función de las necesidades. Pero
solo se debe utilizar para punteros u objetos.
Así, para declarar una API en un entorno de 64 bits, escribirá:
3. Coexistencia de plataformas de 32 bits/64 bits
Como acabamos de ver, la llamada a las API no es la misma en los dos sistemas. Sin embargo, podemos escribir un
programa que será comprensible tanto por una arquitectura de 32 bits y como de 64, e incluso, por un Office de 32
bits que funciona en una plataforma de 64 bits.
Para realizar esto, basta con crear una condición If al nivel de su módulo, fuera de cualquier procedimiento. Ahora
bien, siempre hemos dicho que no era posible escribir ni una sola línea de código fuera de un procedimiento, por eso
debemos hacer preceder a nuestras instrucciones por el símbolo #. El siguiente código, en función de la versión de
su Office (VBA7) y de su arquitectura (Win64) atribuirá el tipo LongPtr a nuestras variables que empiecen por la
letra Z. VBA7 tiene como valor True en Office 2010 y 2013.
’Definición del tipo de datos por defecto para las variables que empiezan por Z
#If Win64 And VBA7 Then
DefLngPtr Z
#Else
DelLng Z
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
#End If
Y para una declaración API, tenemos:
Encontrará un ejemplo de aplicación en el archivo Ejemplo 15F.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Introducción
Es muy habitual, en el ámbito profesional, querer optimizar la exportación de sus hojas o sus libros, ya sea
generando archivos pdf, o también generando automáticamente correos electrónicos.
Hasta la versión de Excel 2003, para realizar estas tareas, había que utilizar dll complementarias, pero desde la
llegada de la versión de Office 2007 y con los complementos de las aplicaciones Acrobat, es mucho más simple crear
programas de exportación sin llamar a las dll externas.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Eliminar las dll que faltan
Uno de los mayores problemas con el que nos encontramos actualmente en la migración de programas escritos en
Excel 2003 hacia una versión más reciente, es la llamada a librerías (dll) que ya no existen. Y el impacto en su
programa a menudo supera incluso el ámbito del uso de esta antigua librería.
Efectivamente, es corriente que un programa que llama a una antigua librería se detenga en las funciones básicas
como Range, Ucase, etc. Si se encuentra ante un caso similar, debe tener los reflejos para comprobar las librerías
llamadas por su programa.
En el Visual Basic Editor, active el menú Herramientas Referencias.
Aparecerá la siguiente ventana:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Llamada a una biblioteca inexistente en su proyecto.
Desmarque sistemáticamente las casillas en las que ponga FALTA.
Sin entrar en detalles de las distintas bibliotecas llamadas, puede ver en el ejemplo siguiente que una dll está
marcada como FALTA. Esto sucede frecuentemente cuando el programa llama a antiguas dll de Office (calendar o
spreadsheet) o a dll complementarias por ejemplo para exportan a PDF.
En este caso:
1. Desmarque la dll que falta.
2. Cierre la aplicación Excel.
3. Reinicie el programa, se habrán resuelto los problemas.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
La instrucción CreateObject
Para llamar a programas ya instalados en su ordenador, debe utilizar la función CreateObject. Esta función
permite llamar desde un programa VBA a las funciones de otros programas como, por ejemplo, el envío de emails, la
generación de documentos PDF, etc.
Para usar la función CreateObject es necesaria la siguiente información:
l ServerName.TypeName: Servername representa el nombre de la aplicación que suministra el objeto y Typename
precisa su tipo o su clase.
l [location]: opcional, indica la ubicación en la que se debe crear el objeto.
Por ejemplo, podemos tener:
En resumen, basta con que indique el nombre del programa al que quiere llamar y Visual Basic se encargará de
encontrarlo en la base de registro de su ordenador en la que está guardado.
Pero crear un objeto que corresponda a una aplicación no es suficiente, a continuación hay que crear un nuevo objeto
para abrir una nueva instancia en esta aplicación. En los dos párrafos siguientes, veremos dos ejemplos de uso de la
función CreateObject.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Envío de emails Outlook
En muchas empresas que necesitan hacer envíos masivos de correos (mailing), el uso de macros es ineludible. El
código siguiente lo ha creado otro Microsoft MVP Excel, Ron de Bruin. Encontrará otros tutoriales (en inglés) en su
página: http://www.rondebruin.nl/win/section1.htm
El código funciona con la mayoría de programas de correo electrónico, excepto para los de Lotus Notes.
1. Programa para enviar un correo electrónico
Para enviar un correo electrónico con texto y un posible archivo adjunto.
Sub Mail_small_Text_Outlook()
’Working in Office 2000-2013
Dim OutApp As Object
Dim OutMail As Object
Dim Cuerpo_Mail As String
Dim Mail_Destinatario As String
2. Explicación del código
Como podrá comprobar, el código no es muy largo. Ahora vamos a estudiarlo punto por punto y verá que el código
es muy simple y que nada es superfluo.
Tras la declaración de las variables, creamos dos objetos. El primero OutApp, permite llamar al programa Outlook y
el segundo crea un nuevo mensaje: creación de un mensaje ( CreateItem) en el objeto OutApp que corresponde
a la aplicación Outlook.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
A continuación escriba el mensaje que va a enviar a sus destinatarios. Para insertar saltos de línea, puede utilizar la
constante vbNewLine, pero también el carácter salto de línea con la instrucción Chr(10) o Chr(13) como vimos
en el capítulo Administrar las listas de caracteres así como en el anexo.
Además, puede personalizar el mensaje usando balizas HTML. Por ejemplo, si desea poner en negrita el nombre de
su interlocutor, escribirá el mensaje de la siguiente manera:
Después escriba todos los parámetros necesarios para el envío de un mail:
l el destinatario (To)
l las personas en copia (CC)
l las personas en copia oculta (BCC)
l el asunto del mensaje (Subject)
l el cuerpo del mensaje (Body)
l el envío (Send) o la vista previa (Display). Puede escoger una u otra, pero no las dos opciones.
También puede adjuntar directamente un archivo quitando el apóstrofo (Attachments.Add).
Por último, cierre los dos objetos para liberar la aplicación llamada.
3. Bucles en sus contactos recogidos en una columna
Si sus contactos están todos recogidos en la columna A de su libro de Excel, puede englobar todo el código anterior
en un bucle similar a este código:
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Creación de un archivo PDF
Desde que la empresa Adobe (Acrobat Reader) integra una dll de creación de pdf en el directorio Office en la
instalación de sus productos, es fácil llamar a esta librería para generar un archivo pdf de su libro.
De nuevo, vamos a reutilizar el código de Ron de Bruin que Microsoft emplea en sus tutoriales.
1. Función para la generación de un archivo PDF
A diferencia de la creación de un mail, en primer lugar vamos a crear una función que administrará la creación del
archivo PDF.
Para usar esta función son necesarios cuatro parámetros:
l El elemento que desea publicar.
l La ruta de acceso de su archivo. Si la ruta está vacía "", entonces la ventana Guardar como aparecerá durante el
proceso de publicación.
l Parámetro para indicar si quiere eliminar (True) o conservar (False) la versión anterior del PDF, si existe.
l Parámetro para indicar si quiere abrir el archivo en Acrobat Reader al final del tratamiento.
El código necesario para la generación de un archivo PDF se encuentra en la siguiente función:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
On Error Resume Next
Myvar.ExportAsFixedFormat _
Type:=xlTypePDF, _
FileName:=Fname, _
Quality:=xlQualityStandard, _
IncludeDocProperties:=True, _
IgnorePrintAreas:=False, _
OpenAfterPublish:=OpenPDFAfterPublish
On Error GoTo 0
Se puede llamar a esta función para exportar todo un libro o una simple hoja del libro en formato PDF.
2. Exportar un libro entero
Para exportar todo un libro a PDF, debe llamar a la función creada anteriormente con el siguiente procedimiento:
Sub RDB_Workbook_To_PDF()
Dim FileName As String
Descargue el archivo Ejemplo 16E2 para obtener el código de creación de un PDF.
3. Exportar una hoja de cálculo en PDF
Este programa le permitirá enviar una o varias hojas de cálculo en la función de creación de un archivo PDF.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
En este caso, solo hay una diferencia con respecto al código anterior, es el paso como parámetro de la instrucción
ActiveSheet que corresponde a una o varias hojas seleccionadas.
Sub RDB_Worksheet_Or_Worksheets_To_PDF()
Dim FileName As String
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Conectar con una base de datos Access
1. Presentación
Desde un programa desarrollado con VBA en Excel, es posible conectar con una base Access y trabajar con los dos
programas en paralelo para explotar los datos de un programa en el otro. Trabajando con Access desde Excel, es
posible es posible recuperar solo los datos que quiere explotar. De esta forma, no recargará el libro de Excel con
datos inútiles.
Para relacionar las aplicaciones de Office, deberá pasar por ActiveX Data Objects (ADO).
Sin esta funcionalidad, no será posible interpretar las líneas de código que presentamos a continuación.
2. Puesta en marcha
Para trabajar en bases de datos Access desde Excel, utilizaremos dos objetos: ADOBD.Connection y
ADODB.RecordSet.
El principio consiste en declarar las bases de datos a través de una conexión. Si la conexión funciona, podremos
ejecutar las consultas mediante la instrucción RecordSet.
En primer lugar deberá declarar los dos objetos en el programa:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Dim Mi_Consulta As New ADODB.Recordset
A continuación, abrirá la base de datos especificando la ruta:
Será necesario acceder al componente Microsoft Jet, pero es inútil que nos entretengamos en explicaciones sobre
su funcionamiento; deberá precisar el nombre y la ruta de la base de datos en el parámetro Data Source.
Para asegurarse de que la base se ha abierto correctamente puede comprobar que no haya ningún error con el
siguiente texto:
If Mi_Base.Errors.Count = 0 Then
Instructions
End If
En la parte Instrucciones recurrirá al objeto RecordSet para transmitir la consulta. Los parámetros que debe
transmitir son:
l Apertura del RecordSet.
l Su consulta.
l El objeto Connection.
l Un parámetro de acceso que hay que dejar por defecto en adOpenForwardOnly.
Para comunicarse entre Excel y bases de datos como Access, puede transmitir las instrucciones en lenguaje SQL o
por línea de comandos, como veremos en los siguientes ejemplos.
Para saber si la consulta devuelve al menos un dato existen varias posibilidades:
Comprobar si el número de registros leídos es superior a 0:
Comprobar que no se ha alcanzado el final de RecordSet:
Comprobar que el código de retorno es igual a 0:
If Mi_Consulta.Status = 0 Then
En el caso de que su consulta SELECT devuelva varias líneas, es posible copiar todo el RecordSet, sin bucles,
dentro de un rango de celdas en una sola línea de código usando la instrucción CopyFromRecordset.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Range("A1").CopyFromRecordset Mi_Consulta
Después de un RecordSet deberá cerrar el objeto para liberar la memoria.
A continuación encontrará un ejemplo completo de acceso a una tabla Access que también podrá consultar en el
archivo Ejemplo 16Access1.xlsm desde la página Información.
Sub Consulta_Access_SELECT()
Dim Mi_Base As New ADODB.Connection
Dim Mi_Consulta As New ADODB.Recordset
Dim Base_Data As String
Dim SQL_Req As String
’Ubicación y Nombre de la base de datos
Base_Data = "C:\Users\Base_Access_Ejemplo.accdb"
’ Abrir la conexión con la base de datos
Set Mi_Base = New ADODB.Connection
Mi_Base.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & Base_Data & ";"
’ Creación de la consulta
SQL_Req = "SELECT * From Table1"
’Ejecución de la consulta
Mi_Consulta.Open SQL_Req, Mi_Base, adOpenForwardOnly
’Test para cerciorarse de que no hay errores en el acceso a la tabla
If Mi_Consulta.Status = 0 Then
’copia de la consulta en celda A1
Range("A1").CopyFromRecordset Mi_Consulta
End If
’Cierre del RecordSet y de la conexión
Mi_Consulta.Close
’Cierre de la conexión a la base para liberar memoria
Mi_Base.Close
End Sub
3. Insertar nuevos registros en Access
Desde Excel pueden añadirse nuevos registros a una base de datos. Esto puede hacerse a través de una consulta
SQL o bien añadiendo métodos al objeto RecordSet. A continuación presentamos este último método, pero en el
archivo Ejemplo 16Access2.xlsm, encontrará las dos soluciones.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Set Mi_Base = New ADODB.Connection
Mi_Base.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & Base_Data & ";"
La primera parte, que concierne a la conexión a la base, es exactamente igual que con la instrucción SELECT.
A continuación, abrimos el RecordSet en el exterior del bucle. De esta manera no tendremos que gestionar un
RecordSet en cada inserción.
Después en el bucle añadimos al RecordSet Mi-Consulta los métodos:
l AddNew: nuevo registro vacío.
l Fields: cumplimentado de los diferentes campos de la tabla, ya sea dando el nombre de la columna, ya sea dando
el valor del índice de la columna partiendo de 0.
l Update: para validar la inserción.
4. Actualizar una base Access desde Excel
También es posible actualizar registros en las tablas a partir de los datos contenidos en hojas de cálculo. En esos
casos, resulta más sencillo realizar la tarea mediante una consulta SQL que hacerlo con los métodos del objeto
RecordSet.
El código, que es posible consultar desde la página Información, Ejemplo 16Access3.xlsm, es el siguiente:
Sub Consulta_Access_UPDATE()
Dim Mi_Base As New ADODB.Connection
Dim Mi_Consulta As New ADODB.Recordset
Dim Base_Data As String
Dim SQL_Req As String
Dim i_Fila as Long
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
’Ubicación y Nombre de la base de datos
Base_Data = "C:\Users\Base_Access.mdb"
’ Abre la conexión a la base
Set Mi_Base = New ADODB.Connection
Mi_Base.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & Base_Data & ";"
’Ejecución de la consulta
Mi_Base.Execute SQL_Req
i_Fila = i_ Fila + 1
Wend
’Cierre de la conexión
Mi_Base.Close
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Repaso del inicio por Visual Basic Editor
Hasta ahora, hemos iniciado los programas a través de Visual Basic Editor haciendo clic en el icono o pulsando
la tecla [F5].
Pero también puede iniciar un programa desde una hoja de cálculo de varias formas distintas.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Combinación de teclas [Alt][F8]
Desde una hoja de cálculo, pulsando las teclas [Alt][F8], aparecerá el siguiente cuadro de diálogo:
En este cuadro de diálogo no aparecen todos los procedimientos o funciones de su aplicación: solo se muestran los
procedimientos sin parámetros.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Inicio mediante un botón u otro objeto
También puede provocar el inicio de un programa insertando controles en una hoja de cálculo.
En la pestaña Programador, haga clic en el botón Insertar.
Hay dos tipos de control disponibles:
l controles de formulario,
l controles ActiveX.
Los controles de formulario proceden de las antiguas versiones de Excel; se siguen conservando para asegurar la
compatibilidad con versiones anteriores de los libros. Se pueden seguir usando en Excel 2007, 2010 y 2013.
Los controles ActiveX son similares a los controles de un cuadro de diálogo personalizado (UserForm) (ver el capítulo
siguiente), estos poseen más propiedades que los controles de formulario. En los ejemplos de este capítulo, solo
utilizaremos los controles de formulario ya que son más sencillos de utilizar a nivel de hojas de cálculo.
1. Los botones
Lo más sencillo para iniciar su programa es agregar un botón a la hoja de cálculo.
Active la pestaña Programador, haga clic en el botón Insertar.
En los controles de formulario, seleccione la herramienta Botón.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
El puntero del ratón se transforma en una cruz con líneas finas, esto significa que puede dibujar un objeto en la
hoja de cálculo.
Dibuje el botón con la ayuda del ratón en la hoja de cálculo.
Cuando haya dibujado el botón, aparecerá un cuadro de diálogo con la lista de procedimientos que es posible
seleccionar.
Este cuadro de diálogo le pide que asigne al botón uno de los procedimientos sin parámetros. Como ocurre con la
combinación de teclas [Alt][F8], solo puede seleccionar los procedimientos sin argumento.
Seleccione el procedimiento que desea asociar al botón.
Haga clic en el botón Aceptar.
Acaba de crear un botón en su hoja de cálculo: cada vez que haga clic en él, ejecutará la macro asociada al botón.
2. Los botones de opción (o botones radio)
Cada botón de opción presenta una elección posible pero solo se puede activar una de estas opciones a la vez.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Basta con hacer un test a cada botón de opción para saber cuál está seleccionado.
Tomemos el ejemplo de la visualización de la hora en una hoja de cálculo. Hay dos casos posibles: la detención de la
actualización (que fija la hora mostrada) o la activación de la actualización automática para visualizar los segundos
que transcurren.
En la celda A2, escriba =Ahora().
Haga clic con el botón derecho del ratón en la celda A2 y escoja Formato de celdas.
En la categoría Número Personalizada, elija el formato: dd/mm/aaa hh:mm y confirme.
En la pestaña Programador, haga clic en el botón Insertar y después en la herramienta Botón de opción
en los controles de formulario.
Inserte los dos objetos en su hoja de cálculo:
Para modificar su nombre, haga clic en el objeto para seleccionar el nombre actual o haga clic con el botón
derecho del ratón sobre el objeto para hacer aparecer el menú contextual:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Después haga clic en Modificar texto.
Escriba el nuevo nombre: ON y OFF para su ejemplo.
A continuación, seleccione el botón ON y haga clic en la opción Formato de control del menú contextual.
En el cuadro de diálogo que aparece, seleccione en la pestaña Control una celda en su hoja de cálculo;
por ejemplo, la celda A1:
Tras aceptar, cuando seleccione uno de los dos botones de opción, el valor de A1 cambiará. Vamos a construir el
código en función de este valor.
En VBA, escriba el siguiente código:
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Sub Test_Activo()
While Cells(1, 1) = 1
Calculate
DoEvents
Wend
End Sub
Por último, debe asociar todos los botones de opción a este mismo procedimiento: haga clic con el botón
derecho y seleccione la opción Asignar macro.
Aparecerá un cuadro de diálogo: seleccione el procedimiento que desea iniciar cada vez que se seleccione
un botón de opción.
Haga lo mismo para el segundo botón.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Por consiguiente, cada vez que escoja una de las dos opciones, verá cómo la hora cambia o bien se mantiene fija.
Encontrará ese ejemplo en el archivo del Ejemplo 17C2.
3. Los menús desplegables
También puede agregar menús desplegables en su hoja de cálculo y asociarle una macro: según la opción escogida,
su macro se comportará de un modo distinto.
Active la pestaña Programador, haga clic en el botón Insertar.
Seleccione, en los controles de formulario, la herramienta Cuadro combinado.
Con el ratón, trace el cuadro combinado.
Haga clic con el botón derecho y señale la opción Formato de control.
Aparecerá un cuadro de diálogo:
- 6- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
En la zona Rango de entrada, seleccione el rango de celdas que se visualizará en el menú desplegable.
En la zona Vincular con la celda, escoja una celda: cada vez que seleccione un elemento de la lista
desplegable, la celda vinculada mostrará el rango del elemento en esta lista.
Por ejemplo, si en la columna A tiene los doce meses del año, pondrá en el rango de entrada las celdas A1:A12 y en
la celda vinculada la celda B1.
A continuación, si selecciona Enero, la celda B1 mostrará 1, si selecciona Junio, la celda B1 mostrará 6.
El archivo Ejemplo 17C3 corresponde a un calendario dinámico en función de los valores contenidos en el menú
desplegable de los meses y los años:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 7-
Sin embargo, el archivo no es perfecto ya que el calendario muestra siempre 31 días, sea cual sea el mes escogido.
Vamos a crear una macro que ocultará los días cuando el mes seleccionado no tenga 31 días.
En primer lugar, utilizaremos la Grabadora de macros para recuperar el código que permite ocultar y
mostrar una columna:
Columns("AF:AF").Select
Selection.EntireColumn.Hidden = True
Columns("AE:AG").Select
Selection.EntireColumn.Hidden = False
Una posible solución (pero no la única) consiste en hacer un test en las distintas celdas que contienen una fecha y
después comprobar si el valor Mes de las celdas sigue siendo igual al mes seleccionado en el menú desplegable;
esto equivale a hacer un test al valor de la celda vinculada.
En torno a este test, vamos a construir un bucle con las tres últimas columnas. Todos los meses tienen al menos 28
días, por lo tanto no es útil hacer un test en los días 1 a 28.
El programa pasa a ser:
Sub Ocultar_los_Días()
Dim Núm_Col As Integer
For Núm_Col = 30 To 32
If Month(Cells(5, Núm_Col)) <> Cells(3, 4) Then
Columns(Núm_Col).Hidden = True
Else
Columns(Núm_Col).Hidden = False
End If
Next
End Sub
El error en este programa sería no volver a mostrar las columnas en caso de que se pase de un mes de 30 días a un
mes de 31 días: si no prevé mostrar las columnas para los días 29, 30 y 31, estas columnas siempre estarán ocultas.
4. Ubicación de los objetos
- 8- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Cuando introduce objetos en una hoja de cálculo, no siempre es fácil alinearlos. En efecto, no es posible activar una
casilla que permita asegurar una alineación y una distancia entre los objetos. Por lo tanto, puede tener objetos
colocados un poco al azar como estos:
Aunque esta alineación se podría hacer mediante las opciones de la pestaña Diseño de página, vamos a escribir
una macro que colocará las casillas en las celdas respetando las propiedades de tamaño de las celdas. Vamos a
crear un bucle en cada objeto de la hoja empezando por la colección de objetos.
Sub BucleCheckBoxes_Formulario()
Dim Cb As CheckBox
For Each Cb In Hoja1.CheckBoxes
Instrucciones
Next Cb
End Sub
Para colocar un objeto en una celda, vamos a recuperar la celda en la que el objeto está colocado mediante la
propiedad Shape.TopLeftCell. La esquina superior izquierda del objeto es el punto de referencia.
Sub BucleCheckBoxes_Formulario()
Dim La_Celda as Range
Dim Cb As CheckBox
Dim La_Celda as Range
For Each Cb In Hoja1.CheckBoxes
Set La_Celda = Cb.TopLeftCell
Next Cb
End Sub
A continuación, utilizaremos las propiedades Left (izquierda) y Top (arriba) para definir la posición y las
propiedades Height (altura) y Width (anchura) para definir las dimensiones del objeto y recolocar cada casilla de
verificación.
Sub BucleCheckBoxes_Formulario()
Dim La_Celda As Range
Dim Cb As CheckBox
For Each Cb In Hoja1.CheckBoxes
Set La_Celda = Cb.TopLeftCell
With Cb
.Select
.Left = La_Celda.Left + 2
.Top = La_Celda.Top
.Height = 15
.Width = 75
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 9-
End With
Next Cb
End Sub
Tras la ejecución de este programa, todos los objetos se colocarán de la misma forma con respecto al alto de las
filas de la hoja de cálculo.
- 10 - © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Procedimiento Auto_Open/Auto_Close
Puede iniciar un programa al abrir un libro poniendo en este un módulo que contenga un procedimiento llamado
Auto_Open. Así, al abrir un libro, las líneas de código contenidas en este procedimiento se ejecutarán
automáticamente al inicio.
Sub Auto_Open()
Instrucción
End Sub
Del mismo modo, puede iniciar un programa al cerrar el libro añadiendo en un módulo, un procedimiento llamado
Auto_Close.
Sub Auto_Close()
Instrucción
End Sub
Por ejemplo, puede forzar el guardado del libro al cerrarlo escribiendo este sencillo fragmento de código.
Sub Auto_Close()
ActiveWorkbook.Save
End Sub
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Evento en una hoja de cálculo
1. Principio de los eventos
Tiene la posibilidad de iniciar procedimientos desde una hoja de cálculo mediante un doble clic o seleccionando una
celda. Para ello, es necesario que cree un código en una hoja de cálculo y no en un módulo.
Como muestra la imagen precedente, a la derecha del VBE tenemos el editor de código, pero en el explorador de
proyectos, a la izquierda, no tenemos ningún módulo.
También habríamos podido seleccionar la opción ThisWorkbook para que el código se aplicara a todas las hojas
de cálculo del libro y no solo a una de ellas.
Sin embargo, cuando escribimos un código desde una hoja de cálculo o para todo el libro no trabajamos con
procedimientos estándar sino con procedimientos ocasionales. Es decir, procedimientos que se activarán cuando se
produzca un evento en la hoja de cálculo, como por ejemplo un doble clic.
2. Lista de eventos
La lista de eventos se obtiene seleccionando la opción Worksheet en el menú desplegable de la izquierda. A
continuación, en el menú desplegable de la derecha, podrá ver la lista de eventos existentes.
Lista de eventos de la versión de Office 365
La lista de eventos puede variar dependiendo de la versión de Excel. Pero no se preocupe, los ejemplos que
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
aparecen a continuación se aplican a todas las versiones de Excel.
Si se encuentra en el objeto ThisWorkbook, la lista de eventos será diferente y se aplicará a los eventos del libro
(abrir, activar, etc.).
3. El evento Change
Seleccione Change en la lista de eventos de una hoja de cálculo.
Se mostrará entonces un procedimiento llamado Worksheet_Change con el parámetro Target.
El evento se comportará de la manera siguiente: los cambios en las celdas conducirán a la ejecución del
procedimiento. Por ejemplo, vamos a hacer un programa que ocultará la columna B cuando el valor de la celda A1
sea igual a "Sí" y que mostrará la columna B cuando el valor de la celda A1 sea distinto de "Sí".
Vamos a crear el código siguiente en un procedimiento Worksheet_Change (este procedimiento deber estar en
una hoja y no en un módulo).
Para simplificar la escritura de la palabra "Sí" haremos que el contenido de la celda sea en minúsculas usando la
instrucción LCase. De esta forma, el evento podrá interpretarse siempre, independientemente de cómo el usuario
lo escriba.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
4. El parámetro Target
El parámetro Target corresponde a la celda que activa el evento. La variable es un objeto en el sentido de que
varios métodos y propiedades están vinculados al parámetro Target.
Las principales propiedades que deberá usar son:
En los ejemplos que presentamos a continuación veremos cómo usar esas propiedades en los tests.
5. Controlar la selección
Para evitar un error de selección, puede agregar un control al número de celdas seleccionadas. En el siguiente
ejemplo, si selecciona más de una celda, la parte del código que oculta la columna B no se leerá:
Encontrará el código correspondiente en el archivo Ejemplo 17E.
6. El evento SelectionChange
Con el evento Change hemos visto que podíamos iniciar el programa cuando se había modificado el contenido de
una celda, pero también podemos iniciarlo cuando cambiamos de celdas. Para ello usaremos el evento
SelectionChange.
Por ejemplo, para colorear a la vez la línea y la columna de la celda activa, el código será:
Cells.Interior.ColorIndex = xlNone
Fila = Target.Row
Columna = Target.Column
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Set RngRow = Rows(Fila)
Set RngCol =Columns(Columna)
Set RngFinal = Union(RngRow, RngCol)
Al cambiar la celda, la fila y la columna cambian de color.
7. El evento doble clic
Este evento podría resultar peligroso ya que anula el comportamiento estándar del doble clic en las hojas de
cálculo, es decir, el paso a modo edición.
Por tanto, para permitir que se eluda el comportamiento estándar del doble clic, se recomienda definir siempre el
rango de aplicación del evento.
Por ejemplo, con el siguiente código permitimos omitir el doble clic personalizado en el rango de celdas B5:B10.
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Introducción
En el capítulo sobre las variables vimos cómo ofrecer a los usuarios la posibilidad de transmitir valores al programa
usando la instrucción InputBox. Ocurre que esta instrucción es muy limitada, ya que no dispone de opciones para
poder personalizarla.
Para mejorar esto, Visual Basic ofrece la posibilidad de crear sus propios cuadros de diálogo para proponer a los
usuarios que seleccionen datos que le servirán en su programa mediante botones de opción, casillas de verificación o
menús desplegables. Así, podrá comprobar los datos que se transmitan a su programa y evitará los errores de
entrada.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Crear un cuadro de diálogo
1. Insertar un nuevo UserForm
En Visual Basic Editor, seleccione el menú Insertar UserForm o haga clic en el siguiente icono en la
barra de menús:
Aparecerá una nueva carpeta en el Explorador de proyectos, así como un rectángulo gris en la zona de trabajo.
Este rectángulo gris corresponde a un cuadro de diálogo en blanco. A continuación debe añadir los Controles
mediante el Cuadro de herramientas que aparece cuando ha seleccionado el UserForm.
Si el Cuadro de herramientas no se muestra o si, por descuido, lo ha suprimido, puede recuperarlo
mediante el menú Ver Cuadro de herramientas.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Puede cambiar el tamaño del cuadro de diálogo deslizando uno de los bordes del UserForm.
En la ventana de propiedades, verá todas las propiedades relacionadas con el objeto seleccionado:
Como podrá comprobar, existe una gran cantidad de propiedades relacionadas a un UserForm esto también
ocurrirá para los Controles que añadiremos más adelante. El objeto UserForm posee, entre otras, las siguientes
propiedades:
Name Para dar un nombre personalizado al cuadro de diálogo.
Caption Para cambiar el título de la barra de título.
ScrollBars Para autorizar o no la vista de las barras de desplazamiento.
ShowModal Para mostrar el cuadro de diálogo siempre en primer plano.
SpecialEffect Para modificar el aspecto del cuadro de diálogo.
2. Escribir un código en un UserForm
Además del aspecto gráfico de un cuadro de diálogo, un UserForm se compone también de líneas de código que se
encuentran fuera de los módulos. Estas líneas de código se conocen como Private y solo pueden ejecutarse
cuando se llama al cuadro de diálogo. Para mostrar estas líneas de código:
Seleccione el icono del UserForm en el Explorador de proyectos.
Haga clic con el botón derecho y elija el menú Ver código.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Le recomendamos encarecidamente que cambie el nombre genérico (UserForm1) por un nombre que
defina mejor la función del cuadro de diálogo que va a crear: en la ventana de propiedades, cambie el
valor de la propiedad Name. Este nombre también se utilizará en su programa.
3. Hacer referencia a un UserForm
Para activar la visualización de un cuadro de diálogo personalizado desde un procedimiento, debe escribir su
nombre seguido del método Show.
Sub Programa_Principal
UserForm1.Show
End Sub
También puede visualizar su cuadro de diálogo desde Visual Basic Editor sin la instrucción Show:
Colóquese sobre el objeto UserForm.
Seleccione el objeto UserForm y pulse la tecla [F5].
Para trabajar con los controles del cuadro de diálogo, en primer lugar debe recordar el nombre de su UserForm, el
nombre del control y la propiedad del control:
Mi_Cuadro.Mi_Control.Propiedad
Cuando trabaje en el código integrado en el UserForm, podrá sustituir el nombre que ha atribuido a su UserForm
por Me.
Desde un módulo, la instrucción Me es incomprensible por Visual Basic. En ese caso, debe escribir el nombre exacto
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
del UserForm para que se pueda interpretar.
Por ejemplo, para insertar la fecha del día en un cuadro de diálogo personalizado se puede escribir el código
siguiente desde el evento Activate:
Me.Label1.Caption = Date
Pero si desea efectuar la misma operación desde un módulo, deberá remplazar Me por el nombre del cuadro de
diálogo personalizado.
Userform1.Label.Caption = Date
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Los eventos
Un evento atañe a todas las acciones que pueden realizarse en un control. Cada evento es un tratamiento específico
en el control que no interfiere a los otros eventos de los demás controles.
Por ejemplo, puede inicializar valores cuando su cuadro de diálogo personalizado se active (Evento).
Tendrá que usar los eventos para comprobar los datos introducidos y también para transmitir los elementos
seleccionados a los módulos de su programa.
Para conocer la lista de eventos que pueden estar relacionados con un control, hay que seleccionar el nombre del
control en el menú desplegable situado en la parte superior de la zona de trabajo; en el segundo menú desplegable,
encontrará la lista de los eventos que el control puede administrar.
Los eventos se declaran en Private, ya que solo son visibles y accesibles desde el cuadro de diálogo.
Desde un módulo no se puede llamar a los eventos en Private.
En el código del cuadro de diálogo, tendrá la instrucción siguiente:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Los controles
Un control es un objeto elemental utilizado para transmitir valores al programa. Los controles evitan tener que
escribir datos "literalmente" en un programa (como una ruta de acceso). Un control se ubica obligatoriamente en un
UserForm. Cada control posee sus propias propiedades.
Visual Basic propone controles que pueden clasificarse en las siguientes familias:
l Los controles textuales como los Labels (o títulos) y los TextBox (o cuadro de texto).
l Los marcos agrupan visualmente los controles que tratan los mismos datos.
Cada control posee propiedades y eventos propios. El capítulo Los controles está dedicado exclusivamente al estudio
de los diferentes controles, junto con ejemplos de utilización.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Ubicación de los controles
Puede colocar libremente sus controles en un UserForm; gracias a la herramienta Cuadrícula, también puede
imponer un espacio concreto (medido en puntos) entre cada control.
Para mostrar los parámetros de la cuadrícula, active el menú Herramientas Opciones y seleccione
General.
Puede precisar el espaciado modificando las Unidades de la cuadrícula en Ancho y/o Alto (en número de
puntos).
Active la opción Forzar controles a cuadrícula para facilitar el posicionamiento de los controles en la
cuadrícula cuando los desplace.
Si esta opción no está marcada, se arriesga a crear cuadros de diálogo que se parecerán a este:
En este ejemplo, no hay ninguna coherencia entre los controles: el tamaño, la alineación y el espaciado entre los
controles son diferentes.
Sin embargo, incluso cuando la opción Forzar controles a cuadrícula está activa, no es siempre fácil colocar
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
correctamente los controles los unos con respecto a los otros.
Para ayudarle a alinear los controles y armonizar el espacio entre ellos, utilice el menú Formato.
Tomando como ejemplo el cuadro de diálogo anterior, vamos a ver cómo alinear los botones de opción.
Debe seleccionar previamente los controles trazando un marco ficticio con el ratón para englobar los
controles en cuestión.
El primer control seleccionado será el control base: es el único que está delimitado con cuadrados blancos. Este
control será la referencia para los demás en términos de tamaño, altura, posición, etc.
Para cambiar el control base, pulse la tecla [Ctrl] y haga clic en el control deseado.
Para alinear a la izquierda los controles con respecto al control base, active el menú Formato Alinear
Izquierda.
Automáticamente, todos los controles se alinearán al punto más a la izquierda del control base.
Para armonizar la altura de los controles OptionButton, seleccione los tres controles y active el menú
Formato Igualar tamaño Alto.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Ahora todos los controles tendrán la misma altura.
Del mismo modo, si selecciona el menú Formato Igualar tamaño Ancho, ajustará el ancho de los
controles en función del ancho del control base:
Para ajustar el espacio entre los controles, seleccione el menú Formato Espacio vertical Aumentar y
después el menú Formato Espacio vertical Igualar.
Así, todos los controles estarán separados exactamente como la altura del control base.
Para alinear el botón Aceptar con el botón OptionButton2, seleccione solo esos dos controles, escoja como
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
control base el botón de opción y utilice los siguientes menús:
n Formato Igualar tamaño Alto
n Formato Alinear Superior (o Inferior en función de lo que prefiera).
Por lo tanto, tendrá:
Para acabar, seleccione los dos CommandButtons (con el control Aceptar como control base) y active los
menús:
n Formato Igualar tamaño Alto
n Formato Igualar tamaño Ancho
n Formato Espacio vertical Aumentar
n Formato Alinear Izquierda (o Derecha)
Al final, su cuadro de diálogo se parecerá a este:
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Orden de tabulación
Una vez que todos los elementos están colocados en el cuadro de diálogo, podrá utilizar la propiedad TabIndex de
cada uno de los controles para definir el orden de selección con la tecla [Tab].
El primer número de orden es 0.
El número de orden que va a atribuir será obligatoriamente único. Si, por un descuido, atribuye el mismo número a
dos controles distintos, Visual Basic atribuirá automáticamente al segundo control el primer número de orden que
esté libre.
Al final, durante la ejecución del programa, cada vez que pulse la tecla [Tab], pasará de un control a otro según el
orden de los números atribuidos a cada control.
Por ejemplo, puede definir el siguiente orden de tabulación:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Introducción
Este capítulo presenta una serie de ejemplos que le mostrarán como usar los controles en los cuadros de diálogo
personalizados.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Las etiquetas (Labels o títulos)
Los usuarios no pueden modificar esta información. Generalmente se trata de títulos, elementos o información que se
le impone al usuario, como una fecha, por ejemplo.
Para agregar un control Label en un UserForm, haga clic en el icono del cuadro de herramientas.
El puntero del ratón se transforma en una cruz fina acompañada de una A mayúscula.
A continuación, cree el control con ayuda del ratón:
Por defecto, el nombre del control es Label1, Label2, etc. Para modificar este nombre, modifique la
propiedad Caption del control.
Para cambiar el título que se visualizará en el cuadro de diálogo, escriba el nombre del UserForm, el nombre del
control tal cual lo define la propiedad Name seguido de la propiedad Caption.
Por ejemplo, podemos escribir la fecha del sistema en el control Label1 de la siguiente forma:
Me.Label1.Caption = Date
Atención: no confunda la propiedad Caption (que corresponde a la palabra que se muestra en el cuadro de diálogo),
con la propiedad Name del control (que define el control en sí). Esto se aplica a TODOS los controles.
Por el contrario, si cambia la propiedad Name de su control (como por ejemplo La_Fecha), tendrá que escribir en su
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
línea de comando:
Me.La_Fecha.Caption = Date
Las propiedades más comunes del control Label son las siguientes:
Name Para atribuir un nombre único a un objeto.
Caption Para cambiar el valor visible en el cuadro de diálogo.
Visible Para mostrar o no el objeto en el cuadro de diálogo.
TextAlign Para gestionar la alineación del texto en el control.
SpecialEffect Para modificar el grafismo del control (en 2D o en 3D).
ForeColor Para gestionar el color de la escritura.
BackColor Para gestionar el color de fondo del control.
BorderStyle Para mostrar o no los bordes alrededor del control.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Los cuadros de texto (o TextBox)
Los controles TextBox permiten al usuario realizar entradas de texto.
Para agregar un control TextBox en un UserForm, haga clic en el icono del cuadro de herramientas.
El puntero del ratón se transforma en una cruz fina acompañada de abl.
Dibuje el control con la ayuda del ratón en el cuadro de diálogo.
La entrada de texto es libre en un control TextBox. Pero en cambio, puede realizar tests en la
información introducida por los usuarios en un evento asociado a la salida del control.
Las propiedades más comunes del control TextBox son las siguientes:
Name Para atribuir un nombre único a un objeto.
Text Para recuperar el valor introducido por el usuario.
Visible Para mostrar o no el objeto en el cuadro de diálogo.
Enabled Hace que el objeto pueda editarse o no.
Tomemos por ejemplo un programa de cálculo financiero que requiere la introducción de una tasa de interés:
En este ejemplo, el dato introducido debe ser un valor numérico. Va a crear un test cuando el usuario abandone la
zona de texto para comprobar que la información escrita es un valor numérico.
Haga doble clic en el control en el que quiere escribir el código.
Su UserForm se borrará y aparecerá un procedimiento para el evento Change del control.
Vamos a crear un test que comprobará que la información escrita es un valor numérico. Vamos a escribir en el evento
Exit (es decir, cuando el usuario abandone el control) el código que comprobará el contenido del control.
En el evento Exit, vamos a hacer un test a la propiedad Text del control TextBox para comprobar que su contenido
es un valor numérico. Nuestro test se escribirá de la siguiente forma:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
End Sub
El código puede mejorarse si realizamos un test únicamente cuando el control TextBox está compuesto por al menos
un carácter. Además, puede verificar que el valor está comprendido entre 0 y 10:
Encontrará ese ejemplo de código en el archivo del Ejemplo 19C.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Los botones (o CommandButton)
Los botones (CommandButton) son fáciles de configurar, pero sumamente importantes en un cuadro de diálogo.
Las principales propiedades del control CommandButton son:
Name Para atribuir un nombre único a un objeto.
Caption Para cambiar el valor del título del control.
Visible Para mostrar o no el objeto en el cuadro de diálogo.
Enabled Para hacer el objeto accesible o no.
Generalmente tiene dos botones en un UserForm:
l El botón Aceptar que iniciará el programa.
l El botón Cancelar que cerrará el UserForm.
1. Agregar un botón
En el cuadro de herramientas, haga clic en el icono y con ayuda del ratón, dibuje el botón en el
cuadro de diálogo. Aparecerá un nuevo CommandButton.
2. El botón Cancelar
El botón Cancelar es el más sencillo de codificar.
Cuando hace clic en el botón Cancelar de cualquier cuadro de diálogo, cierra el cuadro de diálogo, pero también
borra todos los parámetros en la memoria que se cargaron cuando estaba abierto ese cuadro de diálogo.
Haga doble clic en el control, para abrir directamente el código del control.
Por defecto, los eventos estándar son Click o Change.
Para cerrar un cuadro de diálogo, debe escribir, en el evento Click del botón, la siguiente instrucción:
3. El botón Aceptar
Es el botón principal del cuadro de diálogo ya que es el que va a provocar la ejecución del programa.
En el evento Click del botón Aceptar, puede utilizar todos los valores de sus controles para iniciar los tratamientos
en función de los diferentes valores.
Encontrará un ejemplo del uso de este evento en la sección Los botones de opción.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Las casillas de verificación (CheckBox)
Las casillas de verificación (ChekBox) solo pueden devolver dos valores: marcada o no marcada (True o False). En
cada clic del usuario, el control pasa del estado marcado al estado no marcado, y viceversa.
Para agregar una casilla de verificación a su cuadro de diálogo, haga clic en el icono del Cuadro de
herramientas y haga clic y arrastre el ratón en el UserForm para hacer aparecer un control CheckBox.
Las principales propiedades del control CheckBox son:
Name Para atribuir un nombre a un objeto.
Caption Para cambiar el valor del título en el cuadro de diálogo.
Visible Para mostrar o no el objeto en el cuadro de diálogo.
En el siguiente ejemplo, la casilla de verificación permite activar el botón Aceptar solo cuando la casilla está marcada.
Al abrir el UserForm, debemos especificar que:
l El botón Aceptar no es accesible,
l El estado de la casilla de verificación es no marcada.
Encontrará ese código en el archivo del Ejemplo 19E.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Las casillas de verificación son independientes entre sí: si en su cuadro de diálogo debe comprobar varias casillas de
verificación, debe comprobar todas las combinaciones posibles.
Por ejemplo, el siguiente cuadro de diálogo contiene cuatro casillas de verificación. Cada control puede tener dos
estados (True o False). En ese caso, habría que verificar los cuatro controles, por lo tanto, hay 24 = 16 combinaciones
posibles y similar número de verificaciones.
Procure no crear cuadros de diálogo con demasiadas casillas de verificación.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Los botones de opción (OptionButton o botones radio)
A diferencia de las casillas de verificación que son independientes entre sí, los botones de opción (OptionButton)
están relacionados los unos con los otros.
Un grupo de botones de opción se utiliza para escoger una opción entre varias. Cuando el usuario seleccione un
botón de opción, los demás botones de opción se deseleccionarán.
En el ejemplo siguiente solo se puede seleccionar una opción:
Para agregar un botón de opción a su cuadro de diálogo, haga clic en el icono del cuadro de
herramientas y haga clic y arrastre el ratón en el UserForm para hacer aparecer un control OptionButton.
Las principales propiedades del control son:
Name Para atribuir un nombre a un objeto.
Caption Para cambiar el valor del título en el cuadro de diálogo.
Value Para recuperar la indicación marcada (True) o no marcada (False).
Visible Para mostrar o no el objeto en el cuadro de diálogo.
Enabled Para hacer el objeto accesible o no.
Para recuperar en su código el valor seleccionado, debe hacer un test en el valor True (valor cuando el botón está
seleccionado) para cada uno de los controles. Lo mejor es utilizar la instrucción Select Case y comprobar el valor
True.
En un evento Clic del botón Aceptar, puede escribir el siguiente código:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Case Me.OptionButton4.Value
MsgBox Me.OptionButton4.Caption
Case Me.OptionButton5.Value
MsgBox Me.OptionButton5.Caption
End Select
End Sub
Cada vez que haga clic en el botón Aceptar, aparecerá un mensaje correspondiente al nombre (Caption) del control
en un cuadro de diálogo.
Este ejemplo de UserForm se encuentra en el archivo del Ejemplo 19F1.
Para que los botones de opción actúen en conjunto, deben estar colocados en un continente que puede ser el
UserForm o un marco (Frame).
Un marco (Frame) permite delimitar una zona en su cuadro de diálogo. Permite agrupar visualmente los elementos,
pero también hacer cohabitar botones de opción para permitir seleccionar varios.
Por ejemplo, podemos tener el siguiente cuadro de diálogo:
Gracias a los dos marcos, puede elegir dos botones de opción.
Encontrará este ejemplo de UserForm con dos marcos en el archivo del Ejemplo 19F2.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Los cuadros de lista (o ListBox)
1. Presentación
Los cuadros de lista (ListBox) de un cuadro de diálogo permiten al usuario seleccionar un elemento entre una lista
de datos. El usuario no tiene la posibilidad de agregar o modificar los valores de una lista cuando el cuadro de
diálogo aparece al ejecutar el programa.
Para agregar un cuadro de lista a su cuadro de diálogo, haga clic en el icono del cuadro de
herramientas y haga clic y arrastre el ratón en el UserForm para hacer aparecer un control ListBox.
Las principales propiedades del control son:
Name Para atribuir un nombre a un objeto.
Caption Para cambiar el valor del título en el cuadro de diálogo.
Visible Para mostrar o no el objeto en el cuadro de diálogo.
Enabled Para hacer el objeto accesible o no.
RowSource Para precisar el origen de los valores. Se puede tratar de celdas de una hoja de cálculo o
de datos transmitidos por un programa.
ListStyle Para agregar un icono delante de los datos (1) o mostrar únicamente los valores (0).
MultiSelect Para permitir seleccionar un solo valor (0) o varios (1). Puede realizar una selección
múltiple ya sea seleccionando cada valor pulsando al mismo tiempo la tecla [Ctrl], o
haciendo una selección pulsando la tecla [Mayús].
MatchEntry Para poder usar el teclado para acceder más rápidamente a los elementos de la lista.
Por ejemplo, puede crear un cuadro de lista como este:
Con las siguientes propiedades:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
2. Manipular los datos de la lista
Recuperar el valor del elemento seleccionado en un cuadro de lista es más difícil que para otros controles. En primer
lugar, debe recuperar la posición del elemento seleccionado y después el valor correspondiente a este número en la
lista.
Para recuperar el número correspondiente a la posición en la lista, utilice la propiedad ListIndex. Como
para las tablas en la memoria, el primer elemento de un cuadro de lista empieza siempre por el índice 0.
Val_Índice = Me.ListBox1.ListIndex
Para encontrar el valor seleccionado, utilice el índice del valor tal y como se indica en la línea de código
precedente e integre ese valor con el método List para mostrar el nombre del valor seleccionado.
Para este ejemplo, obtenemos el siguiente código en el evento Change del control ListBox:
Encontrará ese ejemplo en el archivo del Ejemplo 19G2.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
En caso de una selección múltiple, debe hacer un bucle en todos los elementos de la lista y verificar cada uno de
ellos para saber si se han seleccionado o no.
Si retomamos el ejemplo anterior con una selección múltiple posible, puede visualizar los meses
seleccionados en un cuadro de diálogo tras haber hecho clic en el botón Aceptar.
Cuando pulse el botón Aceptar, aparecerá el siguiente mensaje:
El código es el siguiente:
Encontrará el código de este ejercicio en el archivo del Ejemplo 19G2b.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
3. Alimentar una lista en el programa
En vez de rellenar su ListBox a partir de datos de una hoja de cálculo, puede alimentarla en el momento de cargar
el cuadro de diálogo. Así, puede agregar o suprimir elementos sin tener que abandonar el UserForm.
Por ejemplo, quiere crear una lista de los números pares del 0 al 10. Con el método AddItem, puede cargar sus
propios datos:
Al abrir el cuadro de diálogo, tendrá el siguiente resultado:
También puede suprimir elementos del cuadro de lista con el método RemoveItem; por ejemplo, puede eliminar de
su lista el elemento seleccionado haciendo clic en el botón Suprimir.
El código será:
Tras haber pulsado en el botón Suprimir, aparecerá su lista sin el elemento que acaba de eliminar.
- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
El código de este ejemplo se encuentra en el archivo del Ejemplo 19G3.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Los cuadros combinados (ComboBox o menús desplegables)
Los menús desplegables (ComboBox) son los controles más utilizados son sencillos de utilizar pero también son los
más difíciles de codificar ya que debe gestionar el elemento seleccionado en la lista, pero también gestionar la adición
del nuevo elemento.
Los cuadros combinados combinan a la vez la selección de un elemento y la adición de un nuevo elemento como si el
menú desplegable fuera una zona de texto (TextBox). Los controles ComboBox no permiten la selección múltiple.
Para agregar un cuadro combinado a su cuadro de diálogo, haga clic en el icono del cuadro de
herramientas y haga clic y arrastre el ratón en el UserForm para hacer aparecer un control ComboBox.
Las principales propiedades del control son:
Name Para atribuir un nombre a un objeto.
Caption Para cambiar el valor del título en el cuadro de diálogo.
Visible Para mostrar o no el objeto en el cuadro de diálogo.
Enable Para hacer el objeto accesible o no.
RowSource Para precisar el origen de los valores. Se puede tratar de celdas de una hoja de cálculo o de
datos transmitidos por un programa.
ListStyle Para agregar un icono delante de los datos (1) o mostrar únicamente los valores (0).
MultiSelect Para permitir seleccionar un solo valor (0) o varios (1). Puede realizar una selección múltiple ya
sea seleccionando cada valor pulsando al mismo tiempo la tecla [Ctrl], o haciendo una
selección pulsando la tecla [Mayús].
MatchEntry Para poder usar el teclado para acceder más rápidamente a los elementos de la lista.
Para devolver el dato seleccionado en el menú desplegable, escriba el siguiente código en el envento Change del
control ComboBox:
Si permite la entrada en el cuadro combinado de un valor que no está en la lista, tendrá que gestionar un evento que
agregue este elemento a la lista inicial.
En el siguiente ejemplo, la columna A contiene cuatro nombres. Para que los usuarios puedan agregar un nombre en
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
esta lista, debe crear un botón Adición que recuperará el valor introducido por el usuario y agregará dicho valor a la
lista inicial.
Call UserForm_Initialize
End Sub
El código de este ejemplo se encuentra en el archivo del Ejemplo 19H.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Síntesis
Como muestran los ejemplos, las posibilidades que ofrecen los distintos controles son numerosas y las
manipulaciones en los datos transmitidos por cada control son muy diferentes.
El siguiente ejemplo le muestra cómo inicializar todos los controles de su cuadro de diálogo. Como puede comprobar,
una zona de texto no se inicializa como un botón de opción, ni como un cuadro de lista:
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Introducción
En VBA, un error se traduce siempre por la interrupción del programa. Sin embargo, todos los errores no tienen
porqué serlo para usted. Por ejemplo, si quiere seleccionar una hoja que no existe aún, su programa le indicará un
error pero para usted, es precisamente una información para crear la nueva hoja de cálculo o no.
Según la naturaleza del error, el lenguaje VBA devolverá un número de anomalía. En el anexo (sección Lista de
códigos de error transmitidos por Visual Basic) encontrará la lista de anomalías y su significado. A continuación, en
función de los códigos devueltos, podrá realizar tratamientos específicos.
Para evitar que su programa se bloquee por un error, debe integrar una redirección en el procedimiento.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Las instrucciones para la gestión de errores
Antes de ver cómo gestionar los errores en un programa, vamos a conocer las funciones que nos permitirán tratarlos.
1. On Error
Para indicar que desea gestionar los errores en un procedimiento, va a escribir en su procedimiento la instrucción
On Error. Esta función sola no tiene ninguna utilidad, normalmente hay que añadirle la instrucción GoTo.
No separe las palabras Go y To: deben ir en una sola palabra.
2. La instrucción Resume
La instrucción Resume indica que el programa se retomará en la línea que ha generado el error.
3. La instrucción Resume Next
Si desea continuar su programa tras la línea que ha provocado el error, debe escribir la instrucción Resume Next.
4. La instrucción Err
La instrucción Err permite recuperar el número de la anomalía. Con esta instrucción se pueden administrar varios
tipos de anomalía en su programa.
La instrucción Err puede complementarse con otras propiedades:
Esta propiedad devuelve el texto del error. Puede utilizarla en un mensaje que se mostrará en la pantalla:
5. GoTo
La instrucción GoTo permite, en caso de que se detecte un error durante la ejecución, ir, en el mismo procedimiento,
a un bloque de código para tratar la o las anomalías encontradas (ver los ejemplos a continuación).
6. GoTo 0
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
La instrucción GoTo 0 anula las instrucciones específicas que haya escrito para tratar los errores y deja que Excel
gestione los errores deteniendo el programa.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Redirección de errores
Gracias a las instrucciones anteriores, puede transformar sus programas para tener en cuenta los errores.
1. Ejemplo 1
Pongamos por caso que crea un libro de síntesis anual en el que crea cada mes una nueva hoja que recoge la
actividad del mes corriente. Cada vez que abra el programa quiere que el documento se abra en la hoja del mes
actual.
Por lo tanto, escribirá el siguiente código:
Sub Auto_Open()
Dim Nombre_Hoja as String
Nombre_Hoja = Format(Date, "mmmm - yyyy")
Sheets(Nombre_Hoja).Select
End Sub
El problema es que cada nuevo mes, el libro querrá colocarse en una hoja que no existe. Por lo tanto aparecerá el
siguiente mensaje:
Vamos a transformar el procedimiento para gestionar esta anomalía.
En primer lugar, vamos a indicar que las anomalías las gestiona el módulo con la instrucción On Error y después,
al final del procedimiento, vamos a escribir el código que añadirá la nueva hoja.
Sub Auto_Open()
Dim Nombre_Hoja as String
On Error Goto Gestión_Error
Nombre_Hoja = Format(Date, "mmmm - yyyy")
Sheets(Nombre_Hoja).Select
Gestión_Error:
Instrucción
End Sub
En caso de una redirección, la instrucción Goto irá obligatoriamente seguida de un nombre de etiqueta. A
continuación, debe hacer referencia a esta etiqueta al final del procedimiento. De hecho, esta etiqueta es similar a
un subprograma, por lo tanto es indispensable escribirla al final del procedimiento para distinguir su programa de la
gestión de errores.
En la etiqueta Gestión_Error, vamos a escribir el código que permita agregar una nueva hoja. Y, para
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
renombrar la hoja, vamos a utilizar la misma variable ya que estamos en el mismo procedimiento.
Sub Auto_Open()
Dim Nombre_Hoja as String
On Error Goto Gestión_Error
Nombre_Hoja = Format(Date, "mmmm - yyyy")
Sheets(Nombre_Hoja).Select
Gestión_Error:
Sheets.Add After:=Sheets(Sheets.Count)
ActiveSheet.Name = Nombre_Hoja
End Sub
En este ejemplo, se añadirá una nueva hoja pero el programa se detendrá justo tras la línea en la que se renombra
a la hoja. Para volver al programa principal, debemos volver a añadir la instrucción Resume para volver a la línea
que ha provocado la anomalía o Resume Next para volver a la línea siguiente.
Por el contrario, cuando el código principal (fuera de la etiqueta) haya acabado, el programa continuará leyendo las
instrucciones, incluso si no hay error. Para evitar que estas líneas se traten, debe hacer un test en el número del
código del error.
El código de este ejemplo pasa a ser:
Sub Auto_Open()
Dim Nombre_Hoja as String
On Error Goto Gestión_Error
Nombre_Hoja = Format(Date, "mmmm - yyyy")
Sheets(Nombre_Hoja).Select
Gestión_Error:
If Err.Number = 9 Then
Sheets.Add After:=Sheets(Sheets.Count)
ActiveSheet.Name = Nombre_Hoja
Resume
End If
End Sub
También puede detener el programa justo antes de la etiqueta agregando la instrucción Exit Sub para salir
instantáneamente de su procedimiento.
El código pasa a ser:
Sub Auto_Open()
Dim Nombre_Hoja as String
On Error Goto Gestión_Error
Nombre_Hoja = Format(Date, "mmmm - yyyy")
Sheets(Nombre_Hoja).Select
Exit Sub
Gestión_Error:
If Err.Number = 9 Then
Sheets.Add After:=Sheets(Sheets.Count)
ActiveSheet.Name = Nombre_Hoja
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Resume
End If
End Sub
2. Ejemplo 2
En la parte que trata los errores, puede realizar varias acciones en función del número de anomalía. Para ello, basta
con hacer un test en el número de anomalía (Err.Number) y, para cada valor, se realizarán instrucciones
específicas.
Gestión_Error:
Select Case Err.Number
Case 9
Instrucción
Case 1004
Instrucción
Case Else
MsgBox "Otro Error " & Err.Number & " " & Err.Description
End Select
3. Ejemplo 3
En lugar de indicar en su procedimiento que se conecte a una etiqueta para tratar los errores, también puede
precisar que el error se pase sin interrumpir la ejecución del código.
Para ello, puede, desde el principio del procedimiento (o función), utilizar la instrucción On Error pero, en este
caso, sustituya la instrucción Goto por Resume Next.
Estudiemos el código de la siguiente función que prueba si la hoja existe o no en un libro.
El nombre de la hoja probada ( sname) se coloca como parámetro y este nombre se transmite a una variable
Objeto_Hoja declarada en Objeto.
En caso de que la hoja no exista, el programa debería haberse detenido en la instrucción Set Objeto_Hoja....
Ahora bien, como hemos escrito la instrucción On Error Resume Next al principio de la función, el programa
continuará.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Tipos de variables
Boolean La variable solo puede tomar dos valores: True o False (o bien 0 o 1).
Byte Este tipo se utiliza para la manipulación de datos binarios. Un dato binario está representado por
un número de 8 bits (es decir, 8 cifras). Cada bit es un 0 o un 1. Un valor de tipo Byte puede
tener un valor entre 0 y 255. Si el contenido de un valor superase los 255, el programa se
detendría.
Date El tipo Date posee todas las fechas comprendidas entre el 1 de enero del año 100 y el 31 de
diciembre de 9999, de las 0:00:00 a las 23:59:59 horas de cada día. Este tipo se encuentra en la
tipología de las variables ya que los días o los meses no se añaden como cifras.
Currency El tipo Currency representa todos los datos monetarios: son números comprendidos entre
922337203685477,5808 y 922337203685477,5807.
Integer El tipo Integer devuelve un número entero comprendido entre 32768 y 32767. Este tipo de
variable se utiliza mucho para hacer bucles en fila o en columnas (con la condición de no superar
las 32767 filas).
Long Es una extensión del tipo Integer. Los valores están comprendidos entre 2147483648 y
2147483647.
Single El tipo Single representa valores decimales. Los valores posibles están comprendidos entre
3,402823 x 10 38 y 1,401298 x10 45 para los valores negativos y entre 1,401298 x 10 45 y
3,402823 x 10 38 para los valores positivos.
Double El tipo Double representa los valores de números con coma flotante de doble precisión. Los
valores posibles están comprendidos entre 1,79769313486231 x 10 308 y 4,94065645841247
x10 324 para los números negativos y entre 4,94065645841247 x 10 324 y 1,7976931348623 x
10 308 para los números positivos. Más allá de toda consideración de ocupación en la memoria, es
un tipo al que hay que dar prioridad.
String Las cadenas de caracteres (String en inglés) son las expresiones de texto. Estas no se pueden
utilizar para cálculos matemáticos u operaciones lógicas. De hecho, estas expresiones son la
concatenación de varios caracteres. Una cadena de caracteres no puede contener más de 2.000
millones de caracteres aproximadamente (¡es más que suficiente!).
Variant El tipo Variant es un tipo que agrupa todos los demás tipos citados anteriormente. Es una especie
de "trastero" muy práctico, pero a veces puede parecer desconcertante.
Object El tipo Object tiene como valor el de una clase. Una clase es un modelo que posee propiedades y
métodos. En Excel, se consideran como objeto las celdas, filas, columnas, hojas de cálculo,
gráficos, libros, etc. Estas variables se utilizan en colecciones de objetos.
LongLong Tipo de datos de 8 bytes únicamente disponible en los sistemas de 64 bits. De tipo numérico.
Números enteros comprendidos entre 9 223 372 036 854 775 808 y 9 223 372 036 854 775 807.
LongLong es un tipo únicamente declarado válido en las plataformas de 64 bits.
LongPtr Tipo de datos de variable de 4 bytes en las versiones de 32 bits y de 8 bytes en las versiones de
64 bits de Office 2010. Se trata del método recomendado para declarar un puntero o un
controlador para un código nuevo, pero también para un código heredado si este debe ejecutarse
en la versión de Office de 64 bits.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Colección de objetos
Aquí presentamos la lista de colecciones de objetos más comunes en Excel y sus campos de aplicación. Una colección
de objetos puede aplicarse en un libro, a una hoja de cálculo, a gráficos.
AddIns Representa el conjunto de macros complementarias que existen en la aplicación.
AllowEditRanges Representa el conjunto de celdas no cerradas en una hoja de cálculo (cuando la hoja
está protegida).
Areas Para una selección de celdas, Areas representa el conjunto de celdas de esta
selección. Esta colección se usa básicamente para la propiedad Count que devuelve el
número de celdas de la selección.
Axes Representa el conjunto de ejes de un gráfico.
Borders Representa el conjunto de bordes de una selección.
CalculatedMembers Solo se aplica a una tabla cruzada dinámica: representa el conjunto de elementos
calculados en la tabla cruzada dinámica.
Charts Representa el conjunto de curvas, barras, etc. que representan las series de datos en
un gráfico.
Comments Representa el conjunto de comentarios de una hoja de cálculo.
CustomProperties Representa el conjunto de propiedades de un libro.
DataLabels Representa el conjunto de etiquetas de sus series de datos (se aplica únicamente a
los gráficos).
Dialogs Representa el conjunto de cuadros de diálogo integrados en Excel.
Filters Representa el conjunto de filtros utilizados en una hoja de cálculo.
FormatConditions Representa el conjunto de configuraciones condicionales en un rango de celdas.
Hyperlinks Representa el conjunto de hipervínculos en un rango de celdas o en una hoja de
cálculo.
Names Representa el conjunto de celdas nombradas en su aplicación o en su libro.
PivotTables Representa el conjunto de tablas cruzadas dinámicas de una hoja de cálculo.
RecentFiles Representa el conjunto de archivos abiertos recientemente en la aplicación.
Scenarios Representa el conjunto de escenarios contenidos en una hoja de cálculo.
Shapes Representa el conjunto de objetos gráficos en una hoja de cálculo.
Sheets Representa el conjunto de hojas de cálculo de un libro.
Windows Representa el conjunto de ventanas abiertas en la aplicación.
Workbooks Representa el conjunto de libros abiertos en la aplicación.
Worksheets Representa el conjunto de hojas de cálculo de un libro.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Lista de constantes
Lista de constantes para ubicarse en las rutas de acceso estándar de Windows.
&H5 = My Documents
&H2E = \Documents
&H6 = \Favorites
&H8 = \Recent
&H9 = \SendTo
&H10 = \Desktop
&H15 = \templates
&H17 = \Programs
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
&H18 = \Startup
&H19 = \Desktop
&H1B = \PrintHood
&H25 = GetSystemDirectory()
&H28 = \
&H2D = \Templates
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
&H37 = My Video folder for all users
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Lista de códigos de error transmitidos por Visual Basic
3 Return sin GoSub.
5 Llamada o argumento de procedimiento no válido.
6 Desbordamiento.
7 Sin memoria.
9 Suscripción fuera del intervalo.
10 Esta matriz se ha fijado o está bloqueada temporalmente.
11 División por cero.
12 Pérdida de precisión en la conversión de una Variante.
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 produjo una interrupción por parte del usuario.
20 Reanudar sin error.
28 Espacio de pila insuficiente.
35 Sub o Function no definida.
48 Error al cargar la biblioteca DLL.
49 Convención de llamada a archivo DLL no válida.
51 Error interno.
52 Número o nombre de archivo incorrecto.
53 No se encuentra el archivo.
54 Modo de archivo incorrecto.
55 Archivo ya abierto.
57 Error de E/S del dispositivo.
58 El archivo ya existe.
59 Longitud de registro incorrecta.
61 Disco lleno.
62 La entrada 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 al archivo.
76 No se encuentra la ruta de acceso.
91 Variable de objeto o de bloque With no establecida.
92 Bucle For no inicializado.
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
93 Cadena modelo no válida.
94 Uso no válido de Nul.
95 Error definido por el usuario.
323 Imposible cargar el módulo; formato no válido.
423 No se encuentra la propiedad ni el método.
424 Se requiere un objeto.
430 Esta clase no admite automatización o no admite la interfaz esperada.
438 El objeto no acepta este método o propiedad.
440 Error de automatización.
445 El objeto no acepta esta acción.
446 El objeto no acepta argumentos con nombre.
447 El objeto no acepta la configuración regional actual.
448 Argumento con nombre no encontrado.
449 Argumento no opcional.
450 El número de argumentos es erróneo o la asignación de propiedad no era válida.
451 El procedimiento Let de la propiedad no está definido y el procedimiento Get no ha devuelto un objeto.
452 El ordinal no es válido.
453 No se encuentra la función de biblioteca DLL especificada.
454 No se encuentra el recurso del código.
455 Error al bloquear el recurso de código.
1000 Nombreclase no posee la propiedad nombrepropiedad.
1001 Nombreclase no posee el método nombremétodo.
1002 Falta el argumento nombreargumento.
1003 El número de argumentos no es válido.
1004 El método Nombremétodo de la clase nombreclase ha fracasado.
1005 Imposible definir la propiedad nombrepropiedad de la clase nombreclase.
1006 Imposible leer la propiedad nombrepropiedad de la clase nombreclase.
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Lista de caracteres no imprimibles
Código en base Significado
0 Carácter nulo
1 Inicio de encabezamiento
2 Inicio de texto
3 Fin de texto
4 Fin de transmisión
5 Consulta, fin de línea
6 Acuse de recibo
7 Timbre
8 Retroceso
9 Tabulación horizontal
10 Salto de línea
11 Tabulación vertical
12 Salto de página
13 Retorno de carro
14 Mayúsculas fuera
15 En mayúsculas
16 Enlace de datos / escape
17 Dispositivo de control 1 DC1
18 Dispositivo de control 2 DC2
19 Dispositivo de control 3 DC3
20 Dispositivo de control 4 DC4
21 Acuse de recibo negativo
22 Síncrono en espera
23 Fin de transmisión del bloque
24 Cancelar
25 Finalización del medio
26 Sustituto
27 Escape
28 Separador de archivo
29 Separador de grupo
30 Separador de registro
31 Separador de unidad
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-