Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Excel VBA y macros: Una herramienta muy útil para trabajar hojas de cálculo (2).
Esta es la segunda parte de los posts para enseñar a usar macros de Excel. Si te perdiste la primera parte, aquí la puedes encontrar. En esta segunda lección nos
familiarizaremos con el editor de código y aprenderemos a trabajar con variables y algunas estructuras de datos.
Trata de ir despacio, un poco cada día, comprendiendo bien y luego prosiguiendo. No vayas con prisa porque voy a presentar bastante información, y lo más
importante es que te familiarices poco a poco.
1. Módulos
2. Propiedades
3. Código o form
4. Pantalla de mensajes de depuración
Módulos
Los módulos son como una especie de pergamino largo donde escribes código. Cada uno de los "pergaminos" de las hojas de cálculo abiertas se muestran en
esta zona. Los módulos pueden tener asociada una interface gráXca (una ventana de Windows) asociada, o pueden no tenerla y ejecutar instrucciones sin
desplegar nada.
Propiedades
Si seleccionas un módulo o un elemento de la interface gráXca de tu programa, verás que se tiene asociada una lista de valores asociados a características,
llamadas propiedades, para cada uno.
Código o form
El código está compuesto por instrucciones que tu le das a la máquina. Esas instrucciones se ejecutan, pero no necesariamente resultan visibles al usuario
durante la ejecución. En pocas palabras aquí es donde escribirás el código. Sólo asegúrate de que estás ubicado en el módulo apropiado.
Los forms (o formularios) son lo que tu llamarías una "ventana" que en realidad es una superXcie que contiene controles, como por ejemplo un botón o una zona
para escribir texto, y que se muestra visible en algún momento de la ejecución.
Editando forms
1. Paleta de controles
2. Form
En la paleta de controles escoges un control al pincharlo y vas al form a colocar el control. Los controles se colocan al dibujar un rectángulo encima del form,
como cuando dibujas un rectángulo en MSPaint. Si haces doble clic sobre un control que colocaste sobre el form, pasarás a editar el código para dicho control.
Cuando escribas código dentro del módulo incluirás procedimientos o subrutinas (Sub) y funciones (Function). Las subrutinas y funciones son fragmentos de
código que tienen un propósito especíXco y que se activan en determinadas circunstancias, deXnidas por el que crea la macro. Cada subrutina o función tendrá
un inicio y un Xnal claramente deXnidos.
Antes de las subrutinas y funciones se efectúa la declaración de variables y estructuras de datos que vas a usar y que serán utilizadas por varias subrutinas y
funciones del módulo.
Puedes imaginar las variables como celdas de datos que existen en memoria pero que no puedes ver, y al igual que en matemática, a dichas celdas se les asigna
un nombre de una variable. Por ejemplo, en lugar de decir que la celda A2 contiene un número 3, podríamos decir que la variable X contiene un número 3. La
variable X es como una celda oculta que no ves y que contiene el número. Esas variables necesitan ser creadas en la memoria, algo a lo que se le llama
"dimensionar" o "declarar" una variable.
Para declarar o crear una variable X debemos indicar el tipo de variable que queremos, dependiendo del tipo de dato que almacenaremos. En este caso
crearemos una variable X del tipo Long (sólo admite números enteros). El tipo indica el tipo de datos que va almacenado en la variable.
Dim X As Long
Aunque existen muchos tipos de datos, sólo voy a enumerar los tipos de datos más comunes que deberías usar:
String
String: Representa variables que contienen texto (en realidad contienen un grupo de caracteres alfanuméricos y simbólicos).
Long
Long: Adminten valores enteros solamente
Double
Double: Admiten valores con punto decimal, ya sea valores muy grandes o valores con muchas cifras decimales.
Date
Date: Fechas. Este tipo de dato lo analizaremos más adelante.
Variant
Variant: Este no es un tipo de datos que vayas a usar. Si se te olvida declarar una variable, no te dará un error, sino que VB lo asignará al tipo Variant y puede
aceptar valores de cualquier tipo, pero a un costo. Procesar variables de tipo Variant hace muy lento lo que hagas. Evita la presencia de variables Variant o
variables no declaradas.
En las subrutina o precedimiento ahora podemos usar esta variable X como la usaríamos en matemáticas. Cabe señalar que siempre es buena práctica inicializar
la variable, darle un valor inicial. Imaginemos el siguiente código dentro de un módulo. Este código desplegará los valores de las variables en la pantalla de
depuración, porque usa el comando Debug.Print
Debug.Print.
En este ejemplo X tendrá un valor de 3 y la variable Y usará el valor de X al que le sumará 2. Se parece mucho a la manera de hacer fórmulas en secundaria. A la
izquierda tienes la variable que almacenará el resultado y a la derecha una expresión de la cual resultará un valor que se almacena en la variable.
Dim X As Long
Dim Y As Long
Sub Main()
X = 3
Y = X + 2
End Sub
Cabe indicar que si declaras las variables al inicio, antes de la primera subrutina o función, los valores serán visibles por todas las subrutinas y funciones del
módulo. Si colocas la declaración dentro de la subrutina, sólo será visible dentro de la subrutina.
Sub Main()
Dim X As Long
Dim Y As Long
X = 3
Y = X + 2
End Sub
Los vectores son como una colección de celdas que se llaman con un nombre de una variable, pero al contener varios valores deben ser direccionados por un
subíndice.
He aquí un ejemplo que crea el vector y lo llena con valores, usando fórmulas. El asterisco (*) se usa para multiplicación y el slash (/) se usa para división.
Sub Main()
A(0) = 100
A(1) = A(0) * 2
A(3) = 356
A(4) = 890 / 2
End Sub
Cabe notar que en el código anterior el tamaño del vector es Xjo. Tu puedes crear vectores de tamaño variable. En el siguiente ejemplo se crea el vector A, luego
se le cambia el tamaño para que albergue el elemento cero, y luego se le cambia el tamaño para que albergue hasta el elemento 4. Este proceso de crear vectores
sin un tamaño, y luego cambiarles el tamaño se conoce como "dynamic memory allocation" (asignación dinámica de memoria). La palabra Preserve indica que
no debe borrar los valores ya existentes en el vector. Si no le pones esa palabra, cambiará el tamaño y vaciará el vector.
Sub Main()
Redim A(0)
A(0) = 100
A(1) = A(0) * 2
A(4) = 890 / 2
End Sub
Las matrices de dos dimensiones son como tablas. En este caso tenemos una matriz en dos dimensiones, pero podríamos tener una matriz de 3 dimensiones.
A una matriz también le podemos aplicar el dynamic memory allocation, pero sólo para la última dimensión. Si declaraste una matriz de 3 x 5 (3 Xlas y 2
columnas) sólo podrás agregar columnas.
A la hora de usar los valores de la matriz, primero va el valor de la Xla y luego el valor de la columna. En este ejemplo la Xla 2 y columna 1 tendrá un valor de 6.
B(2,1) = 6
B(3,1) = B(2,1) + 2
En los casos anteriores tenemos una variable que representa un grupo de datos llamado Array (Arreglo). En los casos que vimos el tipo de dato que se usa es
siempre el mismo para todos los elementos del arreglo. Sin embargo a veces podríamos tener estructuras de datos que no siempre contienen datos del mismo
tipo.
Imagina que tenemos una tabla que contiene los siguientes datos de bolsa.
Fecha y hora
Precio de apertura
Precio de cierre
Precio máximo
Precio mínimo
En lugar de crear 5 vectores, o crear 1 vector tipo Date para la fecha y una matriz de tipo Double para los precios, podemos crear una estructura que combina
ambos.
Escribimos el siguiente código para declarar una estructura llamada TipoRegistro que es en realidad un tipo personalizado que combina varios tipos. La
estructura estará fuera de las subrutinas y funciones, en la sección de declaración del módulo respectivo.
Fecha As Date
Apertura As Double
Cierre As Double
Maximo As Double
Minimo As Double
End Type
Y luego creamos una variable que contendrá esa estructura. La variable puede estar dentro o fuera de una subrutina o función.
Cuando queramos usar un valor de esa estructura, lo haremos de la siguiente manera. En este ejemplo Stop es otra variable que debería ser declarada en algún
lado para que no sea de tipo Variant. Las variables no sólo pueden estar compuestas por una sola letra, sino que puedes darle un nombre a la variable (sin usar
espacios) que signiXque algo.
D(0).Apertura = 100
Stop = D(0).Apertura
Como notarás, D es un vector que en lugar de contener una Xla de datos, contiene en realidad una Xla de datos de un registro bursátil. Hasta ahora hemos
aprendido a navegar en el editor, y hemos comprendido cómo crear espacios en memoria para extraer o almacenar datos, usando fórmulas.
Sin embargo las celdas de Excel también pueden usarse para almacenar valores o para extraer valores. En este ejemplo tomamos el valor de la celda E3 (Xla 3,
columna 5) y sumamos 1 y almacenamos el resultado en X. Asimismo la celda B1 (Xla 1 y columna 2) almacenará el resultado de multiplicar Y por 5.
X = Cells(3,5) + 1
Cells(1,2) = Y * 5
Cabe añadir que aunque te parezca tentador usar celdas en lugar de variables, extraer o almacenar valores en celdas es un proceso muy lento, y por eso es mejor
usar variables y minimizar el uso de celdas en fórmulas dentro de tu código. Lo mejor si vas a usar valores de celdas es pasar el valor de la celda a una variable y
hacer operaciones con esa variable.
¿Podremos realizar cálculos más complejos que involucren procesos que se repiten muchas veces? Si. Seguramente recuerdas que en el código anterior
teníamos este código:
¿Qué pasaría si el vector que usamos tuviese 10 mil elementos en lugar de 5 elementos (desde 0 hasta 4)? Evidentemente deberías declarar el arreglo para que
tenga 10 mil elementos.
Sería terriblemente cansado realizar el proceso de escribir 10 mil veces lo mismo. Lo mejor sería reemplazarlo por código que use For / Next:
For i = 0 to 10000
Next i
En este caso la variable i (que deberías haber declarado también) sirve de contador, y su valor variará desde 0 hasta 10000. El código que se encuentra entre la
línea donde stá el comando FOR y la línea donde está el NEXT, se repetirá y en cada iteración la variable i se incrementará de 1 en 1.
Cabe notar que si el FOR usa la variable "i", también el NEXT debe referirse a "i". Además, si haces el ciclo FOR NEXT desde 0 hasta 10 mil y el vector A tiene
menos de 10 mil elementos, en algún momento lanzará un aviso de error, porque la variable "i" apunta a un valor del vector que no existe.
Sub Main()
For columna = 1 to 4
For fila = 1 to 10
Next fila
Next columna
End Sub
El resultado te parecerá muy interesante. Como observas aquí tenemos dod ciclos FOR, uno dentro del otro, que es lo que se llama tener "ciclos anidados". Cabe
notar que el último FOR es el de la Xla, y por ende el primer NEXT deberá ser para la Xla.
Vamos a llenar las primeras 10 Xlas de la primera columna en la hoja de Excel con valores numéricos. Si el valor de la primera columna es mayor que 5, entonces
despliegue "SI" o de lo contrario despliegue "NO".
Sub Main()
Dim i As Long
For i = 1 to 10
Cells(i,1) = Int(Rnd * 10) 'Agregar un valor aleatorio entero de 0 a 10 en las celdas de la primera columna
If Cells(i,1)>5 Then 'Inicia toma de decisión. Si se cumple la condición de que el valor de la celda en la primera columna es mayo
Next i
End Sub
Como puedes observar, lo que hizo el programa fue tomar una decisión. Rnd es un número aleatorio (en inglés se dice "random") cuyo valor oscila entre 0 y 1 pero
nunca llega a ser 1. La función Int(x) lo que hace es tomar el valor x, para recortarle los decimales y obtener un número entero. Al multiplicar un número aleatorio
entre 0 y 1 por 10, se obtiene un número aleatorio entre 0 y 10.
Epílogo
Hasta ahora no hemos visto un ejemplo completo, sino que hemos experimentado un poco con código. Aprender a programar al inicio resulta un poco diXcil
porque uno requiere aprender muchas reglas, así que tómate tu tiempo para comprender cada ejemplo, lo que hace el código. Y si tienes preguntas las puedes
postear aquí.
Creo que ya estamos listos para un ejemplo un poco más real para el siguiente post. Mientras llega, trata de familiarizarte y experimentar. Aquí se trata de hacer
cosas a ver qué pasa, familiarizarse con una ambiente extraño. Todavía no vamos en serio.
Estoy consciente de que he ido un poco rápido y no he cubierto todo lo que tiene que ver con FOR/NEXT o IF/THEN/ELSE pero es que no he querido saturar de
información.
Si quieres saber más y estar al día de mis rekexiones, suscríbete a mi blog y sé el primero en recibir las nuevas publicaciones en tu correo electrónico.
Suscribirme al blog
5 Compartir
Comentarios
Recibir comentarios Comentar
15
Eplanas
Enrique
Responder
Feinmann
Responder
Comstar
#3 Creo haber comprendido la idea, pero aún me hace falta conXrmar si así fue. Primero necesitaba escribir esto antes de escribir tu código. Si tengo
preguntas lo sabrás por esta vía.
Responder
Comstar
#4 Traté de hacerlo, pero HTML me anula los espacios de indentación. ¿Alguien sabe cómo hacer esto con tags de HTML? Yo se de VB, no tanto de
HTML.
Responder
X4v13r
Por cierto, añadir unos cuantos tipos más de variable que me parecen muy útiles:
Integer
Boolean
S2
Responder
X4v13r
Responder
Comstar
#7 El problema de los boolean es que llegan hasta un valor máximo de la mitad de 65535 y cuando se tienen proyectos largos resulta terriblemente
incómodo depurar código con este tipo de variables, porque es muy fácil llegar a exceder ese valor en la mayoría de los casos. Por eso en lugar de
"Integer" yo preXero "Long".
Responder
X4v13r
En general para aquellos usuarios que se meten en este mundillo, yo siempre recomiendo lo mismo, el primer paso para diseñar un buen programa
es saber qué es lo que quieres que haga y luego saber como quieres que lo haga, el resto es ponerse a "escribir" y si ya llevas mucho programas con
ctrl+c-ctrl+v te acaba valiendo jejeje
Responder
Comstar
#9 Entiendo tu punto. Sin embargo mi experiencia me ha llevado a comprender que las variables Integer son la excepción y no la regla. Las variables
Long presentan la ventaja de la escalabilidad. No hay como tener proyectos grandes sólo para empezar a recibir quejas de varios usuarios porque
ocurren errores debido a que declaraste una variable como Integer y no como Long y en el programa, debido a razones de uso termina habiendo más
elementos de los que pensaste que iban a usar, o valores que no pensaste que fuesen a surgir en el camino. Una cosa es lo que tu crees que pasará,
y otra es la realidad de las cosas.
Enseñar el uso de Integer está bien para proyectos de juguete, pero estoy seguro de que los rankianos en algún momento tendrán que llevar a cabo
proyectos de programación de verdad, y yo preXeron que no se encuentren con esa molestia.
Actualmente sueles tener 1 GB de RAM como mínimo más la memoria virtual de un swap Xle. Las variables Integer ocupan 2 bytes y un Long usa 4
bytes. Tendrías que tener varios millones de datos para que represente un problema. Si tienes tantos datos lo mejor es no usar Excel, sino comprarse
Visual Basic 6 Enterprise Edition que es el que funciona igual a Excel VBA pero con las mejores capacidades de bases de datos y otros.
En cambio, el tiempo de depurar errores por declarar variables como Integer, y cambiar todas las referencias de conversión a entero (cambiar
funciones cInt(x) por cLng(x) que convierten x al tipo Long) en proyectos grandes es realmente engorroso. Ya me ha ocurrido, y ya he encontrado
otros programadores a los que les ha pasado lo mismo.
Aunque Excel VBA no use demasiados datos, un programa realmente podría volverse grande, como ya me ha ocurrido antes, al punto que he tenido
que recurrir al uso de objetos.
Aunque parece un poco ineXciente, en realidad se trata de un asunto de ahorro de tiempo de depuración. Si hay algo que hace ver mal a un
programador es un mensaje de error. Y perseguir ese error en un proyecto grande y evaluar todas las implicaciones y las interfaces entre objetos y
llamados de funciones, puede resultar en un verdadero dolor de cabeza.
Responder
X4v13r
Como bien dices si un proyecto es grande lo mejor es recurrir a VB, si un proyecto grande lo quieres meter en excel pues será ineXcaz, por proyecto
grande entiendo uno que requiera múltiples conexiones a DBS bien con conexiones tipo ADO u otro tipo de conexiones, con varias interfaces de
usuario, formularios, módulos, deXnición de librerías, etc, por otra parte para un rankiano que quiera hacer esto en su casa el VB 6 enterprise Edition
no tiene sentido, cuando se puede bajar el VB Express 2010 de registro gratuito con unas pocas limitaciones que en la práctica en un entorno
doméstico apenas se aprecian.
Si lo que esperas es que un rankiano cree todo un software con varios formularios, módulos y gestione conexiones a DBs, creo que tendrá los
suXcientes conocimientos como para prescindir del excel en este aspecto y por otro lado dudo que todo esto lo vaya a usar sólo para hacer una
pequeña simulación de una estrategia o volcado de datos de forma sencilla que parece ser que es lo que la mayoría desea al acudir a estas
herramientas que estamos tratando aqui.
Por otro lado diré que entiendo los usos del Long y no digo que sea preferible este tipo de variables a los Integer, simplemente digo que cada una
tiene su función, ahora, que sean la excepción las Integer tampoco, y por otro lado si lo que deseas es codiXcar grandes números sin problemas de
precisión puedes recurrir a los Double, no voy a hablar ya de la gestión de memoria que eso daría para otro tanto, pero efectivamente hoy día
problemas de memoria ya apenas encuentras, lo que no quiere decir que por ello se deba abusar de la capacidad de computación, yo preXero que un
programa funcione con los mínimos recursos prescindibles, y por experiencia te digo también que la ley de Pareto se cumple también en
programación (20% del tiempo diseñando, 80% del tiempo depurando), claro que un buen diseño del software disminuye el tiempo global dedicado al
proyecto, también hay que asumir que el proceso de depuración es más largo y engorroso que la propia programación.
lo mejor es construir los programas como os lego, por piezas XD, esa creo yo que es la auténtica clave para ahorrar tiempo de depuración, cuanto
mejor diseñes tu clases y objetos (casos de POO) o más pequeñas y básicas sean tus funciones (caso PE) mejor resultará el programa y menos
errores se cometerán (obviamente siempre harán falta clase, rutinas, módulos, funciones... que implementen las más pequeñas) pero como te digo
creo que esto se sale un poco del tema ¿no? que son las macros de excel, aunque estaría muy bien tratar un poco la programación incluido C# y en
general Visual Studio (F#, VB, etc), ya que cada vez más el software Xnanciero que conozco y manejo tiende a construirse con estos lenguajes,
incluido aplicaciones de software libre
PD: cada uno tiene su forma de programar, eso es indiscutible, sólo pretendía completar un poquito la información dada, puesto que hablabas de
deXnición de variables y sólo he aportado los que a mi juicio son dos tipos básicos de variable, con ello no pretendía ofender a nadie, y si así ha sido
me disculpo.
PD: por cierto el tema de los bits y cuánta información se puede codiXcar con un tipo u otro se puede ver aqui:
Integer: http://msdn.microsoft.com/es-es/library/06bkb8w2(VS.80).aspx
Long: http://msdn.microsoft.com/es-es/library/y595sc15(VS.80).aspx
según leo aqui en sistema de 32 bits el Integer es más eXciente, pero como digo cada programador es un mundo...
s2
Responder
Comstar
#11 Creo que me he expresado mal. Al hablar de programas de juguete me reXero a proyectos pequeños, donde la memoria no es un problema tampoco.
No quise decir que tu hicieras programas pequeños. Es entendible que tu busques la eXciencia, y eso es muy loable. Es especialmente útil en
programas muy pesados que consumen muchos recursos de la máquina.
Sin embargo sí queda el riesgo de tener problemas de depuración al trabajar variables Integer. Si se tratara de ahorrar recursos en contadores, se
puede usar variables tipo Byte. Sin embargo a veces creo que irse al mínimo puede generar problemas futuros de escalabilidad, principalmente al
usar variables que sirven como punteros en VB. El programador conoce los requerimientos actuales, pero no necesariamente los requerimientos
futuros.
Recordemos que por ahorrar memoria en punteros es que Outlook tiene un horrible bug que hace que los archivos OST tengan problemas después
de exceder cierto tamaño y que exigen reparación del archivo de correos. Principalmente en punteros es donde preXero ser un poco ineXciente para
evitar problemas similares.
Cada uno tiene su propia manera de matar pulgas. La mía es una, la tuya es otra, y me alegro de que surja el debate, porque así el lector podrá decidir
por una opción u otra.
Responder
X4v13r
creo que así puedes mejorar la escalabilidad de un programa (se trataría un poco de tender a lo que pretende la programación orientada a objetos
OOP), el problema es que esto no siempre sea posible claro jeje, es muy interesante este tema, yo personalmente (por costumbres mías) no me
gusta asignar más espacio del estrictamente necesario a una variable, ¿tu qué opinas?¿has encontrado problemas a la hora de acotar la memoria
necesaria para codiXcar una variable? me interesa si puedes dar algún ejemplo concreto porque así yo también mejoro mi forma de programar
basándome en la experiencia de otros programadores (y que me perdonen los economistas del foro por llevar estos foros a mi terreno jeje). Gracias ;)
PD2: por cierto esto del HTML que comentabas, ¿qué es?
Responder
Comstar
#13 Puede decirse que cuando se escribe Dim X() se crea el puntero a la posición inicial del array, todavía no tiene una dimensión especíXca. Al darle
Redim X(n) lo que se hace es asignar una cantidad de n elementos al array.
Sin embargo en VB no existe el concepto de puntero, sólo el de variable. Si quieres usar punteros, usas variables donde almacenas el valor para usar
como subíndice, pero no haces referencias a direcciones de memoria como en C++. Esto tiene ventajas al simpliXcar las cosas para novatos, pero
resulta algo impráctico cuando quieres simplemente almacenar información con punteros. Si estás acostumbrado a trabajar con punteros
encontrarás VB un poco rígido y quizá hasta ineXciente, y el manejo de objetos muy burocrático. Pero para novatos en programación es más que
suXciente por su sencillez.
Para efectos de aquellos que no conocen nada de C++ y nada de VB, lo mejor es decir que Dim X() crea el array sin un tamaño deXnido, dejándolo
listo para darle un tamaño, y Redim X(n) le da un tamaño n, con n elementos que están listos para usarse.
En VB puedes hacer recursividad siempre y cuando no llenes el stack. Yo en lo personal preXero no hacerlo.
Muchos consideran que VB no es un lenguaje muy profesional, sino uno para principiantes, pero yo no lo creo así. VB trae algunas características que
son muy ineXcientes y lentas, pero si uno logra esquivarlas puede hacer código que funciona a una velocidad decente.
Algunos ejemplos son las variables Variant, el usar referencias a valores de celdas y controles en lugar de meter los valores en variables, usar el API
de Windows para saltarse algunas ineXciencias, uso del API de DirectX en lugar de herramientas nativas de dibujo, etc.
VB es mucho más sencillo que C++, pero también mucho más limitado. VB es como un coche automático, mientras que C++ es como un coche con
palanca de marchas y pedal de embrague. Cada uno tiene sus ventajas y desventajas.
Responder
Ramon13
http://economia-excel.blogspot.com/
Responder
Ramon13
http://blogs.mathworks.com/
http://blog.wolframalpha.com/2010/11/05/keeping-an-eye-on-energy-prices-with-wolframalpha/
http://blogs.mathworks.com/videos/
Responder
Comstar
Top 25
Envía tu consulta
Recibir nuevos posts
Te puede interesar...
Más leído Más recomendado
Entendiendo la economia de un
3
país en forma simple
Ver todas
Últimos comentarios
Ajddd
14/02/2020
Comstar
17/01/2020
Gamok1011
16/01/2020
Moinelo
08/01/2020
Rankia
Copyright © 2003 - 2020 Rankia S.L. Aviso legal · Política de privacidad · Política de cookies · Contacta con nosotros · Quiénes somos