Sei sulla pagina 1di 336

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.excel­exercice.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- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Por defecto, su nombre genérico es "Módulo1, 2, 3, …" 

Para  darle  otro  nombre,  como  por  ejemplo  Primer_Programa,  escriba  el  nombre  en  la  ventana  de 
propiedades en lugar de la palabra Módulo 1. 

Se ha modificado el nombre de su módulo en el Explorador de proyectos. 

2. Los cuadros de diálogo personalizados

Hacer macros también es crear sus propios cuadros de diálogo. 

Para  insertar  un  cuadro  de  diálogo,  en  el  Explorador  de  proyectos,  haga  clic  con  el  botón  derecho  del 
ratón  en  el  documento  y  seleccione  el  menú  Insertar  ­  UserForm  (que  es  la  traducción  de  cuadro  de 
diálogo). 

Aparecerá un cuadro de diálogo en blanco en la zona de trabajo: 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
En los capítulos Los cuadros de diálogo personalizados y Los controles, veremos cómo rellenar un cuadro de diálogo 
y  también  cómo  recuperar  la  información  introducida.  Podemos  observar  que  del  mismo  modo  que  aparecen  los 
módulos, aparece un icono UserForm1 en el árbol del Explorador de proyectos y que la ventana de propiedades 
contiene muchos más elementos para un cuadro de diálogo que para un módulo. 

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 

- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
el siguiente menú contextual. 

En este ejemplo, solo está marcada la opción Estándar. 

Marque las dos primeras opciones para que aparezcan la barra de Depuración y la barra de Edición. 

Si  estas  barras  de  herramientas  se  muestran  como  una  barra  flotante  y  quiere  colocarlas  en  la  parte 
superior  de  la  ventana  de  la  aplicación,  haga  clic  en  la  barra  de  título  de  la  barra  de  herramientas  y 
deslícela  hacia  las  otras  barras  de  herramientas.  Cuando  suelte  el  botón  del  ratón,  la  barra  de 
herramientas se colocará en el mismo nivel que las demás barras de herramientas. 

Es importante señalar que las barras agregadas de esta forma aparecerán de nuevo cada vez que se inicie el editor; 
el editor conserva las opciones de vista. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Introducción
La ventaja de Visual Basic, con respecto a otros lenguajes de programación, es su simplicidad de comprensión para 
cualquier neófito; es un lenguaje orientado a objetos. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
¿Qué es un objeto?
En Visual Basic, un objeto corresponde a uno de los elementos de la aplicación Excel: un libro (Workbook), una hoja 
de cálculo (Worksheet), una columna (Column), una fila (Row), un rango de celdas (Range), una celda (Cells), etc. 

A esos objetos se les asociará ya sea una propiedad o un método. 

1. Propiedad de un objeto

Una propiedad corresponde a las características de un objeto. 

l Para una celda, las propiedades pueden ser su valor, su color, su tamaño, su fuente de carácter, etc. 

l Para una hoja, las propiedades pueden ser su nombre, su visibilidad (oculta o no), su color de pestaña, etc. 

Las propiedades que se aplican a un objeto son diferentes de un objeto a otro. 

En  el  capítulo  Depuración  veremos  de  qué  manera  mostrar  la  lista  de  métodos  y  propiedades  vinculadas  a  un 
objeto. 

2. Método de un objeto

Un método corresponde a una acción efectuada a un objeto. 

l Una celda se puede copiar, pegar, borrar, etc. 

l Una hoja se puede copiar, suprimir, renombrar, etc. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Regla de codificación
La  codificación  de  los  métodos  y  de  las  propiedades  es  muy  sencilla:  un  objeto  se  asocia  a  un  método  o  a  una 
propiedad separándolos por un punto: 

Objeto.Método

   O 

Objeto.Propiedad

Por ejemplo, podemos escribir: 

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

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Workbooks("libro2.xlsx").Sheets("Hoja1").Cells(1, 3)

Atención:  respete  el  orden  de  los  términos.  Una  celda  está  incluida  en  una  hoja  de  cálculo.  Por  lo  tanto  debe 
escribir  el  objeto  Hoja  antes  que  el  objeto  Celda.  Las  hojas  de  cálculo  tienen  extensiones  .xlsm  porque  solo 
las  hojas  de  cálculo  con  esas  extensiones  guardan  también  el  código  VBA.  Las  hojas  de  cálculo  xlsx  están  vacías  de 
código VBA. 

2. Asociación de propiedades o de métodos

Del mismo modo, puede asociar a un objeto varias propiedades o métodos. Por ejemplo, si quiere contar el número 
de filas no vacías desde la celda A1, puede escribir la instrucción siguiente: 

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

Esta  escritura  puede  traducirse  del  siguiente  modo:  a  partir  de  la celda  A1,  seleccionamos  el  conjunto  de celdas 
adyacentes (tanto en filas como en columnas), después nos centramos en las filas que contamos. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Ayuda en línea 
Ya  hemos  mencionado  algunos  términos  importantes  que  permiten  identificar  celdas  y  filas.  El  cúmulo  de  términos, 
propiedades y métodos puede llegar a confundirle, pero existe una manera muy simple de encontrar propiedades y 
métodos vinculados a un objeto y es utilizando la ayuda en línea. 

Para hacerlo bastará con: 

l Seleccionar el término cuya ayuda quiere ver. 

l Pulsar la tecla [F1] del teclado. 

En su navegador aparecerá una ventana con el término seleccionado. Si la página web está vacía querrá decir que el 
término seleccionado no existe o bien que la selección no es correcta.  

Un  truco  para  saber  si  los  términos  están  correctamente  escritos  consiste  en  escribirlos  siempre  en 
minúsculas.  Si  los  términos  forman  parte  de  instrucciones  reconocidas,  VBE  los  pondrá  siempre  en 
mayúsculas. Si las instrucciones permanecen en minúsculas, querrá decir que el lenguaje VBA no los 
reconoce. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Codificación de las celdas y de los rangos de celdas
Todos  sus  programas  van  a  utilizar,  de  una  forma  o  de  otra,  el  contenido  de  una  celda  o  de  un  rango  de  celdas. 
Llegados aquí es importante explicar cómo comunicar con una celda y/o una hoja mediante el código VBA. 

1. La celda

Una celda se codifica del siguiente modo: 

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  referencias  de  las  celdas  se  escriben  "literalmente"  entre  comillas.  No  se 
pueden variar esas referencias, están congeladas. 

[A1:C5].Select  Aquí,  reemplazamos  la  instrucción  Range  por  unos  corchetes,  las  referencias 
están escritas sin comillas. 

Range(Cells(1, 1), Cells(3,  Esta  escritura  puede  parecer  más  compleja,  pero  es  el  método  que  queremos 
5)).Select  destacar, ya que con este cada componente de las referencias de celda puede 
gestionarse por una variable, como veremos a continuación. 

3. Las celdas nombradas

Cuando se nombra una celda o un rango de celdas, puede recordar sus nombres en lugar de dar las referencias de 
las celdas. 

Por ejemplo, si la celda A1 se llama IVA, puede escribir simplemente: 

[IVA].Select 

De este modo, incluso si desplaza esta celda a otro lugar de su hoja de cálculo, la instrucción no se modificará en su 
código. En el capítulo Optimización, sección Las celdas con nombre y las tablas, veremos las ventajas de tratar de 
esta manera las celdas importantes de nuestro programa. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Significado del signo =
El signo = debe considerarse como un puente. La información que está a la derecha del signo = se traslada hacia el 
elemento que está a la izquierda. 

Por ejemplo, para asignar el valor 15 a la celda A1, escribimos: 

Cells(1,1) = 15

Para colorear de rojo el fondo de la celda A1, escribimos: 

Cells(1,1).Interior.Color = vbRed

También  podemos  invertir  la  escritura.  Para  conocer  el  código  del  color  de  la  celda  A1  y  poner  ese  resultado  en  la 
celda D1, vamos a escribir el código siguiente: 

Cells(1,4) = Cells(1,1).Interior.Color

Por último, para reproducir el color de la celda A1 a la celda D1: 

Cells(1,4).Interior.Color = Cells(1,1).Interior.Color

A continuación, si queremos efectuar un cálculo retomando el contenido de la celda A1 (que contiene el valor 7, por 
ejemplo) para añadirle el valor 5 y que el resultado aparezca en B1, escribiremos la fórmula de la siguiente manera: 

Cells(2, 1) = Cells(1, 1) + 5

Le resultado será 12 en la celda B1. 

También  podemos  usar  la  misma  celda  como  valor  para  usar  en  el  cálculo  y  como  celda  para  almacenar  el 
resultado.  De  esta  forma,  si  queremos  usar  el  contenido  de  la  celda  A1,  agregarle  una  unidad  complementaria  y 
transcribir el resultado también en A1, escribiremos: 

Cells(1, 1) = Cells(1, 1) + 1

La consecuencia de esta línea de código será que el valor en A1 se modificará cada vez que el programa lea la línea. 
Ahora quizá le parezca algo extraño, pero cuando estudiemos las variables y los bucles, esta escritura nos permitirá 
avanzar de fila en fila al ejecutar el programa. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Los procedimientos
Todas las líneas de código deben escribirse en uno o varios procedimientos. 

Un  procedimiento  se  caracteriza  por  la  escritura  de  la  instrucción  Sub  (diminutivo  de  Subroutine  que  significa 
Procedimiento en español) y de la instrucción End Sub que concluye el procedimiento. 

Sub Cambiar_el_color()
Su programa
End Sub
 
Para iniciar este programa, puede o bien pulsar la tecla [F5] o bien hacer clic en el icono  .

Para  nombrar  un  procedimiento,  se  admiten  todos  los  términos  salvo  las  palabras  reservadas  (como  For,  Next, 
While, Cells,  Date, etc.). Las palabras reservadas son necesariamente palabras en inglés. Además, si nombra su 
procedimiento con varias palabras, el único separador autorizado es _ (underscore  o  guión  bajo).  Los  espacios  y  el 
guión (­) están prohibidos ya que podrían impedir que el programa se ejecutara. 

Si su proyecto se compone de varios procedimientos, (véase capítulo Estructura de un programa), cada procedimiento 
deberá tener un nombre único. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Las funciones
Las  funciones  se  diferencian  de  los  procedimientos  por  el  hecho  de  que  estas  devuelven  un  valor  al  final  del 
tratamiento. Son muy importantes para aislar acciones o test concretos. Por ejemplo, si queremos saber si un archivo 
existe  en  un  directorio,  escribiremos  una  función  personalizada  que  nos  dirá  si  el  archivo  existe  o  no;  la  función 
devolverá Sí o No (para ver todo el código de la función consulte el capítulo Trabajar con los archivos ­ Encontrar un 
archivo en un directorio). 

Para escribir una función, hay que escribir el código entre las instrucciones Function y End Function. 

Por  ejemplo,  vamos  a  crear  una  función  personalizada  que  devolverá  en  una  celda  el  nombre  de  su  hoja  activa. 
Escribiremos esta función de la forma siguiente: 

Function Nombre_Hoja()
Nombre_Hoja = ActiveSheet.Name
End Function

Aunque simple, este código muestra la diferencia fundamental existente entre una función y un procedimiento. En las 
funciones, el nombre de la función (Nombre_Hoja) se utiliza a la vez como nombre de la función y como nombre para 
el resultado del cálculo. Todas las funciones creadas pueden nombrarse en una hoja de cálculo. 

Escriba el nombre de su función en una celda. 

Observará  que  su  función  Nombre_Hoja  aparece  en  el  menú  desplegable  con  el  mismo  título  que  las  funciones 
integradas de Excel. 

Termine la escritura de su función (no olvide los paréntesis). 

El resultado de la función se muestra en la celda: 

En una hoja de cálculo, las funciones se interpretan directamente sin que usted tenga que iniciar el programa (como 
para un procedimiento). 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Esta  función  se  ha  creado  sin  ningún  parámetro,  pero  en  el  capítulo  Estructura  de  un  programa  ­  Parámetros  de 
llamada veremos cómo podemos transmitirle parámetros personalizados. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Introducción
Una vez vistos los principios básicos de la programación, podemos escribir nuestro primer programa. Para ello, vamos 
a pedirle a Excel que nos ayude gracias a la Grabadora de macros. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
La Grabadora de macros
Esta herramienta grabará todas las acciones realizadas con Excel: selección de una celda, de un grupo de celdas, dar 
formato, etc. 

Muy a menudo, tendrá que eliminar algo de código para guardar solo lo esencial. 

1. Versión Excel 2003 (o anterior)

Para iniciar la Grabadora, vaya al menú Herramientas ­ Macro, y active la opción Grabar nueva macro. 

Aparecerá un cuadro de diálogo que le pide que escoja un nombre para su macro. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Indique el nombre de la macro y haga clic en Aceptar. 

A partir de ese momento, todas las acciones que realice se grabarán en el Visual Basic Editor. 

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. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Indique el nombre de la macro y haga clic en Aceptar. 

A partir de ese momento, todas las acciones que realice se grabarán en el Visual Basic Editor. 

Para detener la grabación, haga clic en el mismo sitio (el icono habrá cambiado de apariencia): 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Primer ejercicio
Para  nuestro  primer  programa,  vamos  a  trabajar  con  el  libro  (Ejemplo  4­C)  que  podrá  descargar  desde  la  página 
Información. 

El objetivo de nuestro trabajo es combinar los nombres de la columna A cuando estos sean idénticos para alcanzar el 
resultado siguiente: 

Como  comprobará,  el  número  de  líneas  que  se  van  a  combinar,  varía.  Por  lo  tanto,  no  es  posible  utilizar  la 

herramienta  Copiar formato   ya  que  esta  herramienta  respeta  no  solo  el  formato,  sino  también  el  número  de 

líneas afectadas. Así que debemos crear una macro para realizar esta tarea automáticamente. 

En un primer momento, vamos a utilizar la Grabadora de macros para codificar la primera combinación de celda. Es 
importante que respete los pasos siguientes para que pueda llegar exactamente al mismo código que el que figura a 
continuación. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Inicie la Grabadora. 

