Está en la página 1de 351

Macros y lenguaje VBA

Aprender a programar con Excel (3ª edición)

Capítulo 1: Introducción

A. Introducción 14

B. ¿A quién va dirigido este libro? 14

C. ¿Qué es una macro? 14

D. ¿Qué interés tiene hacer macros? 15

E. Contenido del libro 15

Capítulo 2: El editor de Visual Basic

A. Introducción 18

B. ¿Cómo iniciar Visual Basic Editor? 18


1. Versión Excel 2003 (o anterior) 18
2. Versión Excel 2007 (o posterior) 19

C. La interfaz 20
1. Los módulos 21
2. Los cuadros de diálogo personalizados 23
3. Las barras de herramientas 25

Capítulo 3: La programación en Visual Basic

A. Introducción 28

B. ¿Qué es un objeto? 28

www.ediciones-eni.com © Ediciones ENI 1/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

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

E. Codificación de las celdas y de los rangos de celdas 31


1. La celda 31
2. El rango de celdas 32
3. Las celdas nombradas 32

F. Significado del signo = 33

G. Los procedimientos 34

H. Las funciones 34

Capítulo 4: Primer programa

A. Introducción 38

B. La Grabadora de macros 38

1. Versión Excel 2003 (o anterior) 38


2. Versión Excel 2007 (o posterior) 39

C. Primer ejercicio 41

D. Examen del código 45

www.ediciones-eni.com © Ediciones ENI 2/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

E. Ejecución del código 46

F. Otras técnicas para mejorar el código 47


1. Grabar acciones con dos hojas de cálculo 47
2. La instrucción Select 48
3. La instrucción Copy 48
4. Transferencia de datos 49
5. El bloque de datos With ... End With 49
6. El código optimizado 50

G. Síntesis 51

Capítulo 5: Las variables

A. Introducción 54

B. ¿Qué es una variable? 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

D. Declaración de una variable 58


1. ¿Declaración obligatoria o no? 58
2. Comprobación de las declaraciones 59
3. Tipo de variable 60 a.
Declaración de texto 60 b.
Declaración de números 61 c.
Declaración fechas 62 d.
Declaración de objetos 63 e.
Declaración booleana 63

www.ediciones-eni.com © Ediciones ENI 3/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

f. Declaración en Variant, declaración cajón de sastre 64


4. Alcance de las variables 64
a. La instrucción Dim 64
b. La instrucción Static 65
c. La instrucción Public 66

E. Caso práctico de utilización de una variable 66

F. El método InputBox 68

G. Las tablas en memoria 69

1. Presentación 69
2. Las ventajas de trabajar con tablas 70

Capítulo 6: Las condiciones

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

C. La instrucción SELECT CASE 77

1. Presentación 77
2. Ejemplo de utilización 78
a. Test a un solo valor 78
b. Test en varios valores no contiguos 78
c. Test en valores contiguos 79
3. Reversibilidad 79

www.ediciones-eni.com © Ediciones ENI 4/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

D. ¿IF o SELECT CASE? 81

E. Ejemplo de uso de dos instrucciones 81


1. Crear un test en función de los parámetros 81
2. Crear los parámetros 82
3. Crear un test en el programa 83
4. Programa completo 85

Capítulo 7: Los bucles

A. Introducción 88

B. La instrucción For ... Next 88

1. Etapas de un bucle For ... Next 88


2. Primer ejemplo de bucle 89
3. Explicación del código 89
4. Ejemplo de bucle con dos variables 90
a. Etapa nº 1 90
b. Etapa nº 2 91
c. Etapa nº 3 91
d. Síntesis 91

C. Bucle según condición 92

1. While ... Wend 92


a. Principio 92
b. Ejemplo de aplicación 92
c. Obligación 93
2. Ejemplo de código 93
3. Do ... Loop 97
a. Presentación 97
b. Ejemplo de aplicación 97
c. Explicación del código 99

www.ediciones-eni.com © Ediciones ENI 5/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

d. Mejora del código 99 e.


Trabajar con dos hojas 101

D. Bucle en objetos Excel 102


1. Presentación 102
2. Explicación del código 102

Capítulo 8: Depuración

A. Presentación 106

B. Buenas prácticas 107

C. Lectura "Paso a paso" 108


1. La tecla 8 108
2. La combinación de teclas m 8 109

D. Inspeccionar las variables 110

E. La ventana Inspecciones 112

F. La ventana de variables locales 113

G. El punto de interrupción 115

H. La instrucción Debug.Print 117

I. Interrupción según condición 118

J. Intervenir durante la ejecución del código 120


1. Vuelta atrás 120
2. Cambiar manualmente el valor de las variables 121

www.ediciones-eni.com © Ediciones ENI 6/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

K. Ejemplo de aplicación de la depuradora 123


1. Resolución del primer error 124
2. Resolución del segundo error 126

Capítulo 9: Estructura de un programa

A. Dividir un programa en varios procedimientos 130


1. Código inicial 130
2. División del código 131
3. La instrucción Call 132
4. El interés de dividir en varios procedimientos 133

B. Alcance de las variables 133

1. Vuelta a la declaración de las variables 134


a. Dim dentro de un procedimiento 134
b. Dim al principio del Módulo 134
c. Declaración en Public 136
2. Dim o Public 137

C. Parámetros de llamada 137

1. Principio de transmisión de variables locales 137


a. Respeto del tipo de variable 138
2. Ayuda en la escritura y en la navegación 139
a. Uso de las etiquetas informativas 139
b. Navegación simplificada 140
3. Flexibilidad de programación 141
a. Finalizar el programa 143
b. Procedimientos invisibles 144

D. Las llamadas a funciones 145

1. Crear una función personalizada con parámetros 145


2. Llamada a la función personalizada 146

www.ediciones-eni.com © Ediciones ENI 7/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

3. Afectar un tipo a la función personalizada 147


4. Transmitir un rango de celdas 147

E. Ejemplo de aplicación 148


1. Etapa 1: creación del código para la primera celda 149
2. Etapa 2: extracción del cálculo de la suma en una función 149
3. Etapa 3: creación de la función Media 150
4. Etapa 4: creación del bucle para las filas y explicación del código 151
a. El código 151
b. Explicación del código 151
5. Etapa 5: creación del bucle para las columnas 152
6. Conclusión 153

F. Parámetros opcionales 154

Capítulo 10: Las funciones básicas

A. Los operadores 158

1. Los operadores aritméticos 158


2. Los operadores de comparación 159
3. Los operadores lógicos (o booleanos) 159
4. Simplificación de la escritura de los tests 160

B. Conversión de variable 161

1. Funciones de conversión 161


2. Probar una variable 161

C. Funciones matemáticas 162

1. Funciones usuales 162


2. Las funciones Excel 163

Capítulo 11: Administrar las listas de caracteres

www.ediciones-eni.com © Ediciones ENI 8/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

A. Introducción 166

B. Funciones básicas 166

1. El operador & 166


a. Utilización en un programa 166
b. Ejemplo de uso para cambiar el nombre a una hoja 166
c. Entrar en bucle con todos los nombres 167
2. Las tres instrucciones habituales 168
a. La instrucción Left 168
b. La instrucción Right 168
c. La instrucción Len 169
d. Ejemplo de uso de instrucciones de texto 169
e. Extracción de una parte de una celda 170
3. Sustitución 171
a. Función Mid 171
b. Función Replace 171
4. Posicionamiento de un carácter 172
a. La instrucción InStr 172
b. La instrucción InstrRev 173
5. Cortar una cadena 174
6. Supresión de los espacios 174
7. Mayúsculas y minúsculas 174
a. Todos los caracteres en mayúsculas 174
b. Todos los caracteres en minúsculas 174
c. Primera letra en mayúscula 175
8. Invertir las letras 175
9. Comparación de cadenas 176
a. Función StrComp 176
b. Función Like 176
10. Los caracteres ASCII 177
a. La instrucción Asc 177
b. La instrucción Chr 178

C. Leer un archivo de texto 178

www.ediciones-eni.com © Ediciones ENI 9/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

1. Abrir el archivo de texto 179


a. La ruta o el nombre del archivo 179
b. El tipo de acceso 179
c. Número de archivo 179
2. Leer una línea 180
3. La instrucción EOF 180
4. Cerrar un archivo 180

D. Crear un archivo de texto 181


1. Crear un archivo 181
2. Escribir una línea 181
3. Declarar variables 181
4. Ejemplo de aplicación 182
5. Ejercicios de aplicaciones 183
a. Nueva herramienta : Power Query 183
b. Ejercicio: Extraer los datos de un archivo de texto 184
c. Corte según un carácter de separación 190

Capítulo 12: Administración de las fechas y las horas

A. Introducción 198

B. Introducción a las fechas 198

1. Configurar las fechas 199


2. ¿Mi celda contiene una fecha? 200
3. Dar formato a una fecha 202

C. Las funciones básicas 203

D. Las funciones de extracción 204

1. Extracción de las fechas 204


2. Extracción de las horas 204

www.ediciones-eni.com © Ediciones ENI 10/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

E. La instrucción DateSerial 205


1. Convertir un número en fecha 205
2. Realizar operaciones con las fechas 206
3. Manipulación de las fechas 206
4. Meses en letras 207

F. Calcular la diferencia entre dos fechas 209

1. La función SIFECHA en Excel 209


2. La función DATEDIFF en VBA 210
3. Integración de la función SIFECHA de Excel en VBA 211

G. Funciones de semanas 211

1. ¿Qué día de la semana? 211


2. Número de días laborables en la semana 211
3. Número de semana 212
4. Días festivos 213

Capítulo 13: Trabajar en un libro Excel

A. Introducción 216

B. Manipulación de los libros 216