Conserve el nombre Macro1 y haga clic en Aceptar. 

Seleccione las celdas A2 a A5. 

Abra el cuadro de diálogo Formato de celdas (Formato ­ Celda en Excel 2003 o, en Excel 2007, 2010, 2013 
 
y 2016, haga clic en el icono de cuadro de diálogo   del grupo Alineación en la pestaña Inicio).

Aparecerá el siguiente cuadro de diálogo: 

Ventana de configuración de alineación de una celda 

Marque la opción Combinar celdas. 

Escoja la alineación Horizontal: Izquierda (sangría). 

Escoja la alineación Vertical: Centrar. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Pulse Aceptar. 

Aparecerá un mensaje de error que le indica que la combinación hará desaparecer valores, pero no le 
haga caso: haga clic en Aceptar. 

El resultado en la pantalla será el siguiente: 

 
Detenga la grabación haciendo clic en el botón Stop .

A continuación acceda a Visual Basic Editor: en el Módulo1 encontrará un programa similar a este: 

Sub Macro1()

’ Macro1 by.................

Range("A2:A5").Select
With Selection
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlCenter
.WrapText = False
.Orientation = 0
.AddIndent = False

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
.IndentLevel = 0
.ShrinkToFit = False
.ReadingOrder = xlContext
.MergeCells = True
End With
End Sub

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

- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Examen del código
El código comienza por líneas escritas en verde precedidas de un apóstrofo: estas líneas son comentarios. Una línea 
precedida de un apóstrofo no se interpreta como código. 

La primera línea que se interpretará corresponde a la selección del rango de celdas A2 a A5: 

Range("A2:A5").Select

A  continuación,  visualizará  el  conjunto  de  datos  reunidos  en  un  bloque  With/End
With.  Un  bloque  de  datos 
With/End With permite asociar varias propiedades a un solo objeto. Aquí, para el objeto Selection, las líneas 
corresponden  a  nueve  propiedades  del  cuadro  de  diálogo  Formato  ­  Celda  ­  pestaña  Alineación: 
HorizontalAlignment, VerticalAlignment, WrapText, etc. 

Es  uno  de  los  principales  defectos  de  la  Grabadora  de  macros:  cuando  activa  un  cuadro  de  diálogo  de  Excel 
(Formato de celdas, Configurar página, etc.) la Grabadora codifica todos los elementos de este cuadro de diálogo, 
aunque no los haya modificado.  

No dude en suprimir las líneas de código inútiles. 

En  nuestro  ejemplo,  como  solo  hemos  cambiado  tres  parámetros  en  el  cuadro  de  diálogo,  solo  podemos 
conservar las siguientes líneas: 

Sub Macro1()
Range("A2:A5").Select
With Selection
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlCenter
.MergeCells = True
End With
End Sub

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Ejecución del código
Ahora vamos a utilizar el código para dar formato a las demás celdas del libro. 

 
Inicie su programa, haciendo clic en el icono   o pulsando la tecla [F5].

¡No  ve  ningún  cambio  en  su  hoja  de  cálculo!  De  hecho,  la  primera  línea  de  código  indica  que  ha  seleccionado  las 
celdas A2 a A5, el programa solo se aplicará en esta selección (debido a la instrucción With Selection). 

Para que este programa se aplique a cualquier selección de celdas, debe eliminar la línea de código Range
("A2:A5").Select o, mejor incluso, ponerla como comentario precediéndola de un apóstrofo. 
El código pasa a ser: 

Sub Macro1()
’Range("A2:A5").Select
With Selection
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlCenter
.MergeCells = True
End With
End Sub

Ahora comprobemos la buena ejecución del programa. 

Seleccione las celdas A6:A12 e inicie su programa. 

Las celdas A6 a A12 se han combinado. 

Seleccione las celdas A13:A14 e inicie su programa. 

Para cada selección realizada, el programa combina las celdas y alinea el texto en las celdas combinadas. Cada vez 
que lo ejecute, aparecerá un mensaje de alerta de la combinación. En el capítulo Trabajar en un libro Excel, verá cómo 
evitar estos mensajes con la propiedad DisplayAlerts. 

En el capítulo sobre los bucles veremos cómo automatizar el programa para combinar todas las celdas sin necesidad 
de seleccionarlas previamente. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Otras técnicas para mejorar el código
Cuando  use  la  Grabadora  de  macros,  puede  reescribir  fácilmente  algunas  acciones  para  mejorar  la  ejecución  y  la 
lectura del código. 

1. Grabar acciones con dos hojas de cálculo

Ilustraremos este punto con un ejemplo muy simple. 

Realice las siguientes operaciones: 

En un nuevo libro, introduzca una palabra o una cifra en la celda A1. 

Inicie la Grabadora de macros. 

Inserte una nueva hoja. 

Vuelva a la Hoja1. 

Copie el contenido de la celda A1 en B4. 

Copie el contenido de la celda B4. 

Seleccione la celda Hoja2 del libro. 

Pegue el contenido del Portapapeles en la celda C2. 

Cambie el formato de la celda C2 (fuente, color). 

Vuelva a la hoja Hoja1. 

Elimine el contenido de la celda A1. 

Detenga la grabación. 

El código generado debería ser similar a esto: 

Sub Macro1()
Sheets.Add After:=ActiveSheet
Sheets("Hoja1").Select
Range("A1").Select
Selection.Copy
Range("B4").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Selection.Copy
Sheets("Hoja2").Select
Range("C2").Select
ActiveSheet.Paste
Application.CutCopyMode = False
Selection.Font.Bold = True
Selection.Font.Underline = xlUnderlineStyleSingle
With Selection.Interior
.Pattern = xlSolid
.PatternColorIndex = xlAutomatic
.Color = 65535
.TintAndShade = 0
.PatternTintAndShade = 0

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
End With
Sheets("Hoja1").Select
Range("A1").Select
Selection.ClearContents
End Sub

Observe que cada etapa (seleccionar, copiar, pegar, eliminar) se ha codificado en el orden especificado. Veamos a 
continuación cómo reducir el código sin que el resultado varíe. 

2. La instrucción Select

Un análisis rápido del código muestra que la instrucción  Select está presente prácticamente en todas las líneas. 
Cuando tenga una línea que termine por  Select y el siguiente empiece por  Selection, podrá eliminar los dos 
términos y escribir una sola línea de código : 

Range("A1").Select
Selection.Copy

Pasará a : 

Range("A1").Copy

Al eliminar todas esas repeticiones en  Select, limpiará el código y reducirá sensiblemente el número de líneas de 
código generado por la Grabadora. 

3. La instrucción Copy

La grabadora de macros traduce la operación Copiar/Pegar en cuatro líneas de código: 

Range("A1").Select
Selection.Copy
Range("B4").Select
ActiveSheet.Paste

Es  posible  escribir  todas  esas  instrucciones  en  una  sola  línea  de  código.  El  método  Copy  posee  una  serie  de 
opciones entre las que se encuentra una llamada Destination. Con esta opción podrá copiar el contenido de una 
celda y pegarlo en otra dentro de la misma instrucción. 

Range("A1").Copy Destination:=Range("B4")

Como veremos en la siguiente sección, el método  Copy puede reemplazarse muy bien por otro método, siempre y 
cuando solo debamos copiar el contenido de una celda. Por el contrario, si lo que debemos copiar es un rango de 
celdas Range("A1:C3"), deberá usarse el método Copy, que es sumamente sencillo de usar. 

4. Transferencia de datos 

Cuando tenga que copiar el contenido de una sola celda en otra, no será preciso usar el método  Copy, bastará con 
transferir el valor de una celda a la otra. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Range("B4") = Range("A1") ’Copia el contenido de A1 en B4
Cells(2, 4) = Cells(1, 1) ’Misma acción

Esto es también válido para copiar el contenido de celdas entre hojas de cálculo. En ese caso habrá que especificar 
el nombre de las hojas en la instrucción: 

Sheets("Hoja2").Range("C2") = Sheets("Hoja1").Range("B4")
Sheets("Hoja2").Cells(3, 2) = Sheets("Hoja1").Cells(2, 4)

5. El bloque de datos With ... End With 

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: 

With Sheets("Hoja2").Range("C2")
.Font.Bold = True
.Font.Underline = xlUnderlineStyleSingle
.Interior.Pattern = xlSolid
.Interior.Color = 65535
End With

O también 

With Sheets("Hoja2").Range("C2")
.Font.Bold = True
.Font.Underline = xlUnderlineStyleSingle
With .Interior
.Pattern = xlSolid
.Color = 65535
End With
End With

6. El código optimizado

En definitiva, si aplicamos los diferentes métodos enumerados arriba, podremos escribir el código en pocas líneas: 

Sub Macro1()
Sheets.Add After:=ActiveSheet
Sheets("Hoja1").Select
Range("B4") = Range("A1")
Sheets("Hoja2").Range("C2") = Sheets("Hoja1").Range("B4")
With Sheets("Hoja2").Range("C2")
.Font.Bold = True
.Font.Underline = xlUnderlineStyleSingle
.Interior.Pattern = xlSolid
.Interior.Color = 65535

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
End With
Sheets("Hoja1").Range("A1").ClearContents
End Sub

Escrito  de  esta  forma,  el  código  es  más  fácil  de  leer  ya  que  una  línea  de  código  corresponde  a  una  acción  y  la 
ejecución se ve sensiblemente mejorada. 

- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Síntesis
Utilizar la Grabadora de macros tiene ventajas, pero también inconvenientes: 

Ventajas  Inconvenientes 

Permite recuperar el código de objetos, de propiedades,  La Grabadora de macros escribe muchos código inútil. 
de  métodos,  así  como  los  parámetros  de  formato  Todas  las  referencias  de  celdas  se  graban 
(color, bordes, orientación, casillas de formulario, etc.).  "literalmente"  (se  transcriben  con  sus  coordenadas,  sin 
posibilidad de cambiarlas). 
Todas  las  acciones  se  escriben  a  medida  que  se  van 
realizando,  sin  posibilidad  de  repetición  (véase  Los 
bucles). 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Introducción
Como vimos en el capítulo Primer programa, la Grabadora de macros convierte cada una de las selecciones de celda, 
de rango de celdas, en referencias fijas: 

Range("A3:B5").Select
Range("C8").Select
Columns("D").Select

Este tipo de escritura del código tiende  a  desaparecer ya que las referencias serán invariablemente las mismas. Es 
decir, el interés de hacer un programa es aplicar una instrucción a un elemento (una celda, una hoja de cálculo, un 
libro, un gráfico, etc.) y después reproducir esta instrucción en otros elementos. 

Este  es  el  motivo  por  el  que  no  deben  escribirse  las  referencias  de  una  celda  directamente  en  el  código,  sino  que 
deberá usarse una variable que, como su propio nombre indica, permitirá hacer variar las coordenadas de la celda. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
¿Qué es una variable?
Las variables pueden verse como cajas en las que se almacenan una serie de informaciones: cifras, fechas, texto, etc. 

Por  supuesto  que  no  se  trata  de  una  caja  en  el  sentido  literal,  sino  de  un  espacio  reservado  en  la  memoria  del 
ordenador.  Como  el  ordenador  administra  este  espacio  en  la  memoria,  la  cuestión  no  está  ahí.  Lo  que  debemos 
recordar es que creando una variable (una caja) con un nombre propio, el VBA sabrá siempre en qué caja deberá leer 
o recuperar los datos. De hecho, bastará con declarar un nombre de variable y atribuirle un tipo de datos para que 
Visual Basic se ocupe del resto. 

Realmente no hay reglas para el nombre que le da a sus variables; puede escoger cualquier palabra con la condición 
de que no sea una de las palabras reservadas (palabras clave) de VBA (como Sheets, Cells, Worksheets, Columns, 
Rows, etc.). 

Una variable puede estar compuesta por una o varias palabras, pero estas no deben estar separadas por un espacio
o por un guion (­). El único carácter de separación autorizado es el guion bajo (_). 

Para lograr mayor eficacia en la gestión de las variables es preferible optar por nombres comprensibles (Núm_Fila, 
Nombre_Libro, Nombre_Hoja, etc.), en lugar de elegir nombres compuestos de una sola letra (i, j, k, etc.). 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
El método MsgBox
El método MsgBox es una función importante para comprender programas en Visual Basic ya que permite mostrar en 
todo momento mensajes personalizados. Pero  MsgBox no solo muestra mensajes personalizados, sino que también 
bloquea la ejecución del resto del código. 

1. Vista de un mensaje personalizado

Escriba, por ejemplo, el programa siguiente: 

Sub Test_Vista()
MsgBox "Mensaje personalizado"
End Sub

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ódulo 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) = 1 + 1
Cells(1, 3) = 1 * 1
End Sub

El resultado es el siguiente: 

Si  iniciamos  varias  veces  este  programa,  obtendremos  siempre  el  mismo  resultado.  Es  lógico,  ya  que  siempre 
llamamos a los mismos valores. 

Para hacer más dinámico este programa, vamos a reemplazar todos los valores 1 por una variable. 

El código pasa a ser: 

Sub Cálculo()
Dim Val_Data As Long
Val_Data = 1
Cells(1, 1) = Val_Data
Cells(1, 2) = Val_Data + Val_Data
Cells(1, 3) = Val_Data * Val_Data
End Sub

Si iniciamos varias veces este programa, el resultado seguirá invariable ya que la ejecución se hará siempre con el 
valor 1. 

Ahora, si le damos el valor 2 a la variable Val_Data, obtendremos el siguiente resultado: 

Por descontado, cambiar a mano el valor de la variable es una herejía, pero en el capítulo Los bucles veremos cómo 
automatizar  la  actualización  del  valor  de  nuestra  variable.  También  podemos  utilizar  el  método  InputBox  como 
veremos en el siguiente párrafo. 

La variable Val_Data también puede usarse como parámetro del número de fila en la instrucción Cells. 

El código pasa a ser: 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Sub Cálculo()
Dim Val_Data As Long
Val_Data = 1
Cells(Val_Data, 1) = Val_Data
Cells(Val_Data, 2) = Val_Data + Val_Data
Cells(Val_Data, 3) = Val_Data * Val_Data
End Sub

Inicie tres veces seguidas el programa con los valores para la variable Val_Data: 1, 2 y 3. 

El resultado figura en su hoja de cálculo en las filas 1, 2 y 3: 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
El método InputBox
En  el  ejemplo  precedente,  para  cambiar  el  valor  de  la  variable,  no  tenemos  otra  opción  que  modificar  el  programa 
cambiando manualmente el valor de la variable  Val_Data. Coincidirá con nosotros en que esa no es una solución 
demasiado práctica. 

Para evitar tener que cambiar a mano el valor de algunas variables en el programa, es posible transmitir el valor de 
una variable en un programa en curso de ejecución. Esto puede hacerse gracias al método InputBox. 

El método InputBox se construye en parte como el método MsgBox pero además, hay que prever una variable que 
recibirá el valor que se quiere transmitir al programa.  

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 As Variant


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 si Verdadero]
[ELSE]
[Instrucciones si Falso]
END IF

1. Presentación

La instrucción IF es muy simple de entender. Se realiza un test (o condición) que sea o bien verificado (Verdadero) o 
bien no verificado (Falso). 

Por ejemplo, puede comprobar: 

l el valor de los números de fila, 

l si una celda está o no vacía, 

l la diferencia de valor entre dos celdas, 

l la presencia de una hoja en un libro, 

l ... 

Una condición solo devuelve dos datos: el test es Verdadero o Falso (y nada más). 

En el caso de que el test sea Verdadero, el programa ejecuta las instrucciones que se encuentran después de THEN
(traducción de Entonces). 

Si el resultado de la condición es Falso, el programa realiza las instrucciones que se encuentran después de  ELSE
(traducción de Si no). 

"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 Cells(Núm_Fila , 3) = 1 Then
Cells(Núm_Fila , 2) = Cells(Núm_Fila , 2) + 3
Else
Cells(Núm_Fila , 2) = Cells(Núm_Fila , 2) + 1
End If
End Sub

Ahora, basta con que cambie el número de línea para aplicar este código a todos los equipos: 

Inicie su programa para Núm_Fila = 3. 

Inicie su programa para Núm_Fila = 4. 

Inicie su programa para Núm_Fila = 5. 

Inicie su programa para Núm_Fila = 6. 

Inicie su programa para Núm_Fila = 7. 

En el capítulo Los bucles veremos cómo hacer para que los valores de las variables se modifiquen automáticamente. 

Y el resultado en la pantalla pasa a ser: 

5. Abreviatura de escritura

Como la instrucción IF es una de las funciones más utilizadas en programación, existen otras formas de escribirla. 

Retomando  el  mismo  ejemplo,  si  el  resultado  es  una  derrota  sin  ningún  punto,  ya  no  necesitamos  la  instrucción 
Else. Añadir 0 al resultado anterior obviamente no tiene sentido. Por lo tanto, nuestro test se escribiría: 

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

Pero en ese caso, también podríamos haber escrito toda la instrucción en una sola línea, colocando el resultado de 
la condición justo después de la instrucción THEN: 

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-
Una instrucción IF con Else también puede escribirse en una sola línea. En ese caso, hay que utilizar la instrucción 
lif que respeta la misma sintaxis que la función SI en Excel: 

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


Case Valor1
Instrucción
Case Valor2
Instrucción
Case Valor...
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 Case también puede especificar en una misma conexión, todos los valores no contiguos posibles 
que puede tomar el valor verificado. Para ello, basta con separar cada uno de ellos con una coma. 

Por ejemplo, quiere crear un test que muestre la palabra "Número primo" en B1 en función del valor contenido en 
A1. 

Sub Es_Primo()
Select Case Cells(1, 1)
Case 1, 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37,
Cells(1, 2) = "Número primo"
Case Else
Cells(1, 2) = "No es un número primo"
End Select
End Sub

c. Test en valores contiguos

Puede  indicar  que  una  conexión  Case  debe  ejecutarse  para  todos  los  valores  comprendidos  en  un  intervalo 
mediante  la  instrucción  To.  Por  ejemplo,  si  realiza  un  test  que  devuelva  la  calificación  en  función  del  valor 
contenido en A1. Su test se escribirá de la siguiente forma: 

Sub Resultado_Examen()
Select Case Cells(1, 1)
Case 0 To 4.99
Cells(1, 2) = "No aprobado"
Case 5 To 5.99
Cells(1, 2) = "Aprobado"
Case 6 To 6.99
Cells(1, 2) = "Aprobado. Bien"
Case 7 To 8.99
Cells(1, 2) = "Aprobado. Notable"
Case Else
Cells(1, 2) = "Aprobado. Sobresaliente"
End Select
End Sub

Observe  que  las  diferentes  conexiones  no  se  solapan.  Sin  embargo,  si  se  diese  el  caso,  el  programa  no  habría 
detectado la anomalía y habría devuelto el primer caso respondiendo al criterio de selección. 

3. Reversibilidad

Hasta ahora, hemos realizado tests en el valor de una celda o de una variable. Pero a la inversa también es posible. 
La instrucción Select Case permite verificar un valor y encontrar en qué caso se ha verificado ese test. 

A modo de ejemplo, cojamos el siguiente libro (Ejemplo 6­C3): 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Queremos aplicar un porcentaje de descuento en función del estado civil de un individuo. 

Para ello, creamos una función personalizada llamada Estado_Civil. 

Vamos a utilizar la instrucción Select Case para verificar que una celda es igual a 1 o bien Verdadero (True). 

Function Estado_Civil
Select Case True
Case Cells(1, 2)
Estado_Civil = 5
Case Cells(2, 2)
Estado_Civil = 0
Case Cells(3, 2)
Estado_Civil = 10
Case Cells(4, 2)
Estado_Civil = 15
Case Else
Estado_Civil = ”Imposible”
End Select
End Function

En la celda B6, escriba =Estado_Civil(). 

Observe que en caso de que tenga que verificar el valor 1 o 0, también puede verificar en valores  True (Verdadero) 
o False (Falso). 

Esta técnica de programación es muy útil para hacer tests en cuadros de diálogo y saber qué casillas de verificación 
se han marcado y cuáles no. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
¿IF o SELECT CASE?
Hace algunos años, la instrucción Select Case desapareció de los programas ya que requería demasiada memoria. 
Después cambiaron las cosas y el problema de la memoria se volvió obsoleto. Sin embargo, las ideas arraigadas son 
difíciles de cambiar y la instrucción Select Case no es muy popular entre los programadores. 

Lejos  de  estas  consideraciones,  es  más  coherente  utilizar  la  función  IF  cuando  solo  hay  una,  dos  o  incluso  tres 
posibilidades. A partir de ahí, es preferible utilizar la función Select Case. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Ejemplo de uso de dos instrucciones
Tomemos el siguiente ejemplo donde queremos extraer datos de una hoja de cálculo para copiarlos en otra. Sabemos 
que  este  trabajo  puede  hacerse  a  través  la  herramienta  Filtro  de  Excel,  sin  embargo,  si  debemos  llevar  a  cabo  la 
operación a menudo, el hecho de crear un programa nos hará ganar mucho tiempo. Para ello escribiremos un test que 
usará la instrucción IF y la instrucción Select Case. 

1. Crear un test en función de los parámetros

Desea  crear  un  programa  que  extraerá  una  serie  de  información  a  partir  de  un  rango  de  datos  y  quiere  que  los 
propios usuarios escojan ellos mismos la columna de filtrado y el valor que desean filtrar. 

En tales casos, muchos desarrolladores de Excel usarían la Grabadora de macros para recuperar el código generado 
por Excel. Esta solución funciona, por supuesto, pero genera un bloqueo porque obliga a conservar en el código el 
valor de la columna que queremos filtrar, el criterio de filtrado (mayor, menor, diferente, etc.) y el valor a partir del 
cual se hará el filtro. 

Ahora bien, lo que nosotros queremos es que el usuario pueda elegir libremente esos tres elementos: la columna a 
filtrar, el criterio de filtrado y el valor para realizar el filtro. 

Supongamos  que  tenemos  el  siguiente  documento,  en  el  que  hay  fechas,  nombres  de  los  clientes,  artículos, 
cantidades y valores. Podrá descargar este ejemplo, llamado Ejemplo 6­E1.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 6­E2.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 6­E2.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

Al principio, la variable Index se inicia con el valor indicado. Si escribimos  For
Index = 1, la variable Index valdrá 
1, si escribimos For Index = 50, la variable Index valdrá 50, y así sucesivamente. 

A continuación, el programa interpretará las líneas de código correspondientes a su Instruction usando el valor 
de la variable Index. 

Por último, cada vez que se alcance la instrucción  Next, la variable Index se incrementará. El incremento estará en 
función del valor del Paso (si se omite el Paso, el incremento será de una unidad). 

Todas las etapas del bloque Instruction se repetirán hasta que la variable Index alcance el valor límite definido 
por la instrucción To. 

2. Primer ejemplo de bucle

Vamos a retomar el ejemplo del método InputBox realizado en el capítulo Las variables pero vamos a remplazar la 
instrucción InputBox por un bucle para que el programa ejecute 10 veces los cálculos. El programa pasa a ser: 

Sub Programa_Principal()
Dim Val_Data As Long
For Val_Data = 1 To 10
Cells(Val_Data, 1) = Val_Data
Cells(Val_Data, 2) = Val_Data + Val_Data
Cells(Val_Data, 3) = Val_Data * Val_Data
Next Val_Data
End Sub

3. Explicación del código

Al iniciar el bucle, la variable Val_Data toma el valor 1. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
A continuación, el programa accede al bloque de instrucciones que se repetirá; la variable Val_Data se utiliza en 
los  parámetros  de  cálculo  y  para  escribir  el  resultado.  En  nuestro  primer  pasaje,  el  resultado  se  inscribirá  en  la 
primera fila de la hoja de cálculo. El programa escribirá en la celda A1 el valor 1, en A2, el resultado 1 + 1 es decir, 2 
y en A3, el resultado 1 * 1 es decir, 1. 

A continuación, el programa llega a la instrucción Next que aumentará (o incrementará) la variable Val_Data en una
unidad. Al mismo tiempo, se realiza un test para verificar que la variable Val_Data no ha alcanzado el valor máximo 
situado  después  de  To,  es  decir,  10  en  nuestro  ejemplo.  Como  en  este  momento,  Val_Data  vale  2,  el  programa 
volverá a la instrucción For. Y así sucesivamente, hasta que la variable Val_Data alcance el último valor del bucle, es 
decir, 10. 

Al final del proceso, el resultado será el siguiente en nuestra hoja de cálculo: 

Llegados aquí podrá poner como valor máximo del bucle un valor diferente de 10. Reinicie el programa cambiando el 
valor máximo para que el nuevo resultado aparezca en la hoja de cálculo.  

A  título  de  ejemplo,  ponga  1000  como  valor  máximo  y  observe  cuánto  tiempo  emplea  su  ordenador  en  hacer  los 
cálculos. 

4. Ejemplo de bucle con dos variables

Hasta ahora, hemos utilizado una sola variable para modificar la referencia de las filas de una celda. Pero como ya 
sabe, la instrucción Cells se compone de la referencia de una fila y de una columna. También es posible crear un 
programa que haga variar el índice de las filas y el índice de las columnas. 

En el ejemplo siguiente vamos a crear una tabla de multiplicación 15x15. Y para que entienda bien la lógica de la 
construcción del programa, vamos a desgranar cada etapa. 

a. Etapa nº 1 

Para su primer programa, no trate de diseñar el problema entero. Empiece siempre su programa calculando una 
sola celda. A continuación, agregue los bucles y variables que permitan reproducir este cálculo en las demás celdas 
de la hoja. 

Empecemos, pues, por el cálculo de la primera celda: 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Sub Tabla_Multiplicación()
Cells(1, 1) = 1 * 1
End Sub

b. Etapa nº 2

Ahora introduzca el primer bucle que permita el incremento de filas. Reemplazaremos el índice de las filas por una 
variable que servirá también en nuestro cálculo. El código pasa a ser: 

Sub Tabla_Multiplicación()
Dim Núm_Fila as Long
For Núm_Fila = 1 To 15
Cells(Núm_Fila, 1) = Núm_Fila * 1
Next
End Sub

Este programa completará las quince primeras filas de la columna A dando los valores de 1x1 a 15x1. 

c. Etapa nº 3

Para finalizar, vamos a construir un segundo bucle que permita hacer variar el índice de las columnas: 

Sub Tabla_Multiplicación()
Dim Núm_Fila as Long
Dim Núm_Col as Long
For Núm_Col = 1 To 15
For Núm_Fila = 1 To 15
Cells(Núm_Fila, Núm_Col) = Núm_Fila * Núm_Col
Next
Next
End Sub

d. Síntesis

El  encadenamiento  de  tareas  es  muy  sencillo.  El  programa  ejecuta,  en  primer  lugar,  el  bucle  de  las  columnas  y 
después, el de las filas que se realiza quince veces. 

Cuando  termina  el  bucle  de  las  filas,  incrementamos  en  una  unidad  la  variable  de  las  columnas  para  rellenar  la 
columna B. Y después, volvemos a empezar el bucle de las filas partiendo del valor 1 (iniciando siempre la variable 
al principio del bucle). Esta vez los resultados se introducirán en la columna B (ya que el índice de la columna vale 
2)  para  los  valores  que  van  de  2x1  a  2x15.  Y  así  sucesivamente,  hasta  que  el  bucle  de  las  columnas  llegue  al 
último valor, 15. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Bucle según condición

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 test (ver capítulo Las condiciones). 

Por ejemplo, es posible realizar un bucle hasta que el programa alcance la primera celda conocida. Así, sea cual 
sea el número de celdas no vacías de una columna, el bucle se detendrá cuando el programa alcance la primera 
celda vacía. 

b. Ejemplo de aplicación

Vamos a escribir un programa que recorrerá todas las filas de la columna A hasta que lleguemos a la última celda. 
Por cada celda no vacía, escribiremos el número de fila de la columna B. 