1. Diferencia entre Workbooks y ActiveWorkbook 216


2. Abrir un libro 217
3. Cerrar un libro 217
4. Guardar un libro 218
5. Guardar un libro con un nombre nuevo 218

C. Las propiedades de un libro 218

D. Interactuar con la aplicación Excel 220

www.ediciones-eni.com © Ediciones ENI 11/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

E. El objeto Application 221


1. ScreenUpdating 221
2. DisplayAlerts 221
3. StatusBar/DisplayStatusBar 222
4. Llamada a funciones de cálculo de Excel 223 a. Cómo
usar las funciones de cálculo de Excel 223 b. La función
Match 223 c. La función Index
224
5. Añadir un tiempo de latencia 225
6. El cuadro de diálogo Abrir 226
7. El cuadro de diálogo Guardar como 226
8. Suspender la comunicación con la impresora 227
9. Modo copiar-pegar suspendido 227
10. Llamada a una macro externa 227
11. Hacer que el ordenador hable 228

Capítulo 14: Trabajar con los archivos

A. Introducción 230

B. Operación con archivos 230


1. Copiar un archivo 230
2. Cambiar el nombre de un archivo 230
3. Mover un archivo 231
4. Eliminar un archivo 231
5. Recuperar la hora y la fecha de un archivo 232
6. Averiguar el tamaño de un archivo 232
7. Encontrar un archivo en un directorio 233

C. Operaciones con los directorios 234


1. Definir un directorio de trabajo 234
2. Crear un directorio 235
3. Eliminar un directorio 235

www.ediciones-eni.com © Ediciones ENI 12/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

4. Test para saber si un directorio existe 235

D. "Barrer" un directorio 236


1. Bucles con los archivos 236
2. Bucles con los directorios 236
3. Barrer todos los subdirectorios 238

E. Recuperar los datos sin abrir un libro 240

F. Seleccionar un directorioI 241

G. Seleccionar un archivo 242

Capítulo 15: Optimización

A. Introducción 244

B. Instrucciones de búsqueda 244


1. El método FIND 244
2. Resultado de una búsqueda 245
3. Búsqueda del elemento siguiente 246
4. Opciones de búsqueda 247
5. Encontrar el número de la fila 248

C. Las tablas en memoria 249


1. Utilidad de trabajar con tablas en memoria 249
2. Tablas de una o dos dimensiones 249 a. Tabla
de una dimensión 249 b. Tabla de dos
dimensiones 251
3. Insertar datos en una tabla en memoria 252
4. Borrar una tabla 255
5. Cambiar el tamaño de una tabla 256
6. Tamaño de una tabla 257

www.ediciones-eni.com © Ediciones ENI 13/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

7. Buscar en una tabla 258 a.


Transferir el contenido de una tabla a un rango de datos 260

D. Las celdas con nombre y las tablas 261


1. Presentación 261
2. Función dentro de un programa 262
3. Coordenadas de las celdas con nombre 263
4. Uso de las tablas 264
a. El objeto ListObject 264
b. Propiedades específicas de las tablas 265
c. Problemas vinculados con la tabla 266

E. Una API para los milisegundos 268

F. El entorno de 64 bits 269


1. La instrucción PtrSafe 269
2. Las variables de 64 bits 269
3. Coexistencia de plataformas de 32 bits/64 bits 270

Capítulo 16: Llamada de aplicaciones externas

A. Introducción 272

B. Eliminar las dll que faltan 272

C. La instrucción CreateObject 274

D. Envío de e-mails Outlook 275

1. Programa para enviar un correo electrónico 275


2. Explicación del código 276
3. Bucles en sus contactos recogidos en una columna 276

www.ediciones-eni.com © Ediciones ENI 14/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

E. Creación de un archivo PDF 277


1. Función para la generación de un archivo PDF 277
2. Exportar un libro entero 278
3. Exportar una hoja de cálculo en PDF 279

F. Conectar con una base de datos Access 280


1. Presentación 280
2. Puesta en marcha 281
3. Insertar nuevos registros en Access 283
4. Actualizar una base Access desde Excel 285

Capítulo 17: Iniciar un programa de varias maneras

A. Repaso del inicio por Visual Basic Editor 288

B. Combinación de teclas A 8 288

C. Inicio mediante un botón u otro objeto 289


1. Los botones 289
2. Los botones de opción (o botones radio) 291
3. Los menús desplegables 294
4. Ubicación de los objetos 298

D. Procedimiento Auto_Open/Auto_Close 300

E. Evento en una hoja de cálculo 301


1. Principio de los eventos 301
2. Lista de eventos 301
3. El evento Change 303
4. El parámetro Target 303
5. Controlar la selección 304
6. El evento SelectionChange 304

www.ediciones-eni.com © Ediciones ENI 15/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

7. El evento doble clic 305

Capítulo 18: Los cuadros de diálogo personalizados

A. Introducción 308

B. Crear un cuadro de diálogo 308


1. Insertar un nuevo UserForm 308
2. Escribir un código en un UserForm 310
3. Hacer referencia a un UserForm 311

C. Los eventos 312

D. Los controles 313

E. Ubicación de los controles 314

F. Orden de tabulación 319

Capítulo 19: Los controles

A. Introducción 322

B. Las etiquetas (Labels o títulos) 322

C. Los cuadros de texto (o TextBox) 324

D. Los botones (o CommandButton) 325


1. Agregar un botón 326
2. El botón Cancelar 326
3. El botón Aceptar 326

www.ediciones-eni.com © Ediciones ENI 16/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

E. Las casillas de verificación (CheckBox) 327

F. Los botones de opción (OptionButton o botones radio) 329

G. Los cuadros de lista (o ListBox) 331


1. Presentación 331
2. Manipular los datos de la lista 332
3. Alimentar una lista en el programa 335

H. Los cuadros combinados (ComboBox o menús desplegables) 337

I. Síntesis 339

Capítulo 20: Gestión de errores

A. Introducción 342

B. Las instrucciones para la gestión de errores 342

1. On Error 342
2. La instrucción Resume 342
3. La instrucción Resume Next 342
4. La instrucción Err 343
5. GoTo 343
6. GoTo 0 343

C. Redirección de errores 343

1. Ejemplo 1 343
2. Ejemplo 2 346
3. Ejemplo 3 346

Anexos

www.ediciones-eni.com © Ediciones ENI 17/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)

A. Tipos de variables 350

B. Colección de objetos 351

C. Lista de constantes 352

D. Lista de códigos de error transmitidos por Visual Basic 355

E. Lista de caracteres no imprimibles 357

índice 359

Lista de instrucciones, operadores y funciones 367

www.ediciones-eni.com © Ediciones ENI 18/18


Macros y lenguaje VBA
Aprender a programar con Excel (3ª edición)
El objetivo de este libro es enseñarle, mediante una serie de ejercicios prácticos, cómo diseñar macros, nombre que se le da a
los programas realizados en un entorno de Microsoft® Office y que permiten reproducir automáticamente y de manera
infinita un conjunto de tareas realizadas con Excel. El presente manual está dirigido a usuarios sin nociones de programación,
pero también a programadores que deseen mejorar la ejecución de sus programas. A lo largo del libro, se detallan ejemplos
variados, etapa por etapa, con el fin de mostrar la lógica de la programación y los errores que se deben evitar.

Tras la descripción del entorno de trabajo utilizado para la creación de macros, descubrirá los conceptos básicos de la
programación con VBA a través de los objetos, de sus métodos y de sus propiedades; a continuación, realizará su primer
programa gracias a la Grabadora de macros y después abordaremos los elementos fundamentales de la programación
VBA que son las variables, las condiciones y los bucles, antes de aprender a «depurar» su programa para corregir los
errores de programación.

La siguiente parte aborda la noción de programación modular y presenta, a través de ejemplos concretos, las
principales funciones que puede insertar en un programa como la gestión de cadenas de caracteres, la gestión de fechas y
horas, las manipulaciones en los libros Excel y sus propiedades; también verá cómo recuperar y trabajar desde un
programa VBA con todos los tipos de archivos que tenga en los directorios de su ordenador.

Los desarrolladores más aguerridos podrán aprender a optimizar su programa, trabajar con tablas en la memoria, celdas
con nombre y también con aplicaciones externas (envío de mails, creación de archivos pdf, conexión a bases Access). Por
último, aprenderá a crear cuadros de diálogo personalizados, insertar controles (etiqueta, zona de texto, botón, etc.) y poder
desarrollar así aplicaciones profesionales y elaboradas.

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] ).

Al inicio, la zona de trabajo está siempre vacía, pero vamos a añadir módulos o cuadros de diálogo (traducido por
Userform) para empezar a crear un programa.

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-
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:


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.

Para ordenar cada elemento (Hoja de cálculo, Módulo y Userform) en subdirectorios, basta con activar el icono
Alternar carpetas del Explorador de proyectos.

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 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.
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.
¿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.


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:

Objet.oMétodo

Objet.oPropiedad

Por ejemplo, podemos escribir:

Sheets("Hoja1").Delete ’Supresión(Método) de la hoja 1(Objeto)

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) = _
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.

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.
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:

Cells(número de fila, número de columna)

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 referencia s 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 destacar ,
5)).Select 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.
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.
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 .

For, Next,
Para nombrar un procedimiento, se admiten todos los términos salvo las palabras reservadas (como
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 prohibido s 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.
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).

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.
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.
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.
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 botón Detener grabación que aparece en una barra de
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.
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):
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.
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.
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
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
End Sub

Encontrará ese código en el archivo del Ejemplo 4B2.

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

With/End With. Un bloque de datos


A continuación, visualizará el conjunto de datos reunidos en un bloque
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
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.

Otras técnicas para mejorar el código


Cuando use l a 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

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")S.elect
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.
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