Obtendremos el siguiente código, pero así escrito, no puede funcionar: 

Sub Programa_Principal()
Dim Fila_Leída As Long
While Cells(Fila_Leída, 1) <> ""
Cells(Núm_Fila, 2) = Núm_Fila
Wend
End Sub

c. Obligación

A  diferencia  de  un  bucle  FOR  ...  NEXT,  un  bucle  WHILE  impone  inicializar  el  primer  valor  de  la  variable  e 
incrementar la variable en el programa. 

El código pasa a ser: 

Sub Programa_Principal()
Dim Fila_Leída As Long
Fila_Leída = 2 ’Inicialización de la variable
While Cells(Fila_Leída, 1) <> ""
Cells(Fila_Leída, 2) = Fila_Leída
Fila_Leída = Fila_Leída + 1 ’Incremento
Wend
End Sub

Por  desgracia,  frecuentemente  olvidamos  incrementar  la  variable  del  bucle,  y  como  consecuencia,  se  bloquea  el 
programa.  Para  salir  de  esta  situación,  pulse  las  teclas  [Ctrl][Pausa]  y  podrá  volver  a  tener  el  control  de  su 
programa. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
2. Ejemplo de código

Vamos  a  retomar  el  ejemplo  del  capítulo  Primer  programa  ­  Primer  ejercicio,  que  combina  las  celdas  de  un  mismo 
cliente a partir del archivo Ejemplo 4­C. 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


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

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

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

Como habrá comprobado, para la misma fecha, puede haber uno o varios nombres. Para mejorar la legibilidad de 
este  documento,  quiere  organizar  su  tabla  presentando  en  la  misma  fila,  una  fecha  y  todos  los  nombres 
correspondientes a esa fecha. 

Para realizar esta permutación, hemos escrito el siguiente programa: 

Sub Main()
Dim Núm_Fila As Long
Dim Col_Escritura As Long, Fil_Escritura As Long

Fil_Escritura = 1

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Col_Escritura = 5
Do
Cells(Fil_Escritura, 4) = Cells(Núm_Fila, 1)
Cells(Fil_Escritura, Col_Escritura) = Cells(Núm_Fila, 2)
Col_Escritura = Col_Escritura + 1
Núm_Fila = Núm_Fila + 1
Loop While Cells(Núm_Fila - 1, 1) = Cells(Núm_Fila, 1)
Fil_Escritura = Fil_Escritura + 1
Wend
End Sub

c. Explicación del código

Empezamos  inicializando  la  variable  que  leerá  las  celdas  de  la  columna  A  Núm_Fila  y  la  que  se  utilizará  para 
escribir el resultado final (Fil_Escritura). 

A continuación, escribimos el bucle que leerá todas las celdas hasta la última celda no vacía (bucle realizado con la 
instrucción WHILE ... WEND). 

Justo  después  de  iniciar  el  bucle,  inicializamos  la  variable  de  la  columna  de  escritura  Col_Escritura.  La 
inicialización  se  hace  dentro  del  primer  bucle  ya  que  debemos  volver  a  colocarnos  en  la  columna  D  cuando 
hayamos tratado todos los nombres asociados a la misma fecha (para una explicación más detallada, consulte el 
capítulo siguiente sobre la depuración). 

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_Fila - 1, 1) = Cells(Núm_Fila, 1)
Fil_Escritura = Fil_Escritura + 1
Wend
End Sub

Otra técnica: habría sido posible escribir la fecha al salir del segundo bucle, y así evitamos realizar un test: 

Sub Main()
Dim Núm_Fila As Long
Dim Col_Escritura As Long
Dim Fil_Escritura As Long

Fil_Escritura = 1
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Col_Escritura = 5
Do
Cells(Fil_Escritura, Col_Escritura) = Cells(Núm_Fila, 2)
Col_Escritura = Col_Escritura + 1
Núm_Fila = Núm_Fila + 1
Loop While Cells(Núm_Fila - 1, 1) = Cells(Núm_Fila, 1)
Cells(Fil_Escritura, 4) = Cells(Núm_Fila - 1, 1)
Fil_Escritura = Fil_Escritura + 1
Wend
End Sub

En ese caso particular, es necesario devolver el valor de la fecha de la fila anterior. En efecto, en este momento 
acabamos de terminar el test de igualdad de la fecha y, por tanto, al salir del bucle, el valor de la fila leída señala 
la fecha siguiente. Vamos a escribir la fecha de la penúltima fila leída, es decir Núm_Fila - 1. 

Encontrará el código correspondiente en el archivo del Ejemplo 7­C3d. 

e. Trabajar con dos hojas

Seguimos queriendo leer los datos de hoja1, pero el resultado debe copiarse en hoja2 en la columna A. La tarea 
puede parecer compleja, pero, de hecho, es muy sencillo de codificar. 

Partiendo del código anterior, vamos a agregar a cada objeto Cells, el objeto Sheets. 

Para las celdas leídas, agregamos el objeto  Sheets("Hoja1") y para las celdas en las que vamos a escribir, 
agregamos el objeto Sheets("Hoja2"). 

El código pasa a ser: 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 7-
Sub Main()
Dim Núm_Fila As Long
Dim Col_Escritura As Long
Dim Fil_Escritura As Long

Fil_Escritura = 1
Núm_Fila = 1
While Sheets("Hoja1").Cells(Núm_Fila, 1) <> ""
Col_Escritura = 2
Do
Sheets("Hoja2").Cells(Fil_Escritura, Col_Escritura) =
Sheets("Hoja1").Cells(Núm_Fila, 2)
Col_Escritura = Col_Escritura + 1
Núm_Fila = Núm_Fila + 1
Loop While
Sheets("Hoja1").Cells(Núm_Fila - 1, 1) =
Sheets("Hoja1").Cells(Núm_Fila, 1)
Sheets("Hoja2").Cells(Fil_Escritura, 1) =
Sheets("Hoja1").Cells(Núm_Fila - 1, 1)
Fil_Escritura = Fil_Escritura + 1
Wend
End Sub

Encontrará el código completo en el archivo Ejemplo 7­C3e. 

- 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étodo para poder explotarla. 

Por ejemplo, desea extraer el nombre de todas las hojas de un libro para escribir el resultado en la columna A de la 
hoja Hoja1. El código es el siguiente: 

Sub Bucle_Hoja()
Dim Objeto_Hoja As Object
Dim Escrit_Fila As Long

Escrit_Fila = 1
For Each Objeto_Hoja In Worksheets
Sheets("Hoja1").Cells(Escrit_Fila, 1) = Objeto_Hoja.Name
Escrit_Fila = Escrit_Fila + 1
Next
End Sub

2. Explicación del código

Mucha  información  está  en  la  línea  FOR  EACH:  el  término  WorkSheets  indica  que  el  bucle  se  va  a  aplicar  a  la 
colección de objetos Hoja: vamos a centrarnos en el objeto "Hoja de cálculo" de nuestro libro y recorrer cada una de 
ellas. 

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  Objetos  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 hoja sobre la 
que se coloque el bucle. La siguiente imagen, que proviene de un depurador, muestra una parte de las propiedades 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
relacionadas con la hoja en la que se coloca el bucle: 

En el capítulo siguiente sobre las depuraciones veremos cómo visualizar el conjunto de propiedades de un objeto. 

Al  final,  el  programa  se  interpretará  de  la  siguiente  forma:  "Para  cada  hoja  de  nuestro  libro,  escribimos  su  nombre 
(propriedad Name del objeto) en una nueva celda. 

Desde la página Información, encontrará el archivo Ejemplo 7­D 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  voluntariamente  dos 
errores que vamos a encontrar gracias a la herramienta de depuración: 

Sub Organización_Nombre()
Dim Núm_Fila As Long
Dim Col_Escrit As Long
Dim Fil_Escrit As Long

Fil_Escrit = 1
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Col_Escrit = 5
Do
Cells(Fil_Escrit, Col_Escrit) = Cells(Núm_Fila, 2)
Col_Escrit = Col_Escrit + 1
Núm_Fila = Núm_Fila + 1
Loop While Cells(Núm_Fila - 1, 1) = Cells(Núm_Fila, 1)
Cells(Fil_Escrit, 4) = Cells(Núm_Fila, 1)
Fil_Escrit = Fil_Escrit + 1
Wend
End Sub

El código correspondiente se encuentra en el archivo Ejemplo 8­C. 

Sitúe el cursor en el procedimiento que desea iniciar. 

Inicie el programa en modo Paso a paso pulsando la tecla  [F8]. Inmediatamente verá aparecer una línea 
amarilla al principio de su procedimiento. 

La línea amarilla indica la instrucción que se va a ejecutar. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Para hacer avanzar paso a paso el programa, basta con pulsar la tecla  [F8]: cada vez que pulse la tecla 
[F8], la línea de código en amarillo se ejecuta y pasa a la línea siguiente. 

2. La combinación de teclas [Mayús][F8]

Si  trabaja  en  un  programa  que  comporta  varios  procedimientos  y  funciones,  existe  un  truco  muy  interesante  que 
permite ejecutar íntegramente procedimientos o funciones sin tener que pasar Paso a paso por el procedimiento. 

En el capítulo siguiente, Estructura de un programa, veremos cómo construir programas con varios procedimientos, 
pero aquí solo nos centraremos en el uso del depurador en estos casos. 

Imagine que tiene un programa donde hay un procedimiento que lo único que hace es buscar un valor en una tabla 
de  memoria.  Utilizar  la  depuradora  para  limpiar  fila  a  fila  toda  la  tabla  en  memoria  es  una  tarea  sumamente 
fastidiosa que además no le enseñará nada sobre el desarrollo del programa. 

De  hecho,  cuando  se  encuentra  en  la  línea  de  llamada  de  un  procedimiento  (Call)  o  una  función,  al  pulsar 
simultáneamente  las  teclas  [Mayús][F8], ejecutará el contenido del procedimiento al que se ha llamado sin tener 
que pasar todas las líneas del procedimiento en modo Paso a paso. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Inspeccionar las variables
Ahora  que  sabe  controlar  el  desarrollo  del  programa,  vamos  a  visualizar  el  contenido  de  las  variables  durante  la 
ejecución. 

Hasta ahora, para leer el contenido de las variables, hemos visto que podíamos usar el método MsgBox como vimos 
en el capítulo sobre las variables, pero este método es desventajoso ya que bloquea la ejecución del programa cada 
vez  que  aparece  el  cuadro  de  diálogo  personalizado.  Por  ese  motivo,  es  mucho  más  eficaz  usar  la  herramienta  de 
inspección para ver el contenido de las variables sin bloquear la ejecución. 

Seleccione  la  variable  que  desea  observar  mediante  un  clic  de  arrastre  y  active  el  menú  Depuración  ­ 
Inspección rápida... 

También puede activar la Inspección rápida mediante la combinación de teclas [Mayús][F9] o haciendo clic 
 
en el icono  .

Es necesario que la variable que va a inspeccionar esté previamente seleccionada. 

Aparecerá el siguiente cuadro de diálogo: 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Haga  clic  en  el  botón  Agregar,  la  variable  inspeccionada  aparece  en  una  nueva  ventana  llamada 
Inspecciones. 

La ventana Inspecciones aparece bajo el código 

Observe que, en este estadio, el valor de la variable es igual a 0. Esto se debe a que el programa aún no ha leído la 
línea amarilla. La leerá la próxima vez que pulse la tecla [F8]. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
La ventana Inspecciones
La ventana Inspecciones le permite visualizar todas las variables que ha seleccionado. 

En esa ventana, verá para cada variable: 

l su nombre, 

l su valor, 

l su tipo, 

l su procedimiento de aplicación. 

También puede seleccionar varios datos, como una operación matemática o un test. 

Del  mismo  modo,  también  puede  seleccionar  un  objeto  (como  una  hoja  de  cálculo,  etc.);  en  ese  caso,  la  ventana 
Inspecciones no muestra directamente la información. 

Haga  clic  en  el  símbolo    situado  a  la  izquierda  del  nombre  del  objeto  para  desplegar  todas  las 
propiedades relacionadas con ese objeto: 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Lo mismo ocurre con las tablas en la memoria. Al seleccionar el nombre de la tabla no verá aparecer 
ningún valor, sin embargo, si pulsa sobre el icono   situado a la izquierda del nombre de la tabla, 
aparecerá todo el contenido de la misma. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
La ventana de variables locales
Si trabaja en proyectos grandes en los que se administra un gran número de variables, puede resultar muy fastidioso 
tener que seleccionarlas unas tras otras para ver su contenido en la ventana Inspecciones. 

Para ganar tiempo, puede mostrar  todas las variables del procedimiento en curso de ejecución seleccionando en la 
barra de herramientas el menú Ver y, a continuación, el submenú Ventana Locales. 

De esta manera, bajo las líneas de código aparecerá la ventana Locales. 

Vista de todas las variables locales y procedimientos en curso 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
En este ejemplo podemos ver todas las variables del Módulo1 del procedimiento Main_Pgm (primera información que 
aparece justo antes de la ventana). 

Si trabaja en un proyecto que contiene varias Sub o Functions, al llamar a una nueva, solo serán visibles las variables 
contenidas en el nuevo procedimiento o función y lo mismo ocurrirá para todo el programa. 

Las variables locales ya no son las mismas porque el programa está ahora dentro de otra función 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
El punto de interrupción
Para evitar pasar por todo su código en modo Paso a paso, puede colocar un punto de interrupción. El principio es 
leer el código de forma normal hasta que el programa alcance el punto de interrupción; a continuación, usted retoma 
el control en modo Paso a paso. 

Acceda a la línea en la que desea marcar una parada. A continuación, haga clic en el icono   o pulse la 

tecla [F9]. 

Ahora, toda la línea de código aparece resaltada en rojo. 

También puede utilizar el ratón para hacer clic en el margen gris para mostrar/quitar un punto de interrupción. 

Inicie su programa con  [F5]. La ejecución se detendrá en el punto de interrupción y la línea amarilla (modo 
paso a paso) se superpondrá a la línea roja (punto de interrupción): 

Para continuar la ejecución, puede pulsar la tecla  [F8] para leer el programa Paso a paso o pulsar la tecla 
[F5]  para  leer  el  programa  de  forma  continua  hasta  el  próximo  punto  de  interrupción.  Si  el  punto  de 
interrupción está colocado en un bucle, el programa se detendrá en cada iteración del bucle. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
La instrucción Debug.Print
Cuando tiene un programa que repite varios cientos de veces el mismo bucle, resulta fastidioso tener que pulsar la 
tecla [F5] para que el programa continúe después del punto de interrupción. 

Para evitar esto, se pueden posicionar "marcadores" que ayudarán a proseguir la ejecución del programa. Al acabar, 
bastará con releer los diferentes marcadores para analizar el programa y ver dónde está el error. 

Para  añadir  un  marcador  al  programa  es  preciso  añadir  la  instrucción  Debug.Print  seguida  del  nombre  de  la 
variable que se quiere analizar. 

Retomaremos el primer ejemplo de este capítulo y vamos a añadirle la instrucción para seguir el valor de la variable y 
también el resultado obtenido. 

Sub Bucle_Simple()
Dim Núm_Fila As Long
For Num_ Fila = 1 To 7
Cells(Núm_Fila, 2) = Cells(Num_ Fila, 1) * 10
Debug.Print "Valor de la fila : " & Num_ Fila
Debug.Print "Resultado del cálculo : " & Cells(Num_ Fila, 1) * 10
Next
End Sub

El error de la celda A4 se ha corregido reemplazando "Hola" por el valor 4. 

Al  acabar  de  ejecutar  el  programa,  para  ver  el  seguimiento  de  la  instrucción  Debug.Print,  seleccione  la  opción 
Ventana Inmediato en la barra de menú (o utilice el método abreviado de teclado [Ctrl] G). 

Por debajo de las líneas de código verá aparecer sus líneas personalizadas con los diferentes valores de variables y 
cálculos. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Interrupción según condición
En modo depuración también puede detener la ejecución de un programa cuando una variable alcance un valor. De 
esta  manera,  los  bucles  se  ejecutarán  normalmente  hasta  el  momento  en  que  la  variable  de  referencia  alcance  el 
valor deseado. 

Imaginemos  un  documento  Excel  que  contiene  100  celdas  conocidas;  queremos  detener  la  ejecución  del  programa 
cuando este llegue a la fila 98 (para visualizar la ejecución del código hasta su término). 

Vamos  a  modificar  la  inspección  de  la  variable  Núm_Fila  para  que  el  programa  se  detenga  cuando  se  alcance  el 
valor 98. 

En la ventana Inspecciones, seleccione la variable Núm_Fila. 

Haga clic con el botón derecho y señale la opción Modificar inspección. 

Aparecerá una ventana. 

En la zona Expresión, indique el valor que debe alcanzar la variable para detener el programa (aquí 98). 
En la zona Tipo de inspección, active la opción Interrupción cuando el valor sea verdadero. 

Después de confirmar, la ventana Inspecciones ya no muestra en la primera columna el icono   sino el icono 
para indicar que se trata de una variable de tipo Interrupción. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Inicie su programa pulsando la tecla [F5], el programa se detendrá cuando la variable Núm_Fila alcance 
el valor 98. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Intervenir durante la ejecución del código
En modo Paso a paso, es posible modificar una línea de código ya ejecutada y después volver atrás situándose sobre 
ella  para  interpretarla  de  nuevo.  También  es  posible  modificar  el  valor  de  las  variables  manualmente  para  actuar 
sobre el comportamiento del programa. 

1. Vuelta atrás

Imaginemos  que  tenemos  un  programa  idéntico  al  primer  código  de  este  capítulo,  pero  con  la  instrucción 
While ... Wend. 

Sub Bucle_Simple()
Dim Núm_Fila As Long
Núm_ Fila = 1
While Cells(Núm_ Fila, 1) <> ""
Cells(Núm_ Fila, 2) = Cells(Núm_ Fila, 1) * 10
Núm_ Fila = Núm_ Fila + 1
Wend
End Sub

Inicie el programa. 

Efectúe 2 o 3 pasos en el bucle. 

Ahora supongamos que desea escribir el resultado, no en la columna B, sino en la columna C. En lugar de detener el 
programa, cambiar el valor de la columna y volver a iniciar el programa, es posible intervenir en algunos parámetros 
del código sin detener la ejecución. 

Cambie el valor de la columna 2 por 3 en el código. 

Desplace  la  línea  de  ejecución  (la  línea  amarilla)  para  situarla  antes  del  bucle  (justo  al  principio  de  la 
variable). 

Continúe con su programa en modo  Paso a paso para iniciar de nuevo el bucle con la nueva columna y 
escribir el resultado en la columna C. 

En  VBA  hay  elementos  que  no  se  pueden  modificar  cuando  el  programa  se  está  ejecutando  como,  por  ejemplo, 
cambiar el nombre a una variable, modificar el tipo de una variable o cambiar el tamaño de una tabla en memoria. 

2. Cambiar manualmente el valor de las variables

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 ... Next no 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 principal (el programa no volverá a pasar por esta instrucción hasta el final). 

Para  corregir  este  problema,  basta  con  desplazar  la  instrucción  Col_Escrit = 5  debajo  de  la  línea 
While para que la variable Col_Escrit se inicialice después de cada ciclo del bucle While. 

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_Fila - 1, 1) = Cells(Núm_Fila, 1)
Cells(Fil_Escrit, 4) = Cells(Núm_Fila - 1, 1)
Fil_Escrit = Fil_Escrit + 1
Wend
End Sub

- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Dividir un programa en varios procedimientos
Hasta el momento, hemos creado cada programa en un solo procedimiento. Pero el interés de VBA es poder construir 
un  programa  con  varios  procedimientos  o  varias  funciones  que  puedan  ejecutarse  varias  veces  a  lo  largo  de  la 
ejecución. 

1. Código inicial

La carpeta Ejemplo 9­A contiene dos libros: Cliente.xlsx y Ejemplo 9­A.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_Archivo(Rep_Trabajo)
Call Seleccionar_Datos
End Sub

Sub Abrir_Archivo (Ruta_Acceso As String)


Workbooks.Open Filename:=Ruta_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 9­A.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 9­C.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)


Range(Letra_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  9­C.  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) = Fahrenheit(Cells(Núm_Fila, 2))
Núm_Fila = Núm_Fila + 1
Wend
End Sub

3. Afectar un tipo a la función personalizada

Como las funciones personalizadas devuelven un valor, está perfectamente autorizado precisar el tipo de datos que 
devolverá la función (aunque no es obligatorio). En nuestro ejemplo podíamos haber escrito: 

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 9­D3.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 9­D4 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 9­E.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 To Ubound(Tab_Valor.Value)
La_Suma = La_Suma + Tab_Valor(indice_Tab)
Next
End Function

La escritura de la función se comprende con bastante facilidad. Hemos trasmitido el contenido de diez celdas a la 
función, lo que se traduce por la transmisión de una tabla como parámetro.  

A continuación, recorreremos toda la tabla con la variable  indice_Tab hasta llegar al último valor de la tabla dado 
por la instrucción UBound. 

Esta  instrucción  es  muy  práctica,  ya  que  sin  conocer  exactamente  el  número  de  elementos  que  la  tabla  contiene, 
sabemos que leeremos siempre todos los valores de la tabla en memoria. Estamos obligados a especificar .Value
ya que nos centramos solo en los valores transmitidos en la tabla y no en las demás propiedades. 

En el bucle principal, el resultado que la función devuelve se divide entre 10. 

3. Etapa 3: creación de la función Media

Podemos detallar aún más nuestro código separando el cálculo de la suma y el cálculo de la media, metiendo cada 
uno en una función. 

Como el cálculo de la media depende del cálculo de la suma (que es en sí misma una función), vamos a utilizar como 
parámetro de la función Media, el resultado de la función Suma. 

Modifique el código de la siguiente forma: 