Por muy curioso que parezca, la Grabadora de macros optimiza el código usando un bloque de datos With ... End
With. El principio de esta instrucción es aplicar varias propiedades o métodos a un mismo objeto (celda, hoja
de cálculo, etc.).

Todos los formatos dados a una celda se escriben en un bloque With ... End With. Para ganar una línea de
código, también aquí es posible remplazar el término Selection por la referencia de la celda a la que desea
aplicarse el formato:

WithSheets("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

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.

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ámetro s 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).

Introducción
Como v i m o s 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").S
elect
Range("C8").Selec
t
Columns("D").Sel
ect

Este tipo de escritura del código tiende a desaparece r 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.
¿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

Inicie la ejecución del programa pulsando la tecla [F5] o haciendo clic en el icono . El resultado de 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.

MsgBox "Mi_Variable" ’Muestra solo Mi_Variable como mensaje.

Mientras que la siguiente instrucción mostrará el valor de la variable en el cuadro de diálogo.

MsgBox " Mi_Variable tiene como valor " & Mi_Variable

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:

MsgBox Mensaje, Botón, Título

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:

MsgBox "Constante vbCritical", vbCritical, "Alerta urgente !!!!!!"

Obtendremos este mensaje:

Si selecciona la constante vbYesNo, el cuadro de diálogo mostrará los botones Sí y No, pero el texto de la línea

- 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.

Dim Mi_Variable As Date


Mi_Variable = "1 / 1 / 2017"
MsgBox "Valor de la variable: " & Mi_Variable’Vista
Mi_Variable = "10:55:48"
MsgBox "Valor de la variable: " & Mi_Variable’Vista
Mi_Variable = "01/01/2017 10:55:48"
MsgBox "Valor de la variable: " & Mi_Variable’Vista
Mi_Variable = 100
MsgBox "Valor de la variable: " & Mi_Variable’

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).

Dim Mi_Variable As Boolean


Mi_Variable = 0 ’El programa continúa
Mi_Variable = 1 ’El programa continúa
Mi_Variable = 2 ’El programa continúa con el valor
Verdadero (cifra par)

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

Existen tres formas de declarar una variable, Dim, Static o Public. Según el tipo de declaración, la variable no
será "visible" por todo el programa.

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

STATIC Nombre_de_la_variable AS Tipo de


variable

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

En el primer paso, el valor es Núm_Fila = 0; la instrucción Núm_Fila = Núm_Fila +1 cambiará el valor de la


variable a 1. Por lo tanto, en la celda A1 el programa mostrará 1.

En el segundo paso, Núm_Fila sigue valiendo 1. Entonces, la instrucción Núm_Fila = Núm_Fila +1 colocará el valor de
la variable a 2, y por lo tanto en B1 el valor mostrado será 2. Y así sucesivamente al realizar las diferentes acciones de
este programa.

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ódul o y, sobre todo, no hacerlo en procedimientos
en modo Public de la siguiente forma:

PUBLIC Nombre_de_la_variable AS Tipo de variable

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) =+ 11
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) V=al_Data
Cells(1, 2) V=al_Data + Val_Data
Cells(1, 3) V=al_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
CellVsa(l_Data, 1) = Val_Data
CellVsa(l_Data, 2) = Val_Data + Val_Data
CellVsa(l_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.

Num_Fila = InputBox("¿Qué valor damos a la fila?")

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:

Sub Cálculo() Dim Val_Data AsVariant


Val_Data = InputBox("¿Qué valor le damos a la fila ?")
Cells(Val_Data, 1) = Val_Data
Cells(Val_Data, 2) = Val_Data + Val_Data
Cells(Val_Data, 3) = Val_Data * Val_Data End Sub

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 siVerdadero]
[ELSE]

[Instrucciones siFalso]
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).

"Si el test es verdadero entonces .... 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.

If Mi_Variable = True Then

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 línea Cells(2, 2) = Cells(2, 2) + 3 debe retrasarse ya que la celda B2 se presenta dos veces para 2
utilizaciones diferentes .

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 CellsN(úm_Fila , 3) = 1 Then
CellNsú(m_Fila , 2) = Cells(Núm_Fila , 2) + 3
Else