Sub Pgm_Principal()
Cells(11,4) = La_Media(Range("C2:C11"))
End Sub

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 (Tab_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 bucle While que se detendrá cuando el programa llegue a la última celda no vacía de la columna 
A y cuando hayamos recorrido 10 filas (test con la función If), transmitiremos el rango de celdas a la función. 

Escriba el bucle de la siguiente forma, sustituyendo el código creado en la etapa 1: 

Sub Pgm_Principal()
Dim NúmFil As Long
Dim EncabCol As Long
NúmFil = 2
EncabCol = Cells(1, 4) ’Valor en celda D1
While Cells(NúmFil, 1) <> ""
If NúmFil > EncabCol Then
Cells(NúmFil, 4) = _
La_Media(Range(Cells(NúmFil - EncabCol + 1,3),Cells(NúmFil,3)))
End If
NúmFil = NúmFil + 1
Wend
End Sub

b. Explicación del código

Al inicio del programa, en la variable EncabCol recuperamos el valor del encabezamiento (el valor 10 en D1). 

Dentro del bucle, llevamos a cabo un test para saber si el valor de la fila leída (NúmFil) es mayor que el valor del 
encabezado de la columna. De esta forma sabremos cuándo tendremos al menos 10 celdas que debemos pasar 
como parámetros a las funciones. Por ejemplo, si la variable NúmFil vale 8, habremos leído menos valores de lo 
esperado y, por tanto, no llamaremos a la función personalizada para efectuar los cálculos. 

Cuando  hayamos  leído  al  menos  10  celdas,  llamaremos  a  la  función  La_Media  pasándole  como  parámetro  el 
rango de celdas de las 10 celdas leídas anteriormente. 

Para  escribir  esto,  vamos  a  usar  la  función  Range  y  usaremos  como  parámetro  las  coordenadas  de  la  primera 
celda Cells(NúmFil - EncabCol + 1, 3) y la última celda del rango  Cells(NúmFil, 3). En el caso de 
que la variable  NúmFil valga 11, tomaremos las coordenadas de la celda  Cells(11-10+1, 3) y de la celda 
Cells(11, 3). 

5. Etapa 5: creación del bucle para las columnas

Para hacer el cálculo de la media de las tres columnas D, E y F, basta con reemplazar el parámetro de la columna en 
la instrucción Cells por una variable y crear un nuevo bucle, solo para hacerla variar el valor de las columnas. 

Para  realizar  este  último  bucle,  podemos  utilizar  la  instrucción  FOR ... NEXT  ya  que  sabemos  que  debemos 
hacer el bucle 3 veces, para los valores 10, 20 y 30. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Ya solo quedaría reemplazar las referencias que se hacen en la columna 4 por la variable NúmCol. 

Modifique el código de la siguiente forma: 

Sub Pgm_Principal()
Dim NúmFil As Long
Dim NúmCol As Long
Dim EncabCol As Long
For NúmCol = 4 To 6
NúmFil = 2
EncabCol = Cells(1, NúmCol) ’Valor de los encabezados
While Cells(NúmFil, 1) <> ""
If NúmFil > EncabCol Then
Cells(NúmFil, NúmCol) = _
La_Media(Range(Cells(NúmFil - EncabCol + 1, 3),_
Cells(NúmFil, 3)))
End If
NúmFil = NúmFil + 1
Wend
Next
End Sub

6. Conclusión

Al final tenemos un único procedimiento que efectúa un bucle en las filas y otro en las columnas. También tenemos 
dos funciones de cálculo: la primera para el cálculo de la suma y la otra, para el cálculo de la media. El código final 
es: 

Sub Pgm_Principal()
Dim NúmFil As Long
Dim NúmCol As Long
Dim EncabCol As Long
For NúmCol = 4 To 6
NúmFil = 2
EncabCol = Cells(1, NúmCol) ’Valor encabezados
While Cells(NúmFil, 1) <> ""
If NúmFil > EncabCol Then
Cells(NúmFil, NúmCol) = _
La_Media (Range(Cells(NúmFil - EncabCol + 1, 3),_
Cells(NúmFil, 3)))
End If
NúmFil = NúmFil + 1
Wend
Next
End Sub

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 9­E5. 

© É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 9­F. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Los operadores
Uno de los aspectos clave de la programación es realizar comparaciones entre datos y, en función del resultado de 
esta comparación, efectuar un tratamiento específico. 

Este capítulo le presentará la lista completa de los operadores que están a su disposición para efectuar tests entre 
variables. 

1. Los operadores aritméticos

La siguiente tabla presenta la lista de los operadores y su significado: 

Operador   Resultado  

a  + b  Suma los valores a y b. 

a  ­ b  Resta el valor b del valor a. 
Atención, a ­ b no da el mismo resultado que b ­ a. 

a  * b  Multiplica los valores a y b. 

a  / b  Divide el valor a entre el valor b. 

a  ˆ b  Eleva una variable a a la potencia b. 

a  Mod b  Devuelve el resto de la división de a entre b (Mod significa Módulo). 

Los operadores aritméticos respetan el orden de prioridades matemáticas. 

Si  una  operación  utiliza  varios  operadores  aritméticos,  las  potencias  se  calcularán  siempre  antes  que  la 
multiplicación y la división, que a su vez, se calcularán antes que la resta y la suma. 

Para modificar el orden de prioridad de los cálculos, puede emplear los paréntesis. 

Por ejemplo: 

l 4*4ˆ2­1/4 = 63,75 

l 4*4ˆ(2­1)/4 = 4 

l 4*4ˆ((2­1)/4) = 5.65 

l (4*4)ˆ((2­1)/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 (par­par/impar­impar). 

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 textuales (String), deberá convertir el tipo de sus variables en uno de los tipos de datos 
numéricos existentes. 

1. Funciones de conversión

La siguiente tabla le presenta el conjunto de funciones de conversión de Visual Basic: 

Función  Resultado 

CDbl (variable)  Convierte la variable en tipo Double. 

CLng (variable)  Convierte la variable en tipo Long. 

CStr (variable)  Convierte la variable en tipo String. 

CDate (variable)  Convierte la variable en tipo Date. 

Pero atención, la conversión de una variable en un cálculo no transforma su tipo permanentemente para el resto del 
programa. La conversión solo se aplica para la instrucción o el cálculo en el que se utiliza la variable. 

2. Probar una variable

La utilización de una cadena de caracteres en un cálculo provoca la detención del programa. Si tiene dudas sobre el 
contenido de una variable, es preferible efectuar un test sobre el tipo.  

Se  pueden  probar  dos  tipos  de  datos:  los  datos  que  utilizan  la  función IsDate  y  los  datos  numéricos  con 
IsNumeric. 

Por ejemplo, puede realizar el test siguiente para comprobar el tipo de datos contenidos en la celda A1. 

Sub Test_Dato()
If IsNumeric(Cells(1,1)) Then
MsgBox "La celda A1 contiene un valor numérico"
Else
MsgBox "La celda A1 no contiene cifras"
End If
End Sub

La instrucción  IsNumeric devuelve Verdadero o Falso; según el valor contenido en la celda A1, se mostrará uno de 
los dos mensajes. 

En  este  ejemplo,  podemos  omitir  precisar  el  test  =   True,  ya  que  es,  por  defecto,  el  valor  probado  con  If. Puede 
agregar = True para más claridad, esto no cambiará en absoluto el resultado del test: 

’ 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  11­B1b.  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:=Sheets(Sheets.Count)
ActiveSheet.Name = Sheets("Hoja1").Cells(Núm_Fila, 1) & " " &
Sheets("Hoja1").Cells(Núm_Fila, 2)
Núm_Fila = Núm_Fila + 1
Wend
End Sub

El resultado corresponde a la imagen siguiente: 

Encontrará el código completo en el archivo del Ejemplo 11­B1c. 

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) = Mid(Cells(Núm_Fila, 1), 11, 7)
Núm_Fila = Núm_Fila + 1
Wend
End Sub

- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
3. Sustitución

a. Función Mid

La función Mid tiene un segundo uso: también permite reemplazar una parte de los caracteres de una cadena por 
otros en un lugar concreto. 

Tomando el ejemplo anterior, deseamos reemplazar el carácter "­" por el carácter "/". 

Modifique el código del siguiente modo: 

Sub Bucle_Principal()
Dim Núm_Fila As Long
Dim Cadena_a_tratar As String
Núm_Fila = 1
While Cells(Núm_Fila, 1) <> ""
Cadena_a_tratar = Cells(Núm_Fila, 1)
Mid(Cadena_a_tratar, 9, 1) = "/"
Cells(Núm_Fila, 1) = Cadena_a_tratar
Núm_Fila = Núm_Fila + 1
Wend
End Sub

Atención: la substitución se hace en la memoria. No es posible hacer la modificación y, al mismo tiempo, mostrar el 
resultado en la hoja de cálculo. 

Ese es el motivo por el cual el contenido de la celda se almacena en la variable Cadena_a_tratar, la sustitución 
se hará desde esta variable y el contenido de esta variable se copiará en la misma celda que la celda de origen. 

b. Función Replace

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 (0­9) 

[ 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, 68­64 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 absolutamente necesario que especifique si accede a un archivo de lectura (Input) o de escritura (Output). Sin 
este parámetro, su archivo no se podrá abrir nunca. 

c. Número de archivo

Para  cada  archivo  que  abra,  tendrá  que  concretar  un  número  de  orden  que  permitirá  identificar  sus  archivos 
durante el tratamiento. Puede gestionar usted mismo los números (1, 2, 3,...) o pedirle a VBA que gestione esos 
números mediante la instrucción FreeFile. 

Para nuestro ejemplo, podemos escribir la siguiente instrucción que abrirá nuestro archivo de texto: 

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 11­D4. 

© É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 11­D4. 

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  (add­in)  que  puede  descargarse  de  forma  gratuita  en  esta  dirección: 
https://www.microsoft.com/es­es/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  11­D5.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 11­D5b1. 

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 11­D5b2. 

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) = " " Then ’Si 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 11-B5.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 11­D5b3. 

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, Extract ’Lectura primera fila del archivo

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


If InStr(Extract, "[Billar]") > 0 Then
Tabla_Extracción = Split(Extract, ",")
Call Escritura_Excel(Tabla_Extracción) ’ver más 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_Extracción = Split(Cells(Núm_Fil, 3), "")
i_tab = 0
Do
ActiveSheet.Cells(Núm_Fil, i_tab + 4) =
Trim(Tabla_Extracción(i_tab))
i_tab = i_tab + 1
Loop While i_tab <= Ubound(Tabla_Extracción)
Núm_Fil = Núm_Fil + 1
Wend
End Sub

Esta  vez,  no  recorremos  todo  el  archivo  de  texto  sino  solo  la  columna  C  desde  la  fila  1.  Para  cada  celda  leída, 
utilizamos la función Split para almacenar en la memoria cada subcadena. El resultado se inscribe en la columna D 
(en el programa, la columna D se traduce por el valor i_tab + 4). 

El resultado no siempre es satisfactorio ya que para los números de provincias inferiores a 10, perdemos el 0 del 
principio. A continuación, para el nombre de las ciudades compuesto por varias palabras tenemos la información 
escrita en varias columnas como vemos en la imagen siguiente: 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 11 -
Concatenación de las ciudades  

Solo queremos conservar el número de la provincia y el nombre de las ciudades. 

Para ello, tendremos que crear toda una serie de condiciones muy complejas para tratar todos los casos posibles: 

En efecto, la información contenida en la columna C no está nada estructurada. Tras el nombre de la ciudad, puede 
haber: 

l ninguna otra información; 

l el nombre de la sala de billar; 

l información sobre los billares; 

l el número de teléfono. 

Por  lo  tanto  es  absolutamente  necesario  realizar  tests  para  cada  caso,  lo  que  supone  un  código  enormemente 
pesado. 

Como verá, es preferible trabajar con archivos bien estructurados para evitar tener que tratar un gran número de 
casos de test y cargar inútilmente sus programas. 

Por último, también hay que realizar un test para gestionar la extracción de las ciudades compuestas por una o 
varias palabras. 

El código completo es el que presentamos a continuación. 

Sub Tratamiento_Columna_C()
Dim Núm_Fil As Long
Dim i_tab As Long
Dim Tabla_Extracción As Variant
Dim Nombre_Ciudad As String
Dim Max_Dim_Tabla As Long
Dim Test_Fin_Bucle As Boolean ’Variable que le servirá para dejar
de recorrer la tabla en la memoria.

Núm_Fil = 1
While Cells(Núm_Fil, 3) <> ""
Tabla_Extracción = Split(Cells(Núm_Fil, 3), "")

’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ínea, 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_tab + 1 ’Incremento de la tabla
Wend
Núm_Fil = Núm_Fil + 1 ’Incremento de la fila de escritura
Wend
End Sub

Encontrará en la página Información el archivo Ejemplo 11­D45c 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á siempre el último día del mes: 

DateSerial(Year(Date); Month(Date) + 1; 1) - 1

4. Meses en letras

La instrucción  MonthName permite convertir un número en un mes escrito con letras. Por ejemplo, si tiene el valor 
9, la siguiente escritura le dará la indicación Sept o Septiembre. 

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 12­E4: 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Tiene un documento que representa las notas de los gastos para el mes de enero. Para evitar volver a copiar once 
veces la hoja Enero y después cambiar manualmente el nombre de las hojas, puede construir una macro: 

Utilice  la  Grabadora  de  macros  para  crear  una  copia  de  la  hoja  Enero  y  cambiar  el  nombre.  El  código 
obtenido es: 

Sheets("Enero").Select
Sheets("Enero").Copy After:=Sheets(1)
Sheets("Enero (2)").Select
Sheets("Enero (2)").Name = "test"

Podemos reducir la escritura de las dos últimas líneas en una sola, ya que cuando se agrega una nueva hoja, esta 
pasa a ser automáticamente la hoja activa. Podemos escribir: 

Sheets("Enero").Copy After:=Sheets(1)
ActiveSheet.Name = "test"

Ahora vamos a  crear un bucle que irá del mes de febrero al mes de diciembre. Por lo tanto, el bucle empezará por 2 
y acabará por 12. 

Sub Añadir_Hoja()
Dim Mi_Mes As Long

For Mi_Mes = 2 To 12
Sheets("Enero").Copy After:=Sheets(1)
ActiveSheet.Name = MonthName(Mi_Mes, False)
Next
End Sub

Nos falta resolver un problema en este programa, ya que la adición de hojas no respeta el orden de los meses. Para 
que la nueva hoja se agregue en última posición, y así conservar el orden natural de los meses, vamos a sustituir la 
cifra 1 del parámetro After:=Sheets(1) por la variable Mi_Mes. De esta forma, cada nueva hoja se agregará en 
última posición. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Y, para que la primera letra de cada mes esté en mayúscula, vamos a poner la función StrConv:  

Sub Adición_Hoja()
Dim Mi_Mes As Long

For Mi_Mes = 2 To 12
Sheets("Enero").Copy After:=Sheets(Mi_Mes - 1)
ActiveSheet.Name = StrConv(MonthName(Mi_Mes, False), _
vbProperCase)
Next
End Sub

Puede descargar el código completo de este ejemplo, el archivo correspondiente se llama Ejemplo 12­E4b. 

- 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
Nº_Dí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)
NºSEM = DateSerial(Year(D + (8 - WeekDay(D)) Mod 7 - 3), 1, 1)
NºSEM = ((D - NºSEM - 3 + (WeekDay(NºSEM) + 1) Mod 7)) \ 7 + 1
End Function

Encontrará el código de esta función en el archivo Ejemplo 12­G3. 

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
Nº_Dí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 12­G4. 

© É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/es­es/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 13­E.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 copiar­pegar suspendido

Cuando  lleva  a  cabo  una  operación  de  copiar­pagar  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 "Informe - " & Nombre_Archivo
Nombre_Archivo = Dir
Wend
End Sub

2. Bucles con los directorios

Si solo desea recuperar los nombres de subdirectorios del nivel inferior, puede añadir un parámetro a la instrucción 
Dir: 

Dir(Ruta, parámetro)

Los posibles valores del parámetro son: 

vbNormal  (Predeterminado) Especifica los archivos sin atributos. 

vbReadOnly  Especifica los archivos accesibles solo en modo lectura, así como los archivos sin atributos. 

vbHidden  Especifica los archivos ocultos, así como los archivos sin atributos. 

vbSystem  Especifica los archivos del sistema, así como los archivos sin atributos. 

vbVolume  Especifica  el  nombre  de  volumen;  si  se  especifica  otro  atributo,  la  constante  vbVolume  se 
ignora. 

vbDirectory  Especifica las carpetas, así como los archivos sin atributos. 

Para  recuperar  los  nombres  de  los  directorios,  hay  que  utilizar  el  parámetro  vbDirectory.  Pero  atención, 
recuperará los nombres de los directorios, pero también los nombres de los archivos. 