CellNsú(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:

If Cells(2, 3) = 1 Then Cells(2, 3) = Cells(2, 3) + 3

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
IF con Else también puede escribirse en una sola línea. En ese caso, hay que utilizar la instrucción
Una instrucción
lif que respeta la misma sintaxis que la función SI en Excel:

Iif(Test, Verdadero, Falso)

Cells(2, 3) = Iif( Cells(2, 3) = 1, Cells(2, 3) + 3, Cells(2, 3) + 1)

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

SELECT CASE Expresión


CaVsael
or1
Instrucción
CaseValor2
Instrucción
CaseValor...
Instrucción
Case Else
Instrucción
End Select

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 Casetambié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 T0o 4.99
Cells(1, 2) = "No aprobado"
Case T5o 5.99
Cells(1, 2) = "Aprobado"
Case T6o 6.99
Cells(1, 2) = "Aprobado. Bien"
Case T7o 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 Casepermite 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 Casepara 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
Es”tIamdposCiibvliel” =
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 Casedesapareció 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 Caseno 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.

’Carga de los parámetros en la hoja


Val_Columna = Cells(2, 8)
Val_Sign = Cells(2, 9)
Val_Filter = Cells(2, 10)

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:

’Conversión de la letra de la columna en número


Num_Columna = Columns(Val_Columna & ":" & Val_ Columna).Column

A continuación, debemos escribir todos los casos posibles con ayuda de la función SELECT CASE.

Select Case Val_Sign


Case "<"
Test1 = Cells(Num_Fila, Num_Columna) < Val_Filter
Case "<="
Test1 = Cells(Num_ Fila, Num_Columna) <= Val_Filter
Case "="
Test1 = Cells(Num_ Fila, Num_Columna) = Val_Filter
Case ">="
Test1 = Cells(Num_ Fila, Num_Columna) >= Val_Filter
Case ">"
Test1 = Cells(Num_ Fila, Num_Columna) > Val_Filter
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:

Columna Signo Valor

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

FOR Índice= Principio TO Fin [STEP paso]


[Instrucciones]
NEXT[Índice]

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

For Index = 1, la variable Index valdrá


Al principio, la variable Index se inicia con el valor indicado. Si escribimos
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
ForVal_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
NextVal_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
ForNúm_Fila = 1 To 15
CellNsú(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
ForNúm_Col = 1 To 15
For Núm_Fila = 1 To 15
Cells(Núm_FilNaú,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

1. While ... Wend

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 tes t (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 variabl e 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 + ’1Incremento
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.

Sub Fusión celdas()


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 similitud de un nombre de cliente
While Cells(Fila_Fin, 1) = Cells(Fila_Fin + 1, 1)
Fila_Fin = Fila_Fin + 1
Wend

’ Fusión sobre el rango de datos seleccionado


WitRhange(Cells(Núm_Fila, 1), Cells(Fila_Fin, 1))
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlCenter
.MergeCells = True
End With
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

DO {while | Until} condición


Instrucción
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_Fil-a 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 bucl e 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).

A continuación, construimos nuestro segundo bucle (instrucción DO ... LOOP) que se parará cuando ya no haya
igualdad en el valor de la fecha entre dos filas. Cuando haya una igualdad, escribiremos el resultado en una misma fila.
Solo la variable que corresponde al número de columna se incrementará.

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_Fil-a 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_Fil-a 1, 1) = Cells(Núm_Fila,
1) Cells(Fil_Escritura, 4) = Cells(Núm_Fil-a 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
WhileSheets("Hoja1").Cells(Núm_Fila, 1) <>
"" Col_Escritura = 2
Do
Sheets("Hoja2").Cells(Fil_Escritura, Col_Escritura) =
Sheets(."CHeoljlas1("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("Ho.jCae2l"l)s(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

FOR EACH variable IN Colección de Objetos


Instrucción
NEXT

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étod o 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 EacOhbjeto_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.

Es interesante puntualizar la diferencia entre WorkSheet y WorkSheets. El primer término (sin la s) corresponde al Objeto
Hoja, mientras que WorkSheets (con una s) corresponde a la Colección de Objeto s worksheets (el
conjunto de hojas de un libro). Esto es aplicable para todos los Objetos/Colecciones de Objetos (Row/Rows;
Column/Columns; etc.) que utilice.

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 hoj a 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

’ Vuelta al sumario de cada hoja


Sheets(Mi Hoja.Name).Hyperlinks.Add _
Anchor:=Sheets(Mi hoja.Name).Cells(1, 4), Address:="", _
SubAddress:=" Sumario!A1", TextToDisplay:="Vuelta"
Num_Fila = Num_Fila + 1
End If
Next End Sub
- 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 voluntariament e 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_Fil-a 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 variable s 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

No le habrá pasado desapercibido que el ejemplo precedente contiene un bucle While ... Wend, mientras que el primer
ejemplo de este capítulo producía el mismo resultado, pero con la instrucción For ... Next.

De hecho, si hubiera querido ilustrar la vuelta atrás con un bucle For ... Next, el programa no habría iniciado la variable
situando la línea de ejecución (la línea amarilla) en la instrucción For. Es el principio mismo de los bucles For ... Next;
la variable se inicia justo entrando en ese bucle. En los demás pasos, el For ... Nextno hace
más que comprobar si se alcanza o no el límite. Por lo tanto, volviendo a situar la instrucción de mi programa en la instrucción
For ... Next, habré proseguido con el mismo valor para Núm_Fila.

Ahora bien, habría podido volver desde el principio de mi bucle For ... Next cambiando yo mismo el valor de la variable.
Para ello, es preciso:

© É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 principa l (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.

De este modo, la variable Col_Escrit se inicializará a 5 antes de cada nuevo bucle Do ... Loop.

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_Fil-a 1, 1) = Cells(Núm_Fila, 1)
Cells(Fil_Escrit, 4) = CellNsú(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:

Sub Abrir_Archivo (Ruta_Acceso As String)


Workbooks.Open Filename:=Ruta_Acceso & "Cliente.xlsx"
End Sub

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_ArchivoR(ep_Trabajo)
Call Seleccionar_Datos
End Sub

Sub Abrir_Archivo (Ruta_Acceso As String)


Workbooks.Open Filename:R=uta_Acceso & "Cliente.xlsx"
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

Sub Abrir_Archivo (Ruta_Acceso As String)


Workbooks.Open Filename:= Ruta_Acceso & "Cliente.xlsx"
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

Sub Abrir_Archivo(Ruta_Acceso As String)


Workbooks.Open Filename:=Ruta_Acceso & "Cliente.xlsx" 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

Sub Abrir_Archivo(Ruta_Acceso As String)


Workbooks.Open Filename:=Ruta_Acceso & "Cliente.xlsx" End
Sub

Sub Seleccionar_Datos(Letra_Selección As String)


RangeL(etra_Selección & "1").Select
Selection.CurrentRegion.Select
ActiveWorkbook.Worksheets("Hoja1").Sort.SortFields.Clear
ActiveWorkbook.Worksheets("Hoja1").Sort.SortFields.Add _
Key:=Range(Letra_Selección & "2:" & Letra_Selección & "201") _
, SortOn:=xlSortOnValues, Order:=xlAscending, _
DataOption:=xlSortNormal
With ActiveWorkbook.Worksheets("Hoja1").Sort
.SetRange Range("A1:J201")
.Header = xlYes
.MatchCase = False
.Orientation = xlTopToBottom
.SortMethod = xlPinYin
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
.Apply
End With
End Sub

En el procedimiento principal, hemos recuperado la columna de selección (variable Columna_Letra) antes de proceder a
abrir el archivo Cliente.xlsx.

¿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.

A modo de ejercicio, posicione la línea de comando Columna_Letra = Cells(1, 1)después de la llamada a abrir el
archivo. Verá que el programa genera un error de ejecución cuando se efectúa la selección del rango de
datos.

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.

Function Fahrenheit(Valor_Grados As Double)


Fahrenheit = Valor_Grados * 9 / 5 + 32
End Function

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) F=ahrenheit(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:

Function Fahrenheit(Valor_Grados As Double) As Double


Fahrenheit = Valor_Grados * 9 / 5 + 32
End Function

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

Function Mi_Suma (Tab_Cell As Object)


Dim Indice_Tab As Long
For Indice_Tab = 1 To UBound(Tab_Cell.Value)
Mi_Suma = Mi_Suma + Tab_Cell(Indice_Tab)
Next
End Function

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

Function La_Suma) Tab_Valor As Integer Variant) As Double

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Dim indice_Tab As Long
For indice_Tab = 1 ToUbound(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

Function La_Suma(Tab_Valor As Variant) as Double


Dim indice_Tab As Long
For indice Tab = 1 To Ubound(Tab Valor)
La suma=La_Suma = + Tab_Valor(indice_Tab)
Next
End Function

Function La_Media(Tab_Valor As Variant) As Double


La_Media = La_Suma Ta(b_Valor)/Ubound(Tab_Valor.Value)
End Function

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 bucleWhile 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úmF-ilEncabCol +
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.

esto, vamos a usar la función Range y usaremos como parámetro las coordenadas de la primera celda
Para escribir
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 ... NEXTya 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
ForNúmCol = 4 To 6
NúmFil = 2
EncabCol = Cells(1N,úmCol) ’Valor de los encabezados
While Cells(NúmFil, 1) <> ""
If NúmFil > EncabCol Then
Cells(NúmNFúimlC,ol) = _
La_Media(Range(Cells(Nú-mFEinlcabCol + 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ú-mFEinlcabCol + 1, 3),_
Cells(NúmFil, 3)))
End If
NúmFil = NúmFil + 1
Wend
Next
End Sub

Function La_Suma(Tab_Valor As Variant) As Double


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

- 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

Function Precio_SinIVA_ ConIVA (Precio _U As Double, Ctd As Long)


Precio_ SinIVA _ ConIVA = Precio _U * Ctd
End Function

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

Function Precio_SinIVA_ConIVA(Precio_U As Double, Ctd As Long, Optional


País As String,
Optional TVA As Double)
If País <> "" Then
If País = "ES" Then
Precio_SinIVA_ConIVA = (Precio_U * Ctd) * (1 + IVA)
Else

Precio_SinIVA_ConIVA-=" "
End If
Else
Precio_SinIVA_ConIVA = Precio_U * Ctd
End If
End Function

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 resultad o 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:

If Cells(1, 1) Mod 2 = 0 Then


Msgbox "Es un número par"
Else
Msgbox "Es un número impar"
End If

Para realizar un test a una celda para saber si su valor es un múltiplo de 12, puede escribir el siguiente código:

If Cells(1, 1) Mod 12 = 0 Then


© É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).

l El operador Eqv es la inversa de Xor: Eqv devuelve True si las dos expresiones son idénticas y devuelve False si las dos
expresiones son diferentes.

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:

If Mi_Variable1 = True And Mi_Variable2 = True


Then

If (Mi_Variable1 And Mi_Variable2) = True


Then

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:

If (Cell(1, 2) = "Viudo" Or Cells(1, 2) =


"Soltero") And Cells(1, 1) = "Mujer" Then

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:

If Variable1 Then ’ Esta condición prueba que la variable es


’ verdadera o igual a 1

© É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 textuale s (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:

’ Las dos escrituras son equivalentes


If IsNumeric(Cells(1,1)) Then ...

If IsNumeric(Cells(1,1)) = True Then ...

© É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:

Sheets("Hoja2").Name = Sheets("Hoja1").Cells(Núm_Fila, 1) & " " &


Sheets("Hoja1").Cells(Núm_Fila, 2)

© É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:

Sheets("Hoja2").Name = Sheets("Hoja1").Cells(Núm_Fila, 1) & "-"


&
Sheets("Hoja1").Cells(Núm_Fila, 2)

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:=SheetSsh(eets.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:

Nombre_Archivo = Variable & ".xlsx" ’Interpretada por el VBA sin error


Nombre_Archivo = Variable&".xlsx" ’el VBA no comprende la instrucción
(sin espacio)

- 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) M=id(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

Replace(Texto, Carácter a reemplazar, Carácter de reemplazo)

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
":

Cells(1, 1) =Replace(Cells(1, 1), "a",


"i")

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:

Resultado = InStr(Valor_Test, "e")’el resultado es 14


Resultado = InStr(Valor_Test, "de"’)el resultado es 13

Valor de partida conocido


Resultado = InStr(1, Valor_Test, "as"’)el resultado es 26
Resultado = InStr(1, Valor_Test, "un"’)el resultado es 0 la cadena y no existe
Resultado = InStr(15, Valor_Test, "mo"’)el resultado es 0 porque
la búsqueda empieza en la posición 15
Resultado = InStr(Valor_Test, ":"’)el resultado es 29

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.

InstrRev(Cadena de búsqueda, Texto buscado, [opcional: posición de partida)

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

’ Código para recuperar el nombre del último directorio


’ Solo conservamos la parte situada a la derecha del último "\"
Último_Dir = Right(Ruta, Len(Ruta) - InstrRev(Ruta, "\"))

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

StrConv(Texto, tipo de conversión)

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:

Comparación = StrComp(Texto_1, Texto_2, vbTextCompare)


El resultado es 0
Comparación = StrComp(Texto_2, Texto_1)
El resultado es 1

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.

If Texto_1 Like Texto_2 Then ...

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:

If Mi_Texto Like "*@*.*" Then


MsgBox "Es una dirección de correo electrónico"
End If

Para comprobar que tiene una dirección de correo electrónico que termina por .es, puede escribir:

If Mi_Texto Like "*@*.es*" Then


MsgBox "Es una dirección de correo electrónico que termina por .es"
End If

Para comprobar que tiene un número de teléfono móvil, puede escribir:

If Mi_Texto Like "6[0-9]######" Then


MsgBox "teléfono móvil"
End If

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.

Valor_ASCII = Asc("A")") =>


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:

Inicio_Col_En_Cifra = Asc(Valor dado por el usuario) - 64

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:

MsgBox "Fila_1" & Chr (13) & "Fila_2"

- 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.

If Left(Mi_Cadena, 1) = Chr (34)


Then

© É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

Open Archivo For Acceso As #Número de archivo

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.

Open "C:\Mis Documentos\Ejemplo 11-D5.txt" For ...



’ o

Ruta = " C:\Mis Documentos\"
Open Ruta& "Ejemplo 11-D5.txt" For ...

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 absolutament e 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:

Open Ruta & "Ejemplo 11-D5.txt" For Input As #1

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
2. Leer una línea

Line Input #Número de archivo, Variable

Para recuperar una línea del archivo, hay que utilizar la instrucción Line Input sin olvidar precisar el número de archivo
(recuerde no omitir el signo #).

La línea leída se transmitirá a la variable que figura tras la coma, aquí la variable Cadena_Leída.

Line Input #1, 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

Close #Número de atribución

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

Open Archivo For Output As Número de 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

Print# Número de archivo, Variable

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.

Dim Variable As String * longitud

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

Ruta = "C:\Su_Ruta "


Open Ruta & "\ Archivo_Salida.txt" For Output As #1
i_Fil = 2
While Cells(i_Fil, 1) <> ""
CP = Cells(i_ Fil, 1)
Ciudad = Cells(i_ Fil, 2)
Ref = Cells(i_ Fil, 3)
Apell = Cells(i_ Fil, 4)
Nombre = Cells(i_ Fil, 5)
Archivo = CP & Ciudad & Ref & Apell & Nombre
Print #1, Archivo
i_ Fil = i_ Fil + 1
Wend
Close #1
End Sub

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 disponible con Excel 2016 en la pestaña Datos y con Excel 2013, en forma de
módulo complementario (addin) que puede descargarse de forma gratuita en esta dirección:
https://www.microsoft.com/eses/download/details.aspx?id=39379

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

Open "C:\Users\Mis documentos \Ejemplo 11-D5.txt" For Input As #1

While Not EOF(1)


Line Input #1, Cadena_Leída

’ Call Instruction que corta la línea leída en el archivo


’ La línea leída se pasa como parámetro del procedimiento
Call Separación_Columna(Cadena_Leída)
Wend

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:

Sub Separación_Columna (Texto A Tratar As String)


Dim Última_Fil As Long

Ú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

ReDim t_col(0) ’Inicialización de la tabla


t_col(0) = 1 ’Primer valor de la tabla obligatoriamente 1
’porque la primera columna empieza necesariamente
’en posición 1
i_tab = 1

’Esta instrucción será reemplazada en el código definitivo por un parámetro entrante


Línea_A_Tratar = "Número_id Lengua_id dm_etiqueta dm_orden"

For i_car = 1 To Len(Línea_A_Tratar)’Bucle hasta el final de la línea


If Mid(Línea_A_Tratar, i_car, 1) = " " The’nSi se ha llegado a un espacio

’ Cuando detectamos un espacio, leemos el carácter siguiente


’ Este bucle permite llegar hasta el siguiente carácter que no sea un espacio
While Mid(Línea_A_Tratar, i_car, 1) = "
" i_car = i_car + 1
Wend

’ Al salir de un bucle, nos posicionamos en la siguiente columna


ReDim Preserve t_col(i_tab’)Redimensionado de la tabla
’ conservando los datos
t_col(i_tab) = i_car ’ Guardado del valor del clonado
’ en la tabla
i_tab = i_tab + 1
End If
Next

ReDim Preserve t_col(i_tab)


t_col(i_tab) = i_car
End Sub

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

’ La instrucción Rows.Count permite devolver el máximo número de filas


’ de la hoja de cálculo
Última Fila = Cells(Rows.Count, 1).End(xlUp).Row
’Test para gestionar el primer archivo (no hay fila vacía)
Última Fila e = IIf(Cells(1, 1) = "", 1, Última Fila + 1)
i_tab = 0
Do
’Transferencia de los valores del archivo de texto en cada columna
ActiveSheet.Cells(Última Fila, i_tab + 1) = _
Trim(Mid(Texto, t_col(i_tab), t_col(i_tab + -1)t_col(i_tab)))
i_tab = i_tab + 1
Loop While i_tab < UBound(t_col) ’ Bucle mientras no se alcance
’ el último índice de la tabla
End Sub

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.

Line Input #1, Cadena_Leída


Call Estructura_Archivo(Cadena_Leída)
Call Separación_Columna(Cadena_Leída)

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

Open "C:\Mis documentos\Ejemplo -1B15.txt" For Input As #1


Encabezamiento = True
While Not EOF (1)
Line Input #1, Cadena_Leída
If Encabezamiento Then
Call Estructura_Archivo(Cadena_Leída)
Encabezamiento = False
End If
Call Separación_Columna(Cadena_Leída)
Wend

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:

If InStr(Extract, "[Billar]") > 0


Then

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á:

Tabla_Extracción = Split(Extract, ",")

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

Ruta = "C:\Mis documentos\"

© É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, Ext’rLaeccttura primera fila del archivo

While Not EOF(1) ’Bucle en todo el archivo hasta el final


If InStr(Extract, "[Billar]") > 0
Then
Tabla_ExStprlaictc(iEóxntr
=act, ",")
Call Escritura_Excel(Tabla_Ext’rvaecrcimóáns)abajo
End If
Line Input #1, Extract’Lectura del archivo
Wend

Close #1 ’Cierre 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.

Sub Escritura_Excel(Tabla_Extracción As Variant)


Dim i_tab As Long
Dim Última_Fil As Long

Última_Fil = Cells(Rows.Count, 1).End(xlUp).Row


Última_Fil _ IIF(Cells(1, 1) = "", 1, Última_Fil + 1)
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_ExtracciSópnli=t(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), "")

’Inicio de los parámetros


i_tab = 1
Nombre_Ciudad = ""
Test_Fin_Bucle = False
Max_Dim_Tabla = Ubound(Tabla_Extracción)

’Dejamos de hacer el bucle cuando hayamos recuperado el nombre de la


ciudad.
While Test_Fin_Bucle = False

’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ín’ea", &4)
= " Trim(Tabla_Extracción(i_tab))
Else

’Test necesario para evitar que se cuelgue en caso de


rebasamiento de la tabla
If Max_Dim_Tabla = 2 Then
Cells(Núm_Fil, 5) = Ucase(Trim(Tabla_Extracción(i_tab)))
Test_Fin_Bucle = True
Else
Do
Nombre_Ciudad = Nombre_Ciudad & " " & _
Cstr(Trim(Tabla_Extracción(i_tab)))
’Concatenación ciudad
i_tab = i_tab + 1

’Los tests de fin de bucles son:


’ - carácter = (
’ - carácter = >
’ - carácter = "
’ - fin de tabla
Loop While Left(Trim(Tabla_Extracción(i_tab)), 1) <> "("
_ And Left(Trim(Tabla_Extracción(i_tab)), 1) <> ">"
_
And Right(Trim(Tabla_Extracción(i_tab)), 1) <> Chr(34) _
And i_tab < Max_Dim_Tabla
Cells(Núm_Fil, 5) = Ucase(Trim(Nombre_Ciudad))
Test_Fin_Bucle = True
End If
End If
i_tab = i_t’aIbnc+re1mento de la tabla
Wend
Núm_Fil = Núm_Fil’I+nc1remento de la fila de escritura
Wend
End Sub

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:

FORMAT(Valor numérico, Argumento del formato)

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.

Formato(Cells(1, 1), "d mmm yy")

- 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:

El_Año = Left(Cells(1, 1), 4)


El_Mes = Mid(Cells(1, 1), 5, 2)
El_Día = Right(Cells(1, 1), 2)
Cells(1, 2) = DateSerial(El_Año, El_Mes, El_Día)

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:

DateSerial(Year(Cells(1, 1)), Month(Cells(1,1)), Day(Cells(1, 1)) + 32)

Da como resultado 01/02/2013. En ese caso, la fecha se ha aumentado en 2 meses.

l Añadir 2 meses:

DateSerial(Year(Cells(1, 1)), Month(Cells(1,1)) + 2, Day(Cells(1, 1)))

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.

DateSerial(Year(Cells(1, 1)), Month(Cells(1,1)) - 3, Day(Cells(1, 1)) + 1)

¿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á siempr e 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.

MsgBox MonthName (9, True) ’Sept


MsgBox MonthName (9, False) ’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:=SheetMsi(_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

DATEDIFF(Parámetro, Fecha1, Fecha2)

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.

Número_Día = WeekDay(Date, 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:

Function Nº_Día_Laborable(Date1 As Date, Date2 As Date) As Long


Dim Día_Tiemp as Long
For Día_Tiemp = Date1 To Date2
If WeekDay(Día_Tiemp, vbMonday) < 6 Then
º_DNía_Laborable = Nº_Día_Laborable + 1
End If
Next
End Function

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:

Function NºSEM(D As Date) As Long

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
D = Int(D)
ºNSEM = DateSerial(Year(D + (8 - WeekDay(D)) Mod 7 - 3), 1, 1)
ºNSEM = ((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.

Function Día_Festivo(Date1 As Date) As Boolean


Dim AÑO As Integer
Dim NºOr As Long
Dim Epacto As Integer
Dim PLuna As Long
Dim Pascua As Long
AÑO =
Year(Date1)
Select Case Date1
Case DateSerial(AÑO, 1, 1), DateSerial(AÑO, 5, 1), _
DateSerial(AÑO, 5, 8), DateSerial(AÑO, 7, 14), _
DateSerial(AÑO, 8, 15), DateSerial(AÑO, 11, 1), _
DateSerial(AÑO, 11, 11), DateSerial(AÑO, 12, 25)
Día_Festivo = True: Exit Function
End Select
NºOr = (AÑO Mod 19) + 1
Epacto = (11 * NºOr - (3 + Int(2 + Int(AÑO / 100)) * 3 / 7)) Mod 30
PLuna = DateSerial(AÑO, 4, 19) - ((Epacto + 6) Mod 30)
If Epacto = 24 Then PLuna = PLuna - 1
If Epacto = 25 And (AÑO >= 1900 And AÑO 2200) Then PLuna = PLuna- 1
Pascua = PLuna - Weekday(PLuna) + vbMonday + 7 ’Lunes Pascua
Select Case Date1
Case Pascua, Pascua + 38, Pascua + 49, Pascua + 50: Día_Festivo = True
End Select
End Function

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.

Function Nº_Día_Laborable(Date1 As Date, Date2 As Date) As Long


Dim Día_Tiemp as Long
For Día_Tiemp = Date1 To Date2
If WeekDay(Día_Tiemp, vbMonday) <> 6 And _
Día_Festivo(Día_Tiemp) = False Then
º_DNía_Laborable = Nº_Día_Laborable + 1
End If

- 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

Workbooks(Nombre del Archivo).Propiedades

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.).

ActiveWorkbook ’Libro activo


Workbooks("Libro.xlsx") ’Trabajo con el libro "Libro.xlsx"

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(Nombre del Archivo).Close SaveChanges:=True/False

El método Close cierra el archivo especificado. También puede utilizar el objeto ActiveWorkbook.Close para cerrar el
libro activo, pero puede ser un método peligroso si cerrase el libro que contiene el programa en ejecución.

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

Workbooks(Nombre del Archivo).Save

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

Workbooks(Nombre del Archivo).SaveAs Filename:=Nuevo Nombre

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"

’o para cambiar de directorio


ActiveWorkbook.SaveAs "C:\Documentos\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.

’ Al principio del programa


Application.ScreenUpdating = False

’ Al final del programa


Application.ScreenUpdating = True

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.

’ Al principio del programa


Application.DisplayAlerts = False

’ Al final del programa


Application. DisplayAlerts = True

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.

’ Mostrar la barra de estado


Application.DisplayStatusBar = True

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.

’ Mostrar su información de mensajes en la barra de estado


Application.StatusBar = "Valor leído " & Variable

Para borrar sus mensajes personales en la barra de estado, debe colocar el valor False en la propiedad StatusBar:

’ Borra todos sus mensajes personales


Application.StatusBar = False

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.

Nombre_Archivo = Application.GetOpenFilename("xls Files (*.xls), *.xls")


Workbooks.Open Nombre_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).

’ Bloquea el acceso a la impresora


Application.Interactive = False

’ Activa el acceso a la impresora


Application.PrintCommunication = True

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:

Application.Speech.Speak "Su Texto"

- 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

FileCopy Fuente, Destino

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

Name Nombre_Actual AS Nuevo_Nombre

Con esta función, podrá cambiar el nombre de un archivo en una carpeta.

Name "libros1.xls" As "nuevo_nombre.xls"

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.

Name Ruta_Inicio & Nombre_Archivo AS Ruta_Destino & Nombre_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 Ruta & Archivo

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).

Fecha_Hora_Archivo = FileDateTime("C:\Mis Documentos\Libro.xlsx")

Para recuperar la fecha o la hora, puede utilizar las funciones de texto para realizar un recorte:

Fecha_Hora_Archivo = FileDateTime("C:\Mis Documentos\Libro.xlsx")


Cells(1, 1) = CDate(Left(Fecha_Hora_Archivo, 10))
Cells(1, 2) = Right(Fecha_Hora_Archivo, 5)

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 .

Tamaño_Archivo = FileLen("C:\Mis Documentos\Libro.xlsx")

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:

Nombre_Archivo = Dir("C:\Mis Documentos\*.txt")

Del mismo modo, puede precisar una parte del nombre para filtrar más su búsqueda.

’Empieza por la palabra informe


Nombre_Archivo = Dir("C:\Mis Documentos\informe*.txt")

’Termina por 2015


Nombre_Archivo = Dir("C:\Mis Documentos\*2015.txt")

’Contiene la expresión 2015 en cualquier parte del nombre


Nombre_Archivo = Dir("C:\Mis Documentos\*2015*.txt")

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:

Nombre_Archivo = Dir("C:\Mis Documentos\*2015*.txt") If


Nombre_Archivo <> vbNullString Then
MsgBox "El archivo existe"
Else

MsgBox "El archivo no existe"


End If

Puede escribir el mismo test, pero dentro de una función. De esta forma podrá llamar al test desde cualquier parte del código.

Function Existe_Archivo(Directorio As String, Nombre_Archivo As String) As Boolean


Existe_ Archivo = False
Nombre_Archivo = Dir(Directorio & Nombre_Archivo ) If
Nombre_Archivo <> vbNullString Then

© É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).

Sub Test_ Archivo


If Existe_ Archivo ("C:\Mis Documentos\","Mi_Archivo.xlsx")
MsgBox "El archivo existe"
Else

MsgBox "El archivo no existe"


End If
End Sub

- 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.

Así, la instrucción Dir se ubicará en otro archivo del mismo tipo y, cuando se hayan recorrido todos los archivos, esta
devolverá una cadena vacía.

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 "Inform-e " & Nombre_Archivo
Nombre_Archivo D=ir
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

La instrucción GetAttr (Variable_Nombre_Archivo) devuelve los atributos de los archivos. Esta instrucción es muy
útil para hacer un test que controle si el elemento seleccionado es un archivo o un directorio.

’ Test para saber si el archivo está oculto


If GetAttr(Nombre_Archivo) = vbHidden Then
Instrucciones
End
If

’ Test para saber si se trata de un directorio


If GetAttr(Nombre_Archivo) = vbDirectory
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.

Sub BuscarDirectorio(MyPath As String)


Dim Lista() As String
Dim MyName As String
Dim a As Long
MyName = Dir(MyPath, vbDirectory)
Do While MyName <> ""
’ Ignorar el directorio actual y el directorio superior
If MyName <> "." And MyName <> ".."
Then
IGfet(Attr(MyPath & MyName) And vbDirectory) = vbDirectory Then
ReDim Preservar Lista(a)
Lista(a) = MyName
a = a + 1

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

Sub RecorridoDir(ByVal stDir As String)


On Error GoTo Tratamiento_error

’ Test si el objeto probado existe


If oFSO.FolderExists(stDir) Then
Set oFld = oFSO.GetFolder(stDir)
’Test si el directorio no es un directorio
’virtual (MiMúsica, MisVídeos, ...)
If (oFld.Attributes And 1024) = 0 Then
’ Comprueba el nombre del subdirectorio en stDir
If oFld.SubFolders.Count > 0 Then
’Bucle en todos los subdirectorios
For Each oSubFolder In oFld.SubFolders
ReDim Preserva Tab_Dir(i)
’Escribe en la tabla en memoria
Tab_Dir(i) = oSubFolder.Path
’Escribe el resultado en columna A Cells(i
+ 1, 1) = oSubFolder.Path i = i + 1
DoEvents
’llamada recursiva del procedimiento
RecorridoDir oSubFolder.Path
Next
End If

© É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(msoFileDialoFgolderPicker).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_ Archiv-o 1)
Tab_Nombre_ Archivo (Index_ Archiv-o 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:

Set Nombre_ok = Columns("A").Find("SMITH")

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:

Número_Fila = Nombre_ok.Row ’Es decir 40 en el archivo


Número_Col = Nombre_ok.Column ’Igual 1 lo cual es lógico ya que la
’búsqueda se hace en columna A

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:

Set Nombre_ok = Columns("A").Find("SMITH")

© É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:

Sub Método_Búsqueda Siguiente()


Dim Nombre_ok As Object
Dim Núm_Fila_1 As Long
With
Columns("A")
Set Nombre_ok = .Find("Smith")
If Not Nombre_ok Is Nothing Then
Núm_Fila_1 = Nombre_ok’.PRroiwmera búsqueda
Do
MsgBox "El valor Smith se ha encontrado Fila:
" & Nombre_ok.Row
Set Nombre_ok = .FindNext(Nombre_ok)
Loop While Núm_Fila_1 <> Nombre_ok.Row
End If
End With
End Sub

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 LookIn: corresponde a la opción Mirar en: puede precisar la búsqueda en los valores (xlValue) o en las fórmulas
(xlFormulas).

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:

Set Nombre_ok = Columns("A").Find(Valor_Buscado,LookAt:=xlPart)

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

Function Encuentra_Fila(Valor_Leído As String)


Dim Encuentra_Valor As Object
Set Encuentra_Valor = Columns("A").Find(Valor_Leído)
Encuentra_Fila =Encuentra_Valor.Row
End Function

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:

Mi_Tabla(0) = " Lunes "


Mi_Tabla(1) = " Martes "
Mi_Tabla(2) = " Miércoles "

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:

Dim Mi_Tabla_1(8) ’Inicialización tabla 1 dimensión


Dim Mi_Tabla_2(5,10) ’Inicialización tabla 2 dimensiones

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.

ReDim Mi_Tabla(5) ’Redimensiona una tabla de tamaño 5

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:

Núm_Filas = Cells(1, 1).CurrentRegion.Rows.Count


ReDim Mi_Tabla(Núm_Filas - 1)

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.

Dim Mi_Tabla() As Long


For i = 1 to 10
ReDimPreserve Mi_Tabla(i) = i
Next

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.

For i = LBound(Mi_Tabla) To UBound(Mi_Tabla)


Instruction
Next

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.

Filter(Mi_Tabla, Mi_Búsqueda[, include[, compare]])

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"

Tab_Resultado = Filter(Mi_Tabla, "a"T,rue)

For i = LBound(Tab_Resultado) To Ubound(Tab_Resultado)


Cells(i + 1, 1) = Tab_Resultado(i)
Next i
End Sub

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"F,alse)

For_i = LBound(Tab_Resultado) To Ubound(Tab_Resultado)


Cells(i + 1, 1) = Tab_Resultado(i)
Next i
End Sub

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

Mi_Tabla(0) = "gris perla"


Mi_Tabla(1) = "petigrís"
Mi_Tabla(2) = "gris"
Mi_Tabla(3) = "grisáceo"
Palabra_Buscada = "gris"

Tab_Resultado = Filter(Mi_Tabla, Palabra_Buscada, True)

For_i = LBound(Tab_Resultado) To Ubound(Tab_Resultado) If


Tab_Resultado(i) = Palabra_Buscada Then
MsgBox Tab_Resultado(i)
End If
Next i
End Sub

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.

’ Carga de la tabla en la memoria


MiTabla= Range("G1:G7")
’ Descargar en la hoja de cálculo
Range("F4:F10") = MiTabla

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.

Tasa_IVA = [Mi_IVA].Value ’Solo se recupera el valor

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:

Dim Importe_Factura As Double


Dim Val_Fila As
Long
Importe_Factura = 100
Val_Fila = [Fecha_de_Factura].Row
Cells(Val_Fila + 4, 1) = Importe_Factura

Pero también podemos reducir la escritura a una sola línea de código de la siguiente manera:

Dim Importe_Factura As Double


Importe_Factura = 100
Cells([Fecha_de_Factura].Row + 4, 1) = Importe_Factura

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.

For Each Mi_Tabla In ActiveSheet.ListObjects


MsgBox Mi_Tabla.Name
Next

La instrucción ListObject debe asociarse a una hoja de cálculo. ListObject sola no funciona. Esto acarrea líneas de
código muy largas para mostrar la fila de totales de una tabla, como podemos ver a continuación.

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.

Dim Mi_Tabla As Object


Set Mi_Tabla = ActiveSheet.ListObjects("Tabla_Ejemplo")
For Each Mis_Columnas In Mi_Tabla.ListColumns
MsgBox Mis_Columnas.Name
Next

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:

Dim Mi_Tabla As Object


Set Mi_Tabla = ActiveSheet.ListObjects("Tabla_Ejemplo")
Col_Nombre = Mi_Tabla.ListColumns("Nombre").Index

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.

Dim Mi_Tabla As Object

- 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:

Dim NumFilas As Long


NumFilas = Cells(1, 1).CurrentRegion.Rows.Count

o
NumFilas = Cells(Rows.Count, 1).End(xlUp).Row

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

’Carga de la tabla como objeto

© É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.

Public Declare Function timeGetTime Lib "winmm.dll" () As Integer Public


Declare Function timeBeginPeriod Lib "winmm.dll" (ByVal uPeriod As Integer)
As Integer
Public Declare Function timeEndPeriod Lib "winmm.dll" (ByVal uPeriod As
Integer) As Integer

Sub Pgm_Principal()
’ Colocar al principio del programa
timeBeginPeriod 1
t_start = timeGetTime()

’ Colocar al final del programa t_end


= timeGetTime()
Cells(1, 1) = (t_end- t_start) / 1000 ’ división entre 1000 para
’ los milisegundos
End Sub

© É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:

Private Declare PtrSafe Function ShellExecute Lib "shell32.dll"

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á:

Private Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal
Hwnd As LongPtr, ByVal lpOperation As String,_ByVal lpFile As String, ByVal
lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As
LongPtr

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:

#If Win64 And VBA7 Then


’ Esta función API busca una ventana
Private DeclarPetrSafe Function FindWindow Lib "User32" Alias _
"FindWindowA" (ByVal lpClassName As String, ByVal _
lpWindowName As StringL)onAgsPtr
#Else
’ Esta función API busca una ventana
Private Declare Function FindWindow Lib "User32" Alias _
"FindeWindowA" (ByVal lpClassName As String, ByVal _
lpWindowName As String) As Long
#End If

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:

Set Mi_Objeto = CreateObject("Excel.Sheet")


Set Mi_Objeto = CreateObject("InternetExplorer.Application") Set
Mi_Objeto = CreateObject("Outlook.Application")

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

Set OutApp = CreateObject("Outlook.Application") Set


OutMail = OutApp.CreateItem(0)

Cuerpo_Mail = "Este es el mensaje de su correo electrónico." & vbNewLine & _ "Para el


salto de línea puede utilizar vbNewLine o Chr(13)"

On Error Resume Next


With OutMail
.To = Mail_Destinatario
.CC = ""
.BCC = ""
.Subject = "Escriba aquí el asunto"
.Body = Cuerpo_Mail
’Puede insertar un archivo quitando el apóstrofo de más abajo
’.Attachments.Add ("C:\test.txt")
.’Soen.dDisplay solo para ver el mail
End With
On Error GoTo 0

Set OutMail = Nothing


Set OutApp = Nothing
End Sub

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:

Cuerpo_Mail = "Hola <B>xxxxxxxxx</B>"

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:

Dim cell as Object


For Each cell In Columns("A").Cells.SpecialCells(xlCellTypeConstants)
INSTRUCTION para el envío de un mail
Next

- 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:

Function RDB_Create_PDF(Myvar As Object, FixedFilePathName As String, _


OverwriteIfFileExist As Bookean, OpenPDFAfterPublish As Boolean)
As String
Dim FileFormatstr As String
Dim Fname As Variant

’Test para comprobar si la dll está instalada


If Dir(Aproximadamente("commonprogramfiles") & "\Microsoft Shared\OFFICE"
& Format(Val(Application.Version), "00") & "\EXP_PDF.DLL") <> "" Then

If FixedFilePathName = "" Then


’Apertura del cuadro Guardar como e introducir el nombre del archivo PDF
FileFormatstr = "Archivos PDF (*.pdf), *.pdf"
Fname = Application.GetSaveAsFilename ("", filefilter:=FileFormatstr, _
Title:="Create PDF")

’Si cancela este cuadro, abandona la función If Fname =


False Then Exit Function Else
Fname = FixedFilePathName
End If

’Si el parámetro OverwhiteIfFileExist = Falso, entonces se realiza un test


’para saber si el archivo ya no existe en la carpeta
If OverwriteFileExist = False Then
If Dir(Fname) <> "" Then Exit Function
End If

’Ahora Exportación del archivo PDF

© É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

’Si la exportación ha salido bien, el nombre del archivo PDF


’se reenvía a la función.
IfDir(Fname) <> "" Then RDB_Create_PDF = Fname
End If
End Function

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

’Llamada de la función con los 4 argumentos esperados.


FileName = RDB_Create_PDF(ActiveWorkbook, "", True, True)

’Si el archivo debe eliminarse cada vez que inicia el tratamiento


’quite el comentario de la línea siguiente.
’RDB_Create_PDF(ActiveWorkbook, " C:\MisDocumentos\ArchivoPDF ", True, True)

If FileName <> "" Then


’Quite el comentario siguiente si desea enviar por correo electrónico
’el archivo pdf.
’RDB_Mail_PDF_Outlook FileName, destin@ta.rio, "Su Asunto", _
"Texto de su mensaje", False
Else

MsgBox "No es posible crear PDF por una de las razones siguientes:
" & vbNewLine & _

"La dll no está instalada" & vbNewLine & _ "Ha


cancelado Guardar como" & &vb_NewLine
"La ruta indicada no es correcta" & vbNewLine & _ "No
quiere eliminar el PDF existente."
End If
End Sub

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

If ActiveWindow.SelectedSheets.Count > 1 Then


MsgBox "Hay más de una hoja seleccionada," &vbNewLine & _ "y
cada hoja se imprimirá en formato PDF."
End If

’Llamada de la función con los argumentos esperados.


FileName = RDB_Create_PDF(ActiveSheet, "", True, True)

’Si el archivo debe eliminarse cada vez que inicia el tratamiento


’quite el comentario de la línea siguiente.
’RDB_Create_PDF(ActiveWorkSheet, " C:\MisDocumentos\ArchivoPDF.pdf ",
True, True)

If FileName <> "" Then


’Quite el comentario siguiente si desea enviar por correo electrónico el archivo
pdf.
’RDB_Mail_PDF_Outlook FileName, destin@ta.rio, "Su Asunto", _
"Texto de su mensaje", False
Else
MsgBox "No es posible crear el PDF por una de las razones siguientes:" "La dll
& vbNewLine &
_
no está instalada" & vbNewLine & _
"Ha cancelado Guardar como" & vbNewLine & _
"La ruta indicada no es correcta" & vbNewLine & _ "No
quiere eliminar el PDF existente."

End If
End Sub
© É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).

Para activar el ADO, con VBA, abra el menú Herramientas Referencias... y active la opción Microsoft
ActiveX Data Objects 6.0 Library (u otra versión disponible en su ordenador).

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 objeto ADOBD.Connection permite conectarse a una base de datos. El objeto ADOBD.RecorSet contendrá el resultado
de la consulta.

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:

Dim Mi_Base As New ADODB.Connection

© É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:

Ubicación y Nombre de la base de datos


Nombre_Base = "C:\Users\Base_Datos.accdb"
’ Abrir la connexión con la base de datos
Set Mi_Base = New ADODB.Connection
Mi_Base.Open "Provider=Microsoft.Jet.OLEDB.12.0;" & _
"Data Source=" & Nombre_Base & ";"

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.

SQL_Req = "Select * From Table1"


’Ejecución de la consulta
Mi_Consulta.Open SQL_Req, Mi_Base, 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:

If Mi_Consulta.RecordCount > 0 Then

Comprobar que no se ha alcanzado el final de RecordSet:

If Mi_Consulta.EOF = False Then

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="Ba&se_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.

Sub Consulta _Access_Nuevo_Registro() Dim


Mi_Base As New ADODB.Connection
Dim Mi_Consulta As New ADODB.Recordset Dim
Base_Data As String ’Ruta de acceso Dim
SQL_Req As String ’Consulta
Dim i_Fila As Long ’Índice fila

’Ruta y Nombre de la base de datos


Base_Data = "C:\Users\Base_Access_Ejemplo.accdb"
’ Abre la conexión a la base

© É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 & ";"

’ Abre un nuevo recordset


Set Mi_Consulta = New ADODB.Recordset
Mi_Consulta.Open "Table1", Mi_Base, adOpenForwardOnly
i_Fila = 1

’Bucle en todas las celdas de la columna A


While Cells(i_Fila, 1) <> ""
’Insertar datos en la base Access
With Mi_Consulta
.’AAdñdaNdeiwr un nuevo registro vacío
.Fields(0) = Cells(i_Fila, 1)
.Fields("Valor") = Cells(i_Fila, 2)
.’UApcdtautaelización del registro
End With
i_ Fila = i_ Fila + 1
Wend
’Cierre del Recordset
Mi_Consulta.Close
’Cierre de la base
Mi_Base.Close
End Sub

La primera parte, que concierne a la conexión a la base, es exactamente igual que con la instrucción SELECT.

RecordSet en el exterior del bucle. De esta manera no tendremos que gestionar un


A continuación, abrimos el
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 & ";"

’ Abre un nuevo recordset


Set Mi_Consulta = New ADODB.Recordset
Mi_Consulta.Open "Table1", Mi_Base, adOpenForwardOnly
i_Fila = 1
While Cells(i_ Fila, 1) <> ""
SQL_Req = "UPDATE Table1
"
SQL_Req = SQL_Req & "Set Valor = " & Cells(i_ Fila, 2)
SQL_Req = SQL_Req & " WHERE Nombre = " & Chr(34) & _
Cells(i_ Fila, 1) & Chr(34)

’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.Sav
e
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.

Private Sub Worksheet_Change(ByVal Target As Range)


’Instruction
End Sub

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).

Sub Worksheet_Change(ByVal Target As Range) If


LCase(Cells(1, 1)) = "Sí" Then
Columns("B").Hidden = True
Else
Columns("B").Hidden = False
End If
End Sub

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:

Target.Row ’ Fila de la celda que ha activado el evento


Taget.Column ’ Columna de la celda
Target.Address ’Recupera la referencia de la celda
Target.Count ’Devuelve el número de celdas seleccionadas

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á:

Sub Worksheet_Change(ByVal Target As Range)


If Target.Count = 1 Then
If LCase (Cells(1, 1)) = "Sí" Then
Columns("B").Hidden = True
Else

Columns("B").Hidden = False
End If
End If
End Sub

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á:

Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim


RngRow As Range
Dim RngCol As Range
Dim RngFinal As Range
Dim Fila As Long
Dim Columna As Long

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)

RngFinal.Interior. Color = 15395562’Gris claro


End Sub

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.

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)


If Target.Row >= 5 Or Target.Row <= 10 And Target.Column = 2 Then
MsgBox "Mensaje personalizado"
End If
End Sub

- 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 prime r 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 accesible s 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:

Private Sub UserForm_Activate()


Instrucción
End Sub

© É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).

los CommandButton que son los botones tradicionales


l Los botones como (como Aceptar o Cancelar), los
CheckBox (casillas de verificación) y los OptionButton (los botones de opción).

l Las listas son listados de elementos en las que los usuarios pueden elegir un elemento; pueden ser listas simples como los ListBox
(o cuadro de lista) o listas editables como los ComboBox (las listas desplegables).

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 mostra r 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:

Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean) If Not


IsNumeric(Me.TextBox1.Text) Then
MsgBox "Debe escribir un valor numérico"
End If
© É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:

Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean) If


Me.TextBox1.Text <> "" Then
If Not IsNumeric(Me.TextBox1.Text) Then
MsgBox "Debe escribir un valor numérico"
Else

If Me.TextBox1.Text <= 0 Or Me.TextBox1.Text > 10 Then


MsgBox "Valor erróneo"
End If
End If
End If
End Sub

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 mostra r 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:

Private Sub CommandButton1_Click()


Unload UserForm1 ’El nombre del cuadro de diálogo
End Sub

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.

Value Para recuperar la indicación marcada ( True) o no marcada ( False).

Visible Para mostra r o no el objeto en el cuadro de diálogo.

Enabled Para hacer el objeto accesible ( True) o no ( False).

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.

’ Evento en el clic de la casilla de verificación


Private Sub CheckBox1_Click()
If Me.CheckBox1.Value = True Then
Me.CommandButton1.Enabled = True
Else

Me.CommandButton1.Enabled = False
End If
End Sub

’ Evento al cargar el cuadro de diálogo


Private Sub UserForm_Initialize()
Me.CommandButton1.Enabled = False
Me.CheckBox1.Value = False
End Sub

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 mostra r 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:

Private Sub CommandButton1_Click()


Select Case True
Case Me.OptionButton1.Value
MsgBox Me.OptionButton1.Caption
Case Me.OptionButton2.Value
MsgBox Me.OptionButton2.Caption
Case Me.OptionButton3.Value
MsgBox Me.OptionButton3.Caption

© É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:

Private Sub ListBox1_Change()


Dim Val_Índice As Byte
Val_Índice = Me.ListBox1.ListIndex
Me.Label1.Caption = "Valor seleccionado: " & _
Me.ListBox1.List(Val_Índice)
End Sub

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:

Public Val_Seleccionado As String

Private Sub CommandButton1_Click()


MsgBox Val_Seleccionado
End Sub

Private Sub ListBox1_Change()


Dim i As Byte
Val_Seleccionado = ""
With ListBox1
For i = 0 To .ListCount- 1
If .Selected(i) Then
Val_Seleccionado = Val_Seleccionado & Me.ListBox1.List(i) & Chr(13) End
If
Next
End With
End Sub

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:

Private Sub UserForm_Initialize()


Dim i As Byte
Me.ListBox1.RowSource =
"" For i = 0 To 5
Me.ListBoxA1d.dItem (i * 2)
Next
End Sub

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á:

Private Sub CommandButton1_Click()


Me.ListBox1R.emoveItem (Me.ListBox1.ListIndex)
End Sub

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 mostra r 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:

Private Sub ComBox1_Change()


Dim Val_Índice As Byte
Val_Índice = Me.ListBox1.ListIndex
Me.Label1.Caption = "Valor seleccionado: " & _
Me.ListBox1.List(Val_Índice)
End Sub

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.

’Código para la adición


Private Sub CommandButton1_Click()
Dim Última_Fila As Long
Última_Fila = Cells(1, 1).CurrentRegion.Rows.Count + 1
Cells(Última_Fila, 1) = Me.ComboBox1.Text

Call UserForm_Initialize

End Sub

’Código para iniciar el UserForm


’con carga de la lista
Private Sub UserForm_Initialize()
Dim i_Fila As Long
Me.ComboBox1.RowSource = ""
i_Fila = 1
While Cells(i_Fila, 1) <> ""
Me.ComboBox1.AddItem (Cells(i_Fila, 1))
i_Fila = i_Fila+ 1
Wend
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:

Private Sub B_raz_Click()


Dim c As Control
For Each c In Me.Controls
Select Case TypeName(c)
Case "TextBox"
c.Value = ""
Case "CheckBox"
c.Value = False
Case "ListBox", "ComboBox"
c.ListInd-e1x =
End Select
Next c
End Sub

© É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:

Err.Number ’Devuelve el número del error

Err.Description ’Devuelve el mensaje del error

Esta propiedad devuelve el texto del error. Puede utilizarla en un mensaje que se mostrará en la pantalla:

MsgBox "Error " & Err.Description & " detectado"

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).

On Error GoTo Gestión_Error


Instruction
Gestión_Error

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.

Public Function SheetExists(sname) As Boolean


Dim Objeto_Hoja As Object
On Error Resume Next
Set Objeto_Hoja = ActiveWorkbook.Sheets(sname)
If Err = 0 Then SheetExists = True Else SheetExists = False
End Function

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.

Set Objeto_Hoja.... Ahora bien,


En caso de que la hoja no exista, el programa debería haberse detenido en la instrucción
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:0 0 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 represent a todos los datos monetarios: son números comprendidos entre
922337203685477,580 8 y 922337203685477,5807.

Integer El tipo Integer devuelve un número entero comprendid o 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 expresione s de texto. Estas no se pueden utilizar
para cálculos matemático s 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 complementaria s 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

&HC = (Virtual) \My Documents\

&H27 = \My Documents\My Pictures

&H2E = \Documents

&HD = \My Documents\My Music

&HE = \My Documents\My Video

&H0 = Virtual Desktop

&H1 = Virtual Internet Explorer (icon on desktop)

&H2 = Start Menu\Programs

&H3 = Virtual My Computer\Control Panel

&H4 = Virtual My Computer\Printers

&H6 = \Favorites

&H7 = Start Menu\Programs\Startup

&H8 = \Recent

&H9 = \SendTo

&HA = Virtual \Recycle Bin

&HB = \Start Menu

&H10 = \Desktop

&H11 = Virtual My Computer

&H12 = Virtual Network Neighborhood

&H13 = \nethood (may dupe My Network Places)

&H14 = Virtual windows\fonts

&H15 = \templates

&H16 = \Start Menu

&H17 = \Programs

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
&H18 = \Startup

&H19 = \Desktop

&H1A = \Application Data

&H1B = \PrintHood

&H1C = \Local Settings\Application Data (non roaming)

&H1D = nonlocalized startup program group

&H1E = (NT) nonlocalized Startup group for all NT users

&H1F = (NT) all user’s favorite items

&H20 = temporary Internet files

&H21 = (NT) Internet cookies

&H22 = (NT) Internet history items

&H23 = \Application Data

&H24v = Windows directory or SYSROOT

&H25 = GetSystemDirectory()

&H26 = \Program Files

&H28 = \

&H29 = x86 system directory on RISC

&H2A = x86 Program Files folder on RISC

&H2B = \Program Files\Common

&H2C = x86 Program Files Common folder on RISC

&H2D = \Templates

&H2F = \Start Menu\Programs\Administrative Tools

&H30 = \Start Menu\Programs\Administrative Tools

&H31 = Virtual Network and dial-up connections folder

&H35 = My Music folder for all users

&H36 = My Pictures folder for all users

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
&H37 = My Video folder for all users

&H38 = System resource directory

&H39 = Localized resource directory

&H3A = Links to OEM specific apps for all users

&H3B = \Local Settings\Application Data\Microsoft\CD Burning

&H3D = Virtual Computers Near Me folder

© É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.

- 1-
© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
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-

También podría gustarte