También  recuperará  los  indicadores  del  directorio  actual  (simbolizado  por  un  punto)  y  del  directorio  superior 
(simbolizado por dos puntos). Es interesante hacer un test para evitar tratar estos dos casos en su programa: 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
If Nombre_Archivo <> "." And Nombre_Archivo <> ".." Then
Instrucciones
End If

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
If (GetAttr(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 14­D. 

’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(msoFileDialogFolderPicker).Show
End Sub

Pero  mostrar  el  cuadro  de  diálogo  para  seleccionar  un  directorio  no  es  suficiente,  después  es  preciso  recuperar  el 
nombre del directorio seleccionado. Para ello será preciso escribir la siguiente línea de código: 

Sub Dir_Selection ()
Dim Dir As String
Application.FileDialog(msoFileDialogFolderPicker).Show
Dir = Application.FileDialog(msoFileDialogFolderPicker).SelectedItems(1)
MsgBox Dir
End Sub

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Seleccionar un archivo
Continuando con la instrucción FileDialog, también es posible seleccionar uno o varios archivos. Para ello deberá 
modificarse el parámetro entre paréntesis. Por ejemplo, para seleccionar un archivo, escribirá: 

Sub Selection_Un_Archivo()
Application.FileDialog(msoFileDialogFilePicker).AllowMultiSelect = False
Application.FileDialog(msoFileDialogFilePicker).Show
MsgBox Application.FileDialog(msoFileDialogFilePicker).SelectedItems(1)
End Sub

Para seleccionar varios archivos dentro del mismo directorio, deberá posicionar el indicador de multiselección en True y 
después hacer un bucle para recuperar los nombres de los archivos seleccionados. 

Después, lo más sencillo para tratar todos los archivos es almacenar sus nombres en una tabla en memoria (vea el 
capítulo Optimización ­ Las tablas en memoria para comprender cómo trabajar con tablas en memoria). 

Sub Selection_X_Archivos()
Dim Tab_Nombre_Archivo() As String
Dim Index_ Archivo As Long
Application.FileDialog(msoFileDialogFilePicker).AllowMultiSelect = True
Application.FileDialog(msoFileDialogFilePicker).Show
For Index_Archivo = 1 To Application.FileDialog(msoFileDialogFilePicker). _
SelectedItems.Count
ReDim Preserve Tab_Nombre_ Archivo (Index_ Archivo - 1)
Tab_Nombre_ Archivo (Index_ Archivo - 1) = _
Application.FileDialog(msoFileDialogFilePicker).SelectedItems(Index_ Archivo)
Next
End Sub

Encontrará ese código en el archivo Ejemplo 14­G. 

© É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 15­B1 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.Row ’Primera 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
ReDim Preserve 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", True)

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", False)

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 15­D1) 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 15­D4 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 Declare PtrSafe Function FindWindow Lib "User32" Alias _
"FindWindowA" (ByVal lpClassName As String, ByVal _
lpWindowName As String) As LongPtr
#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 15­F. 

- 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 e­mails, 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 e­mails 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")
.Send ’o .Display 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" & vbNewLine & _
"La ruta indicada no es correcta" & vbNewLine & _
"No quiere eliminar el PDF existente."
End If
End Sub

Descargue el archivo Ejemplo 16­E2 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:"
& vbNewLine & _
"La dll 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 16­Access1.xlsm desde la página Información. 

Sub Consulta_Access_SELECT()
Dim Mi_Base As New ADODB.Connection
Dim Mi_Consulta As New ADODB.Recordset
Dim Base_Data As String
Dim SQL_Req As String
’Ubicación y Nombre de la base de datos
Base_Data = "C:\Users\Base_Access_Ejemplo.accdb"
’ Abrir la conexión con la base de datos
Set Mi_Base = New ADODB.Connection
Mi_Base.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & _
"Data Source=" & Base_Data & ";"

’ Creación de la consulta
SQL_Req = "SELECT * From Table1"
’Ejecución de la consulta
Mi_Consulta.Open SQL_Req, Mi_Base, adOpenForwardOnly
’Test para cerciorarse de que no hay errores en el acceso a la tabla

If Mi_Consulta.Status = 0 Then
’copia de la consulta en celda A1
Range("A1").CopyFromRecordset Mi_Consulta
End If
’Cierre del RecordSet y de la conexión
Mi_Consulta.Close
’Cierre de la conexión a la base para liberar memoria
Mi_Base.Close
End Sub

3. Insertar nuevos registros en Access

Desde Excel pueden añadirse nuevos registros a una base de datos. Esto puede hacerse a través de una consulta 
SQL o bien añadiendo métodos al objeto RecordSet. A continuación presentamos este último método, pero en el 
archivo Ejemplo 16­Access2.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
.AddNew ’Añadir un nuevo registro vacío
.Fields(0) = Cells(i_Fila, 1)
.Fields("Valor") = Cells(i_Fila, 2)
.Update ’Actualizació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. 

A continuación, abrimos el  RecordSet en el exterior del bucle. De esta manera no tendremos que gestionar un 
RecordSet en cada inserción. 

Después en el bucle añadimos al RecordSet Mi-Consulta los métodos: 

l AddNew: nuevo registro vacío. 
l Fields: cumplimentado de los diferentes campos de la tabla, ya sea dando el nombre de la columna, ya sea dando 
el valor del índice de la columna partiendo de 0. 

l Update: para validar la inserción. 

4. Actualizar una base Access desde Excel

También es posible actualizar registros en las tablas a partir de los datos contenidos en hojas de cálculo. En esos 
casos,  resulta  más  sencillo  realizar  la  tarea  mediante  una  consulta  SQL  que  hacerlo  con  los  métodos  del  objeto 
RecordSet. 

El código, que es posible consultar desde la página Información, Ejemplo 16­Access3.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 17­C2. 

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 17­C3 corresponde a un calendario dinámico en función de los valores contenidos en el menú 
desplegable de los meses y los años: 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 7-
Sin embargo, el archivo no es perfecto ya que el calendario muestra siempre 31 días, sea cual sea el mes escogido. 
Vamos a crear una macro que ocultará los días cuando el mes seleccionado no tenga 31 días. 

En  primer  lugar,  utilizaremos  la  Grabadora  de  macros  para  recuperar  el  código  que  permite  ocultar  y 
mostrar una columna: 

Columns("AF:AF").Select
Selection.EntireColumn.Hidden = True
Columns("AE:AG").Select
Selection.EntireColumn.Hidden = False

Una posible solución (pero no la única) consiste en hacer un test en las distintas celdas que contienen una fecha y 
después  comprobar  si  el  valor Mes  de  las  celdas  sigue  siendo  igual  al  mes  seleccionado  en  el  menú  desplegable; 
esto equivale a hacer un test al valor de la celda vinculada. 

En torno a este test, vamos a construir un bucle con las tres últimas columnas. Todos los meses tienen al menos 28 
días, por lo tanto no es útil hacer un test en los días 1 a 28. 

El programa pasa a ser: 

Sub Ocultar_los_Días()
Dim Núm_Col As Integer
For Núm_Col = 30 To 32
If Month(Cells(5, Núm_Col)) <> Cells(3, 4) Then
Columns(Núm_Col).Hidden = True
Else
Columns(Núm_Col).Hidden = False
End If
Next
End Sub

El error en este programa sería no volver a mostrar las columnas en caso de que se pase de un mes de 30 días a un 
mes de 31 días: si no prevé mostrar las columnas para los días 29, 30 y 31, estas columnas siempre estarán ocultas. 

4. Ubicación de los objetos

- 8- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Cuando introduce objetos en una hoja de cálculo, no siempre es fácil alinearlos. En efecto, no es posible activar una 
casilla  que  permita  asegurar  una  alineación  y  una  distancia  entre  los  objetos.  Por  lo  tanto,  puede  tener  objetos 
colocados un poco al azar como estos: 

Aunque  esta  alineación  se  podría  hacer  mediante  las  opciones  de  la  pestaña  Diseño  de  página, vamos a escribir 
una  macro  que  colocará  las  casillas  en  las  celdas  respetando  las  propiedades  de  tamaño  de  las  celdas.  Vamos  a 
crear un bucle en cada objeto de la hoja empezando por la colección de objetos. 

Sub BucleCheckBoxes_Formulario()
Dim Cb As CheckBox
For Each Cb In Hoja1.CheckBoxes
Instrucciones
Next Cb
End Sub

Para  colocar  un  objeto  en  una  celda,  vamos  a  recuperar  la  celda  en  la  que  el  objeto  está  colocado  mediante  la 
propiedad Shape.TopLeftCell. La esquina superior izquierda del objeto es el punto de referencia. 

Sub BucleCheckBoxes_Formulario()
Dim La_Celda as Range
Dim Cb As CheckBox
Dim La_Celda as Range
For Each Cb In Hoja1.CheckBoxes
Set La_Celda = Cb.TopLeftCell
Next Cb
End Sub

A  continuación,  utilizaremos  las  propiedades  Left  (izquierda)  y  Top  (arriba)  para  definir  la  posición  y  las 
propiedades Height (altura) y  Width (anchura) para definir las dimensiones del objeto y recolocar cada casilla de 
verificación. 

Sub BucleCheckBoxes_Formulario()
Dim La_Celda As Range
Dim Cb As CheckBox
For Each Cb In Hoja1.CheckBoxes
Set La_Celda = Cb.TopLeftCell
With Cb
.Select
.Left = La_Celda.Left + 2
.Top = La_Celda.Top
.Height = 15
.Width = 75

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 9-
End With
Next Cb
End Sub

Tras la ejecución de este programa, todos los objetos se colocarán de la misma forma con respecto al alto de las 
filas de la hoja de cálculo. 

- 10 - © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Procedimiento Auto_Open/Auto_Close
Puede  iniciar  un  programa  al  abrir  un  libro  poniendo  en  este  un  módulo  que  contenga  un  procedimiento  llamado 
Auto_Open.  Así,  al  abrir  un  libro,  las  líneas  de  código  contenidas  en  este  procedimiento  se  ejecutarán 
automáticamente al inicio. 

Sub Auto_Open()
Instrucción
End Sub

Del  mismo  modo,  puede  iniciar  un  programa  al  cerrar  el  libro  añadiendo  en  un  módulo,  un  procedimiento  llamado 
Auto_Close. 

Sub Auto_Close()
Instrucción
End Sub

Por ejemplo, puede forzar el guardado del libro al cerrarlo escribiendo este sencillo fragmento de código. 

Sub Auto_Close()
ActiveWorkbook.Save
End Sub

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Evento en una hoja de cálculo

1. Principio de los eventos

Tiene la posibilidad de iniciar procedimientos desde una hoja de cálculo mediante un doble clic o seleccionando una 
celda. Para ello, es necesario que cree un código en una hoja de cálculo y no en un módulo. 

Como muestra la imagen precedente, a la derecha del VBE tenemos el editor de código, pero en el explorador de 
proyectos, a la izquierda, no tenemos ningún módulo. 

También habríamos podido seleccionar la opción  ThisWorkbook para que el código se aplicara a todas las hojas 
de cálculo del libro y no solo a una de ellas. 

Sin  embargo,  cuando  escribimos  un  código  desde  una  hoja  de  cálculo  o  para  todo  el  libro  no  trabajamos  con 
procedimientos estándar sino con procedimientos ocasionales. Es decir, procedimientos que se activarán cuando se 
produzca un evento en la hoja de cálculo, como por ejemplo un doble clic. 

2. Lista de eventos

La  lista  de  eventos  se  obtiene  seleccionando  la  opción  Worksheet  en  el  menú  desplegable  de  la  izquierda.  A 
continuación, en el menú desplegable de la derecha, podrá ver la lista de eventos existentes. 

Lista de eventos de la versión de Office 365 

La  lista  de  eventos  puede  variar  dependiendo  de  la  versión  de  Excel.  Pero  no  se  preocupe,  los  ejemplos  que 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
aparecen a continuación se aplican a todas las versiones de Excel. 

Si se encuentra en el objeto ThisWorkbook, la lista de eventos será diferente y se aplicará a los eventos del libro 
(abrir, activar, etc.). 

3. El evento Change

Seleccione Change en la lista de eventos de una hoja de cálculo. 

Se mostrará entonces un procedimiento llamado Worksheet_Change con el parámetro Target. 

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 17­E. 

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

SpecialEffect  Para modificar el aspecto del cuadro de diálogo. 

2. Escribir un código en un UserForm

Además del aspecto gráfico de un cuadro de diálogo, un UserForm se compone también de líneas de código que se 
encuentran  fuera  de  los  módulos.  Estas  líneas  de  código  se  conocen  como  Private  y  solo  pueden  ejecutarse 
cuando se llama al cuadro de diálogo. Para mostrar estas líneas de código: 

Seleccione el icono del UserForm en el Explorador de proyectos. 

Haga clic con el botón derecho y elija el menú Ver código. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Le  recomendamos  encarecidamente  que  cambie  el  nombre  genérico  (UserForm1)  por  un  nombre  que 
defina  mejor  la  función  del  cuadro  de  diálogo  que  va  a  crear:  en  la  ventana  de  propiedades,  cambie  el 
valor de la propiedad Name. Este nombre también se utilizará en su programa. 

3. Hacer referencia a un UserForm

Para  activar  la  visualización  de  un  cuadro  de  diálogo  personalizado  desde  un  procedimiento,  debe  escribir  su 
nombre seguido del método Show. 

Sub Programa_Principal
UserForm1.Show
End Sub

También puede visualizar su cuadro de diálogo desde Visual Basic Editor sin la instrucción Show: 

Colóquese sobre el objeto UserForm. 

Seleccione el objeto UserForm y pulse la tecla [F5]. 

Para trabajar con los controles del cuadro de diálogo, en primer lugar debe recordar el nombre de su UserForm, el 
nombre del control y la propiedad del control: 

Mi_Cuadro.Mi_Control.Propiedad

Cuando trabaje en el código integrado en el UserForm, podrá sustituir el nombre que ha atribuido a su UserForm 
por Me. 

Desde un módulo, la instrucción  Me es incomprensible por Visual Basic. En ese caso, debe escribir el nombre exacto 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
del UserForm para que se pueda interpretar. 

Por  ejemplo,  para  insertar  la  fecha  del  día  en  un  cuadro  de  diálogo  personalizado  se  puede  escribir  el  código 
siguiente desde el evento Activate: 

Me.Label1.Caption = Date

Pero  si  desea  efectuar  la  misma  operación  desde  un  módulo,  deberá  remplazar  Me  por  el  nombre  del  cuadro  de 
diálogo personalizado. 

Userform1.Label.Caption = Date

- 4- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Los eventos
Un evento atañe a todas las acciones que pueden realizarse en un control. Cada evento es un tratamiento específico 
en el control que no interfiere a los otros eventos de los demás controles. 

Por ejemplo, puede inicializar valores cuando su cuadro de diálogo personalizado se active (Evento). 

Tendrá  que  usar  los  eventos  para  comprobar  los  datos  introducidos  y  también  para  transmitir  los  elementos 
seleccionados a los módulos de su programa. 

Para  conocer  la  lista  de  eventos  que  pueden  estar  relacionados  con  un  control,  hay  que  seleccionar  el  nombre  del 
control en el menú desplegable situado en la parte superior de la zona de trabajo; en el segundo menú desplegable, 
encontrará la lista de los eventos que el control puede administrar. 

Los eventos se declaran en Private, ya que solo son visibles y accesibles desde el cuadro de diálogo. 

Desde un módulo no se puede llamar a los eventos en Private. 

En el código del cuadro de diálogo, tendrá la instrucción siguiente: 

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

l Los  botones  como  los 


CommandButton  que  son  los  botones  tradicionales  (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 mostrar o no el objeto en el cuadro de diálogo. 

Enabled  Hace que el objeto pueda editarse o no. 

Tomemos por ejemplo un programa de cálculo financiero que requiere la introducción de una tasa de interés: 

En este ejemplo, el dato introducido debe ser un valor numérico. Va a crear un test cuando el usuario abandone la 
zona de texto para comprobar que la información escrita es un valor numérico. 

Haga doble clic en el control en el que quiere escribir el código. 

Su UserForm se borrará y aparecerá un procedimiento para el evento Change del control. 

Vamos a crear un test que comprobará que la información escrita es un valor numérico. Vamos a escribir en el evento 
Exit (es decir, cuando el usuario abandone el control) el código que comprobará el contenido del control. 

En el evento Exit, vamos a hacer un test a la propiedad Text del control TextBox para comprobar que su contenido 
es un valor numérico. Nuestro test se escribirá de la siguiente forma: 

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 19­C. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Los botones (o CommandButton)
Los botones (CommandButton) son fáciles de configurar, pero sumamente importantes en un cuadro de diálogo. 

Las principales propiedades del control CommandButton son: 

Name  Para atribuir un nombre único a un objeto. 

Caption  Para cambiar el valor del título del control. 

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

Enabled  Para hacer el objeto accesible o no. 

Generalmente tiene dos botones en un UserForm: 

l El botón Aceptar que iniciará el programa. 

l El botón Cancelar que cerrará el UserForm. 

1. Agregar un botón

En  el  cuadro  de  herramientas,  haga  clic  en  el  icono   y con ayuda del ratón, dibuje el botón en el 

cuadro de diálogo. Aparecerá un nuevo CommandButton. 

2. El botón Cancelar

El botón Cancelar es el más sencillo de codificar. 

Cuando  hace  clic  en  el  botón  Cancelar  de  cualquier  cuadro  de  diálogo,  cierra  el  cuadro  de  diálogo,  pero  también 
borra todos los parámetros en la memoria que se cargaron cuando estaba abierto ese cuadro de diálogo. 

Haga doble clic en el control, para abrir directamente el código del control. 

Por defecto, los eventos estándar son Click o Change. 

Para cerrar un cuadro de diálogo, debe escribir, en el evento Click del botón, la siguiente instrucción: 

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 mostrar 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 19­E. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Las casillas de verificación son independientes entre sí: si en su cuadro de diálogo debe comprobar varias casillas de 
verificación, debe comprobar todas las combinaciones posibles. 

Por  ejemplo,  el  siguiente  cuadro  de  diálogo  contiene  cuatro  casillas  de  verificación.  Cada  control  puede  tener  dos 
estados (True o False). En ese caso, habría que verificar los cuatro controles, por lo tanto, hay 24  = 16 combinaciones 
posibles y similar número de verificaciones. 

Procure no crear cuadros de diálogo con demasiadas casillas de verificación. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Los botones de opción (OptionButton o botones radio)

A  diferencia  de  las  casillas  de  verificación  que  son  independientes  entre  sí,  los  botones  de  opción  (OptionButton) 
están relacionados los unos con los otros. 

Un  grupo  de  botones  de  opción  se  utiliza  para  escoger  una  opción  entre  varias.  Cuando  el  usuario  seleccione  un 
botón de opción, los demás botones de opción se deseleccionarán. 

En el ejemplo siguiente solo se puede seleccionar una opción: 

Para  agregar  un  botón  de  opción  a  su  cuadro  de  diálogo,  haga  clic  en  el  icono    del  cuadro  de 

herramientas y haga clic y arrastre el ratón en el UserForm para hacer aparecer un control OptionButton. 

Las principales propiedades del control son: 

Name  Para atribuir un nombre a un objeto. 

Caption  Para cambiar el valor del título en el cuadro de diálogo. 

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

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

Enabled  Para hacer el objeto accesible o no. 

Para recuperar en su código el valor seleccionado, debe hacer un test en el valor True (valor cuando el botón está 
seleccionado) para cada uno de los controles. Lo mejor es utilizar la instrucción Select Case y comprobar el valor 
True. 

En un evento Clic del botón Aceptar, puede escribir el siguiente código: 

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 19­F1. 

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 19­F2. 

- 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 19­G2. 

- 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 19­G2b. 

© É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.ListBox1.AddItem (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.ListBox1.RemoveItem (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 19­G3. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 5-
Los cuadros combinados (ComboBox o menús desplegables)
Los menús desplegables (ComboBox) son los controles más utilizados ­ son sencillos de utilizar ­ pero también son los 
más difíciles de codificar ya que debe gestionar el elemento seleccionado en la lista, pero también gestionar la adición 
del nuevo elemento. 

Los cuadros combinados combinan a la vez la selección de un elemento y la adición de un nuevo elemento como si el 
menú desplegable fuera una zona de texto (TextBox). Los controles ComboBox no permiten la selección múltiple. 

Para  agregar  un  cuadro  combinado  a  su  cuadro  de  diálogo,  haga  clic  en  el  icono    del  cuadro  de 

herramientas y haga clic y arrastre el ratón en el UserForm para hacer aparecer un control ComboBox. 

Las principales propiedades del control son: 

Name  Para atribuir un nombre a un objeto. 

Caption  Para cambiar el valor del título en el cuadro de diálogo. 

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

Enable  Para hacer el objeto accesible o no. 

RowSource  Para  precisar  el  origen  de  los  valores.  Se  puede  tratar  de  celdas  de  una  hoja  de  cálculo  o  de 
datos transmitidos por un programa. 

ListStyle  Para agregar un icono delante de los datos (1) o mostrar únicamente los valores (0). 

MultiSelect  Para permitir seleccionar un solo valor (0) o varios (1). Puede realizar una selección múltiple ya 
sea  seleccionando  cada  valor  pulsando  al  mismo  tiempo  la  tecla  [Ctrl],  o  haciendo  una 
selección pulsando la tecla  [Mayús]. 

MatchEntry  Para poder usar el teclado para acceder más rápidamente a los elementos de la lista. 

Para  devolver  el  dato  seleccionado  en  el  menú  desplegable,  escriba  el  siguiente  código  en  el  envento Change  del 
control ComboBox: 

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 19­H. 

- 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.ListIndex = -1
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. 

En caso de que la hoja no exista, el programa debería haberse detenido en la instrucción Set Objeto_Hoja.... 
Ahora  bien,  como  hemos  escrito  la  instrucción  On Error Resume Next  al  principio  de  la  función,  el  programa 
continuará. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 3-
Tipos de variables

Boolean  La variable solo puede tomar dos valores: True o False (o bien 0 o 1). 

Byte  Este  tipo  se  utiliza  para  la  manipulación  de  datos  binarios.  Un  dato  binario  está  representado  por 
un  número  de  8  bits  (es  decir,  8  cifras).  Cada  bit  es  un  0  o  un  1.  Un  valor  de  tipo  Byte  puede 
tener  un  valor  entre  0  y  255.  Si  el  contenido  de  un  valor  superase  los  255,  el  programa  se 
detendría. 

Date  El  tipo  Date  posee  todas  las  fechas  comprendidas  entre  el  1  de  enero  del  año  100  y  el  31  de 
diciembre de 9999, de las 0:00:00 a las 23:59:59 horas de cada día. Este tipo se encuentra en la 
tipología de las variables ya que los días o los meses no se añaden como cifras. 

Currency  El  tipo  Currency  representa  todos  los  datos  monetarios:  son  números  comprendidos  entre  ­
922337203685477,5808 y 922337203685477,5807. 

Integer  El  tipo  Integer  devuelve  un  número  entero  comprendido  entre  ­32768  y  32767.  Este  tipo  de 
variable  se  utiliza  mucho  para  hacer  bucles  en  fila  o  en  columnas  (con  la  condición  de  no  superar 
las 32767 filas). 

Long  Es  una  extensión  del  tipo  Integer.  Los  valores  están  comprendidos  entre  ­2147483648  y 
2147483647. 

Single  El  tipo  Single  representa  valores  decimales.  Los  valores  posibles  están  comprendidos  entre  ­
3,402823  x  10 38  y  ­1,401298  x10 ­45  para  los  valores  negativos  y  entre  1,401298  x  10 ­45  y 
3,402823 x 10 38 para los valores positivos.  

Double  El  tipo  Double  representa  los  valores  de  números  con  coma  flotante  de  doble  precisión.  Los 
valores  posibles  están  comprendidos  entre  ­1,79769313486231  x  10 308  y  ­4,94065645841247 
x10 ­324  para  los  números  negativos  y  entre  4,94065645841247  x  10 ­324  y  1,7976931348623  x 
10 308  para  los  números  positivos.  Más  allá  de  toda  consideración  de  ocupación  en  la  memoria,  es 
un tipo al que hay que dar prioridad. 

String  Las  cadenas  de  caracteres  (String  en  inglés)  son  las  expresiones  de  texto.  Estas  no  se  pueden 
utilizar  para  cálculos  matemáticos  u  operaciones  lógicas.  De  hecho,  estas  expresiones  son  la 
concatenación  de  varios  caracteres.  Una  cadena  de  caracteres  no  puede  contener  más  de  2.000 
millones de caracteres aproximadamente (¡es más que suficiente!). 

Variant  El tipo Variant es un tipo que agrupa todos los demás tipos citados anteriormente. Es una especie 
de "trastero" muy práctico, pero a veces puede parecer desconcertante. 

Object  El tipo Object tiene como valor el de una clase. Una clase es un modelo que posee propiedades y 
métodos.  En  Excel,  se  consideran  como  objeto  las  celdas,  filas,  columnas,  hojas  de  cálculo, 
gráficos, libros, etc. Estas variables se utilizan en colecciones de objetos. 

LongLong  Tipo de datos de 8 bytes únicamente disponible en los sistemas de 64 bits. De tipo numérico. 
Números enteros comprendidos entre ­9 223 372 036 854 775 808 y 9 223 372 036 854 775 807. 
LongLong es un tipo únicamente declarado válido en las plataformas de 64 bits. 

LongPtr  Tipo de datos de variable de 4 bytes en las versiones de 32 bits y de 8 bytes en las versiones de 
64 bits de Office 2010. Se trata del método recomendado para declarar un puntero o un 
controlador para un código nuevo, pero también para un código heredado si este debe ejecutarse 
en la versión de Office de 64 bits. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Colección de objetos
Aquí presentamos la lista de colecciones de objetos más comunes en Excel y sus campos de aplicación. Una colección 
de objetos puede aplicarse en un libro, a una hoja de cálculo, a gráficos. 

AddIns  Representa el conjunto de macros complementarias que existen en la aplicación. 

AllowEditRanges  Representa  el  conjunto  de  celdas  no  cerradas  en  una  hoja  de  cálculo  (cuando  la  hoja 
está protegida). 

Areas  Para  una  selección  de  celdas,  Areas  representa  el  conjunto  de  celdas  de  esta 
selección.  Esta  colección  se  usa  básicamente  para  la  propiedad  Count  que  devuelve  el 
número de celdas de la selección. 

Axes  Representa el conjunto de ejes de un gráfico. 

Borders  Representa el conjunto de bordes de una selección. 

CalculatedMembers  Solo  se  aplica  a  una  tabla  cruzada  dinámica:  representa  el  conjunto  de  elementos 
calculados en la tabla cruzada dinámica. 

Charts  Representa  el  conjunto  de  curvas,  barras,  etc.  que  representan  las  series  de  datos  en 
un gráfico. 

Comments  Representa el conjunto de comentarios de una hoja de cálculo. 

CustomProperties  Representa el conjunto de propiedades de un libro. 

DataLabels  Representa  el  conjunto  de  etiquetas  de  sus  series  de  datos  (se  aplica  únicamente  a 
los gráficos). 

Dialogs  Representa el conjunto de cuadros de diálogo integrados en Excel. 

Filters  Representa el conjunto de filtros utilizados en una hoja de cálculo. 

FormatConditions  Representa el conjunto de configuraciones condicionales en un rango de celdas. 

Hyperlinks  Representa  el  conjunto  de  hipervínculos  en  un  rango  de  celdas  o  en  una  hoja  de 
cálculo. 

Names  Representa el conjunto de celdas nombradas en su aplicación o en su libro. 

PivotTables  Representa el conjunto de tablas cruzadas dinámicas de una hoja de cálculo. 

RecentFiles  Representa el conjunto de archivos abiertos recientemente en la aplicación. 

Scenarios  Representa el conjunto de escenarios contenidos en una hoja de cálculo. 

Shapes  Representa el conjunto de objetos gráficos en una hoja de cálculo. 

Sheets  Representa el conjunto de hojas de cálculo de un libro. 

Windows  Representa el conjunto de ventanas abiertas en la aplicación. 

Workbooks  Representa el conjunto de libros abiertos en la aplicación. 

Worksheets  Representa el conjunto de hojas de cálculo de un libro. 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
Lista de constantes
Lista de constantes para ubicarse en las rutas de acceso estándar de Windows. 

&H5 = My Documents

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

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-
93  Cadena modelo no válida. 

94  Uso no válido de Nul. 

95  Error definido por el usuario. 

323  Imposible cargar el módulo; formato no válido. 

423  No se encuentra la propiedad ni el método. 

424  Se requiere un objeto. 

430  Esta clase no admite automatización o no admite la interfaz esperada. 

438  El objeto no acepta este método o propiedad. 

440  Error de automatización. 

445  El objeto no acepta esta acción. 

446  El objeto no acepta argumentos con nombre. 

447  El objeto no acepta la configuración regional actual. 

448  Argumento con nombre no encontrado. 

449  Argumento no opcional. 

450  El número de argumentos es erróneo o la asignación de propiedad no era válida. 

451  El procedimiento Let de la propiedad no está definido y el procedimiento Get no ha devuelto un objeto. 

452  El ordinal no es válido. 

453  No se encuentra la función de biblioteca DLL especificada. 

454  No se encuentra el recurso del código. 

455  Error al bloquear el recurso de código. 

1000  Nombreclase no posee la propiedad nombrepropiedad. 

1001  Nombreclase no posee el método nombremétodo. 

1002  Falta el argumento nombreargumento. 

1003  El número de argumentos no es válido. 

1004  El método Nombremétodo de la clase nombreclase ha fracasado. 

1005  Imposible definir la propiedad nombrepropiedad de la clase nombreclase. 

1006  Imposible leer la propiedad nombrepropiedad de la clase nombreclase. 

- 2- © Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella
Lista de caracteres no imprimibles

Código en base  Significado 

0  Carácter nulo 

1  Inicio de encabezamiento 

2  Inicio de texto 

3  Fin de texto 

4  Fin de transmisión 

5  Consulta, fin de línea 

6  Acuse de recibo 

7  Timbre 

8  Retroceso 

9  Tabulación horizontal 

10  Salto de línea 

11  Tabulación vertical 

12  Salto de página 

13  Retorno de carro 

14  Mayúsculas fuera 

15  En mayúsculas 

16  Enlace de datos / escape 

17  Dispositivo de control 1 DC1 

18  Dispositivo de control 2 DC2 

19  Dispositivo de control 3 DC3 

20  Dispositivo de control 4 DC4 

21  Acuse de recibo negativo 

22  Síncrono en espera 

23  Fin de transmisión del bloque 

24  Cancelar 

25  Finalización del medio 

26  Sustituto 

27  Escape 

28  Separador de archivo 

29  Separador de grupo 

30  Separador de registro 

31  Separador de unidad 

© Éditions ENI – Todos los derechos reservados – Copia personal de Omar Enrique Antequera Armella - 1-

Potrebbero piacerti anche