SlideShare una empresa de Scribd logo
Programación con Visual Basic para Aplicaciones en Excel




    •    Introducción
    •    Artículos
    •    Macros
    •    Funciones
    •    Proyectos paso a paso
    •    Complementos (Add-ins)
    •    Otros Lenguajes
    •    Vinculos

Introducción

Programar sobre cualquier lenguaje es fascinante, en la mayoría de ellos, el limite esta más de parte del
programador que del lenguaje, no tengo elementos para decir cual es mejor o peor, creo que cada uno tiene
diferentes propósitos y que el bueno o malo, es el programador. Aprendí a programar de forma empírica, esto
tiene sus pros y sus contras, como desventaja esta que te tardas un poco más de tiempo en aprender y como
ventaja esta que te vuelves un muy buen investigador, estas, solo por nombrar algunas, se que tal vez tenga
muchas deficiencias y muchos otros "vicios" de los cuales, tal vez, ni cuenta me de, pero confío en que algún
buen samaritano que tenga más experiencia que yo en la programación, me los hará notar, por lo pronto, es
mi deseo que este camino que para mi ha sido de más de cinco años, sea mas corto y más leve para ti, esta
es la razón principal de estas páginas. Como notaras la sección que esta más completa es la de Excel, fue de
los primeros programas que use y en que empecé con el VBA y aun me sigue sorprendiendo y cada vez que
escribo unas líneas de código, me surgen nuevas interrogantes, pero eso me gusta y te sugiero que no te
desanime si este es tu caso, veras que poco a poco se va aclarando el camino.

Si bien en un principio no era mi intención hacer un manual, sino tan solo una guía, la verdad es que se ha
impuesto mi espíritu pedagógico, pues te cuento que una de mis actividades favoritas es dar clases, así que
lo que empezó como unos apuntes se esta convirtiendo en este pequeño manual, así que aprovecha,
estudia, lee, investiga, lee, practica y lee, lee mucho...

Artículos

         Preguntale a la Grabadora de macros
         Publica o Privada, ¿cual usar?

    •    Option Explicit, Dim, ¿que es eso?
    •    ¿Cómo puedo proteger un trabajo intelectual desarrollado en Excel? COLABORACION de Héctor
         Miguel Orozco Díaz, GRACIAS...
    •    Variables y objetos, ¿como nombrarlos?

Macros

         Grabando mi primer macro en Excel

    •    Escribiendo mi primer macro en Excel
    •    Escribiendo mi primer macro en Excel II
    •    Escribiendo mi primer macro en Excel III

Funciones

Las funciones personalizadas de Excel, trabajan igual que las incorporadas, con la diferencia de que estas
las creamos nosotros y nos sirven para obtener valores que no nos devuelven las incorporadas o para unir en
una sola, el resultado de varias funciones, su uso y manipulación es muy semejante a las macros, pero como
sabes estas nos devuelven valores, esto no lo pierdas de vista.
       Escribiendo mi primer función en Excel

    •   ¿Como dejar disponibles mis funciones?
    •   Función Numeros a Letras




Proyectos Paso a Paso

Esta sección esta pensada para que, aunque no tengas gran experiencia en la programación, seas capas de
seguir una secuencia de pasos para lograr un propósito, un proyecto completo de alguna tarea, puedes
proponer el desarrollo de algún proyecto, y si es de interés para varios, tal vez se pueda desarrollar entre
todos.

    •   Proyecto de Facturación (en preparación)




Complementos (Add-ins)

En esta sección explicaremos que son, cual es su propósito y como se usan, así como la forma de
"instalarlos" dentro de Excel, también agregaremos complementos probados y terminados para su libre uso y
estudio del código.
         ¿Que son?

    •   Exportador de macros




Otros Lenguajes

Controlar Excel desde otros lenguajes, es sumamente fácil, ademas de que pones a disposición de tu
programa, todas las herramientas de este, basicamente hay dos formas de hacerlo, trataremos de ver ambas,
aunque más adelante solo me concentrare en una de ellas, también, para esta sección, estoy suponiendo
que ya tienes bases de programación...




Preguntale a la Grabadora de Macros

Rara vez, la grabadora de macros, nos deja una macro tal como la queremos, en la mayoría de los casos, hay
que editarla, agregándole o quitándole líneas, complementándola, mejorándola. En mi experiencia, la
grabadora de macros funciona muy bien como profesora, es decir, nos enseña el "como" de casi todo el trabajo
sobre Excel y "casi" nunca se equivoca. Concretamente lo que te quiero decir, es que cuando no sepas como
hacer X tarea, graba una macro, ve el código, checa la ayuda acerca de las líneas que haya agregado y veras
como se aprende bastante, también esto sirve para que cuando realices una consulta, aquí o en cualquier otro
lugar, ya tengas una idea, con código, de lo quieres, veamos estos dos casos con un ejemplo:

En la página de Todo Expertos, un usuario me hizo la siguiente pregunta, que pongo solo con animo ilustrativo,
no se nos vaya a ofender:

        Esta duda me trae de cabeza...... (26/3/2002 18:44:0)
        Hola Valedor, es la primera vez que pregunto, supongo que será facil pero a mi me resulta
        muy complicado, la pregunta en resumen es la siguiente: ¿como puedo hacer para que con
una macro,función, o lo que sea, me copie solo las celdas que contengan texto del rango de
        celdas A1:A20 y me coloque el resultado en el rango C1:C20 ordenados una debajo de la otra,
        es decir que no copie las celdas vacías, teniendo en cuenta que el rango de la columna A son
        celdas vinculadas desde otras hojas y solo se rellenan si hay algún dato que consignar, si me
        puedes ayudar para realizar esa macro con te lo agradecería muchísimo y me solventarías un
        gran problema....

        Grabar macro... (27/3/2002 11:35:0)
        Lo primero que tienes que probar es a grabar una macro, yo lo hice y me dio esto

        Sub Macro2()
        Range("A1:A20").Select
        Selection.SpecialCells(xlCellTypeFormulas, 2).Select
        Selection.Copy
        Range("C1").Select
        ActiveSheet.Paste
        End Sub

        que hace lo que quieres...

Primero, este amigo, no sabe la diferencia entre una Macro, una Función o lo que sea, que son tres cosas
diferentes, pero tu ya los sabes ¿verdad?... Segundo, si el hubiese grabado la macro, tal vez no le hubiese
dado el mismo código que a mi, pero tendría "algo", que ya es ganancia, si antes de preguntar grabas tu
macro, yo pensaré que tienes interés en aprender y me dará más gusto ayudarte, pero que pasos hubiésemos
seguido para grabar esta macro, veamos algunas opciones, supongamos el escenario que nos propone el
amigo, una serie de valores en las celdas A1:A20, pero que son formulas, las cuales pueden ser texto o algo
más que no especifica, de estos datos, hay que seleccionar los que son texto y copiarlos a la celda C1,
eliminando los espacios vacios, para este ejemplo, use los siguientes datos:




Observa la barra de formulas, ve como los datos estan vinculados a otra hoja, observa también, que tenemos
textos y números, ahora, grabaremos nuestra macro con estos pasos :

   1. Activamos la grabadora de macros
   2. Seleccionamos los datos de nuestro interés, en este caso de la celda A1:A12
   3. Presionamos la tecla F5
   4. Presionamos el botón de comando Especial...
   5. Seleccionamos Celdas con formulas y solo dejamos activada la opción Texto.
   6. Presionamos el botón de comando Aceptar
   7. Copia estos datos, por el método que quieras, tienes como cuatro o más opciones
   8. Selecciona la celda C1
   9. Pega los datos
10. Detenemos la grabación

Si seguimos estos pasos al pie de la letra, la macro grabada tiene que quedar así...
Sub Macro1()
   Range("A1:A12").Select
   Selection.SpecialCells(xlCellTypeFormulas, 2).Select
   Selection.Copy
   Range("C1").Select
   ActiveSheet.Paste
End Sub
Si ejecutas esta macro en la hoja donde están las formulas, en nuestro ejemplo dentro de la Hoja1 tendrás que
ver algo como la siguiente imagen:




No te preocupes tanto si tienes algo diferente, seguro algo hiciste de otra manera, en este tema, esto no es lo
relevante, lo importante, es ver y notar como la grabadora de macros, nos ayuda mucho...
Ahora, vamos a darle una pequeña variante para que observes las diferencias, estos son los pasos:

    1. Activamos la grabadora de macros
    2. Seleccionamos la celda A1
    3. Presionamos la tecla F5
    4. Presionamos el botón de comando Especial...
    5. Seleccionamos Region actual
    6. Presionamos el botón de comando Aceptar
    7. Presionamos la tecla F5
    8. Presionamos el botón de comando Especial...
    9. Seleccionamos Celdas con formulas y solo dejamos activada la opción Texto.
    10. Presionamos el botón de comando Aceptar
    11. Copia estos datos, por el método que quieras, tienes como cuatro o más opciones
    12. Selecciona la celda C1
    13. Pega los datos
    14. Detenemos la grabación

Para estos pasos, la grabadora nos crea el siguiente código:
Sub Macro2()
  Range("A1").Select
  Selection.CurrentRegion.Select
  Selection.SpecialCells(xlCellTypeFormulas, 2).Select
  Selection.Copy
  Range("C1").Select
  ActiveSheet.Paste
End Sub
Ejecuta cada una de estas macros y nota las diferencias, dale variantes, por ejemplo, agrega mas datos por
debajo de la celda A20 y vuelve a probar cada una de las dos macros, agrega valores diferentes que no sean
texto o números, agrega constantes, o sea, valores que NO provengan de formulas, pruébalas en otras hojas o
libros. Cierto, esta macro no se adapta a todos los casos, de hecho, hace un trabajo muy especifico, pero notas
que ahora sabemos como seleccionar la región actual Selection.CurrentRegion.Select o también aprendimos
como seleccionar las celdas con formulas que contengan solo texto
Selection.SpecialCells(xlCellTypeFormulas, 2).Select ¿que más aprendiste con esta pequeñisima macro?.

Por ultimo haremos algo que se hace con la "mayoría" de las macros, editarla, si, editarla, es decir, agregarle
líneas que no haya agregado la macro, eliminando las que no nos sirven o mejorando lo que sea posible y
mira que casi siempre es posible.

Como primer paso, entra al Editor VBA y copia la macro que se llama (si no le pusiste otro nombre) Macro2, y
cámbiale el nombre a Macro3, recuerda que NO puedes tener dos macros con el mismo nombre dentro del
mismo módulo, esta macro tres será la que modificaremos y tal vez te sorprenda lo que se puede hacer,
sigamos...

    •   Como primer paso comentare la macro para que sepas que hace cada línea...
    •   Sub Macro3()
    •      'Se selecciona la celda A1
    •      Range("A1").Select
    •      'A partir de la seleccion actual, se selecciona la REGION ACTUAL
    •      Selection.CurrentRegion.Select
    •      'Seleccionamos las celdas con formulas que sean texto
    •      Selection.SpecialCells(xlCellTypeFormulas, 2).Select
    •      'Copiamos la seleccion
    •      Selection.Copy
    •      'Se selecciona la celda C1
    •      Range("C1").Select
    •      'Copiamos el contenido del portapapeles en la hoja activa
    •      ActiveSheet.Paste
    •   End Sub
    •   El siguiente paso será unificar las dos primeras líneas, es decir desde la celda A1 seleccionaremos la
        región actual, para que se vea así...
    •   Sub Macro3()
    •      'Se selecciona la celda A1 y su REGION ACTUAL
    •      Range("A1").CurrentRegion.Select
    •      'Seleccionamos las celdas con formulas que sean texto
    •      Selection.SpecialCells(xlCellTypeFormulas, 2).Select
    •      'Copiamos la seleccion
    •      Selection.Copy
    •      'Se selecciona la celda C1
    •      Range("C1").Select
    •      'Copiamos el contenido del portapapeles en la hoja activa
    •      ActiveSheet.Paste
    •   End Sub
    •   Ejecuta la macro con cada modificación que le hagamos, para que compruebes que sigue realizando
        las mismas acciones y finalizamos con el mismo resultado. Siguiente paso; unificamos la línea de
        selección de la celda A1 y la región actual, con la línea de selección de formulas que contengan texto...
    •   Sub Macro3()
    •      'Se selecciona la celda A1 y su REGION ACTUAL y las
    •      'las celdas con formulas que sean texto
    •      Range("A1").CurrentRegion.SpecialCells(xlCellTypeFormulas, 2).Select
    •      'Copiamos la seleccion
    •      Selection.Copy
    •      'Se selecciona la celda C1
    •      Range("C1").Select
•      'Copiamos el contenido del portapapeles en la hoja activa
    •      ActiveSheet.Paste
    •   End Sub
    •   Siguiente paso; unificaremos la línea de selección y la línea del método Copy...
    •   Sub Macro3()
    •      'Se selecciona la celda A1 y su REGION ACTUAL y las
    •      'las celdas con formulas que sean texto y copiamos
    •      Range("A1").CurrentRegion.SpecialCells(xlCellTypeFormulas, 2).Copy
    •      'Se selecciona la celda C1
    •      Range("C1").Select
    •      'Copiamos el contenido del portapapeles en la hoja activa
    •      ActiveSheet.Paste
    •   End Sub
    •   Siguiente paso; le agregamos el argumento "opcional" al método Copy, donde se le indica el destino
        donde queremos dejar lo que estamos copiando, tiene que ser un argumento tipo Range, o sea un
        rango, para nuestro ejemplo, será la celda C1
    •   Sub Macro3()
    •      'Se selecciona la celda A1 y su REGION ACTUAL y las
    •      'las celdas con formulas que sean texto y copiamos
    •      'le agregamos el argumento "opcional" al metodo Copy
    •      'el DESTINO donde queremos copiar, un Rango
    •      Range("A1").CurrentRegion.SpecialCells(xlCellTypeFormulas, 2).Copy Range("C1")
    •   End Sub
    •   ¿Cómo vez?, ¿has ejecutado la macro?, ¿observas como con UNA sola línea podemos hacer lo que
        se hacia con SEIS?, interesante ¿no crees?, no siempre es así, pero "casi" siempre, la grabadora de
        macros, graba líneas de más, que es muy bueno depurar, pues nos da mucha practica y código más
        limpio y ordenado...

Para terminar, te comento que todavía, hago uso de esta técnica, si no se o no recuerdo como se hace
determinada tarea, simplemente grabo una macro y listo, me muestra como es y en poco tiempo te
sorprenderás como cada vez menos, tienes que consultar la ayuda, saludos...

Creiste que esta vez no habia tareita, pues te fallo, prueba a grabar una macro con alguna acción que te
interese como se hace con código y nos cuentas a todos en la lista de correo, si vemos alguna interesante la
podemos publicar aquí...




Descargar el archivo grabando_macros.zip que contiene el archivo Preguntale a la grabadora de macros.xls
con todo el código mostrado en este artículo.




Publica o Privada, ¿cual usar?




Para este tema, doy por sentado que algunas vez has grabado, al menos, una macro, que has leido al menos
la Introdución que hay en esta página...

Cuando grabamos una macro, la grabadora nos crea un código como este:

Sub Macro1()
'
' Macro1 Macro
' Macro grabada el 03-04-2002 por Tecnico1
'
ActiveCell.FormulaR1C1 = "Hola"
   Range("A2").Select
End Sub
en algunas de mis páginas, en algunas otras páginas o en algún otro lado, habrás visto que algunas macros
tienen una palabra más, detrás del Sub, como se que eres curioso, presionaste F1 y en la ayuda leíste cuales y
para que sirven estas palabras: Public y Private, así que supongo que lo dicho aquí ya lo sabes, pero sigue
leyendo, tal vez encuentres algo nuevo o tal vez me notes algo que me falto y que por supuesto harás el favor
de decirme, ¿verdad?, gracias. Bien, entonces la macro anterior también puede estar escrita así...
Public Sub Macro1()
   ActiveCell.FormulaR1C1 = "Hola"
   Range("A2").Select
End Sub
o también así
Private Sub Macro1()
   ActiveCell.FormulaR1C1 = "Hola"
   Range("A2").Select
End Sub
pero, ¿cuál es la diferencia?, de eso se trata este pequeño articulo...

Veamos que dice la ayuda acerca de estas palabras

Public
          Opcional. Indica que el procedimiento Sub es accesible para todos los demás procedimientos de todos
          los módulos.
Private
         Opcional. Indica que el procedimiento Sub es accesible sólo para otros procedimientos del módulo en
         el que se declara.
A ver si entendimos, probemos con unos ejemplos, realiza los siguiente pasos:

    •     Entra a Excel
    •     Entra al EditorVBA (Alt+F11)
    •     Menú Insertar | Modulo
    •     En la ventana de código escribe lo siguiente
    •     Sub Pruebas1()
    •      MsgBox "Esta macro es PUBLICA"
    •     End Sub
    •     A lo que acabamos de hacer se le llama, declarar un procedimiento.
    •     Ejecútala desde el EditorVBA presionando F5 (recuerda que el cursor debe estar dentro de la macro) y
          nos mostrara este bonito mensaje.




    •     Ahora quiero que la vuelvas a ejecutar, pero desde Excel, regresa a Excel, ve al menú Herramientas |
          Macro | Macros... o si lo prefieres Alt+F8, selecciona la macro Pruebas1 y presiona el botón Ejecutar
          para confirmar que, de nuevo, se ejecuta correctamente.
    •     Ahora, agrégale la primer palabrita que estamos estudiando, para que se vea así.
    •     Public Sub Pruebas1()
    •      MsgBox "Esta macro es PUBLICA"
    •     End Sub
•   Vuelve a ejecutar la macro, de las dos formas que hemos visto y felizmente, nos muestra nuestro
    mensaje.
•   Conclusión: las macros o procedimientos son Publicas por omisión y como dice la ayuda que es
    opcional, entonces es lo mismo poner o no poner la palabra Public antes de la instrucción Sub.
•   Muy bien, muy bien, veo que eres buen estudiante, ahora creamos una segunda macro que se llame
    Pruebas2 (te quemaste el coco para pensar este nombre Mauricio), por que recuerda que no puedes
    tener dos procedimientos que se llamen igual, prueba a ponerle el mismo nombre y veraz que el
    EditorVBA te dirá algo medio feo. Ahora, le ponemos nuestra segunda palabrita.
•   Private Sub Pruebas2()
•     MsgBox "Esta macro es PRIVADA"
•   End Sub
•   Ejecútala desde el EditorVBA, verás que nos sigue mostrando el mensaje, claro, ahora nos dice que es
    PRIVADA (ni tanto ¿verdad?, la seguimos viendo), pero la siguiente prueba será ejecutarla desde
    Excel (Alt+F8).
•   ¿Qué paso?, ¿mande...?!, que!!, que no se ve!!, ¿¡cómo que no se ve!?, pero si estamos declarandolo
    como debe ser, aaahhh ya recuerdo, le agregamos una palabrita mágica, ¿verdad?, Private, si, esta
    palabrita es muy útil, en este caso, la macro ya no aparece listada en el cuadro de lista, del cuadro de
    dialogo Macros, como lo acabamos de demostrar, pero entonces, ¿no se puede ejecutar desde aquí,
    tiene que ser desde el EditorVBA?, para probarlo entra de nuevo al cuadro de dialogo macros y por
    ahora solo veras la macro anterior Pruebas1, ahí, donde dice Nombre de la macro, escribe Pruebas2
    y observa que pasa...
•   Interesante ¿no?, la macro de todos modos la podemos ejecutar con solo saber su nombre y estarás
    de acuerdo que si no queremos que las ejecuten no les diremos como se llaman, sssssshhhh...
•   Te puede suceder que, por error de dedo, hayas escrito mal el nombre de la macro, ¿qué pasa?, ¿qué
    es lo que hace Excel?, te dejo de tareita que me cuentes que pasa en estos casos.
•   ¿Y eso es todo?..., no, ¿cómo crees?, sigamos haciendo pruebas, como sabes, y si no sabias, ahora
    vas a saber, puedes ejecutar una macro desde otra macro, a esto lo nombramos llamar a la macro y
    para comprobarlo, modifica nuestra primer macro para que se vea así.
•   Public Sub Pruebas1()
•     MsgBox "Esta macro es PUBLICA"
•     Pruebas2
•   End Sub
•   Por supuesto ejecútala y observa, interesante, muy interesante... ¿verdad que si?... A la vista de este
    efecto, ¿que deduces?, ¿para que te imaginas que pueda servir el llamar a una macro desde otra?,
    ¿que utilidad tiene el que unas se vean y otras no?...
•   Antes de responder, algunas, por que otras de estas preguntas tu las tienes que responder, hagamos
    otras pruebitas. Insertemos otro modulo en nuestro archivo, menú Insertar | Módulo, nuestro
    Explorador de proyectos se tiene que ver así.




•   En este módulo crearemos una tercer macro Publica, en este momento ya tienes lo elementos para
    hacer tu propio ejemplo, pero por supuesto puedes seguir con los que propongo...
•   Public Sub PruebasA()
•    MsgBox "Esta macro es PUBLICA y esta en un otro Módulo"
•   End Sub
•   Ahora, trata de llamar a la macro Pruebas1 que se encuentra en el primer módulo, la macro se tiene
    que ser así...
•   Public Sub PruebasA()
•    MsgBox "Esta macro es PUBLICA y esta en un otro Módulo"
•    Pruebas1
•   End Sub
•   La macro se ejecuta, o se debería ejecutar sin problemas, si no es así, revisa alguno de los pasos que
    hemos seguido, ahora, trata de llamar a la segunda macro del primer módulo, es decir, trata de llamar
    a la macro que declaramos Privada en el primer módulo y que nombramos Pruebas2.
•   Public Sub PruebasA()
•    MsgBox "Esta macro es PUBLICA y esta en un otro Módulo"
•    Pruebas2
•   End Sub
•   ¿Qué sucedió?, ¿se ejecuta?, creo que no, pero el EditorVBA nos muestra un mensaje de error, más
    específicamente el siguiente error.




•   Después de presionar el botón Aceptar, el Editor nos regresa a la ventana de código, selecciona la
    palabra donde esta el error y nos muestra una línea de un color amarillo bastante distinguible.




•   Muy bien pensado, la razón de que no podamos llamar a una macro de otro módulo, es por que esta
    macro la declaramos Privada (Private), entonces si es cierto lo que dice la ayuda, -indica que el
    procedimiento Sub es accesible sólo para otros procedimientos del módulo en el que se declara-,
    ¿verdad?, de ahí la importancia de leer la ayuda "siempre". Antes de que detengas la ejecución de la
    macro, observa la barra de titulo, por ahí tiene una palabrita que dice [interrupción], ya la viste, bueno,
    por ahora solo lo menciono, pero más adelante se verá un poco más a detalle, cuando ejecutamos
    código, este se puede detener, tanto por errores de sintaxis (como en este caso) o cuando nosotros
    queramos, esto es algo muy útil cuando depuramos nuestras macros, así que lo veremos en otro
    articulo. Ahora si, puede detener la ejecución de la macro, de hecho, no tenemos otra alternativa, esto
    lo haces con el icono Restablecer de la barra de herramientas, que es como el botón Detener de la
    mayoria de los reproductores de musica, o bien, ve al menú Ejecutar | Restablecer y listo, la macro se
    detendra al momento.
•   Concluyendo: las macros pueden ser Publicas (Public) o Privadas (Private), es igual poner el Public o
    no, pero no es lo mismo si ponemos o no el Private, la recomendación es, declara explícitamente si
    tu macro es Publica o Privada.
•   Para terminar te comento que lo visto aquí, acerca de las macros Publicas y Privadas es aplicable,
    también, para las funciones, es decir, también tenemos funciones Publicas y funciones Privadas, pero
    parte de la tareita de esta sección es esa.
        o Crea una segunda macro Privada en el segundo Módulo y realiza todas las pruebas que
            hemos hecho con las demás, incluyendo, el tratar de ejecutarlas desde la ventana de Excel
        o Crea todas las macros y has todas las pruebas que consideres suficientes para que no queden
            dudas de este tema, incluso agrega un tercer o cuarto módulo para esto.
        o Crea varias sencillas funciones, tanto Publicas como Privadas y quiero que me digas, donde se
            ven y donde no, te dare una pista, usa el Asistente para funciones para observarlo. Para crear
            las funciones, si no lo has hecho, lee el tema Escribiendo mi primer función en Excel y después
            haces estas pruebas.
        o Una líneas más arriba, nos hicimos la siguiente cuestión: ¿para que te imaginas que pueda
            servir el llamar a una macro desde otra?, la respuesta a esta pregunta es importantisima,
            tiene mucho que ver con lo que pensaba el señor Descartes, ¿ya lo recuerdas?...
•   Como complemento a este artículo, veremos que diferencia hay entre una función Publica y una
    función Privada

    La siguiente función personalizada nos devuelve un texto con información del tipo de contenido de la
    celda pasada como argumento y nos dice si la celda esta VACIA, si es un NUMERO, si es una FECHA
    o si contiene TEXTO...

    Option Explicit

    Public Function TipoValor(Celda As Range) As String

     If Celda.Value = "" Then
       TipoValor = "VACIA"
     ElseIf IsNumeric(Celda.Value) Then
       TipoValor = "ES NUMERO"
     ElseIf IsDate(Celda.Value) Then
       TipoValor = "ES FECHA"
     Else
       TipoValor = "ES TEXTO"
     End If

    End Function


    Para usar esta función, regresa a la ventana de Excel, en este caso, usaremos el Asistente para
    funciones, que seguro ya dominas, entonces, los pasos serian...

        o   Escribe en la celda A1 un valor cualquiera
        o   Posiciona el cursor en la celda B1
        o   Inicia el Asistente para funciones
        o   En el Cuadro de lista Categoría de la función, busca la ultima opción que dirá, Definidas por el
            usuario
        o   En el Cuadro de lista Nombre de la función, tendrás que ver nuestra función TipoValor, por
            supuesto si tienes más funciones que hayas creado aquí las veras
        o   Seleccionamos esta función y presionamos el Botón de comando Aceptar
o   Como bien sabes, el Asistente te presenta una ventanita con el nombre de la función y un
    cuadro de texto solicitándote el argumento Celda necesario para que la función trabaje
    (bueno, realmente no es un cuadro de texto, sino un control muy especial y muy útil que
    aprenderemos a usar más adelante)
o   Puedes usar el botón Contraer o escribir directamente la referencia a la celda A1, tras lo cual
    presionaras el botón Botón de comando Aceptar y el Asistente introducirá por nosotros, el
    signo igual, la función y el argumento que le establecimos




o   Al terminar, mi celda B1 se tendrá que ver como en la siguiente imagen y verificaremos que la
    función haga el trabajo para la cual la programamos, ¿así es?...
o   Ahora, cambiaremos la palabra Public de nuestra función por la palabra Private, o bien,
    puedes copiar la función y hacer una segunda, por supuesto, con otro nombre, yo usare el
    primer método...
o   Option Explicit
o
o   Private Function TipoValor(Celda As Range) As String
o
o    If Celda.Value = "" Then
o      TipoValor = "VACIA"
o    ElseIf IsNumeric(Celda.Value) Then
o      TipoValor = "ES NUMERO"
o    ElseIf IsDate(Celda.Value) Then
o      TipoValor = "ES FECHA"
o    Else
o      TipoValor = "ES TEXTO"
o    End If
o
o   End Function
o
o   Regresa a la ventana de Excel y copia la formula existente en la celda B1 a la celda B2, ¿qué
    pasa?..., así es, la función sigue trabajando, entonces!..., ¿cuál es la diferencia?, para notarlo,
    trata de agregar un valor cualquiera en la celda A3, posicionate en la celda B3 y trata de usar el
    Asistente para funciones como en nuestro primer ejemplo y observa...
o   Efectivamente, la función no aparece, de hecho, la categoría que usamos Definidas por el
                usuario, ya no aparece (claro, siempre y cuando no tengas otra función declarada), pero trata
                de escribir la función directamente en la celda, ¿funciona?, si, si funciona, es algo similar a lo
                que pasa en las macros, que, como leiste más arriba, cuando la pasas a Privada, ya no se lista
                en el cuadro de dialogo, pero aun la puedes ejecutar si sabes su nombre, del mismo modo, si
                sabes el nombre de alguna función personalizada, la puedes llamar o hacer uso de ella,
                siempre y cuando te sepas su nombre y los argumentos que necesita, tan solo, con escribirla
                directamente en la celda.




            o   Como con las macros, nos preguntamos, ¿para que servirá tener funciones Publicas y
                funciones Privadas?..., observa la función Números a letras para que te des una idea, aunque
                de nuevo, el señor Descartes nos puede ayudar...




    •   Ahora si, Fin...




Descargar el código de este artículo.

Option Explicit, Dim, ¿que es eso?




Para este tema, doy por sentado que algunas vez has grabado, al menos, una macro, que has leido al menos
la Introdución que hay en esta página...

En la mayoría de código que veas en estas páginas, y en muchas otras macros que has visto, habrás notado
que al inicio de estas, casi siempre hay una pequeña línea de dos simples palabras, Option Explicit, las
seleccionaste, presionaste F1 y leíste esto:

Se usa en el nivel de módulo para forzar declaraciones explícitas de todas las variables en dicho
módulo.

Esta comprendido?, si?, bueno, Fin del articulo...

Pero que antipático te estas poniendo Mauricio, anda, explícalo mejor...

-De acuerdo, de acuerdo, trataré...-

Primero los ejemplos y después las explicaciones

    •   Entra Excel
•   Entra al EditorVBA
•   Inserta un nuevo módulo y asegúrate que este en vacío, si tiene las palabras que estamos estudiando,
    bórralas.
•   Teclea o copia la siguiente macro y pruebala
•   Public Sub Sumas()
•
•    Numero1 = Val(InputBox("Dame un número"))
•    Numero2 = Val(InputBox("Dame otro número"))
•
•    Suma = Numero1 + Numero2
•
•    MsgBox "La suma es: " & Format(Suma)
•
•   End Sub
•   Que bien, funciona verdad, ahora, vamos a suponer que tecleamos mal un nombre, por ejemplo, en
    vez de teclear Numero1, tecleamos Numer1, para que nuestra macro quede así, por esta vez, pondré
    en negritas los nombres que hay que probar...
•   Public Sub Sumas()
•
•    Numero1 = Val(InputBox("Dame un número"))
•    Numero2 = Val(InputBox("Dame otro número"))
•
•    Suma = Numer1 + Numero2
•
•    MsgBox "La suma es: " & Format(Suma)
•
•   End Sub
•   Pruébala, ¿funciona?, si, si funciona, solo que NO da el resultado correcto, en este caso, siempre nos
    mostrara el valor del segundo número que le hayamos proporcionado, ¿por qué?, sigamos con las
    pruebas, ahora supondremos que los números están bien y que la que tecleamos mal es la palabra
    Suma, la cual la tecleamos así; Sum
•   Public Sub Sumas()
•
•    Numero1 = Val(InputBox("Dame un número"))
•    Numero2 = Val(InputBox("Dame otro número"))
•
•    Sum = Numero1 + Numero2
•
•    MsgBox "La suma es: " & Format(Suma)
•
•   End Sub
•   Que bien!, también funciona, solo que tampoco nos da el resultado correcto, esta vez es peor, pues
    siempre nos muestra cero, ¿verdad?, bueno, la causa es más que obvia, los nombres no los hemos
    escrito correctamente y por correctamente me refiero a como escribimos esas mismas palabras en las
    líneas anteriores o posteriores, pues aquí no vale la ortografía, para muestra una macro...
•   Public Sub Gardim()
•
•    arvol1 = Val(InputBox("Dame un número"))
•    lovo2 = Val(InputBox("Dame otro número"))
•
•    frrutas = arvol1 + lovo2
•
•    MsgBox "La suma es: " & Format(frrutas)
•
•   End Sub
•   Observa como alucine con los nombres de estas palabras, a parte de que están mal escritas, no tienen
    nada que ver con el propósito de nuestra macro, ya volveremos sobre este asunto más adelante, por
ahora quise mostrarte el sentido de la palabra correctamente, y seguimos... Ahora, vuelve a nuestra
    primer macro y agrega, en la parte superior, las palabras mágicas Option Explicit y trata de ejecutarla.
•   Option Explicit
•
•   Public Sub Sumas()
•
•    Numero1 = Val(InputBox("Dame un número"))
•    Numero2 = Val(InputBox("Dame otro número"))
•
•    Suma = Numero1 + Numero2
•
•    MsgBox "La suma es: " & Format(Suma)
•
•   End Sub
•   ¿Que paso?, ¿no te dejo?, ¿porque?, ¿que te aparece?... efectivamente, nos muestra un bonito
    mensaje, que dice..




•   Y no solo eso, también nos colorea de amarillo la macro donde esta el error y nos selecciona la palabra
    que esta mal, mejor dicho, la variable, déjame repetirlo, la variable que NO hemos declarado.




•   Ahora tenemos una nueva palabra, variable ya sabes que tienes que hacer, presionar F1, buscar esta
    palabra para encontrar...

    Variable
    Un lugar de almacenamiento con nombre que puede contener cierto tipo de datos. Cada variable tiene
    un nombre único que la identifica. Nombres de variable deben comenzar con un carácter alfabético,
    deben ser únicos dentro del mismo ámbito, no deben contener más de 255 caracteres y no pueden
    contener un punto

    Si leíste la ayuda, notaras que no esta todo lo que dice ahí, pues estoy haciendo un poco de trampita
    como diría un amigo, la trampita es que no transcribí todo, si no solo lo que a mi juicio, es relevante
    para este tema, así que vamos por partes...
•   Entonces, una variable es un lugar de almacenamiento con nombre, por ahora, es suficiente que
    recuerdes esto, es muy importante, y... ¿dónde esta es lugar de almacenamiento?, señoras y señores,
    les presento a la señora RAM, bueno, no hace falta, todos la conocemos y la usamos, siempre que
    prendemos nuestra maquina, ¿verdad?, si, esa cosa llamada memoria RAM que por cierto ha subido
    mucho de precio, pero en fin, ahí, en al memoria RAM es el lugar de almacenamiento de nuestras
    variables, pero tenemos que comunicarle al VBA que nos aparte un pedacito de memoria y que
    además le de un nombre para que sepamos donde esta, a la acción de reservar memoria para
    nuestras variables, se le denomina Declaración de variables o Dimencionar variables, para ello,
    usamos otra nueva palabrita mágica, la instrucción Dim, modifica la macro para que se vea así...
•   Option Explicit
•
•   Public Sub Sumas()
•   Dim Numero1
•
•    Numero1 = Val(InputBox("Dame un número"))
•    Numero2 = Val(InputBox("Dame otro número"))
•
•    Suma = Numero1 + Numero2
•
•    MsgBox "La suma es: " & Format(Suma)
•
•   End Sub
•   Ejecutala y..., tampoco nos deja, y ahora ¿que paso?, se detuvo de nuevo, pero ahora en otra variable,
    pero nos muestra el mismo error, ¿no es así?, bueno, pues ni modo, vamos a declarar nuestras
    restantes variables..
•   Option Explicit
•
•   Public Sub Sumas()
•   Dim Numero1
•   Dim Numero2
•   Dim Suma
•
•    Numero1 = Val(InputBox("Dame un número"))
•    Numero2 = Val(InputBox("Dame otro número"))
•
•    Suma = Numero1 + Numero2
•
•    MsgBox "La suma es: " & Format(Suma)
•
•   End Sub
•   ¿Y esta vez?, claro, ahora si funciona de nuevo, pero... ¿qué ventaja percibes al declarar las
    variables?, ¿no es teclear más solamente?, en este ejemplo manejamos tres variables y seria algo
    difícil el escribir mal alguna, pero cuando empiezas a manejar, diez, veinte, cincuenta variables y no se
    diga cuando empieza a combinar más de una macro, funciones y otras cositas que ya veremos,
    notaras todas las ventajas de Declarar explícitamente las variables pues el uso de Option Explicit
    nos evita que usemos variables que antes, no las hayamos declarado.
•   Si lees la ayuda acerca de la instrucción Dim, leerás que no solo es esta, sino que tiene muchas otras
    variantes, tantas que nos saldríamos del tema central de este articulo, pero te recomiendo que lo leas,
    analices y ponga en practica, lo que si veremos es algo de suma importancia, transcribo...

    Dim
    Declara variables y les asigna espacio de almacenamiento

    De esta definición, ya debes de tener comprendida la primer parte Declara variables, la segunda no es
    tan complicada asigna espacio de almacenamiento. Quedamos que nuestras variables quedan en la
    memoria RAM, como sabes esta memoria es limitada y conforme se usa, hay la posibilidad de que se
    acabe, lo cual es muy malo, así como dice la física, que materia es todo lo que ocupa un lugar en el
    espacio, aquí, diremos que toda variable ocupa un espacio en la memoria, la pregunta es ¿cuánto
espacio?, la respuesta es, depende, nueva pregunta ¿de que depende?, nueva respuesta, del tipo de
        variable, (expresión de asombro), ¿pero que hay varios tipos de variables?, respuesta si, ¿cómo
        cuales?, aquí van algunos: Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String,
        Object, Variant, cada uno de estos tipos, ocupa un lugar, tiene un tamaño y puede contener una cierta
        cantidad de información, ¿cuál es la mínima unidad de almacenamiento?, así es, 1(un) byte, entonces,
        las variables, dependiendo su tipo, usan desde un byte y ¿hasta?, esa es tu tarea...

    •   Te estarás preguntando, ¿pero como le decimos que tipo de variable quiero usar?, y la respuesta es
        muy sencilla, solo usamos otra palabrita mágica, As, seguida del tipo de variable que queramos
        declarar, para muestra, declararemos correctamente nuestras variables...
    •   Option Explicit
    •
    •   Public Sub Sumas()
    •   Dim Numero1 As Integer
    •   Dim Numero2 As Integer
    •   Dim Suma As Integer
    •
    •    Numero1 = Val(InputBox("Dame un número"))
    •    Numero2 = Val(InputBox("Dame otro número"))
    •
    •    Suma = Numero1 + Numero2
    •
    •    MsgBox "La suma es: " & Format(Suma)
    •
    •   End Sub
    •   Todavía más preguntas, ¿qué pasa si no le indico de que tipo es?, en nuestro ejemplo anterior
        funciono bien, ¿entonces?, ¿cuál es la diferencia?, la respuesta a esta interrogante, esta en la ayuda,
        así que nuevamente, busca y lee un poquito, por lo pronto, acostúmbrate a declarar explícitamente tus
        variables, reitero, declara explícitamente TODAS tus variables y acostumbrate a que como primer
        línea, en cualquier módulo de código, tengas un Option Explicit, entre más variables uses y mas
        líneas de código tengas, notaras cada vez más, las grandes ventajas de esto.




Descargar el código de este artículo.

¿Cómo puedo proteger un trabajo intelectual desarrollado en excel?.

Por Héctor Miguel Orozco Díaz

La pregunta anterior se hace con cierta frecuencia en los foros públicos de discusión y consulta (tanto en los de
Microsoft como en los "independientes"). Las respuestas siempre serán en relación con el tipo y grado de
protección "deseada". La forma más "fácil" de proteger en Excel (sin utilizar macros), es asignar una
contraseña (ó "password") ya sea a la hoja, al libro, al archivo. Para los dos primeros casos, "basta" con usar el
comando Herramientas | Proteger | Proteger hoja... o Proteger libro...
Para proteger un archivo ("completo") contra apertura y/o escritura, usa el comando Archivo | Guardar como... |
Herramientas (BOTÓN AL FINAL) | Opciones generales.... En los diálogos mostrados por estos comandos,
podrás asignar la contraseña de tu preferencia y a los componentes que se habrán de incluir en la protección
que creas más "convenientes" (se te solicitará una confirmación).
Nota:   Las contraseñas en Excel (y textos en VBA) son "sensibles" a la capitalización (mayúsculas ó
        minúsculas). NO ES LO MISMO "abc" QUE "aBc". Por lo tanto, si usas contraseñas para protección de
        tu trabajo... "¡ QUE NO SE TE OLVIDE... RECORDARLAS !!!" (EXACTAMENTE COMO Y EN DONDE
        LAS ASIGNASTE).

Sin embargo, brincar (ó "crackear") las protecciones para la hoja y el libro (NO al archivo) es "sumamente fácil",
mediante macros que pueden inclusive ser usadas "desde otro" libro cualquiera (ohh... desilusión !!!).

Los siguientes códigos hacen el "trabajo sucio":

Option Explicit

'** Para quitar password en protecciones a hojas ... **
Public Sub RemoverPasswordEnHoja()
  ActiveSheet.Protect "", , , , True
  ActiveSheet.Range("a1").Copy ActiveSheet.Range("a1")
End Sub


'** Para quitar password en protecciones a libros ... **
Public Sub RemoverPasswordEnLibro()
  Dim Protecciones As Integer

 If ActiveWorkbook.ProtectStructure = True Then Protecciones = Protecciones + 1
 If ActiveWorkbook.ProtectWindows = True Then Protecciones = Protecciones + 2
 Select Case Protecciones
   Case 0: ActiveWorkbook.Protect "", False, False
   Case 1: ActiveWorkbook.Protect "", True, False
   Case 2: ActiveWorkbook.Protect "", False, True
   Case 3: ActiveWorkbook.Protect "", True, True
 End Select
 ActiveWorkbook.Unprotect

End Sub
Para quitar password en protecciones a archivos ....

Esta protección "ya empieza" a ser difícil de brincar. Se requiere "apoyo" de algún software especializado (que
generalmente cuesta dinero) cuyas "versiones de prueba" (léase gratis) "rompen" contraseñas con hasta un
máximo de 4 caracteres. Te sugiero que utilices contraseñas "más largas", inclusive puedes usar "mezclas" de
mayúsculas y minúsculas, números y caracteres especiales, como los que se obtienen de la combinación de
las teclas {Alt} + teclado numérico como: {Alt}+174 = «, {Alt}+0140 = Œ, {Alt}+225 = ß, {Alt}+
(la_que_te_encuentres_simpática). Los caracteres que se "visualizan" dependen del tipo de letra que se usa.




USO DE MACRO-CÓDIGOS CON APOYO DE VBA.

Si quieres "llegar" a protecciones más "sofisticadas", tendremos que "echar mano" de las macros, para lo cual,
enseguida se explicarán algunos "trucos" que, haciendo una "buena" combinación de ellos te podrás acercar a
lo que pudiera considerarse como un "Sistema de Protección (casi) Perfecto".
Requisito INDISPENSABLE: Asignar también al proyecto VBA (macros) una contraseña.
SIGUE LAS SUGERENCIAS INDICADAS ANTERIORMENTE... Y ¡OJO! CON LOS ACENTOS.

Toma en consideración que una de las tareas más "quema-neuronas" en cuestiones de programación es:

    o   "Anticipar" (en la medida de lo posible) las acciones del usuario para poder.
    o   "Evaluar" las consecuencias de ejecutar un código y finalmente.
    o   "Diseñar" prevenciones o correcciones de errores "involuntarios" (o premeditados?).

La técnica empleada para este ejemplo, es precisamente el uso combinado de varios "trucos", los cuales se
irán explicando en el curso de estos textos y cuya base principal es: "Mantener" el archivo grabado (en la
unidad de almacenamiento) SIEMPRE OCULTO Y CON CONTRASEÑA, para lo cual es imprescindible contar
con el apoyo de los eventos de la aplicación para "detectar" algunas acciones del usuario y "actuar en
consecuencia".




ANALIZANDO LOS "INCONVENIENTES" (Y SOLUCIONES) DE USAR MACROS:>

Dado que el usuario tiene la opción de decidir si un archivo se abre o no "con permiso" de usar macros ó puede
inclusive "mantener inoperables" los eventos (esto NO lo puedes evitar), las primeras acciones "preventivas"
serán:

    1. Si se ha de abrir sin permiso de usar macros (por elección o alto nivel de protección) ó los eventos son
       "inoperables" (en ese momento), hemos de asegurarnos que el archivo "se mantiene" OCULTO y con
       "password" (en la unidad de almacenamiento).
    2. Si las macros y los eventos "están en operación" (y se va a "permitir" su uso), hemos de EVITAR que
       pueda grabarse el archivo (a la unidad de almacenamiento) de la manera "convencional", ya que
       podría "volverse visible" y quedar completamente "desprotegido" para la siguiente vez que se abra (lo
       haremos por código mediante un procedimiento "especial").
    3. Hemos también de prevenir (y corregir en su caso) que durante el curso de la sesión los eventos sean
       "des-habilitados".

Estas acciones nos permiten darle al usuario "permiso de usar" el archivo "prácticamente" sin restricciones y
"tomar" el control de lo que podrá o no "hacer" con él (y en él).

Algunas opciones que el usuario puede usar para "impedir" el uso de macros son:

    o   "Tener" un nivel alto de protección "contra" archivos con macros.
    o   "Elegir" NO ejecutar las macros del archivo (si el nivel es medio ó bajo).
    o   "Mantener presionada" la tecla {Mayús} (al abrir el archivo y "permitir" las macros).
En cualquiera de estos casos, las macros NO se ejecutan o "se omiten" las de apertura. Otra "forma" que
podría emplearse es: abrir el archivo mediante macros (en otro archivo) usando previamente la instrucción
Application.EnableEvents = False
"Contra" estas (y otras) opciones, nuestra primer acción preventiva prevalecerá: el archivo (desde la unidad de
almacenamiento) "permanece" OCULTO Y CON CONTRASEÑA.
Ahora bien, cuando las macros "son permitidas" y los eventos "están operables", podemos verificar que "se
cumplan" ciertas condiciones para permitir o no el uso de nuestro archivo.
Tales condiciones pueden ser -entre otras-

    A.   Que el archivo está ubicado en algún directorio específico -o uno "alterno"-
    B.   El nombre del usuario
    C.   Si existe algún archivo en ese u otro directorio
    D.   La fecha del sistema
    E.   El nombre mismo del archivo
    F.   Etc., etc., etc.

Podrás encontrar otras que "acomoden" mejor a tus necesidades. En caso de que las condiciones ("mínimas
necesarias") estén cumplidas, se dará acceso al archivo, en caso contrario, se tomarán otras acciones (como
permitirle "verlo sin usarlo" ó definitivamente cerrar el libro -entre otras-).

Si se permite el acceso al libro (total ó "restringido") para evitar que lo grabe de la manera "tradicional"
(segunda acción preventiva), "forzamos" a la aplicación para que los métodos "convencionales" de grabado "no
funcionen" y le proveemos de un "comando especial" que se encargará de que el archivo se grabe (a la unidad
de almacenamiento) SIEMPRE OCULTO Y CON CONTRASEÑA. Es por esto es que "nos tenemos que
asegurar" de que los eventos estén "siempre operables" (tercera acción preventiva).




ALGUNOS "TRUCOS" (COMBINABLES) POR CÓDIGO:

Para continuar con la exposición de los ejemplos, "se dará por entendido" que se tiene al menos un
conocimiento "esencialmente básico" en cuanto al uso del lenguaje Visual Basic para Aplicaciones (VBA) -la
plataforma en la que "trabajaremos"-, así como de los objetos, propiedades, métodos, eventos, instrucciones y
"otros".

Para verificar que el archivo se encuentre ubicado en un directorio específico, usamos la propiedad Path de un
objeto Workbook, que "devuelve" una cadena de texto indicando la ruta (unidad y directorio):

If ThisWorkbook.Path = "C:Mis documentosOtro directorio" Then
Para verificar el nombre del usuario, usaremos la propiedad UserName del objeto Application ("forzada" a
minúsculas -ó mayúsculas-), que "devuelve" una cadena de texto con el nombre "registrado":
If StrConv(Application.UserName, vbLowerCase) = "fulanito de tal" Then
Para verificar si existe algún archivo en ese u otro directorio, existe el método Dir("Ruta_ Archivo"), que
"devuelve" una cadena de texto con el nombre del archivo ó una cadena vacía ("") si no existe:
If Dir("Unidad:Ruta1Ruta2NombreArchivo.ext") <> "" Then
Para comparar dos fechas, primero "tendremos" que identificar el orden de los elementos con la propiedad
International(xlDateOrder) del objeto Application, que "devuelve" un tipo de datos Long (0 = mes-día-año; 1
= día-mes-año; 2 = año-mes-día), de lo contrario, un dato de fecha podría "significar" FECHAS DISTINTAS (en
sistemas "diferentes").

P.e.: La fecha "25 de Mayo de 2002" de un sistema "de origen" del orden 1 (día-mes-año) si se quiere
comparar en un sistema "de destino" del orden 0 (mes-día-año) "indicando" la fecha como "25/5/02" significará
"Mayo 2 de 2025". Una estructuración "confiable" sería:

Dim Fecha_x As Date

Select Case Application.International(xlDateOrder)
 Case 0: Fecha_x = DateValue("5/25/02")
Case 1: Fecha_x = DateValue("25/5/02")
 Case 2: Fecha_x = DateValue("02/5/25")
End Select

If Now <= Fecha_x Then




PRIMER PUNTO: TERCERA ACCIÓN "PREVENTIVA".

Una vez que "obtuvimos permiso" de usar las macros y estando los eventos "operables", puesto que uno de
ellos "detecta" la intención del usuario de grabar el archivo "de manera convencional", aseguramos que los
eventos "permanezcan operables", utilizando para ello el método OnTime del objeto Application, haciendo
una llamada "recursiva" al mismo método una y otra vez (por el tiempo que dure la sesión) para "monitorear"
los eventos.

PRECAUCIÓN !!! - La ejecución del método OnTime de manera recurrente y programada, NO ES
CANCELADA "automáticamente" por la aplicación. Si el libro que la ejecuta es cerrado SIN CANCELAR LA
SIGUIENTE "LLAMADA", Excel volverá a abrir el libro y continuará su ejecución. ¡ ES NECESARIO
CANCELAR AL SALIR !!!.

Para lograr el efecto de "re-llamado" al método, usaremos las variables Públicas:

'Para el "siguiente monitoreo" de los eventos
Public MonitorEventos As Double
'Para monitorear los eventos cada 20 segundos (p.e.)
Public Const IntervaloMonitor As String = "0:00:20"
'Es el nombre de la macro que mantiene activos los eventos
Public Const MacroEventos = "MantenerEventos"
En los siguientes procedimientos:
'Macro de "prevención" contra "suspensión" de eventos
Public Sub MantenerEventos()
  'Mantiene siempre Activos los eventos
  Application.EnableEvents = True
  '(Re)-Inicia un bucle de "Activación" cada "X" tiempo
  ComenzarLoopDeEventos
'Fin del procedimiento
End Sub


'Macro de monitoreo "permanente" de Eventos
Public Sub ComenzarLoopDeEventos()
  'Se determina el "siguiente monitoreo" de los eventos
  MonitorEventos = Now + TimeValue(IntervaloMonitor)
  'Una vez "llegado" el tiempo, "lanza" nuevamente el método OnTime haciendo referencia
  'a la variable pública constante "MacroEventos" (macro "MantenerEventos") especificando
  'que el siguiente "loop" se ejecute (Schedule:=True)
  Application.OnTime _
       EarliestTime:=MonitorEventos, _
       Procedure:=MacroEventos, _
       Schedule:=True
'Fin del procedimiento
End Sub


'Macro para "cancelar" el siguiente método OnTime
'Este procedimiento se llamará "al cierre" del libro.
Public Sub DetenerLoopDeEventos()
'Necesariamente es igual al procedimiento de re-llamada, con excepción de que
  '"la siguiente vez" que el método debiera ejecutarse se especifica como Falso.
  MonitorEventos = Now + TimeValue(IntervaloMonitor)
  Application.OnTime _
       EarliestTime:=MonitorEventos, _
       Procedure:=MacroEventos, _
       Schedule:=False
End Sub
Una vez definidos los procedimientos, los "llamamos" en alguna macro de evento como Auto_Open (ó
Auto_Close) o los procedimientos de evento del objeto Workbook.
'Para iniciar (y mantener) el método:
Private Sub Workbook_Open()
  MantenerEventos
End Sub


'Para detener (y cancelar) el método:
Private Sub Workbook_BeforeClose(Cancel As Boolean)
  DetenerLoopDeEventos
End Sub




SEGUNDO PUNTO: SEGUNDA ACCIÓN "PREVENTIVA".

Ahora que los eventos "permanecerán" activos, vamos a "impedir" que el archivo se grabe (a la unidad de
almacenamiento) de la manera "convencional" (ya sabemos que de esta manera podría "volverse visible" y
quedar completamente "desprotegido" para la siguiente vez que se abra).
Para esto será necesario declarar una variable pública del tipo Boolean (Verdadero ó Falso) como:
PermisoParaGrabar, que será la que "impida" (ó "permita") que el archivo sea grabado y usaremos el evento
Before_Save del objeto ThisWorkbook con una línea como:

If Not PermisoParaGrabar = True Then Cancel = True
Así le estamos "indicando" a Excel que siempre y cada vez que el usuario "pretenda" grabar el archivo, "NO se
lo permita". La variable será usada como "candado" en el código de nuestro "comando especial" para "abrir" el
permiso, grabar (de manera "correcta") y "cerrar" nuevamente el candado.




TERCER PUNTO: PRIMER ACCIÓN "PREVENTIVA".

Con los eventos activos y los comandos convencionales de grabación "fuera del alcance" del usuario,
procederemos a "instruir" a Excel para que, a través de un comando especial nos asegure que el archivo
SIEMPRE "permanecerá" OCULTO Y CON CONTRASEÑA.

'Macro para guardar los cambios (sólo por código)
Public Sub GuardarEspecial()
 'Congelamos la actualización de la pantalla
 Application.ScreenUpdating = False
 'La variable que "permite" o "impide" grabar el archivo
 PermisoParaGrabar = True
 'Ocultamos la ventana del libro protegido
 Windows(ThisWorkbook.Name).Visible = False
 'Protegemos el libro con Contraseña
 '(inclusive su estructura y "arreglo" de ventanas)
 ThisWorkbook.Protect Password:="X_Contraseña", _
   Structure:=True, Windows:=True
 'Grabamos el libro (a la unidad de almacenamiento)
ThisWorkbook.Save
 '"Cancelamos el permiso" que da la variable
 PermisoParaGrabar = False
 'Fin del procedimiento.
End Sub
Una macro como la anterior hará "un excelente trabajo", sólo faltaría "detectar" si el libro "continúa en
operación" (para volverlo a "presentar" al usuario ó cerrarlo si fuera el caso).

El siguiente paso es: "Agregar" el comando a algún menú (o submenú), "aprovechando" el evento Open del
objeto ThisWorkboook, agregando la siguiente línea: AgregarComando., que "hace referencia" a la siguiente
macro:

'Macro para agregar el Comando "Especial"
Public Sub AgregarComando()
  'Se agrega un comando TEMPORAL en la posición # 8 del menú de "Archivo" y ...
  Set MiComando = CommandBars("File").Controls.Add _
        (Type:=msoControlButton, Before:=8, Temporary:=True)
  With MiComando
    .BeginGroup = True
    .Style = msoButtonCaption
    .Caption = "Guardar &especial"
    .FaceId = 1
    'Lo mandamos ejecutar la macro de "GuardarEspecial"
    .OnAction = "GuardarEspecial"
  End With
'Fin del procedimiento
End Sub
Finalmente (y sólo "por si las dudas"), al salir del libro eliminaremos este comando usando el evento
Before_Close del objeto ThisWorkbook con la siguiente instrucción:
  If Application.CommandBars("File").Controls(8).Caption = "Guardar &especial" _
    Then Application.CommandBars("File").Controls("Guardar &especial").Delete (True)




NOMBRE Y POSICIÓN DE LOS OBJETOS.

Generalmente se usan las propiedades Name ó Index (posición) para "referirnos" por código a las hojas de un
libro, p.e.

Worksheets("Resumen")

Worksheets(3)
Si el usuario "modifica" estas propiedades (cambiando nombre o posición), el código fallará lanzando "el
temido" mensaje de: "Subíndice fuera del intervalo", ó estaremos "afectando" a la hoja que "quedó" en la
posición #3 y "creíamos" que era... "la que estaba antes???".
Para efectos "prácticos", es mejor el uso de la propiedad "Name", inclusive puedes "regresar" la hoja a su
nombre "original" en algún evento (como Worksheet_Deactivate) con una línea como la siguiente:
If Hoja3.Name <> "Resumen" Then Hoja3.Name = "Resumen"
Habrás notado que se utiliza Hoja3.Name. Hoja3 es el nombre-código (propiedad CodeName) que cada objeto
tiene en el proyecto de VBA (en este caso "verías" en la ventana de exploración del proyecto, un objeto
Worksheet como - Hoja3 (Resumen) y en la ventana de propiedades, las propiedades: (Name) = Hoja3 y
Name = Resumen.
Pues bien, la propiedad CodeName es aún más "conveniente" que la "simple" propiedad "Name" para el caso
de "asegurarnos" que no afecte al código si el usuario cambia las propiedades "Name" e "Index" de los objetos
sobre los que necesitamos un "control total".
PROTECCIONES "ADICIONALES" PARA "CELDAS ESPECIALES".

Si ya has usado Herramientas | Proteger | Proteger hoja... y/o Proteger libro..., te habrás dado cuenta de que
"se debe quitar" la protección cuando necesitas hacer modificaciones por código a las hojas "protegidas" por
este comando.
Otra manera de "evitar" que el usuario modifique "celdas importantes" es (aprovechando nuevamente los
eventos y código), "detectar" si el usuario selecciona alguna de esas celdas y "pedirle una clave" (para
"permitirle estar ahí" ó "remitirlo" a otra celda). El siguiente código en el evento SelectionChange de un objeto
Worksheet le pedirá esa clave al usuario si selecciona alguna de las celdas que se indiquen como
"especiales":


Private Sub Worksheet_SelectionChange(ByVal Target As Range)
 Dim Permiso As String

 Select Case Target.Address
  'Si el usuario selecciona "B6" ó "B18"...
  Case Range("B6").Address, Range("B18").Address
    'Se le "pide" una clave.
    Permiso = InputBox("¿Cuál es tu clave?")
    'Si la clave es "incorrecta" lo "mandamos" arriba.
    '(Podrías "avisarle" que... ¡ NO es la clave K !!!)
    If Permiso <> "Hocus Pocus" Then Target.Offset(-1, 0).Select
 End Select
End Sub




IMPEDIR QUE EL USUARIO UTILICE "ALGUNOS" COMANDOS.

Habrá ocasiones en las cuales "quisieras" que el usuario no pueda "copiar | cortar | pegar" datos "de" ni "a"
ciertas celdas, hojas o libros.

    1. - Una manera sería "inhabilitar" el modo "Cortar/Copiar" de la aplicación ("imperceptible" para el
       usuario), usando algún evento (SelectionChange, Activate, Deactivate) de los objetos Worksheet ó
       Workbook con la siguiente línea:
    2. Application.CutCopyMode = False

        para "simular" el efecto de presionar {Esc} ("al momento de" copiar ó cortar) "cancelando" de la
        memoria el contenido del "porta-papeles".

    3. - Otra manera sería "inhabilitar" los "atajos de teclado" como {Ctrl}+C, {Ctrl}+X, {Ctrl}+V utilizando para
        ello el método OnKey del objeto Application en cualquiera (o varios) de los eventos mencionados en
        el párrafo anterior.

La sintaxis del método es:
Application.OnKey "Tecla", "Procedimiento"
Donde: argumento Tecla es la tecla (o combinación de teclas) que al ser presionada(s) "ejecutará(n)" la macro
especificada por el argumento Procedimiento. Si se omite el procedimiento, la(s) tecla(s) "vuelve(n)" a su
acción natural.

Por ejemplo, para impedir que se usen esas combinaciones de teclado en una hoja en específico, los
siguientes códigos "trabajan" bien:

'Cuando el usuario "activa" la hoja (con el código)...
Private Sub Worksheet_Activate()
  'Los "atajos de teclado" {Ctrl}+C, {Ctrl}+X, {Ctrl}+V
'para "copiar", "cortar" y "pegar" quedan "inhabilitados"
 'puesto que se especifica un argumento "vacío" para "la macro".
 Application.OnKey "^c", ""
 Application.OnKey "^x", ""
 Application.OnKey "^v", ""
End Sub


'Cuando el usuario "des-activa" la hoja (con el código)...
Private Sub Worksheet_Deactivate()
  'Los "atajos de teclado" {Ctrl}+C, {Ctrl}+X, {Ctrl}+V
  'para "copiar", "cortar" y "pegar" quedan "re-habilitados"
  Application.OnKey "^c"
  Application.OnKey "^x"
  Application.OnKey "^v"
End Sub
Nota: El método OnKey (usado de la manera anterior) NO IMPIDE el uso de los comandos (por menús o
          botones) para efectuar las mismas acciones de "copiar", "cortar" y "pegar".

Si quieres "impedir" que se usen "también" comandos "integrados" de Excel, entonces...




OPCIONES "AVANZADAS" PARA TRABAJAR CON MENÚS Y COMANDOS

"Asegurar" un control de los comandos (sean barras de menús y/o herramientas) implica "averiguar" que tanto
se han personalizado en el "entorno" de cada usuario. Considerando que los menús pueden contener
submenús y éstos a su vez más submenús se debe desarrollar una macro que pueda "ir descendiendo" a todos
los niveles de todos los elementos existentes. Una vez "detectados" los comandos "objetivo", una propiedad
(Enabled o Visible) habrá de permitir (o no) su uso.

Utilizaremos las siguientes variables Públicas:

'Declaramos las variables del tipo "necesario"...
Public Barra As CommandBar, _
       Comando As CommandBarControl, _
       Contenedor As CommandBarControl, _
       Siguiente As Integer
En los siguientes procedimientos | funciones:
'Macro para "Des-Habilitar" comandos
Private Sub DesHabilitarComandos()
  'Por si existiera algún error
  On Error Resume Next
  'Para buscar en TODAS las barras (Herramientas ó Menús)
  For Each Barra In Application.CommandBars
    'Para buscar en TODOS los controles (Comandos ó Submenús)
    For Each Comando In Barra.Controls
      'Inicia un "bucle" de búsqueda (a través de una función "recursiva")
      Siguiente = AtenuarProhibidos(Comando)
    '"Busca" en el siguiente botón
    Next Comando
  '"Busca" en la siguiente Barra de Comandos
  Next Barra
'Fin del procedimiento
End Sub


'Función "recursiva" para "bajar" por los menús
Private Function AtenuarProhibidos(Comando As CommandBarControl) As Integer
'Por si existiera algún error
  On Error Resume Next
  '"Inicializa" la variable del bucle
  Siguiente = 0
  'Para "afectar" sólo a Comandos ó Menús
  Select Case Comando.Type
    Case 1, 2, 4, 6, 7, 13, 18        'Si es un botón de comando...
      Select Case Comando.ID              '"Ver" cuál es
        Case 19, 21, 22           'Si es "copiar", "cortar" ó "pegar"
          Comando.Enabled = False 'Lo "DES-HABILITA"
      End Select
    Case Else                   'Si es un Menú (ó Submenú)
      '... seguir buscando "más abajo"
      For Each Contenedor In Comando.Controls
        '... haciendo una "Re-Llamada" de la función
        Siguiente = Siguiente + AtenuarProhibidos(Contenedor)
      Next Contenedor               '(continuar con el "bucle")
      Siguiente = Siguiente - 1 '(regresar al bucle en el mismo control)
  End Select                    'y ...
  'continuar "la llamada" a la función con "el siguiente"
  AtenuarProhibidos = Siguiente + 1
'Fin de la función
End Function
Aunque es posible que este procedimiento sea "auto-alternante" (podría cambiarse en la función la sentencia:
Comando.Enabled = False
por una que "auto-invierta" el estado del botón +/- así:
If Comando.Enabled = True Then Comando.Enabled = False Else Comando.Enabled = True
para un control "más estable" es mejor "definir" procedimientos "separados" (uno para inhabilitar y otro para re-
habilitar los botones de comando). Dejo a tu criterio "la contra-parte".
Complementariamente (y para NO "perjudicar" la interacción con el usuario) puedes usar los eventos
WindowActivate y WindowDeactivate del objeto ThisWorkbook para que, los comandos queden
inhabilitados "solamente" cuando la ventana "activa" sea "el libro".
Private Sub Workbook_WindowActivate(ByVal Wn As Window)
  DesHabilitarComandos
End Sub


Private Sub Workbook_WindowDeactivate(ByVal Wn As Window)
  ReHabilitarComandos
End Sub
Puedes incluir además en los procedimientos, las opciones del usuario para "personalizar" las barras de menús
y herramientas para que "sufran" el mismo efecto que lo botones. De esta manera, podrá agregar más barras
(con los botones y menús que "no funcionan") siempre y cuando la ventana "activa" sea "otro libro", pero... al
"regresar" a nuestro libro... ¡dejarán de "funcionar" también!!!

Para mayor información acerca de las "ID's" (ó nombres) de otros comandos y menús que pudieras considerar
como "necesarios" de inhabilitar para protección de tu trabajo, visita la página:
http://support.microsoft.com/support/kb/articles/Q213/5/52.ASP

Otra acción "conveniente" de controlar es el uso del comando "especial" de guardar, para lo cual puedes
aprovechar los mismos eventos WindowActivate para "permitir su uso sólo en el libro" con la línea:

Application.CommandBars("File").Controls("Guardar &especial").Visible = True
y el evento WindowDeactivate para "inhabilitar" su uso "fuera del libro" con otra línea "inversa" como:
Application.CommandBars("File").Controls("Guardar &especial").Visible = False
Bueno... dejemos de momento tanta "palabrería", y pasemos a un...
CASO "PRÁCTICO" DE LA COMBINACIÓN DE ALGUNOS TRUCOS

El archivo "descargable" (al final de este artículo) contiene algunos ejemplos de cómo proteger (por código) los
libros de Excel. Te explico "brevemente" como funciona y cuales son las condiciones, contraseñas y "opciones"
consideradas.

    1. Condiciones
            A. Con las macros "habilitadas" y los eventos "operables", el libro se abrirá "sin problemas" si se
               cumple cualquiera de las dos primeras condiciones siguientes:
                  I.   Que el directorio donde se encuentra sea: "C:Mis documentos" o...
                 II.   Que el directorio "alterno" sea: "D:Personales..." (el que yo utilicé). (Obviamente
                       puedes definir tus propias condiciones como se explicó antes.)
                III.   O, si se abre desde otro directorio, avisará que las condiciones de operación no se
                       cumplen y sugerirá "No Continuar" (aunque da la opción de "seguir adelante", se abrirá
                       en modo de "sólo lectura", y... NO "se puede" guardar).




            B. Si las macros NO están "habilitadas" (por elección o nivel alto de protección), o se "abre por
                código" pero los eventos NO están "operables" (Open, Change, etc.), el libro se abrirá, pero
                estará OCULTO y con Contraseña.

                Una vez abierto el libro "sin problemas", solo puede grabarse a través del comando que se
                agrega automáticamente ("Guardar especial" en el menú "Archivo"), de esta manera (aún
                cuando la PC "-???-...¡se apagó!!!") siempre queda "bien" guardado.
2. Contraseñas (Recuerda lo de mayúsculas, minúsculas, acentos y/o signos)
      A. Para el libro y la hoja "Protegida", la contraseña es: «Contraseña (el signo « es la combinación
           de teclas {Alt}+174).
       B. Para el proyecto de macros (VBA) es: «Contrase«Ñ«a (mismo signo).
       C. En la hoja "Protegida", algunas de las celdas "libres" requieren de un "Permiso especial" (con
           un formulario). La clave: Abrete Sésamo
       D. Existe una hoja oculta en el libro (podrías manejar ahí datos "Ultra-Secretos") que SOLO puede
           mostrarse mediante una imagen (con macro) en la hoja "Normal" y también requiere de un
           "Permiso especial". La clave: Abracadabra.
3. Como protección adicional, todos los códigos son Privados (no se pueden ver en la "lista de macros"
          menú Herramientas | Macro | Macros ó teclas {Alt}+{F8}. El método OnTime "monitorea" que los
          Eventos "permanezcan activos", por si a algún "vivillo" se le ocurriera des-habilitarlos para "ver como
          funciona". Puedes eliminar éste método si te resulta "engorroso" ver un ligero parpadeo del cursor cada
          20 segundos (ó el tiempo que determines) ó si lo consideras no necesario. Sólo "asegúrate" de hacerlo
          "correctamente".
   4.     La estructura de códigos es "modulada" (y en orden de aparición) para que se puedan usar
          "interactivamente" y son "funcionales" (si los ejecutas desde la ventana del VBE). Cada línea está
          "comentada" para que sea entendible y clara su intención. Espero que no tengas problemas para
          entenderlo.
   5.     Nota 1.- Cuando la ventana activa es este libro, TODOS los comandos "peligrosos" se des-habilitan (se
          restablecen cuando el libro deja de ser la ventana activa).
          Nota 2.- Si creas nuevas barras con comandos "prohibidos" (o los agregas a las ya existentes), de
          cualquier forma al activar de nuevo la ventana del libro se des-habilitarán.
   6.     La lista que consideré como comandos "peligrosos" es la siguiente (puede modificarse a tu criterio):
           En el menú (o Sub-menú)            Estos comandos SE INHIBEN DE TODAS LAS BARRAS
         "Edición"...                     Eliminar hoja; Copiar o mover hoja
         "Edición"... "Eliminar"...       Eliminar (celdas); Eliminar filas; Eliminar columnas
         "Formato"...                     Formato de celdas (por la pestaña de "protección")
         "Formato"... "Hoja"...           Cambiar nombre; Ocultar; Mostrar
         "Herramientas"...                Ver Nota 2 Personalizar (por si creas barras con "más prohibidos")
         "Herramientas"... "Proteger"... Proteger hoja; Proteger libro; Proteger y compartir
         "Datos"...                       Ordenar; Validación
         "Ventana"...                     Ocultar; Mostrar
         La lista de barras               "Toolbar List" (por aquello del comando "Personalizar")
   7.     Visita la página de Microsoft indicada anteriormente para ver una lista de otros comandos que pudieras
          considerar como "peligrosos".
   8.     Saludos cordiales, y espero "haber sido de utilidad" para tus propósitos.
   9.     Héctor Miguel Orozco Díaz. hemiordi@hotmail.com
   10.
   11. Descargar el archivo Proteger.zip que contiene el archivo Proteger.xls con todo el código
       mostrado en este artículo.
   12.
   13. Nota de Mauricio: Les agradeceria mucho a mis visitantes y como agradecimiento por el gran
       trabajo de Héctor, le notificaran a su correo, de cualquier error, duda, mejora, observación o
       comentario en relación con el presente artículo, GRACIAS Héctor...

Variables y objetos, ¿como nombrarlos?




   •     Supongamos una sencilla macro como la siguiente
   •     Option Explicit
   •
   •     Public Sub Preguntas()
   •     Dim Nombre As String
   •     Dim Edad As Integer
   •
   •      Nombre = InputBox("¿Cuál es tu nombre?")
   •      Edad = InputBox("¿Cuantos años tienes?")
   •
   •      MsgBox "Hola " & Nombre & " tienes " & Edad & " años"
   •
   •     End Sub
   •     Public Sub Preguntas1()
   •     Dim Coche As String
   •     Dim Sol As Integer
•
    •    Coche = InputBox("¿Cuál es tu nombre?")
    •    Sol = InputBox("¿Cuantos años tienes?")
    •
    •    MsgBox "Hola " & Coche & " tienes " & Sol & " años"
    •
    •   End Sub
    •
    •




Descargar el código de este artículo.

Grabando mi primer macro en Excel

Te sugiero que primero realices los pasos que menciono aquí y después, con toda libertad y confianza haz
todas las pruebas que consideres pertinentes

    o   Entra a Excel
    o   Ve al menú Herramientas | Macro | Grabar nueva macro...
    o   Te saldrá el siguiente cuadro de dialogo...




        Los datos que hay que introducir son:

        Nombre de la macro
        Con este nombre identificaremos a la macro, con este la podemos "ejecutar" y "llamar" desde otras
        macros, por default te saldrá Macro1 la primera vez y, si no cambias este nombre, a las sucesivas
        macros las ira nombrando Macro2, Macro3, Macro'n, etc, propongo que se llame Mi_Primer_Macro ,
        las recomendaciones son: usa un nombre corto, pero suficientemente claro en relación con la tarea o
        tareas que hará la macro, NO uses espacios, por ejemplo, si tienes una macro que realiza un reporte,
        podrías llamarla:

            1.   hacerreporte
            2.   HACERREPORTE
            3.   hacer_reporte
            4.   HACER_REPORTE
5. Hacer_Reporte
        6. HacerReporte

    Comúnmente, y lo veraz en estas páginas, uso la opción 5 o 6 pues me parecen mas claras de leer,
    pero no te detengas en hacer uso de tu libre derecho de usar el que te de la gana.
    Método abreviado
    Si sabes para que nos sirve Ctrl + C o Alt + F4 , entonces ya sabes para que es esta opción, así es,
    bien pensado, sirve para relacionar una combinación de teclas con la macro que estamos grabando y
    ejecutarla con solo presionar estas teclas, en lo personal no lo uso, pues ya tengo bastante con las
    decenas de métodos abreviados que tiene Windows, prefiero "asignarlas" a un botón o un menú (te
    enseñare a hacer esto), pero estas en todo tu derecho de usarla si así lo deseas.
    Guardar macro en
    Toda la información ocupa un lugar, verdad?, pues las macros son información y ocupan lugar y hay
    que guardarlas en algún lado, este lado, son los archivos de Excel, es decir, "dentro" del archivo, se
    guardan las instrucciones en un lugar especial que se llama modulo , que aprenderemos a dominar, si
    observas la imagen, tenemos un Cuadro de lista desplegable o ComboBox (así se llama este "objeto")
    que tiene tres opciones: Libro de macros personal, Libro nuevo y Este libro, como veras, los tres son
    libros o sea, archivos de Excel, las macros de Excel solo pueden estar dentro de archivos de Excel.
    Para nuestro ejemplo escogeremos Este libro.
    Descripción
    Creo que el nombre es bastante "descriptivo", aquí puedes poner toda la información que consideres
    conveniente acerca de tu macro, su función más útil, es comentar brevemente cual es el propósito de
    nuestra macro, algunos ponen la fecha y el nombre del autor.

o   Damos un clic en el Botón de Comando (CommandButton) ACEPTAR , a partir de este momento, casi
    cualquier acción, lo repito, casi cualquier acción que realices sobre la ventana de Excel, se grabará en
    nuestra macro, por eso las recomendaciones antes de grabar una macro son:
        1. Planea lo que hara tu macro, las correcciones que hagas, también se grabaran.
        2. Casi nunca una macro queda a la primera, no importa que repitas de nuevo los pasos, pero
            hazla bien, cuando aprendas a editarlas, veremos como quitar lo que no sirve.
        3. Procura no grabar demasiadas instrucciones, es mejor grabar pequeñas macros y después
            llamarlas desde otras o entre si, esto, ya veremos como se hace.




o   Realiza los siguientes pasos tal cual...

        R   Selecciona la celda A1
        S   Escribe "Esta es mi primer macro" (o lo que gustes).
        E   Presiona Enter, si tu selección se movió abajo (normalmente), entonces vuelve a seleccionar la
            celda A1
        c   Dale formato de Negritas , Cursiva , cambia el tamaño de la fuente, el estilo de la fuente y
            por ultimo el color de la fuente
        d   Al final se tiene que ver algo muy parecido a esto:
o

        ο   Da un clic en el botón Detener grabación , este botón (que aparece en la imagen de arriba) se
            encuentra dentro de la barra de herramientas Detener Grabación, esta barra se visualiza (o
            deberia de aparecer) en cuanto empiezas a grabar una macro, si no la vez, ve al menú Ver |
            Barra de Herramientas y activa la barra Detener Grabación o si lo prefieres, en el menú
            Herramientas | Macro veraz, en vez de Grabar Macro , la opción Detener Grabación , esto solo
            cuando tienes activada la grabadora de macros.
        ο   Ahora, probemos la macro, borra o mejor, elimina la celda donde escribiste el texto Esta es mi
            primer macro, en nuestro ejemplo, se trata de la celda A1.
        ο   Ve al menú Herramientas | Macro | Macros... o presiona el método abreviado de teclado Alt +
            F8 , por cualquiera de estos dos métodos, te saldrá el siguiente cuadro de dialogo.




    La imagen lo dice todo, tendras una lista de las macros que esten disponibles en los libros (archivos de
    Excel) abiertos, es decir, para que puedas ejecutar una macro, el libro que la contiene debe estar
abierto. Este cuadro de dialogo tiene más opciones que el anterior, así que las que no se vean aquí, te
dejo de "tareita" investigues para que sirven.

    ο   Selecciona la macro que acabamos de grabar, si no le cambiaste el nombre debe decir Macro1
        , si usaste el propuesto será Mi_Primer_Macro o en su defecto el que hayas escogido, si tienes
        más libros abiertos que tengan macros, aquí las veraz (no todas, ya te explicare por que), da
        un clic en el Boton de Comando (CommandButton) EJECUTAR .
    ο   ¿Que pasó?, se ve bonito no?, ahora, con un solo paso, hacemos varias instrucciones de
        Excel, si fue así?, bien, ahora ya tenemos el 0.01 % de lo necesario para dominar las macros y
        no te estoy desanimando, al contrario, pretendo, con estas páginas, subir un poco mi 5% de
        dominio y también pretendo, que lo hagamos juntos, si estas de acuerdo sigue leyendo y sino
        también sigue leyendo.
    ο   Este es un buen momento para guardar tu archivo, propongo que se llame Mis macros , pero,
        como antes, puedes usar el nombre que gustes ¿como podría impedírtelo?.
    ο   Ahora van las preguntas, lo siento pero te tendrás que acostumbrar a ellas, aun cuando veas
        que trato a detalle los temas, no es así, por que el tema es bastante extenso y muchas cosas
        las tendrás que buscar, descubrir y mejor aun, razonar por tu cuenta.
    l   ¿ Todo salió bien ?
    ¿   ¿ Que pasa si ahora pongo el cursor, o sea la selección en otra celda, por ejemplo la C15 y
        ejecuto la macro?
    e   Prueba a grabar otra macro, pero activa el botón que aparece al lado del Detener grabación y
        que se llama Referencia relativa y haz la prueba anterior, ¿que pasa ahora?
    q   Si cambias de hoja en el libro ¿puedes ejecutar la macro?
    S   Y si cambias de libro ¿aun la puedes ejecutar?
    Y   Prueba a grabar una macro que cambie a otras ventanas fuera de Excel o abra otros
        programas ¿es posible?
    p   Graba una macro un poco mas larga y ejecútala ¿que observas?, ¿como se ve la pantalla
        cuando se esta ejecutando?
    ο   Tal vez pienses que son muchas preguntas para la primera vez, ya veraz que solito te saldrán
        mas, ahora mismo yo tengo más preguntas que respuestas, pero no importa, sigue siendo muy
        divertido crear y grabar macros. Cuando tengas contestadas las preguntas anteriores y cuando
        hagas las "tareitas" que propongo, entonces, pasamos al siguiente punto.
    ο   Esto es más interesante, veamos las instrucciones que graba Excel a estas instrucciones se le
        conoce como código fuente , para esto ve la menú Herramientas | Macro | Macros... o
        presiona el método abreviado de teclado Alt + F8 y ya sabes que sale ¿verdad?, si, el cuadro
        de dialogo Macro , de nuevo, selecciona la primer macro que grabaste y que ejecutaste, pero
        ahora, en vez de ejecutarla, presiona el Botón de Comando (CommandButton) MODIFICAR .
        Esta acción abrirá una nueva ventana (la notaras en la barra de tareas de Windows) y nos
        llevara a una ventana que tal vez nunca has visto, esta ventana se llama Microsoft Visual Basic
        y es una nueva aplicación, un programa, correctamente es un Editor, un Editor del lenguaje
        Visual Basic para crear nuestras macros, también puedes abrir esta ventana desde el menú
        Herramientas | Macro | Editor de Visual Basic o presiona el método abreviado de teclado Alt +
        F11 , este Editor tienes que dominarlo si quieres obtener más provecho de tus macros, más
        adelante veremos las partes principales de este Editor, por lo pronto y si grabaste la macro de
        ejemplo, veraz algo muy similar a la siguiente imagen.
Las ventanitas que están a la derecha de la imagen, tal vez las tengas a la izquierda en tu ventana,
pero no importa, estas ventanas las puedes mover como la mayoría de las ventanas de Windows
(desde la barra de titulo) y posicionar donde gustes, te recomiendo dejarlas como en la imagen de
arriba, para que nos entendamos mejor.

    ο   Te pongo el código aquí por si en la imagen no se ve bien, además de que le faltan unas líneas
        abajo.
    ο   Sub Mi_Primer_Macro()
    ο   '
    ο   ' Macro1 Macro
    ο   ' Macro grabada el 09/01/2002 por Tecnico1
    ο   '
    ο      Range("A1").Select
    ο      ActiveCell.FormulaR1C1 = "Esta es mi primer macro"
    ο      Range("A1").Select
    ο      Selection.Font.Bold = True
    ο      Selection.Font.Italic = True
    ο      With Selection.Font
    ο        .Name = "Arial"
    ο        .Size = 20
ο       .Strikethrough = False
   ο       .Superscript = False
   ο       .Subscript = False
   ο       .OutlineFont = False
   ο       .Shadow = False
   ο       .Underline = xlUnderlineStyleNone
   ο       .ColorIndex = xlAutomatic
   ο     End With
   ο     With Selection.Font
   ο       .Name = "Comic Sans MS"
   ο       .Size = 20
   ο       .Strikethrough = False
   ο       .Superscript = False
   ο       .Subscript = False
   ο       .OutlineFont = False
   ο       .Shadow = False
   ο       .Underline = xlUnderlineStyleNone
   ο       .ColorIndex = xlAutomatic
   ο     End With
   ο     Selection.Font.ColorIndex = 5
   ο   End Sub

Ya la viste bien, ¿verdad que hay líneas repetidas?, ¿porque crees que sea esto?, observa muy bien
los colores, nos dicen mucho, pero lo primero que te enseñare de los colores es que las líneas que
están en verde no se "ejecutan" , esto quiere decir, que el VBA se las salta olímpicamente, las ignora
completamente, esas líneas verdes se llama comentarios y sirven para documentar nuestras macros
para poner notas acerca del propósito o funcionamiento del código, algo muy importante, pues después
de algunos cientos de líneas, ya ni sabes donde vas o para que servía determinada línea, por ejemplo,
observa la primer línea después de la ultima verde, si quisiéramos comentarla, o sea, establecerla de
modo que no se "ejecute", tenemos dos formas, agregando una comilla simple a la izquierda de la línea
o escribiendo, también a la izquierda la palabra REM, me parece más fácil la comilla ¿no crees?.

Sub Mi_Primer_Macro()
'
' Macro1 Macro
' Macro grabada el 09/01/2002 por Tecnico1
'
   Range("A1").Select

  'Range("A1").Select

  Rem Range("A1").Select

Ahora que sabes como se comentan las líneas para que el VBA no las ejecute, te recomiendo que
cuando estés probando código, no lo borres, mejor solo comenta la línea, pues algunas veces pasa
que regresamos a la línea original y si la borramos en ocasiones ya no sabemos como iba, así que te
pregunto, ¿que líneas de este código fuente, se podrían comentar, de modo que no se ejecuten, pero
que la macro siga haciendo lo mismo?... muy bien, podría quedar así...

Sub Mi_Primer_Macro()
' Macro grabada el 09/01/2002 por Tecnico1
'
   Range("A1").Select
   ActiveCell.FormulaR1C1 = "Esta es mi primer macro"
   Range("A1").Select
   Selection.Font.Bold = True
   Selection.Font.Italic = True
   'With Selection.Font
' .Name = "Arial"
  ' .Size = 20
  ' .Strikethrough = False
  ' .Superscript = False
  ' .Subscript = False
  ' .OutlineFont = False
  ' .Shadow = False
  ' .Underline = xlUnderlineStyleNone
  ' .ColorIndex = xlAutomatic
  'End With
  With Selection.Font
    .Name = "Comic Sans MS"
    .Size = 20
    .Strikethrough = False
    .Superscript = False
    .Subscript = False
    .OutlineFont = False
    .Shadow = False
    .Underline = xlUnderlineStyleNone
    .ColorIndex = xlAutomatic
  End With
  Selection.Font.ColorIndex = 5
End Sub

Pero todavía se puede mejorar más, prueba a comentar las líneas que terminen en la palabra False
para que nuestro código quede así:

Sub Mi_Primer_Macro()
' Macro grabada el 09/01/2002 por Tecnico1
'
   Range("A1").Select
   ActiveCell.FormulaR1C1 = "Esta es mi primer macro"
   Range("A1").Select
   Selection.Font.Bold = True
   Selection.Font.Italic = True
   'With Selection.Font
   ' .Name = "Arial"
   ' .Size = 20
   ' .Strikethrough = False
   ' .Superscript = False
   ' .Subscript = False
   ' .OutlineFont = False
   ' .Shadow = False
   ' .Underline = xlUnderlineStyleNone
   ' .ColorIndex = xlAutomatic
   'End With
   With Selection.Font
     .Name = "Comic Sans MS"
     .Size = 20
   ' .Strikethrough = False
   ' .Superscript = False
   ' .Subscript = False
   ' .OutlineFont = False
   ' .Shadow = False
     .Underline = xlUnderlineStyleNone
     .ColorIndex = xlAutomatic
   End With
   Selection.Font.ColorIndex = 5
End Sub
Sigue haciendo lo mismo la macro?, si?, pues entonces vamos bien, con esto te darás cuenta que, la
mayoría de las veces, la grabadora de macro nos escribe mucha "basura", es decir, código de más,
código innecesario para nuestra macro, lo complicado es saber que quitar y que no, incluso que
agregar y que no, ojalá que con todos los ejemplo que haya aquí, te sea más leve esta tarea. Por
ultimo, te escribiré una segunda versión de esta macro, la llamaremos Mi_Primer_Macro2 , regla, no
puede tener dos macros en el mismo modulo de código, que tengan el mismo nombre , no lo
olvides, esta segunda versión, esta basada completamente en la original, tu "tareita" es decirme cuales
son las diferencias, claro, aparte del número de líneas, hice lagunas "trampitas", observa las primeras
líneas, observa las líneas que se quitaron y las que se modificaron, las que se movieron y las que se
dejaron tal cual, ¿de acuerdo?...

Sub Mi_Primer_Macro2()
' Macro modificada por mi
  ActiveCell.FormulaR1C1 = "Esta es mi primer macro, claro, con algunos cambios"
  With Selection.Font
   .Bold = True
   .Italic = True
   .Name = "Comic Sans MS"
   .Size = 20
   .ColorIndex = 5
  End With
End Sub

Se me pasaba comentarte que puedes hacer todas las macros que quieras dentro de un mismo
modulo, lo único que tienes que hacer es procurar separarlas por una línea, como se que eres
observador, habrás notado que todas las macros empiezan con Sub y terminan con End Sub , pues así
son las macros, por ejemplo, podrías tener esto:

Sub CopiarDatos()
' Aqui va el código de esta macro

End Sub

Sub HacerReporte()
' Aqui va el código de esta macro

End Sub

Sub HacerGrafico()
' Aqui va el código de esta macro

End Sub


    ο   Ahora hagamos algo muy interesante, grabaremos nuestra segunda macro, pero con una
        pequeña variante, iremos viendo como es que Excel, va grabando las instrucciones dentro de
        un modulo en el Editor de Visual Basic, para lograrlo abramos el Editor de Visual Basic, ya
        sabes como ¿verdad?, redimensiona y manipula las ventanas, tanto de Excel como del Editor,
        para que ocupen, aproximadamente la mitad de la pantalla cada una, cuida , que la pantalla de
        Excel quede en primer plano y en segundo plano el Editor de Visual Basic, cuidado , si en la
        ventana del Editor, no esta visible el MODULO donde se están grabando las macros no veraz
        nada, tienes que poner el cursor dentro del modulo actual para que veas la grabación, para que
        no haya duda, ve la siguiente imagen:
Observa como Excel esta en primer plano y el Editor en segundo plano, si estas en la misma sesión de
        trabajo, donde grabaste Mi_Primer_Macro , entonces solo deja el cursor dentro del modulo donde está,
        esta macro, si estas usando otra sesión de trabajo, te grabara esta segunda macro, dentro de un
        segundo modulo y tal vez no lo veas, en resumen, el modulo visible debe ser el actual, donde veas que
        Excel esta grabando actualmente tus macros.

Descargar el código de este artículo.

Escribiendo mi primer macro en Excel

Esta vez no usaremos la grabadora de macros, esta vez escribiremos nuestra propia macro desde cero, para
este tema, considero que ya sabes entrar al EditorVBA y que ya sabes ejecutar cualquier macro, ¿estas listo?...

    o   Entramos a Excel
    o   Aquí podemos usar un nuevo libro o si lo prefieres abre tu libro de pruebas favorito.
    o   Entra el Editor de Visual Basic Alt + F11 .
    o   Puedes usar, si ya lo tienes, un modulo existente, o mejor aun, agregamos uno, esto lo hacemos desde
        el menú Insertar | Modulo , nuestro Explorador de Proyectos se tiene que ver así.
o   El cursor de escritura debe de quedar dentro de la ventana de código, observa que estoy usando el
    mismo archivo que hice en el tema anterior Grabando mi primer macro, pero reitero, puedes usar
    cualquier otro que gustes, observa la barra de título, observa si tengo alguna nueva barra de
    herramientas, observa la Ventana de Propiedades, en fin, observa lo más que puedas.
o   El siguiente paso es importante, ¿qué hará nuestra macro?, bueno, realmente al entrar al EditorVBA ya
    "deberíamos" de haber tenidos resuelta esta cuestión, pero debes de recordar que esta es la primera y
    más importante pregunta que debemos hacernos, cuando empecemos a crear una macro, para nuestro
    ejemplo, como estamos considerando que será nuestra primera macro, tendremos que escoger algo
    sencillo, se me ocurre hacer una macro que nos solicite nuestro nombre y el nombre de algún mes,
    después solicitaremos los importes de algunos conceptos "predefinidos" como: transporte, alimentos,
    diversión, por ultimo sumar estos importes, entonces, los pasos que hará nuestra macro son:
          Solicitar nuestro nombre
          Escribirlo en una celda
          Solicitar el nombre de algún mes
          Escribirlo en alguna celda
          Solicitar un importe para el gasto de Transporte
          Escribirlo en alguna celda
          Solicitar un importe para el gasto de Alimentos
          Escribirlo en alguna celda
          Solicitar un importe para el gasto de Diversión
          Escribirlo en alguna celda
          Introducir la formula que sume estos conceptos
o   Esto que acabamos de hacer es muy importante, siempre que te sea posible y repito, siempre,
    procura tratar de escribir la secuencia de pasos necesarios para lograr el proposito establecido, detras
    de esto, hay miles de líneas de teoría, así que puedes investigar los siguientes temas: Analisis de
sistemas, algoritmos, seudocódigo, entre más domines estos temas y entre más claros sean estos
    pasos, más fácil te será, pasarlos el lenguaje que quieras, en nuestro caso, al VBA.
o   Vamos a la ventana de código y escribimos, ojo, no lo copies, quiero que lo teclees en la ventana de
    código...
o   Public Sub Gastos_Mes()
o
o   End Sub
o   Puntos importantes: Toda macro tiene un nombre, para este caso, decidí que se llamará Gastos_Mes,
    pero si tu consideras que otro nombre es adecuado, adelante, no dejes de usarlo, ¿observaste que
    paso, cuando finalizaste con la línea Public Sub Gastos_Mes() y presionaste la tecla Enter?, ayudas
    como esta, nos la da el EditorVBA, en este caso, solito agrego el final de la macro, End Sub, y poco a
    poco te mostrare y te iras dando cuenta de que el EditorVBA, nos da muchas otras ayudas más, que
    hacen un poco más fácil la escritura de código, si observas alguna otra, durante el proceso de esta
    macro, no dejes de comentarla, también observa que después del nombre de la macro, terminamos la
    línea con un abriendo y cerrando un par de paréntesis, más adelante, veremos que podemos introducir
    dentro de estos paréntesis, por lo pronto, las macros que haremos deben de terminar con estos.
o   Recuerda que todo lo que escribamos de aquí en adelante, será entre las lineas Public Sub y End Sub,
    y de acuerdo a los pasos que establecimos, debemos de solicitar un nombre y escribirlo en una celda
    ¿verdad?...
o   Public Sub Gastos_Mes()
o   Dim strNombre As String                      'Declaramos nuestra variable
o
o    strNombre = InputBox("¿Cual es tu nombre?")         'Preguntamos el nombre
o    Range("A1").Value = strNombre                       'Lo escribimos en la celda A1
o
o   End Sub
o   Esta muy fácil ¿verdad?, conforme vayamos esribiendo nuestra macro, ve la probando, y, por ahora, te
    sugiero proporcionarle todos los datos que solicitamos, ya veremos que pasa cuando no es así. Ahora
    trata de solicitar un nombre de mes y escríbelo en la celda A2, como se que no harás trampa, aquí esta
    la solución...
o   Public Sub Gastos_Mes()
o   Dim strNombre As String                 'Declaramos nuestra variable
o   Dim strMes As String                  'Declaramos otra variable
o
o    strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre
o    Range("A1").Value = strNombre         'Lo escribimos en la celda A1
o
o    strMes = InputBox("¿Cual es el mes?")     'Preguntamos el mes
o    Range("A2").Value = strMes            'Lo escribimos en la celda A2
o
o   End Sub
o   Que fácil esta esto, ahora solicitaremos el importe de cada uno de los conceptos, en este caso son tres
    y estos, los escribiremos en las celdas B5, B6 y B7 respectivamente, ¿por qué ahí?, bueno, ya lo
    notaras más adelante, sigue, sigue leyendo por favor, veamos como quedaría para el primer caso...
o   Public Sub Gastos_Mes()
o   Dim strNombre As String                 'Declaramos nuestra variable
o   Dim strMes As String                  'Declaramos otra variable
o   Dim sngImporte As Single                 'Declaramos la variable para los Importes
o
o    strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre
o    Range("A1").Value = strNombre         'Lo escribimos en la celda A1
o
o    strMes = InputBox("¿Cual es el mes?")     'Preguntamos el mes
o    Range("A2").Value = strMes            'Lo escribimos en la celda A2
o
o    'Preguntamos por el importe para el concepto Transporte
o    sngImporte = InputBox("¿Cual es el importe para Transporte?")
o    Range("B5").Value = sngImporte            'Lo escribimos en la celda B5
o
o   End Sub
o   Solo nos resta solicitar los restantes dos importes, de las restantes categorías, y esta es mi pregunta,
    ¿declararemos otras dos variables para "guardar" los valores de estos importes?, ¿o podemos usar la
    misma?, y tu, ¿qué crees?...
o   Public Sub Gastos_Mes()
o   Dim strNombre As String                   'Declaramos nuestra variable
o   Dim strMes As String                    'Declaramos otra variable
o   Dim sngImporte As Single                   'Declaramos la variable para los Importes
o
o    strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre
o    Range("A1").Value = strNombre         'Lo escribimos en la celda A1
o
o    strMes = InputBox("¿Cual es el mes?")     'Preguntamos el mes
o    Range("A2").Value = strMes            'Lo escribimos en la celda A2
o
o    'Preguntamos por el importe para el concepto Transporte
o    sngImporte = InputBox("¿Cual es el importe para Transporte?")
o    Range("B5").Value = sngImporte          'Lo escribimos en la celda B5
o
o    sngImporte = InputBox("¿Cual es el importe para Alimentos?")
o    Range("B6").Value = sngImporte         'Lo escribimos en la celda B6
o
o    sngImporte = InputBox("¿Cual es el importe para Diversión?")
o    Range("B7").Value = sngImporte         'Lo escribimos en la celda B7
o
o   End Sub
o   Y por ultimo, introducimos la formula que nos sume el importe de estas tres categorías, esto lo
    haremos en la celda B8
o   Public Sub Gastos_Mes()
o   Dim strNombre As String                 'Declaramos nuestra variable
o   Dim strMes As String                  'Declaramos otra variable
o   Dim sngImporte As Single                 'Declaramos la variable para los Importes
o
o    strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre
o    Range("A1").Value = strNombre         'Lo escribimos en la celda A1
o
o    strMes = InputBox("¿Cual es el mes?")     'Preguntamos el mes
o    Range("A2").Value = strMes            'Lo escribimos en la celda A2
o
o    'Preguntamos por el importe para el concepto Transporte
o    sngImporte = InputBox("¿Cual es el importe para Transporte?")
o    Range("B5").Value = sngImporte          'Lo escribimos en la celda B5
o
o    sngImporte = InputBox("¿Cual es el importe para Alimentos?")
o    Range("B6").Value = sngImporte         'Lo escribimos en la celda B6
o
o    sngImporte = InputBox("¿Cual es el importe para Diversión?")
o    Range("B7").Value = sngImporte         'Lo escribimos en la celda B7
o
o    'Sumamos las celdas B5 a B7, pero introduciendo una formula
o    Range("B8").FormulaLocal = "=SUMA(B5:B7)"
o
o   End Sub
o   En sentido estricto, lo que tenemos hasta ahora, realiza el propósito para lo que fue creada, pero...
    (siempre hay un pero), ¿como la vez?, ¿te gusta?, ¿qué le agregamos?, ¿qué le quitamos?, ¿siempre
    funciona, en cualquier libro y hoja? (ya sabes a donde contestar estas preguntas). La primer mejora,
    será agregar algunos encabezados para identificar cada valor y la segunda, será darle un poco de
    formato a los datos...
o   Public Sub Gastos_Mes()
o   Dim strNombre As String                  'Declaramos nuestra variable
o   Dim strMes As String                   'Declaramos otra variable
o   Dim sngImporte As Single                  'Declaramos la variable para los Importes
o
o    strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre
o    Range("A1").Value = strNombre         'Lo escribimos en la celda A1
o
o    strMes = InputBox("¿Cual es el mes?")     'Preguntamos el mes
o    Range("A2").Value = strMes            'Lo escribimos en la celda A2
o
o    'Preguntamos por el importe para el concepto Transporte
o    sngImporte = InputBox("¿Cual es el importe para Transporte?")
o    Range("B5").Value = sngImporte          'Lo escribimos en la celda B5
o
o    sngImporte = InputBox("¿Cual es el importe para Alimentos?")
o    Range("B6").Value = sngImporte         'Lo escribimos en la celda B6
o
o    sngImporte = InputBox("¿Cual es el importe para Diversión?")
o    Range("B7").Value = sngImporte         'Lo escribimos en la celda B7
o
o    'Sumamos las celdas B5 a B7, pero introduciendo una formula
o    Range("B8").FormulaLocal = "=SUMA(B5:B7)"
o
o    'Agregamos los encabezados necesarios
o    Range("A4").Value = "Concepto"
o    Range("B4").Value = "Importe"
o    Range("A5").Value = "Transporte"
o    Range("A6").Value = "Alimentos"
o    Range("A7").Value = "Diversión"
o    Range("A8").Value = "Total"
o
o    'Le damos formato a las celdas
o    Range("A1:A2").Font.Bold = True         'Negritas
o    Range("A4:B4").Font.Bold = True
o    Range("A8:B8").Font.Bold = True
o    Range("A4:B4").HorizontalAlignment = xlCenter 'Alineacion horizontal central
o    Range("B5:B8").NumberFormat = "#,##0.00"      'Formato númerico
o
o   End Sub
o   Muy importante , como mencionamos, por lo pronto, proporciónale, a la macro, todos los datos que
    pedimos, no dejes nada vacío, teclea texto donde te pida texto y números donde te pida números, la
    tareita es: modifica la macro, de modo que se vea como la siguiente imagen...
o   Por ultimo, y como preparación para la segunda parte de este tema, prueba, ahora sí, a NO darle todos
    los valores a la macro, a darle texto donde deberían ir números y ver que es lo que hace la macro, se
    muy observador, el EditorVBA, de nuevo nos va a ayudar mucho, LEE la ayuda, investiga más acerca
    de la función InputBox y ve investigando para que sirve la función Val, todo esto, lo encuentras en la
    ayuda, así que solo es cuestión de leer, razonar y comprender un poquito, nos vemos...
o   Como se que hiciste tu tarea, aquí esta la solución a la macro, si no te resulto, verifica en donde están
    las diferencias, recuerda que esto es solo una propuesta...
o   '*****************************************
o   'Esta es la función que TU tenias que hacer
o   Public Sub Gastos_Mes_2()
o   Dim strNombre As String                      'Declaramos nuestra variable
o   Dim strMes As String                       'Declaramos otra variable
o   Dim sngImporte As Single                      'Declaramos la variable para los Importes
o
o    strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre
o    Range("B3").Value = strNombre         'Lo escribimos en la celda A1
o
o    strMes = InputBox("¿Cual es el mes?")     'Preguntamos el mes
o    Range("B4").Value = strMes            'Lo escribimos en la celda A2
o
o    'Preguntamos por el importe para el concepto Transporte
o    sngImporte = InputBox("¿Cual es el importe para Transporte?")
o    Range("B7").Value = sngImporte          'Lo escribimos en la celda B5
o
o    sngImporte = InputBox("¿Cual es el importe para Alimentos?")
o    Range("B8").Value = sngImporte         'Lo escribimos en la celda B6
o
o    sngImporte = InputBox("¿Cual es el importe para Diversión?")
o    Range("B9").Value = sngImporte         'Lo escribimos en la celda B7
o
o    'Sumamos las celdas B5 a B7, pero introduciendo una formula
o    Range("B10").FormulaLocal = "=SUMA(B7:B9)"
o
o    'Agregamos los encabezados necesarios
o    Range("A1").Value = "Reporte de gastos"
o    Range("A3").Value = "Nombre"
o    Range("A4").Value = "Mes"
o    Range("A6").Value = "Concepto"
o    Range("B6").Value = "Importe"
o    Range("A7").Value = "Transporte"
o    Range("A8").Value = "Alimentos"
o    Range("A9").Value = "Diversión"
o     Range("A10").Value = "Total"
    o
    o     'Le damos formato a las celdas
    o     Range("A1").Font.Bold = True           'Negritas
    o     Range("A3:A4").Font.Bold = True
    o     Range("A6:B6").Font.Bold = True
    o     Range("A10:B10").Font.Bold = True
    o     Range("A1:B1").HorizontalAlignment = xlHAlignCenterAcrossSelection
    o     Range("A3:A4").HorizontalAlignment = xlRight 'Alineacion horizontal derecha
    o     Range("A6:B6").HorizontalAlignment = xlCenter 'Alineacion horizontal central
    o     Range("B7:B10").NumberFormat = "#,##0.00"       'Formato númerico
    o
    o   End Sub
    o




Descargar el código de este artículo.

Escribiendo mi primer macro en Excel          II




Para este tema doy por entendido que has leido y comprendido la primer parte de este articulo, que, como
recordaras, la dejamos trabajando perfectamente, la ultima versión quedo así...




'*****************************************
'Esta es la función que TU tenias que hacer
Public Sub Gastos_Mes_2()
Dim strNombre As String                      'Declaramos nuestra variable
Dim strMes As String                       'Declaramos otra variable
Dim sngImporte As Single                      'Declaramos la variable para los Importes

 strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre
 Range("B3").Value = strNombre         'Lo escribimos en la celda A1

 strMes = InputBox("¿Cual es el mes?")     'Preguntamos el mes
 Range("B4").Value = strMes            'Lo escribimos en la celda A2

 'Preguntamos por el importe para el concepto Transporte
 sngImporte = InputBox("¿Cual es el importe para Transporte?")
 Range("B7").Value = sngImporte          'Lo escribimos en la celda B5

 sngImporte = InputBox("¿Cual es el importe para Alimentos?")
 Range("B8").Value = sngImporte         'Lo escribimos en la celda B6

 sngImporte = InputBox("¿Cual es el importe para Diversión?")
 Range("B9").Value = sngImporte         'Lo escribimos en la celda B7

 'Sumamos las celdas B5 a B7, pero introduciendo una formula
 Range("B10").FormulaLocal = "=SUMA(B7:B9)"

 'Agregamos los encabezados necesarios
Range("A1").Value = "Reporte de gastos"
 Range("A3").Value = "Nombre"
 Range("A4").Value = "Mes"
 Range("A6").Value = "Concepto"
 Range("B6").Value = "Importe"
 Range("A7").Value = "Transporte"
 Range("A8").Value = "Alimentos"
 Range("A9").Value = "Diversión"
 Range("A10").Value = "Total"

 'Le damos formato a las celdas
 Range("A1").Font.Bold = True           'Negritas
 Range("A3:A4").Font.Bold = True
 Range("A6:B6").Font.Bold = True
 Range("A10:B10").Font.Bold = True
 Range("A1:B1").HorizontalAlignment = xlHAlignCenterAcrossSelection
 Range("A3:A4").HorizontalAlignment = xlRight 'Alineacion horizontal derecha
 Range("A6:B6").HorizontalAlignment = xlCenter 'Alineacion horizontal central
 Range("B7:B10").NumberFormat = "#,##0.00"       'Formato númerico

End Sub


   o   También quedamos que en esta ocasión, no le vamos a proporcionar los datos esperados, si no que
       pondremos a prueba la "solidez" de nuestra macro, asignándole valores incorrectos o simplemente
       cancelando la operación, esto ultimo muy importante, en la mayoría de los casos, tienes que
       proporcionarle al usuario una forma de cancelar la macro en ejecución...
   o   Como primer prueba le pasaremos una cadena vacía en donde nos solicite un dato, veamos que hace
       la macro y que mejores le podemos hacer, empecemos...
   o   Cuando nos solicite el primer dato, prueba a; directamente dar un clic en el botón Aceptar o a
       introducir puros espacios con la tecla Barra espaciadora, observa como en la imagen siguiente el
       cursor esta unos caracteres adelante, pues se introdujeron algunos espacios.




   o   Al dar clic en el botón Aceptar, la macro continua como si nada, es decir, nos muestra el siguiente
       cuadro donde nos solicita el siguiente dato, ¿pero?, ¿es esto correcto?, no verdad, el dato Nombre es
       un dato (lo pondré en mayúsculas) REQUERIDO, esta palabra es muy importante, nos indica que el
       valor que estamos solicitando es OBLIGATORIO proporcionarlo para que nuestra macro haga el
       trabajo encomendado, si un dato es o no REQUERIDO es algo que Tu tienes que decidir y que es muy
       fácil determinar, tan solo pregúntate; ¿la macro puede resolver el trabajo sin este dato?, si la respuesta
       es NO, entonces es REQUERIDO, si la respuesta es SI, entonces es OPCIONAL, para nuestro caso,
       el dato Nombre es un dato REQUERIDO, por lo que tenemos que garantizar que el usuario
       proporcione este valor, la pregunta del millón ¿cómo lo hacemos?...
   o   Como sabes (y si no lo sabes aquí te lo dijo), la función InputBox "siempre", lo repito, "siempre", nos
       devuelve un String, es decir, una cadena de texto y esta cadena de texto, será de longitud cero,
       cuando: presione inmediatamente el botón Aceptar o cuando presione el botón Cancelar, aun cuando
       ya haya introducido algún texto en el cuadro, con este conocimiento, solo tenemos que medir el
       número de caracteres para saber si el usuario escribió algo en el cuadro de texto, para eso, usamos la
       función Len, que nos devuelve un Long, un número con el número de caracteres de una cadena...
   o   Dim Largo As Long
o
o     strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre
o     Largo = Len(strNombre)
o   En la variable Largo, tenemos el número de caracteres que el usuario escribió, si este valor es cero,
    entonces ya sabes que significa ¿verdad?, ¿pero, como sabemos si es o no cero?, para esto lo
    preguntamos de esta manera
o    If Largo = 0 Then
o       MsgBox "El dato Nombre es requerido"
o     End If
o   Lo que acabamos de hacer, es crear una estructura condicional, o sea, que dependiendo de una
    condición, podemos ejecutar determinado código, en esta caso, nuestra condición es: Largo = 0, que,
    como observas, esta entre las palabras If y Then, es decir, entre estas dos palabras claves de VB,
    pondremos la condición necesaria, como condición, puedes usar "cualquier expresión que se pueda
    evaluar como VERDADERA o FALSA", esta estructura tiene muchas variantes, pero empezaremos por
    su forma más sencilla, en nuestro ejemplo, si la condición es VERDADERA, entonces se ejecuta la
    línea o líneas inmediatas a la condición, en este caso la línea: MsgBox "El dato Nombre es
    requerido", que tan solo le notifica al usuario que no proporciono un dato, pero si continuamos, la
    macro sigue como antes, es decir, nos muestra el siguiente mensaje, lo cual no es correcto, pues
    buscamos obligar al usuario a introducir el dato, para esto, podemos volver a preguntar, pero con esto
    corremos el riesgo de que vuelva a proporcionar una cadena de longitud cero, con este inconveniente,
    decidimos mejor, salir de la macro con la instrucción Exit Sub, con la cual el código quedaría así...
o    If Largo = 0 Then
o       MsgBox "El dato Nombre es requerido"
o       Exit Sub
o     End If
o   Pruébala y verifica como, cuando presionas Cancelar o inmediatamente presionas Aceptar,
    efectivamente nos informa de ello y termina la macro, la instrucción Exit Sub hay que usarla con
    mesura, no abuses mucho de ella, ya aprenderemos otras alternativas para minimizar su uso.
o   Bien, muy bien, ahora prueba a introducir espacios cuando te solicite el nombre, ¿qué paso?, nos deja
    continuar ¿verdad?, esto es por que recuerda que aunque nosotros no veamos los espacios, para la
    computadora son un carácter más, así que cuando evalúa el largo de la cadena, esta devuelve el
    número de espacios vacíos que el usuario tecleo, pero esto también debemos de preverlo con una
    función llamada Trim que elimina los espacios en blanco que tenga una cadena al principio y al final de
    esta...
o   strNombre = Trim(strNombre)

    en este ejemplo, primero le quitamos los espacios a la variable strNombre y después reasignamos el
    valor resultante a ella misma, también podríamos haber usado la función Trim directamente en la
    función InputBox de la siguiente manera...

    strNombre = Trim (InputBox("¿Cual es tu nombre?"))

    solo para que lo notaras, puse en negritas la función Trim, puedes usar cualquiera de las dos, al final el
    resultado es el mismo. Vuelve a hacer las pruebas pertinentes.

o   Como siguiente paso, realizamos la misma evaluación para el dato Mes, garantizaremos que el usuario
    introduzca un dato.
o     strMes = Trim(InputBox("¿Cual es el mes?"))
o     Largo = Len(strMes)
o     If Largo = 0 Then
o       MsgBox "El dato Mes es requerido"
o       Exit Sub
o     End If
o   Una muy buena pregunta; ¿podremos lograr evaluar que el usuario introduzca un nombre de Mes
    válido, es decir, garantizar que el usuario introduzca Enero, Febrero... Diciembre o cualquier mes
    correcto?, te queda de tareita tratar de hacerlo, al fin y al cabo solo son doce meses, pero recuerda que
    la respuesta más obvia no siempre es la mejor.
o   El siguiente dato que tenemos que garantizar que el usuario introduzca es un valor, un número, ya no
    una cadena, esto es importante, más atrás se dijo la función InputBox "siempre", lo repito, "siempre",
    nos devuelve un String, es decir, una cadena de texto, entonces, ¿como es que podemos asignar un
    String (cadena de texto) a una variable de tipo Single (número simple) como en la línea siguiente?...
o   sngImporte = InputBox("¿Cual es el importe para Transporte?")

    La respuesta es simple, cuando VB encuentra que queremos hacer una asignación de un Tipo de dato
    a otro Tipo de dato, si le es posible hace la conversión necesaria, si no le es posible ocurre un error
    (mejor dicho un horror por que nuestro código se detiene), veamos un ejemplo...




o   En la imagen anterior, cuando se nos solicita un importe, en vez de un número, introducimos un texto,
    al presionar el botón Aceptar nos muestra un lindo e interesante mensaje, un mensaje de ERROR, nos
    muestra el número de error (13) y nos muestra la causa del error (No coinciden los tipos), a que tipos...




o   Si presionamos el botón Finalizar simplemente la ejecución de la macro termina, pero si presionamos
    el botón Depurar pasa algo muy interesante, se abre la ventana del Editor del VBA y una línea se
    colorea de un forma bastante llamativa, ¿para que será?...
o   Así es, como lo imaginaste en esa línea ocurrió el error (¡¡que brillante eres Mauricio...!!) y en ese
    momento, podemos modificarla, pero antes, quiero que seas muy observador, aparte de la línea
    amarilla, hay otra cosa que quiero que observes, esta es, la barra de titulo del Editor, obsérvala y ve lo
    que nos va mostrando conforme cambiamos y usamos el Editor VBA, por ahora, detén la ejecución de
    la macro, ¿como?, ve al menú Ejecutar | Restablecer o presiona el botón que encerré en un circulo rojo
    (ya vieron que bien dibujo a mano alzada).
o   Entonces, el error fue que VB no pudo convertir el valor tipo String al tipo Single, pero nuestro trabajo
    es garantizar que si pueda hacerlo, pues si a un usuario le sale el mismo mensaje de "horror" que
    acabamos de ver, ten por seguro que se acordara de ti, pero para que no pase esto, veamos como
    solucionarlo.
o   Como casi siempre, hay más de una manera de resolverlo, probemos una de las más sencillas,
    haciendo uso de la función Val, que convierte "si le es posible" una cadena de texto en un número,
    pero si no le es posible, ya no ocurre un error, sino que lo convierte en cero, su uso es simple...
o   sngImporte = Val(InputBox("¿Cual es el importe para Transporte?"))
o   Ahora, en la variable sngImporte tendremos el valor en "número" si fue posible hacer la conversión, y
    tendremos un cero, si no fue posible hacer la conversión, pregunta; ¿cómo evalúas entonces que el
    dato este correcto?...
o     sngImporte = Val (InputBox("¿Cual es el importe para Transporte?"))
o     If sngImporte = 0 Then
o       MsgBox "El dato Transporte es requerido"
o       Exit Sub
o     End If
o   Muy bien, veo que si estas aprendiendo, pero... ¿qué crees?, pues si, tienes otra tareita, es sencilla,
    solo tienes que responder la pregunta ¿cómo solucionarías el caso, cuando un usuario introduzca un
    número negativo?, más fácil no es posible...
o   Ahora solo te resta hacer lo mismo para los restantes datos, pero... ¿por qué siempre sales con un
    pero?, observa la siguiente imagen, obsérvala muy bien...
o   En este cuadro, se nos esta solicitando el dato Importe (en rojo), que como sabemos debe ser un
    número, pero le estamos proporcionando una cadena de texto (en azul), como ya previmos esto, la
    macro simplemente nos avisara que no es un número válido y se detendrá, ¿pero que pasa?, en el
    fondo (en naranja) ya introdujimos por código, los valores de las dos variables anteriores, pero al
    cancelarse mi macro por la introducción de un dato erróneo, estos valores son obsoletos, es decir,
    inservibles, inútiles, están de más ¿verdad?, solución uno, los borramos antes de salir, solución dos
    (mejor), los escribimos hasta después de haber evaluado todas las variables, pero... ¿otro? (ya me
    estoy cansando de los pero's...), esto es válido para las dos primeras variables, pero en el caso de los
    tres importes, estamos usando una sola variable para los tres, para resolver este pequeño
    inconveniente, usaremos una variable para cada dato y te podrás preguntar ¿y si mis datos a introducir
    son muchos, tendré que declarar una variable para cada dato?, muy buena pregunta, más adelante
    veremos casos como ese, por lo pronto hazme caso y declara una variable para cada concepto o
    cuéntame que otras alternativas que se te ocurren.
o   Bien, nuestro código completo se vera así...
o   Option Explicit
o
o   Public Sub Gastos_Mes_2()
o   'Declaramos las variables a usar
o   Dim strNombre As String
o   Dim strMes As String
o   Dim sngTransporte As Single
o   Dim sngAlimentos As Single
o   Dim sngDiversion As Single
o   Dim Largo As Long
o
o    'Solicitamos cada uno de los datos requerido y verificamos que sean correctos
o    strNombre = Trim(InputBox("¿Cual es tu nombre?"))
o    Largo = Len(strNombre)
o    If Largo = 0 Then
o      MsgBox "El dato Nombre es requerido"
o      Exit Sub
o    End If
o
o    strMes = Trim(InputBox("¿Cual es el mes?"))
o    Largo = Len(strMes)
o    If Largo = 0 Then
o      MsgBox "El dato Mes es requerido"
o      Exit Sub
o    End If
o
o    sngTransporte = Val(InputBox("¿Cual es el importe para Transporte?"))
o    If sngTransporte = 0 Then
o      MsgBox "El dato Transporte es requerido"
o      Exit Sub
o    End If
o
o    sngAlimentos = Val(InputBox("¿Cual es el importe para Alimentos?"))
o    If sngAlimentos = 0 Then
o      MsgBox "El dato Alimentos es requerido"
o      Exit Sub
o    End If
o
o    sngDiversion = Val(InputBox("¿Cual es el importe para Diversion?"))
o    If sngDiversion = 0 Then
o      MsgBox "El dato Diversion es requerido"
o      Exit Sub
o    End If
o
o    'Escribimos los valores ya correctos
o    Range("B3").Value = strNombre
o    Range("B4").Value = strMes
o    Range("B7").Value = sngTransporte
o    Range("B8").Value = sngAlimentos
o    Range("B9").Value = sngDiversion
o
o    'Sumamos las celdas B5 a B7, pero introduciendo una formula
o    Range("B10").FormulaLocal = "=SUMA(B7:B9)"
o
o    'Agregamos los encabezados necesarios
o    Range("A1").Value = "Reporte de gastos"
o    Range("A3").Value = "Nombre"
o    Range("A4").Value = "Mes"
o    Range("A6").Value = "Concepto"
o    Range("B6").Value = "Importe"
o    Range("A7").Value = "Transporte"
o    Range("A8").Value = "Alimentos"
o    Range("A9").Value = "Diversión"
o    Range("A10").Value = "Total"
o
o    'Le damos formato a las celdas
o    Range("A1").Font.Bold = True           'Negritas
o    Range("A3:A4").Font.Bold = True
o    Range("A6:B6").Font.Bold = True
o    Range("A10:B10").Font.Bold = True
o    Range("A1:B1").HorizontalAlignment = xlHAlignCenterAcrossSelection
o    Range("A3:A4").HorizontalAlignment = xlRight 'Alineacion horizontal derecha
o    Range("A6:B6").HorizontalAlignment = xlCenter 'Alineacion horizontal central
o    Range("B7:B10").NumberFormat = "#,##0.00"       'Formato númerico
o
o   End Sub
o   Bien, muy bien, ahora nuestra macro es un poco más profesional, los posibles usuarios "casi" no se
    acordaran de nosotros y estamos contentos de saber un poco más, recuerda que no es la única
    solución, puede y hay más, una de ellas la veremos en el próximo capitulo, no te despegues...
Descargar el código de este artículo.

Escribiendo mi primer macro en Excel      III




Para este tema doy por entendido que has leido y comprendido la primer y segunda parte de este articulo, la
ultima versión es la siguiente...




Option Explicit

Public Sub Gastos_Mes_2()
'Declaramos las variables a usar
Dim strNombre As String
Dim strMes As String
Dim sngTransporte As Single
Dim sngAlimentos As Single
Dim sngDiversion As Single
Dim Largo As Long

 'Solicitamos cada uno de los datos requerido y verificamos que sean correctos
 strNombre = Trim(InputBox("¿Cual es tu nombre?"))
 Largo = Len(strNombre)
 If Largo = 0 Then
   MsgBox "El dato Nombre es requerido"
   Exit Sub
 End If

 strMes = Trim(InputBox("¿Cual es el mes?"))
 Largo = Len(strMes)
 If Largo = 0 Then
   MsgBox "El dato Mes es requerido"
   Exit Sub
 End If

 sngTransporte = Val(InputBox("¿Cual es el importe para Transporte?"))
 If sngTransporte = 0 Then
   MsgBox "El dato Transporte es requerido"
   Exit Sub
 End If

 sngAlimentos = Val(InputBox("¿Cual es el importe para Alimentos?"))
 If sngAlimentos = 0 Then
   MsgBox "El dato Alimentos es requerido"
   Exit Sub
 End If

 sngDiversion = Val(InputBox("¿Cual es el importe para Diversion?"))
 If sngDiversion = 0 Then
   MsgBox "El dato Diversion es requerido"
   Exit Sub
End If

 'Escribimos los valores ya correctos
 Range("B3").Value = strNombre
 Range("B4").Value = strMes
 Range("B7").Value = sngTransporte
 Range("B8").Value = sngAlimentos
 Range("B9").Value = sngDiversion

 'Sumamos las celdas B5 a B7, pero introduciendo una formula
 Range("B10").FormulaLocal = "=SUMA(B7:B9)"

 'Agregamos los encabezados necesarios
 Range("A1").Value = "Reporte de gastos"
 Range("A3").Value = "Nombre"
 Range("A4").Value = "Mes"
 Range("A6").Value = "Concepto"
 Range("B6").Value = "Importe"
 Range("A7").Value = "Transporte"
 Range("A8").Value = "Alimentos"
 Range("A9").Value = "Diversión"
 Range("A10").Value = "Total"

 'Le damos formato a las celdas
 Range("A1").Font.Bold = True           'Negritas
 Range("A3:A4").Font.Bold = True
 Range("A6:B6").Font.Bold = True
 Range("A10:B10").Font.Bold = True
 Range("A1:B1").HorizontalAlignment = xlHAlignCenterAcrossSelection
 Range("A3:A4").HorizontalAlignment = xlRight 'Alineacion horizontal derecha
 Range("A6:B6").HorizontalAlignment = xlCenter 'Alineacion horizontal central
 Range("B7:B10").NumberFormat = "#,##0.00"       'Formato númerico

End Sub

   o      Esta versión funciona bien, pero como habrás notado, cuando el usuario no proporciona un dato
          correctamente, la macro, si bien informa de esta falta, lo que hace es simplemente terminar la
          ejecución, no le da la oportunidad al usuario de intentarlo nuevamente, dicen por ahí que -todos
          merecemos una segunda oportunidad-, así que implementaremos una forma de que el usuario pueda
          intentarlo nuevamente, para ello usaremos una nueva estructura condicional, veamos el ejemplo y
          después lo explicamos...
   o        'Iniciamos la estructura condicional
   o        Do
   o          'Solicitamos el dato requerido quitandole los espacios sobrantes
   o          strNombre = Trim(InputBox("¿Cual es tu nombre?"))
   o          'Verificamos que exista el dato
   o          If strNombre = "" Then
   o            'Notificamos en caso de que no haya dato
   o            MsgBox "El dato Nombre es requerido"
   o          End If
   o          'Volvemos a la línea inmediata a Do si el dato es vacio
   o        Loop While strNombre = ""
   o      Estos cambios, ya lo habrás notado, los haremos para solicitar el primer dato, para entender esta
          nueva estructura, te pondré las instrucciones pero le agregare su interpretación en español...
   o        'Iniciamos la estructura condicional
   o        Do(Hacer)
   o          'Solicitamos el dato requerido quitandole los espacios sobrantes
   o          strNombre = Trim(QuitaEspacios)(InputBox(SolicitaDato)("¿Cual es tu nombre?"))
   o          'Verificamos que exista el dato
o       If(Si) strNombre = "" Then(Entonces)
o         'Notificamos en caso de que no haya dato
o         MsgBox(MuestraMensaje) "El dato Nombre es requerido"
o       End If(Fin Si)
o       'Volvemos a la línea inmediata a Do si el dato es vacio
o     Loop While(Hacer Mientras) strNombre = ""
o   La estructura condicional Do...Loop... While, nos sirve para repetir una serie de instrucciones
    mientras o hasta que se cumpla una condición, fíjate como es muy sencillo, solo hay que iniciar la
    estructura con un Do y terminarla con un Loop While condicion, con esta estructura el código se
    ejecutara mientras la condición sea verdadera, la otra variante es que el código se ejecute hasta que
    la condición sea verdadera, veamos este ultimo ejemplo...
o     'Iniciamos la estructura condicional
o     Do
o       'Solicitamos el dato requerido quitandole los espacios sobrantes
o       strNombre = Trim(InputBox("¿Cual es tu nombre?"))
o       'Verificamos que exista el dato
o       If strNombre = "" Then
o         'Notificamos en caso de que no haya dato
o         MsgBox "El dato Nombre es requerido"
o       End If
o       'Volvemos a la línea inmediata a Do si el dato es vacio
o     Loop Until strNombre <> ""
o   El cambio fue realmente simple, observa la siguiente línea que fue la que se modifico...
o     Loop Until strNombre <> ""
o   Solo sustituimos While por Until e invertimos la condición strNombre <> "" , esto es muy importante,
    es decir, que la condición la establezcas de manera correcta, sino, nuestra estructura no cumplira su
    proposito. Esta estructura tiene otras variantes, por ejemplo, que la condición la realices al principio de
    la estructura, en la misma línea del Do, pero como este no es un curso de programación, te dejo de
    tareita que investigues más de esta estructura, en la ayuda del VBA, viene, creo yo, suficientemente
    explicada, lo que si veremos más adelante son ejemplos de su uso, pues es muy versátil y muy
    poderosa esta estructura.
o   Solo nos resta complementar los restantes datos, para que queden en la misma estructura de la
    siguiente manera, siéntete en libertad de usar cualquier de las dos formas vistas...
o   Option Explicit
o
o   Public Sub Gastos_Mes_3()
o   'Declaramos las variables a usar
o   Dim strNombre As String
o   Dim strMes As String
o   Dim sngTransporte As Single
o   Dim sngAlimentos As Single
o   Dim sngDiversion As Single
o   Dim Largo As Long
o
o
o    'Iniciamos la estructura condicional
o    Do
o      'Solicitamos el dato requerido quitandole los espacios sobrantes
o      strNombre = Trim(InputBox("¿Cual es tu nombre?"))
o      'Verificamos que exista el dato
o      If strNombre = "" Then
o        'Notificamos en caso de que no haya dato
o        MsgBox "El dato Nombre es requerido"
o      End If
o      'Volvemos a la línea inmediata a Do si el dato es vacio
o    Loop While strNombre = ""
o
o   Do
o    strMes = Trim(InputBox("¿Cual es el mes?"))
o    If strMes = "" Then
o      MsgBox "El dato Mes es requerido"
o    End If
o   Loop While strMes = ""
o
o   Do
o    sngTransporte = Val(InputBox("¿Cual es el importe para Transporte?"))
o    If sngTransporte = 0 Then
o      MsgBox "El dato Transporte es requerido"
o    End If
o   Loop While sngTransporte = 0
o
o   Do
o    sngAlimentos = Val(InputBox("¿Cual es el importe para Alimentos?"))
o    If sngAlimentos = 0 Then
o      MsgBox "El dato Alimentos es requerido"
o    End If
o   Loop While sngAlimentos = 0
o
o   Do
o    sngDiversion = Val(InputBox("¿Cual es el importe para Diversion?"))
o    If sngDiversion = 0 Then
o      MsgBox "El dato Diversion es requerido"
o    End If
o   Loop While sngDiversion = 0
o
o   'Escribimos los valores ya correctos
o   Range("B3").Value = strNombre
o   Range("B4").Value = strMes
o   Range("B7").Value = sngTransporte
o   Range("B8").Value = sngAlimentos
o   Range("B9").Value = sngDiversion
o
o   'Sumamos las celdas B5 a B7, pero introduciendo una formula
o   Range("B10").FormulaLocal = "=SUMA(B7:B9)"
o
o   'Agregamos los encabezados necesarios
o   Range("A1").Value = "Reporte de gastos"
o   Range("A3").Value = "Nombre"
o   Range("A4").Value = "Mes"
o   Range("A6").Value = "Concepto"
o   Range("B6").Value = "Importe"
o   Range("A7").Value = "Transporte"
o   Range("A8").Value = "Alimentos"
o   Range("A9").Value = "Diversión"
o   Range("A10").Value = "Total"
o
o   'Le damos formato a las celdas
o   Range("A1").Font.Bold = True           'Negritas
o   Range("A3:A4").Font.Bold = True
o   Range("A6:B6").Font.Bold = True
o   Range("A10:B10").Font.Bold = True
o   Range("A1:B1").HorizontalAlignment = xlHAlignCenterAcrossSelection
o   Range("A3:A4").HorizontalAlignment = xlRight 'Alineacion horizontal derecha
o      Range("A6:B6").HorizontalAlignment = xlCenter 'Alineacion horizontal central
    o      Range("B7:B10").NumberFormat = "#,##0.00"       'Formato númerico
    o
    o     End Sub




    o     CONCLUSIONES
             Casi siempre, hay más de una forma de programar una solución.
             Las diferentes estructuras no están para complicarnos el trabajo, al contrario, son para
               adaptarlas a nuestras diferentes necesidades y sobre todo nuestras diferentes forma de
               razonar una respuesta.
             Estas estructuras tienen muchas variantes, por ejemplo, la capacidad de usar más de una
               condición, si no se vio a fondo es por varias razones; la ayuda del lenguaje viene bastante bien
               explicado y con buenos ejemplos de su uso, si no te gusta mucho la ayuda, en la red hay
               cientos (y no exagero), cientos de páginas que te enseñan a programar en el VB, busca, busca
               un poquito y veras que así es.
             En esta versión de nuestra macro, "obligamos" al usuario a introducir "algo", pero en el artículo
               anterior, mencionamos que es importante, tratar de proporcionarle al usuario una forma de
               cancelar la operación o macro en proceso, de tareita te invito a que trates de hacer las
               siguientes variantes...
                   1. Una versión de esta macro, que le de la oportunidad al usuario de cancelar el proceso,
                        OJO, que no sea la vista en la parte dos de este artículo, sino una combinación
                        digamos de las dos, mira, sin querer ya casi te dije como hacerlo.
                   2. Otra versión de esta macro, que le demos, digamos, tres oportunidades de introducir
                        su dato y salga al llegar a este limite, claro, informando en todo momento al usuario de
                        que es lo esta pasando.

Descargar el código de este artículo.

Escribiendo mi primer función en Excel

Para obtener el mejor provecho de esta sección, estoy asumiendo que manejas con soltura el uso de las
funciones incorporadas de Excel, como SUMA, MAX, BUSCARV, entre otras, recuerda que Excel tiene mas de
300 funciones incorporadas y que también has usado el EditorVBA, sino lo has hecho te recomiendo leer la
Introducción a esta página, bien, entonces, conoces la estructura de cualquier función, veamos cual es:




Las funciones personalizadas, "deben" seguir la misma estructura, si eres observador, notaras que los
argumentos están separados por ";" (punto y coma), pero en la descripción dice que debe ser "," (comas),
¿porque?, ¿cual es la correcta? (esto te queda de tareita ).

Nuestras funciones "deben" de responder de la misma manera que las incorporadas, DEVOLVIENDO
VALORES , esto me parece la parte más importante que algunos olvidan, ¿has visto que alguna función de
Excel te de algún mensaje?, no, lo que hace, cuando no puede hacer resolver la operación, es darnos un error
como #¡NULO!, #¡DIV/0!, #¡VALOR!, #¡REF!, #¿NOMBRE?, #¡NÚM!, #N/A, pero nada más.

Entonces ya conocemos los siguiente términos, Función y Argumentos, ¿verdad?, otro punto importante es
saber que una función puede o no llevar argumentos como la función ALEATORIO y AHORA, una función
puede requerir argumentos de un Tipo y devolver valores de otro Tipo, como las funciones:

Función               Tipo de ARGUMENTO requerido                        Tipo de VALOR devuelto
LARGO                Texto                                    Numero
VALOR                Texto                                    Numero
FILA                 Rango                                    Numero
ESNUMERO                        Numero                                  Booleano
Tareita: Excel, dentro de sus formulas, maneja diferentes Tipos de datos, como fechas y números, ¿que otros
TIPOS DE DATOS conoces que usen las funciones de Excel?, ¿que otros ejemplos de funciones, podrías dar,
que devuelvan un tipo de dato diferente del de su o sus argumentos?.

Como habrás notado, el nombre es importante, el nombre de la función nos sirve para en primera instancia
sepamos que hace o que valor o valores nos devuelve, entonces, una parte importante es saber QUE HARA
NUESTRA FUNCION es decir, que trabajo realizara, cual es su finalidad.

Resumiendo:

   •   Conocer los términos FUNCION, ARGUMENTO, VALOR DEVUELTO y TIPO DE DATO
   •   Conocer la estructura de cualquier función
   •   Conocer que trabajo realiza una función
   •   TODA función devuelve un valor
   •   Una función puede o no, tener argumentos
   •   Una función puede devolver valores de diferente tipo del de sus argumentos
   •   Los argumentos se separan por "comas" o "punto y coma", depende de??.

Ahora que sabemos lo que necesitamos, hagamos nuestra primer función, como ya dijimos, lo primero es
saber, que queremos que haga nuestra función, como ejemplo, haremos la superarchidificilisima formula para
calcular el ¡rea de un triángulo:




   •   Entramos a Excel
   •   Entramos el EditorVBA
   •   Insertamos un nuevo Módulo y escribimos lo siguiente:
   •
   •   Option Explicit
   •
   •   Function AreaTriangulo(Base, Altura)
   •     AreaTriangulo = (Base * Altura) / 2
   •   End Function
   •   Pruébala..., ¿como?, como cualquier función de Excel, que ya lo sabes, si usas el Asistente para
       funciones, veras una nueva categoría, al final de la lista que se llama, Definidas por el usuario, ahí
       encontraras nuestra función.
   •   Ahora, comparemos la formula tradicional con nuestra función:
•   Bueno, nuestra formula funciona, pero no esta optimizada, es decir, estamos cometiendo omisiones
    "técnicas", es decir, no estamos escribiendo nuestra función como lo mandan los "santos cánones" de
    la programación y esto, si bien, no es obligatorio, es muy, muy conveniente hacerlo y más aun, saberlo,
    veamos cuales son esas omisiones...
•   Si no se especifica otra cosa, toda función es Publica, pero procura hacerlo explícitamente...
•   Public Function AreaTriangulo(Base, Altura)
•     AreaTriangulo = (Base * Altura) / 2
•   End Function
•   No le estamos diciendo de que TIPO son nuestros argumentos, en nuestro ejemplo, nuestra función
    debe poder manejar números grandes y con decimales, por lo tanto el Tipo de dato más conveniente
    es el Single (busca en la ayuda, los tipos de datos que se puedes usar en el VBA y me dices cuales
    son), por lo tanto nuestra función quedaría así:
•   Public Function AreaTriangulo(Base As Single, Altura As Single)
•     AreaTriangulo = (Base * Altura) / 2
•   End Function
•   Tampoco le estamos diciendo que tipo de valor es que nos devolverá nuestra función, es muy
    importante, escoger este tipo de dato muy bien, la recomendación es, debe ser lo suficientemente
    grande para contener el resultado de nuestra función, en la misma ayuda, encontraras cuando espacio
    ocupa (en memoria) y que valores pueden contener los diferentes tipos de datos, para nuestro caso, si
    estamos multiplicando un Single por un Single y aunque estemos dividiendo, el más conveniente es un
    Double, para que nuestra función quede así:
•   Public Function AreaTriangulo(Base As Single, Altura As Single) As Double
•     AreaTriangulo = (Base * Altura) / 2
•   End Function
•   Por ultimo, hay que agregarlo otra palabrita, que en otros ejemplos veremos a detalle, por lo pronto,
    solo te menciono que sirve para que los valores que tengan los argumentos, no se puedan modificar
    desde nuestra función y en la mayoría de los casos se usa, esta palabrita se llama ByVal y me gustaría
    que buscaras ayuda de esta palabra, ya sabes donde...
•   Public Function AreaTriangulo(ByVal Base As Single, ByVal Altura As Single) As Double
•     AreaTriangulo = (Base * Altura) / 2
•   End Function
•   Y ahora sí, estarás de acuerdo conmigo, que se ve mucho más bonita y presentable, pero sobre todo,
    esta eficientemente codificada. Para terminar, te mostrare una variante, que te servirá como ejemplo
    para la tareita que te dejare.
•   Public Function AreaTriangulo(ByVal Base As Single, ByVal Altura As Single) As Double
•   Dim Area As Double
•
•    Area = Base * Altura
•    Area = Area / 2
•    AreaTriangulo = Area
•
•   End Function
•   Lo que te he querido decir con esta variante, es que "casi nunca", obtenemos el resultado de nuestra
    función en una línea, "casi siempre" se hace uso del proverbio que dice -divide y vencerás-, ¿recuerdas
    lo que decía Descartes?, puedes hacer uso de VARIABLES intermedias, observa muy bien esta línea

    Dim Area As Double

    te encontraras con líneas como esta muy seguido, lo que le estamos diciendo al VBA es -oye,
    apártame un cachito de memoria (recuerda que todo lo que hagas con tu maquina encendida, usa
    memoria) para que la use-, estamos DECLARANDO UNA VARIABLE. Como se que eres una
    personita muy observadora, notaras que es "casi" igual que con los argumentos, solo que aquí usamos
    la palabra reservada (¿que es eso de palabra reservada?) Dim, pero para decirle el tipo de datos es
    igual As Tipo_Dato

•   Ahora si, esta es la tareita , como sabes, tenemos los pelos de los griegos por cualquier lado que
    mires, allá por el año 500 a.C., vivia el señor Herón que no se conformo con la función que hicimos un
    poco más arriba, así que se puso a investigar como obtener el área, pero de cualquier triángulo con
    solo conocer la longitud de sus lados, para llegar a deducir la siguiente formula...




    En donde a, b y c, son los lados del triángulo y S es el Semiperímetro o sea, la mitad del perímetro y
    hasta te voy a ayudar un poco más, en VBA para obtener la raíz cuadrada de un número, se usa la
    función Sqr (número), en donde número es el número del cual queremos obtener la raíz cuadrada,
    adelante, empieza a codificarla que con gusto la revisaré...

•   Como siempre, pruébala, si tenemos el famoso triángulo 3,4,5 y le pasamos estos datos a nuestra
    primer función, Base = 4 y Altura = 3, el área obtenida sería 6, si le pasamos estos mismos datos, más
    el largo del tercer lado, a la función que escribas, te tiene que dar el mismo resultado, el poder de la
    segunda, como ya se menciono, esta en que se puede obtener el área de cualquier triángulo, tan solo
    conociendo la longitud de sus lados.




•   Después de haber recibido todas las pruebas que han hecho, aquí esta una de varias posibles
    soluciones, pruébala y verifica si esta correcta o cuéntame que es lo que no te gusta o que otras
    variantes podría tener...
•   'Función que obtiene el área de cualquier triangulo, conociendo
•   'la longitud de sus lados, usando la formula de Herón
•   Public Function AreaTrianguloHeron(ByVal LadoA As Single, _
•                          ByVal LadoB As Single, _
•                          ByVal LadoC As Single) As Double
•   Dim Semi As Double
•   Dim Area As Double
•
•    'Obtenemos el semiperimetro
•    Semi = (LadoA + LadoB + LadoC) / 2
•    'Obtenemos los productos
•    Area = Semi * (Semi - LadoA) * (Semi - LadoB) * (Semi - LadoC)
•    'Obtenemos la RAIZ CUADRADA
    •    Area = Sqr(Area)
    •    'Asignamos el valor obtenido al nombre de nuestra función
    •    AreaTrianguloHeron = Area
    •
    •   End Function
    •
    •   Recuerda que debes de probar las dos funciones, de modo que verifiques que te de el mismo
        resultado, en la siguiente imagen, puedes observar los valores asignados a cada función, así mismo,
        en rojo, están las funciones que hemos creado...




Descargar el código de este artículo.

Complementos... ¿que son?




Complemento
      Componentes que pueden instalarse en el equipo para agregar comando o funciones a Excel


Esto es lo que nos dice la ayuda, en otros términos, un complemento es un archivo de Excel, con ciertas
características especiales (que veremos) en el cual podemos crear macros o funciones que extiendan las
posibilidades de Excel, veamos primero un complemento de los que incluye Excel y después crearemos el
nuestro...

    •   Entramos a Excel
    •   Seleccionamos el menú Herramientas | Complementos...
    •   Nos mostrara el siguiente cuadro de dialogo
•   Observa la lista y selecciona Autoguardar. Nota: estos complementos se pueden instalar y desinstalar,
    tal vez la lista no sea igual o tal vez no este instalados en tu equipo, para instalarlos checa la ayuda.
•   Después de seleccionar el complemento Autoguardar y claro, después de que hayas leído la leyenda
    que aparece en la parte inferior del cuadro de dialogo, para que te des una idea de lo que hace,
    presionas el botón Aceptar
•   Si eres observador y si tu maquina no es muy rápida, observa la barra de estado de Excel, notaras que
    dirá Abriendo Autosave.xla... y como es común al abrir libros, mostrara una barra de progreso, al
    terminar "aparentemente" no notaras ningún cambio, pero ve al menú Herramientas y este tendrá una
    nueva opción, como se ve en la siguiente imagen.




•   Selecciona esta nueva opción y te saldrá el siguiente cuadro de dialogo...




•   Como este articulo no es para explicar el uso de este complemento, pues te queda de tarea probarlo,
    que como imaginaras, te permite guardar cada X minutos el libro activo o todos los libros, además de
    que si esta bien instalado, también se instala la ayuda de los complementos.
•   Ahora, quiero que regreses a los complementos y busques en la lista uno que se llama Solver,
    selecciónalo y de nuevo te agregara una nueva opción al menú Herramientas, esto es solo como
    prueba de otro complemento y también como tarea te queda investigar como quitar estos
    complementos.
•   Observa como la herramienta de Autoguardar NO esta implementada en Excel, sino que se agrego
    esta funcionalidad con un complemento o Add-ins como también se les conoce, esto no lo pierdas de
    vista, los complementos son para agregar nuevas funciones o herramientas a Excel, no para repetir
    las ya existentes.
•   Ahora viene lo interesante, como creo mi propio complemento, antes de continuar, no pierda de vista lo
    comentado en el punto anterior y veamos paso a paso como crear un sencillo complemento. Para lo
    que veremos a continuación, estoy suponiendo que ya trabajas, aunque sea muy básico, con macros y
    funciones, si no es así, te recomiendo los siguientes temas vistos en estas páginas:
          Introducción donde vemos como empezar desde cero con las macros y a familiarizarnos con el
             Editor VBA
          Grabando mi primer macro en Excel
          Escribiendo mi primer función en Excel
          Y los primeros tres temas de la sección Articulos
          Como ya se dijo, vamos a usar los complementos para agregar funcionalidades inexistentes en
             Excel, para nuestro ejemplo, implementaremos la posibilidad de cambiar el contenido de las
             celdas de MAYÚSCULAS a minúsculas y viceversa.
          Entramos a Excel.
          Si tenemos más de una hoja (normalmente 3) dejamos solamente una hoja, esto no es
             indispensable, pero dado que no se van a ocupar, las eliminamos para que el complemento
             resultante sea de menor tamaño.
          Guardamos nuestro archivo, por ahora, guárdalo como cualquier archivo de Excel y después
             veremos como hacerlo como complemento.
          Entramos al Editor VBA, método abreviado Alt + F11
          Agregamos un módulo de código Estándar desde el menú Insertar | Módulo
          Escribimos o copiamos las siguientes macros...
          Option Explicit
         
          Public Sub Mayusculas()
          Dim c As Range
         
              For Each c In Selection
               c.Value = StrConv(c.Value, vbUpperCase)
              Next c
         
          End Sub
         
          Public Sub Minusculas()
          Dim c As Range
         
              For Each c In Selection
               c.Value = StrConv(c.Value, vbLowerCase)
              Next c
         
          End Sub
         
          'NOTA la funcion StrConv solo esta disponible de Excel 2000 en adelante
          'para versiones anteriores hacerlo de esta forma
         
          Public Sub Mayusculas()
          Dim c As Range
         
          For Each c In Selection
               c.Value = UCase(c.Value)
              Next c
         
          End Sub
         
          Public Sub Minusculas()
          Dim c As Range
              For Each c In Selection
     c.Value = LCase(c.Value)
    Next c

   End Sub
   Comprobamos que trabajen bien, probándolas desde el Editor VBA o desde la interfaz de Excel
    desde el menú Herramientas | Macro | Macros... o con el método abreviado de teclado Alt + F8
   Estas macros las declaramos Publicas (para detalles de este tema lee el articulo Publica o
    Privada, ¿cual usar?), pero al guardar nuestro archivo como Complemento, estas macros no
    las podrás ver y por consiguiente ejecutar, desde la interfaz de Excel, es como si las macros
    pasaran a ser Privadas, entonces, para poder ejecutarlas tienes que asignarlas a alguna
    elemento de la pantalla, un menú, un botón o algún control, como notaste en los
    Complementos Autoguardar y el Solver, estos agregaban una nueva opción al menú
    Herramientas, esto no es obligatorio, ya que puedes agregar una opción en cualquier parte de
    los menús o submenús existentes o de plano crear un nuevo menú propio, para nuestro
    ejercicio agregaremos un submenú al menú Herramientas que se llame Utilidades y dentro de
    este las opciones Mayúsculas y Minúsculas, para ello usaremos el siguiente código...
   Public Sub PonerMenu()
     Dim NuevoMenu As Object
     Dim OpcionMenu As Object
     Dim MenuHerr As Object

    ' Busca si el menú ya esta existe
    Set NuevoMenu = CommandBars.FindControl(Type:=msoControlPopup, Tag:="Utilidades")
    ' Si no lo encuentra la variable es Nothing
    If NuevoMenu Is Nothing Then
      ' Busca el menú Herramientas y devuelve una referencia a el
      Set MenuHerr = CommandBars.FindControl(ID:=30007)
      ' La posibilidad de que sea Nothing es remota pero hay que considerarla
      If Not MenuHerr Is Nothing Then
        ' Agrega un sunmenú al menú Herramientas
        Set NuevoMenu = MenuHerr.Controls.Add(Type:=msoControlPopup, Temporary:=True)
        With NuevoMenu
          ' Le ponemos Titulo
          .Caption = "&Utilidades"
          ' Usamos esta propiedad como utilidad para la busqueda
          .Tag = "Utilidades"
          'Garantizamos que este visible
          .Visible = True
        End With

      Set OpcionMenu = NuevoMenu.Controls.Add(Type:=msoControlButton, _
                                            Temporary:=True)
      With OpcionMenu
       .Caption = "Mayusculas"
       'Le asignamos la macro que queramos ejecutar
       .OnAction = "Mayusculas"
      End With

      Set OpcionMenu = NuevoMenu.Controls.Add(Type:=msoControlButton, _
                                           Temporary:=True)
      With OpcionMenu
       .Caption = "Minusculas"
       .OnAction = "Minusculas"
      End With

     End If
    End If

    'Liberamos la memoria
    Set MenuHerr = Nothing
    Set NuevoMenu = Nothing
    Set OpcionMenu = Nothing

   End Sub

   Public Sub QuitarMenu()
    Dim Menu As Object

    'Busca el menu, si lo encuentra lo borra, si no, no hace nada
    Set Menu = CommandBars.FindControl(Type:=msoControlPopup, Tag:="Utilidades")
    If Not (Menu Is Nothing) Then
      Menu.Delete
    End If

   End Sub
   Ahora, para que la macro PonerMenu se ejecute de forma automática al abrir el Complemento
    y la macro QuitarMenu se ejecute automáticamente al cerrar el Complemento, las "llamamos"
    desde los eventos Open y BeforeClose del libro, respectivamente...
   Desde el Editor VBA selecciona el objeto ThisWorkbook
   Ve al menú Ver | Código o presiona la tecla F7
   Copia o escribe el siguiente código.
   Option Explicit

   Private Sub Workbook_BeforeClose(Cancel As Boolean)
    QuitarMenu
   End Sub

   Private Sub Workbook_Open()
    PonerMenu
   End Sub
   Ahora, antes de guardarlo como un Complemento, guarda el archivo con estos últimos cambios
    de modo que siempre tengas un "respaldo" de tu complemento como un libro normal XLS.
   Ve al menú Archivo | Guardar Como... y del cuadro de lista desplegable (ComboBox) Guardar
    como tipo, buscas y seleccionas Complemento de Microsoft Excel (*.xla)
   Establece el nombre del Complemento, normalmente será el mismo de mi archivo XLS, pero
    antes de aceptar y cerrar este cuadro de dialogo, observa como Excel, al decirle que queremos
    guardarlo como Complemento, solito nos cambia la ruta de acceso, da un clic en el cuadro de
    lista desplegable (ComboBox) Guardar en, y observa la ruta donde lo dejara, la cual
    normalmente es

    C:WINDOWSApplication DataMicrosoftComplementos

    claro, en este momento, si lo deseas, puedes cambiar esa ruta y guardar tu complemento
    donde gustes.
   En este momento ya tienes dos archivos, uno XLS y otro XLA, aunque el XLA (el
    Complemento) no queda abierto en estos momentos, hay que cargarlo para probarlo y es lo
    que haremos a continuación.
   Cierra y vuelve a entrar a Excel, esto es con la finalidad de que reconozca el nuevo
    complemento, NO es indispensable, pero ya te iras dando cuenta, cuando es conveniente
    hacerlo y cuando no.
   Ve al menú Herramientas | Complementos, la lista de complementos esta en orden alfabético,
    así, que si has usado los nombres propuestos, desplázate hasta la letra U y debe de aparecer
    el Complemento Utilidades como se ve en la siguiente imagen, en caso de que hayas
    guardado tu complemento en otro lugar, tienes que usar el botón de comando
    (CommandButton) Examinar... para localizarlo...




   Ve al menú Herramientas y observa como tenemos nuestro menú personalizado, agregado
    automáticamente al cargar nuestro complemento y que será eliminado automáticamente al
    cerrarse o descargarse.
   Pruébalo, llena algunas celdas con texto y conviértelas a MAYUSCULAS o minúsculas, prueba
    a hacerlo en cualquier otro libro, prueba a cargar y descargar el complemento para verificar
    que se elimina el menú correctamente.
   Por ultimo, habrás notado en los complementos instalados que al seleccionar en la lista de
    Complementos, en al parte inferior aparece una breve descripción del propósito de dicho
    complemento, si bien esto no puede sustituir a la documentación que debe de acompañar a
    todo código o programa, es útil para de primera mano, saber la utilidad del complemento,
    agreguémosle esta propiedad a nuestro complemento, para esto, descarga el complemento y
    abre el archivo XLS original.
   Ve al menú Archivo | Propiedades... y selecciona la ficha Resumen, en esta, puedes llenar
    todos los campos que quieras, pero los importantes son: Titulo y Comentarios, el campo
    Titulo será lo que aparezca en el cuadro de lista Complementos y el campo Comentarios se
    verá en la parte inferior de dicho cuadro, complétalos a tu gusto, te muestro lo que yo escribí...
   Vuelve a realizar el proceso de guardar como Complemento, por supuesto, al querer guardarlo
           con el mismo nombre, te preguntara si quieres reemplazarlo, respondes que si y cierras y
           vuelves a entrar a Excel, vas al menú Herramientas | Complementos buscas tu complemento y
           veras que corresponde lo que escribiste en los campos de las propiedades del archivo, con lo
           que ves aquí...




•   Muy bien hecho, cierto, todavía puede tener muchas mejoras y las tiene, sobre todo en lo que respecta
    a controlar errores, pero eso se verá en otro capitulo, por lo pronto con esto basta...
•   La mayoría de las macros y funciones que hagamos, son susceptibles de usarse desde un modulo
        estándar y un libro común como macro o incorporarse a un Complemento, con el uso y la experiencia,
        tu mismo discernirás cuando es conveniente lo uno y cuando lo otro.
    •   Para los miembros de la lista, el archivo original XLA esta disponible en el área de archivos.




Descargar el código de este artículo.

Exportador de macros

Este complemento, extrae de todos los libros abiertos, las macros o funciones que contenga, con la posibilidad
de Exportarlas a cualquir otro libro abierto, al cargarlo, te agrega una nueva opción al menú Herramientas,
llamada Exportar Macros... el cual, al ejecutarlo, te muestra el siguiente cuadro de dialogo




Su uso de detallará en esta página, aunque realmente es muy sencillo, el complemento esta disponible en el
área de ficheros de la lista, o puedes descargarlo desde aqui, te aclaro que para que puedas ver el código, el
archivo esta guardado como XLS, pero puedes guardarlo como complemento, pues esta pensado para que
funcione como tal...

Descargar el Complemento Exportar Macros de este artículo.

Más contenido relacionado

PDF
Libro de proyectos del kit oficial de Arduino en castellano completo - Arduin...
DOCX
Les eines
PPTX
Tema 10 las primeras civilizaciones históricas
ODP
Madrid
PPSX
5 Annoying Excel Pivot Table Problems
PDF
Interfaz visual basic 6 y arduino
DOCX
Manual basico de practicas con Arduino uno
DOC
Programacinconvisualbasicparaaplicacionesenexcelprogramacinpuraconexcel 12071...
Libro de proyectos del kit oficial de Arduino en castellano completo - Arduin...
Les eines
Tema 10 las primeras civilizaciones históricas
Madrid
5 Annoying Excel Pivot Table Problems
Interfaz visual basic 6 y arduino
Manual basico de practicas con Arduino uno
Programacinconvisualbasicparaaplicacionesenexcelprogramacinpuraconexcel 12071...

Similar a Programación con visual basic para aplicaciones en excel programación pura_con_excel (20)

PPTX
Curso de excel avanzado tema 6 macros
DOCX
Creando macros en Excel 2010 para programdores
PDF
Compilacion macros
PDF
Macros excel ok
PDF
Macros excel ok
PDF
Notas macros excel
PDF
Manual de macros
DOC
7
DOC
Macros en Excel
DOC
Macros en excel
DOCX
Macros
PPTX
Macros
PPT
Macros Basicos
PDF
Macro en excel
PDF
Guia macros y_formularios
PDF
Guia macros y_formularios
DOCX
Taller excel normas APA
PDF
Curso de excel avanzado tema 6 macros
Creando macros en Excel 2010 para programdores
Compilacion macros
Macros excel ok
Macros excel ok
Notas macros excel
Manual de macros
7
Macros en Excel
Macros en excel
Macros
Macros
Macros Basicos
Macro en excel
Guia macros y_formularios
Guia macros y_formularios
Taller excel normas APA
Publicidad

Programación con visual basic para aplicaciones en excel programación pura_con_excel

  • 1. Programación con Visual Basic para Aplicaciones en Excel • Introducción • Artículos • Macros • Funciones • Proyectos paso a paso • Complementos (Add-ins) • Otros Lenguajes • Vinculos Introducción Programar sobre cualquier lenguaje es fascinante, en la mayoría de ellos, el limite esta más de parte del programador que del lenguaje, no tengo elementos para decir cual es mejor o peor, creo que cada uno tiene diferentes propósitos y que el bueno o malo, es el programador. Aprendí a programar de forma empírica, esto tiene sus pros y sus contras, como desventaja esta que te tardas un poco más de tiempo en aprender y como ventaja esta que te vuelves un muy buen investigador, estas, solo por nombrar algunas, se que tal vez tenga muchas deficiencias y muchos otros "vicios" de los cuales, tal vez, ni cuenta me de, pero confío en que algún buen samaritano que tenga más experiencia que yo en la programación, me los hará notar, por lo pronto, es mi deseo que este camino que para mi ha sido de más de cinco años, sea mas corto y más leve para ti, esta es la razón principal de estas páginas. Como notaras la sección que esta más completa es la de Excel, fue de los primeros programas que use y en que empecé con el VBA y aun me sigue sorprendiendo y cada vez que escribo unas líneas de código, me surgen nuevas interrogantes, pero eso me gusta y te sugiero que no te desanime si este es tu caso, veras que poco a poco se va aclarando el camino. Si bien en un principio no era mi intención hacer un manual, sino tan solo una guía, la verdad es que se ha impuesto mi espíritu pedagógico, pues te cuento que una de mis actividades favoritas es dar clases, así que lo que empezó como unos apuntes se esta convirtiendo en este pequeño manual, así que aprovecha, estudia, lee, investiga, lee, practica y lee, lee mucho... Artículos Preguntale a la Grabadora de macros Publica o Privada, ¿cual usar? • Option Explicit, Dim, ¿que es eso? • ¿Cómo puedo proteger un trabajo intelectual desarrollado en Excel? COLABORACION de Héctor Miguel Orozco Díaz, GRACIAS... • Variables y objetos, ¿como nombrarlos? Macros Grabando mi primer macro en Excel • Escribiendo mi primer macro en Excel • Escribiendo mi primer macro en Excel II • Escribiendo mi primer macro en Excel III Funciones Las funciones personalizadas de Excel, trabajan igual que las incorporadas, con la diferencia de que estas las creamos nosotros y nos sirven para obtener valores que no nos devuelven las incorporadas o para unir en una sola, el resultado de varias funciones, su uso y manipulación es muy semejante a las macros, pero como
  • 2. sabes estas nos devuelven valores, esto no lo pierdas de vista. Escribiendo mi primer función en Excel • ¿Como dejar disponibles mis funciones? • Función Numeros a Letras Proyectos Paso a Paso Esta sección esta pensada para que, aunque no tengas gran experiencia en la programación, seas capas de seguir una secuencia de pasos para lograr un propósito, un proyecto completo de alguna tarea, puedes proponer el desarrollo de algún proyecto, y si es de interés para varios, tal vez se pueda desarrollar entre todos. • Proyecto de Facturación (en preparación) Complementos (Add-ins) En esta sección explicaremos que son, cual es su propósito y como se usan, así como la forma de "instalarlos" dentro de Excel, también agregaremos complementos probados y terminados para su libre uso y estudio del código. ¿Que son? • Exportador de macros Otros Lenguajes Controlar Excel desde otros lenguajes, es sumamente fácil, ademas de que pones a disposición de tu programa, todas las herramientas de este, basicamente hay dos formas de hacerlo, trataremos de ver ambas, aunque más adelante solo me concentrare en una de ellas, también, para esta sección, estoy suponiendo que ya tienes bases de programación... Preguntale a la Grabadora de Macros Rara vez, la grabadora de macros, nos deja una macro tal como la queremos, en la mayoría de los casos, hay que editarla, agregándole o quitándole líneas, complementándola, mejorándola. En mi experiencia, la grabadora de macros funciona muy bien como profesora, es decir, nos enseña el "como" de casi todo el trabajo sobre Excel y "casi" nunca se equivoca. Concretamente lo que te quiero decir, es que cuando no sepas como hacer X tarea, graba una macro, ve el código, checa la ayuda acerca de las líneas que haya agregado y veras como se aprende bastante, también esto sirve para que cuando realices una consulta, aquí o en cualquier otro lugar, ya tengas una idea, con código, de lo quieres, veamos estos dos casos con un ejemplo: En la página de Todo Expertos, un usuario me hizo la siguiente pregunta, que pongo solo con animo ilustrativo, no se nos vaya a ofender: Esta duda me trae de cabeza...... (26/3/2002 18:44:0) Hola Valedor, es la primera vez que pregunto, supongo que será facil pero a mi me resulta muy complicado, la pregunta en resumen es la siguiente: ¿como puedo hacer para que con
  • 3. una macro,función, o lo que sea, me copie solo las celdas que contengan texto del rango de celdas A1:A20 y me coloque el resultado en el rango C1:C20 ordenados una debajo de la otra, es decir que no copie las celdas vacías, teniendo en cuenta que el rango de la columna A son celdas vinculadas desde otras hojas y solo se rellenan si hay algún dato que consignar, si me puedes ayudar para realizar esa macro con te lo agradecería muchísimo y me solventarías un gran problema.... Grabar macro... (27/3/2002 11:35:0) Lo primero que tienes que probar es a grabar una macro, yo lo hice y me dio esto Sub Macro2() Range("A1:A20").Select Selection.SpecialCells(xlCellTypeFormulas, 2).Select Selection.Copy Range("C1").Select ActiveSheet.Paste End Sub que hace lo que quieres... Primero, este amigo, no sabe la diferencia entre una Macro, una Función o lo que sea, que son tres cosas diferentes, pero tu ya los sabes ¿verdad?... Segundo, si el hubiese grabado la macro, tal vez no le hubiese dado el mismo código que a mi, pero tendría "algo", que ya es ganancia, si antes de preguntar grabas tu macro, yo pensaré que tienes interés en aprender y me dará más gusto ayudarte, pero que pasos hubiésemos seguido para grabar esta macro, veamos algunas opciones, supongamos el escenario que nos propone el amigo, una serie de valores en las celdas A1:A20, pero que son formulas, las cuales pueden ser texto o algo más que no especifica, de estos datos, hay que seleccionar los que son texto y copiarlos a la celda C1, eliminando los espacios vacios, para este ejemplo, use los siguientes datos: Observa la barra de formulas, ve como los datos estan vinculados a otra hoja, observa también, que tenemos textos y números, ahora, grabaremos nuestra macro con estos pasos : 1. Activamos la grabadora de macros 2. Seleccionamos los datos de nuestro interés, en este caso de la celda A1:A12 3. Presionamos la tecla F5 4. Presionamos el botón de comando Especial... 5. Seleccionamos Celdas con formulas y solo dejamos activada la opción Texto. 6. Presionamos el botón de comando Aceptar 7. Copia estos datos, por el método que quieras, tienes como cuatro o más opciones 8. Selecciona la celda C1 9. Pega los datos
  • 4. 10. Detenemos la grabación Si seguimos estos pasos al pie de la letra, la macro grabada tiene que quedar así... Sub Macro1() Range("A1:A12").Select Selection.SpecialCells(xlCellTypeFormulas, 2).Select Selection.Copy Range("C1").Select ActiveSheet.Paste End Sub Si ejecutas esta macro en la hoja donde están las formulas, en nuestro ejemplo dentro de la Hoja1 tendrás que ver algo como la siguiente imagen: No te preocupes tanto si tienes algo diferente, seguro algo hiciste de otra manera, en este tema, esto no es lo relevante, lo importante, es ver y notar como la grabadora de macros, nos ayuda mucho... Ahora, vamos a darle una pequeña variante para que observes las diferencias, estos son los pasos: 1. Activamos la grabadora de macros 2. Seleccionamos la celda A1 3. Presionamos la tecla F5 4. Presionamos el botón de comando Especial... 5. Seleccionamos Region actual 6. Presionamos el botón de comando Aceptar 7. Presionamos la tecla F5 8. Presionamos el botón de comando Especial... 9. Seleccionamos Celdas con formulas y solo dejamos activada la opción Texto. 10. Presionamos el botón de comando Aceptar 11. Copia estos datos, por el método que quieras, tienes como cuatro o más opciones 12. Selecciona la celda C1 13. Pega los datos 14. Detenemos la grabación Para estos pasos, la grabadora nos crea el siguiente código: Sub Macro2() Range("A1").Select Selection.CurrentRegion.Select Selection.SpecialCells(xlCellTypeFormulas, 2).Select Selection.Copy Range("C1").Select ActiveSheet.Paste End Sub
  • 5. Ejecuta cada una de estas macros y nota las diferencias, dale variantes, por ejemplo, agrega mas datos por debajo de la celda A20 y vuelve a probar cada una de las dos macros, agrega valores diferentes que no sean texto o números, agrega constantes, o sea, valores que NO provengan de formulas, pruébalas en otras hojas o libros. Cierto, esta macro no se adapta a todos los casos, de hecho, hace un trabajo muy especifico, pero notas que ahora sabemos como seleccionar la región actual Selection.CurrentRegion.Select o también aprendimos como seleccionar las celdas con formulas que contengan solo texto Selection.SpecialCells(xlCellTypeFormulas, 2).Select ¿que más aprendiste con esta pequeñisima macro?. Por ultimo haremos algo que se hace con la "mayoría" de las macros, editarla, si, editarla, es decir, agregarle líneas que no haya agregado la macro, eliminando las que no nos sirven o mejorando lo que sea posible y mira que casi siempre es posible. Como primer paso, entra al Editor VBA y copia la macro que se llama (si no le pusiste otro nombre) Macro2, y cámbiale el nombre a Macro3, recuerda que NO puedes tener dos macros con el mismo nombre dentro del mismo módulo, esta macro tres será la que modificaremos y tal vez te sorprenda lo que se puede hacer, sigamos... • Como primer paso comentare la macro para que sepas que hace cada línea... • Sub Macro3() • 'Se selecciona la celda A1 • Range("A1").Select • 'A partir de la seleccion actual, se selecciona la REGION ACTUAL • Selection.CurrentRegion.Select • 'Seleccionamos las celdas con formulas que sean texto • Selection.SpecialCells(xlCellTypeFormulas, 2).Select • 'Copiamos la seleccion • Selection.Copy • 'Se selecciona la celda C1 • Range("C1").Select • 'Copiamos el contenido del portapapeles en la hoja activa • ActiveSheet.Paste • End Sub • El siguiente paso será unificar las dos primeras líneas, es decir desde la celda A1 seleccionaremos la región actual, para que se vea así... • Sub Macro3() • 'Se selecciona la celda A1 y su REGION ACTUAL • Range("A1").CurrentRegion.Select • 'Seleccionamos las celdas con formulas que sean texto • Selection.SpecialCells(xlCellTypeFormulas, 2).Select • 'Copiamos la seleccion • Selection.Copy • 'Se selecciona la celda C1 • Range("C1").Select • 'Copiamos el contenido del portapapeles en la hoja activa • ActiveSheet.Paste • End Sub • Ejecuta la macro con cada modificación que le hagamos, para que compruebes que sigue realizando las mismas acciones y finalizamos con el mismo resultado. Siguiente paso; unificamos la línea de selección de la celda A1 y la región actual, con la línea de selección de formulas que contengan texto... • Sub Macro3() • 'Se selecciona la celda A1 y su REGION ACTUAL y las • 'las celdas con formulas que sean texto • Range("A1").CurrentRegion.SpecialCells(xlCellTypeFormulas, 2).Select • 'Copiamos la seleccion • Selection.Copy • 'Se selecciona la celda C1 • Range("C1").Select
  • 6. 'Copiamos el contenido del portapapeles en la hoja activa • ActiveSheet.Paste • End Sub • Siguiente paso; unificaremos la línea de selección y la línea del método Copy... • Sub Macro3() • 'Se selecciona la celda A1 y su REGION ACTUAL y las • 'las celdas con formulas que sean texto y copiamos • Range("A1").CurrentRegion.SpecialCells(xlCellTypeFormulas, 2).Copy • 'Se selecciona la celda C1 • Range("C1").Select • 'Copiamos el contenido del portapapeles en la hoja activa • ActiveSheet.Paste • End Sub • Siguiente paso; le agregamos el argumento "opcional" al método Copy, donde se le indica el destino donde queremos dejar lo que estamos copiando, tiene que ser un argumento tipo Range, o sea un rango, para nuestro ejemplo, será la celda C1 • Sub Macro3() • 'Se selecciona la celda A1 y su REGION ACTUAL y las • 'las celdas con formulas que sean texto y copiamos • 'le agregamos el argumento "opcional" al metodo Copy • 'el DESTINO donde queremos copiar, un Rango • Range("A1").CurrentRegion.SpecialCells(xlCellTypeFormulas, 2).Copy Range("C1") • End Sub • ¿Cómo vez?, ¿has ejecutado la macro?, ¿observas como con UNA sola línea podemos hacer lo que se hacia con SEIS?, interesante ¿no crees?, no siempre es así, pero "casi" siempre, la grabadora de macros, graba líneas de más, que es muy bueno depurar, pues nos da mucha practica y código más limpio y ordenado... Para terminar, te comento que todavía, hago uso de esta técnica, si no se o no recuerdo como se hace determinada tarea, simplemente grabo una macro y listo, me muestra como es y en poco tiempo te sorprenderás como cada vez menos, tienes que consultar la ayuda, saludos... Creiste que esta vez no habia tareita, pues te fallo, prueba a grabar una macro con alguna acción que te interese como se hace con código y nos cuentas a todos en la lista de correo, si vemos alguna interesante la podemos publicar aquí... Descargar el archivo grabando_macros.zip que contiene el archivo Preguntale a la grabadora de macros.xls con todo el código mostrado en este artículo. Publica o Privada, ¿cual usar? Para este tema, doy por sentado que algunas vez has grabado, al menos, una macro, que has leido al menos la Introdución que hay en esta página... Cuando grabamos una macro, la grabadora nos crea un código como este: Sub Macro1() ' ' Macro1 Macro ' Macro grabada el 03-04-2002 por Tecnico1 '
  • 7. ActiveCell.FormulaR1C1 = "Hola" Range("A2").Select End Sub en algunas de mis páginas, en algunas otras páginas o en algún otro lado, habrás visto que algunas macros tienen una palabra más, detrás del Sub, como se que eres curioso, presionaste F1 y en la ayuda leíste cuales y para que sirven estas palabras: Public y Private, así que supongo que lo dicho aquí ya lo sabes, pero sigue leyendo, tal vez encuentres algo nuevo o tal vez me notes algo que me falto y que por supuesto harás el favor de decirme, ¿verdad?, gracias. Bien, entonces la macro anterior también puede estar escrita así... Public Sub Macro1() ActiveCell.FormulaR1C1 = "Hola" Range("A2").Select End Sub o también así Private Sub Macro1() ActiveCell.FormulaR1C1 = "Hola" Range("A2").Select End Sub pero, ¿cuál es la diferencia?, de eso se trata este pequeño articulo... Veamos que dice la ayuda acerca de estas palabras Public Opcional. Indica que el procedimiento Sub es accesible para todos los demás procedimientos de todos los módulos. Private Opcional. Indica que el procedimiento Sub es accesible sólo para otros procedimientos del módulo en el que se declara. A ver si entendimos, probemos con unos ejemplos, realiza los siguiente pasos: • Entra a Excel • Entra al EditorVBA (Alt+F11) • Menú Insertar | Modulo • En la ventana de código escribe lo siguiente • Sub Pruebas1() • MsgBox "Esta macro es PUBLICA" • End Sub • A lo que acabamos de hacer se le llama, declarar un procedimiento. • Ejecútala desde el EditorVBA presionando F5 (recuerda que el cursor debe estar dentro de la macro) y nos mostrara este bonito mensaje. • Ahora quiero que la vuelvas a ejecutar, pero desde Excel, regresa a Excel, ve al menú Herramientas | Macro | Macros... o si lo prefieres Alt+F8, selecciona la macro Pruebas1 y presiona el botón Ejecutar para confirmar que, de nuevo, se ejecuta correctamente. • Ahora, agrégale la primer palabrita que estamos estudiando, para que se vea así. • Public Sub Pruebas1() • MsgBox "Esta macro es PUBLICA" • End Sub
  • 8. Vuelve a ejecutar la macro, de las dos formas que hemos visto y felizmente, nos muestra nuestro mensaje. • Conclusión: las macros o procedimientos son Publicas por omisión y como dice la ayuda que es opcional, entonces es lo mismo poner o no poner la palabra Public antes de la instrucción Sub. • Muy bien, muy bien, veo que eres buen estudiante, ahora creamos una segunda macro que se llame Pruebas2 (te quemaste el coco para pensar este nombre Mauricio), por que recuerda que no puedes tener dos procedimientos que se llamen igual, prueba a ponerle el mismo nombre y veraz que el EditorVBA te dirá algo medio feo. Ahora, le ponemos nuestra segunda palabrita. • Private Sub Pruebas2() • MsgBox "Esta macro es PRIVADA" • End Sub • Ejecútala desde el EditorVBA, verás que nos sigue mostrando el mensaje, claro, ahora nos dice que es PRIVADA (ni tanto ¿verdad?, la seguimos viendo), pero la siguiente prueba será ejecutarla desde Excel (Alt+F8). • ¿Qué paso?, ¿mande...?!, que!!, que no se ve!!, ¿¡cómo que no se ve!?, pero si estamos declarandolo como debe ser, aaahhh ya recuerdo, le agregamos una palabrita mágica, ¿verdad?, Private, si, esta palabrita es muy útil, en este caso, la macro ya no aparece listada en el cuadro de lista, del cuadro de dialogo Macros, como lo acabamos de demostrar, pero entonces, ¿no se puede ejecutar desde aquí, tiene que ser desde el EditorVBA?, para probarlo entra de nuevo al cuadro de dialogo macros y por ahora solo veras la macro anterior Pruebas1, ahí, donde dice Nombre de la macro, escribe Pruebas2 y observa que pasa... • Interesante ¿no?, la macro de todos modos la podemos ejecutar con solo saber su nombre y estarás de acuerdo que si no queremos que las ejecuten no les diremos como se llaman, sssssshhhh... • Te puede suceder que, por error de dedo, hayas escrito mal el nombre de la macro, ¿qué pasa?, ¿qué es lo que hace Excel?, te dejo de tareita que me cuentes que pasa en estos casos. • ¿Y eso es todo?..., no, ¿cómo crees?, sigamos haciendo pruebas, como sabes, y si no sabias, ahora vas a saber, puedes ejecutar una macro desde otra macro, a esto lo nombramos llamar a la macro y para comprobarlo, modifica nuestra primer macro para que se vea así. • Public Sub Pruebas1() • MsgBox "Esta macro es PUBLICA" • Pruebas2 • End Sub • Por supuesto ejecútala y observa, interesante, muy interesante... ¿verdad que si?... A la vista de este efecto, ¿que deduces?, ¿para que te imaginas que pueda servir el llamar a una macro desde otra?, ¿que utilidad tiene el que unas se vean y otras no?... • Antes de responder, algunas, por que otras de estas preguntas tu las tienes que responder, hagamos otras pruebitas. Insertemos otro modulo en nuestro archivo, menú Insertar | Módulo, nuestro Explorador de proyectos se tiene que ver así. • En este módulo crearemos una tercer macro Publica, en este momento ya tienes lo elementos para hacer tu propio ejemplo, pero por supuesto puedes seguir con los que propongo... • Public Sub PruebasA()
  • 9. MsgBox "Esta macro es PUBLICA y esta en un otro Módulo" • End Sub • Ahora, trata de llamar a la macro Pruebas1 que se encuentra en el primer módulo, la macro se tiene que ser así... • Public Sub PruebasA() • MsgBox "Esta macro es PUBLICA y esta en un otro Módulo" • Pruebas1 • End Sub • La macro se ejecuta, o se debería ejecutar sin problemas, si no es así, revisa alguno de los pasos que hemos seguido, ahora, trata de llamar a la segunda macro del primer módulo, es decir, trata de llamar a la macro que declaramos Privada en el primer módulo y que nombramos Pruebas2. • Public Sub PruebasA() • MsgBox "Esta macro es PUBLICA y esta en un otro Módulo" • Pruebas2 • End Sub • ¿Qué sucedió?, ¿se ejecuta?, creo que no, pero el EditorVBA nos muestra un mensaje de error, más específicamente el siguiente error. • Después de presionar el botón Aceptar, el Editor nos regresa a la ventana de código, selecciona la palabra donde esta el error y nos muestra una línea de un color amarillo bastante distinguible. • Muy bien pensado, la razón de que no podamos llamar a una macro de otro módulo, es por que esta macro la declaramos Privada (Private), entonces si es cierto lo que dice la ayuda, -indica que el procedimiento Sub es accesible sólo para otros procedimientos del módulo en el que se declara-, ¿verdad?, de ahí la importancia de leer la ayuda "siempre". Antes de que detengas la ejecución de la macro, observa la barra de titulo, por ahí tiene una palabrita que dice [interrupción], ya la viste, bueno, por ahora solo lo menciono, pero más adelante se verá un poco más a detalle, cuando ejecutamos código, este se puede detener, tanto por errores de sintaxis (como en este caso) o cuando nosotros queramos, esto es algo muy útil cuando depuramos nuestras macros, así que lo veremos en otro articulo. Ahora si, puede detener la ejecución de la macro, de hecho, no tenemos otra alternativa, esto lo haces con el icono Restablecer de la barra de herramientas, que es como el botón Detener de la mayoria de los reproductores de musica, o bien, ve al menú Ejecutar | Restablecer y listo, la macro se detendra al momento.
  • 10. Concluyendo: las macros pueden ser Publicas (Public) o Privadas (Private), es igual poner el Public o no, pero no es lo mismo si ponemos o no el Private, la recomendación es, declara explícitamente si tu macro es Publica o Privada. • Para terminar te comento que lo visto aquí, acerca de las macros Publicas y Privadas es aplicable, también, para las funciones, es decir, también tenemos funciones Publicas y funciones Privadas, pero parte de la tareita de esta sección es esa. o Crea una segunda macro Privada en el segundo Módulo y realiza todas las pruebas que hemos hecho con las demás, incluyendo, el tratar de ejecutarlas desde la ventana de Excel o Crea todas las macros y has todas las pruebas que consideres suficientes para que no queden dudas de este tema, incluso agrega un tercer o cuarto módulo para esto. o Crea varias sencillas funciones, tanto Publicas como Privadas y quiero que me digas, donde se ven y donde no, te dare una pista, usa el Asistente para funciones para observarlo. Para crear las funciones, si no lo has hecho, lee el tema Escribiendo mi primer función en Excel y después haces estas pruebas. o Una líneas más arriba, nos hicimos la siguiente cuestión: ¿para que te imaginas que pueda servir el llamar a una macro desde otra?, la respuesta a esta pregunta es importantisima, tiene mucho que ver con lo que pensaba el señor Descartes, ¿ya lo recuerdas?... • Como complemento a este artículo, veremos que diferencia hay entre una función Publica y una función Privada La siguiente función personalizada nos devuelve un texto con información del tipo de contenido de la celda pasada como argumento y nos dice si la celda esta VACIA, si es un NUMERO, si es una FECHA o si contiene TEXTO... Option Explicit Public Function TipoValor(Celda As Range) As String If Celda.Value = "" Then TipoValor = "VACIA" ElseIf IsNumeric(Celda.Value) Then TipoValor = "ES NUMERO" ElseIf IsDate(Celda.Value) Then TipoValor = "ES FECHA" Else TipoValor = "ES TEXTO" End If End Function Para usar esta función, regresa a la ventana de Excel, en este caso, usaremos el Asistente para funciones, que seguro ya dominas, entonces, los pasos serian... o Escribe en la celda A1 un valor cualquiera o Posiciona el cursor en la celda B1 o Inicia el Asistente para funciones o En el Cuadro de lista Categoría de la función, busca la ultima opción que dirá, Definidas por el usuario o En el Cuadro de lista Nombre de la función, tendrás que ver nuestra función TipoValor, por supuesto si tienes más funciones que hayas creado aquí las veras o Seleccionamos esta función y presionamos el Botón de comando Aceptar
  • 11. o Como bien sabes, el Asistente te presenta una ventanita con el nombre de la función y un cuadro de texto solicitándote el argumento Celda necesario para que la función trabaje (bueno, realmente no es un cuadro de texto, sino un control muy especial y muy útil que aprenderemos a usar más adelante) o Puedes usar el botón Contraer o escribir directamente la referencia a la celda A1, tras lo cual presionaras el botón Botón de comando Aceptar y el Asistente introducirá por nosotros, el signo igual, la función y el argumento que le establecimos o Al terminar, mi celda B1 se tendrá que ver como en la siguiente imagen y verificaremos que la función haga el trabajo para la cual la programamos, ¿así es?...
  • 12. o Ahora, cambiaremos la palabra Public de nuestra función por la palabra Private, o bien, puedes copiar la función y hacer una segunda, por supuesto, con otro nombre, yo usare el primer método... o Option Explicit o o Private Function TipoValor(Celda As Range) As String o o If Celda.Value = "" Then o TipoValor = "VACIA" o ElseIf IsNumeric(Celda.Value) Then o TipoValor = "ES NUMERO" o ElseIf IsDate(Celda.Value) Then o TipoValor = "ES FECHA" o Else o TipoValor = "ES TEXTO" o End If o o End Function o o Regresa a la ventana de Excel y copia la formula existente en la celda B1 a la celda B2, ¿qué pasa?..., así es, la función sigue trabajando, entonces!..., ¿cuál es la diferencia?, para notarlo, trata de agregar un valor cualquiera en la celda A3, posicionate en la celda B3 y trata de usar el Asistente para funciones como en nuestro primer ejemplo y observa...
  • 13. o Efectivamente, la función no aparece, de hecho, la categoría que usamos Definidas por el usuario, ya no aparece (claro, siempre y cuando no tengas otra función declarada), pero trata de escribir la función directamente en la celda, ¿funciona?, si, si funciona, es algo similar a lo que pasa en las macros, que, como leiste más arriba, cuando la pasas a Privada, ya no se lista en el cuadro de dialogo, pero aun la puedes ejecutar si sabes su nombre, del mismo modo, si sabes el nombre de alguna función personalizada, la puedes llamar o hacer uso de ella, siempre y cuando te sepas su nombre y los argumentos que necesita, tan solo, con escribirla directamente en la celda. o Como con las macros, nos preguntamos, ¿para que servirá tener funciones Publicas y funciones Privadas?..., observa la función Números a letras para que te des una idea, aunque de nuevo, el señor Descartes nos puede ayudar... • Ahora si, Fin... Descargar el código de este artículo. Option Explicit, Dim, ¿que es eso? Para este tema, doy por sentado que algunas vez has grabado, al menos, una macro, que has leido al menos la Introdución que hay en esta página... En la mayoría de código que veas en estas páginas, y en muchas otras macros que has visto, habrás notado que al inicio de estas, casi siempre hay una pequeña línea de dos simples palabras, Option Explicit, las seleccionaste, presionaste F1 y leíste esto: Se usa en el nivel de módulo para forzar declaraciones explícitas de todas las variables en dicho módulo. Esta comprendido?, si?, bueno, Fin del articulo... Pero que antipático te estas poniendo Mauricio, anda, explícalo mejor... -De acuerdo, de acuerdo, trataré...- Primero los ejemplos y después las explicaciones • Entra Excel
  • 14. Entra al EditorVBA • Inserta un nuevo módulo y asegúrate que este en vacío, si tiene las palabras que estamos estudiando, bórralas. • Teclea o copia la siguiente macro y pruebala • Public Sub Sumas() • • Numero1 = Val(InputBox("Dame un número")) • Numero2 = Val(InputBox("Dame otro número")) • • Suma = Numero1 + Numero2 • • MsgBox "La suma es: " & Format(Suma) • • End Sub • Que bien, funciona verdad, ahora, vamos a suponer que tecleamos mal un nombre, por ejemplo, en vez de teclear Numero1, tecleamos Numer1, para que nuestra macro quede así, por esta vez, pondré en negritas los nombres que hay que probar... • Public Sub Sumas() • • Numero1 = Val(InputBox("Dame un número")) • Numero2 = Val(InputBox("Dame otro número")) • • Suma = Numer1 + Numero2 • • MsgBox "La suma es: " & Format(Suma) • • End Sub • Pruébala, ¿funciona?, si, si funciona, solo que NO da el resultado correcto, en este caso, siempre nos mostrara el valor del segundo número que le hayamos proporcionado, ¿por qué?, sigamos con las pruebas, ahora supondremos que los números están bien y que la que tecleamos mal es la palabra Suma, la cual la tecleamos así; Sum • Public Sub Sumas() • • Numero1 = Val(InputBox("Dame un número")) • Numero2 = Val(InputBox("Dame otro número")) • • Sum = Numero1 + Numero2 • • MsgBox "La suma es: " & Format(Suma) • • End Sub • Que bien!, también funciona, solo que tampoco nos da el resultado correcto, esta vez es peor, pues siempre nos muestra cero, ¿verdad?, bueno, la causa es más que obvia, los nombres no los hemos escrito correctamente y por correctamente me refiero a como escribimos esas mismas palabras en las líneas anteriores o posteriores, pues aquí no vale la ortografía, para muestra una macro... • Public Sub Gardim() • • arvol1 = Val(InputBox("Dame un número")) • lovo2 = Val(InputBox("Dame otro número")) • • frrutas = arvol1 + lovo2 • • MsgBox "La suma es: " & Format(frrutas) • • End Sub • Observa como alucine con los nombres de estas palabras, a parte de que están mal escritas, no tienen nada que ver con el propósito de nuestra macro, ya volveremos sobre este asunto más adelante, por
  • 15. ahora quise mostrarte el sentido de la palabra correctamente, y seguimos... Ahora, vuelve a nuestra primer macro y agrega, en la parte superior, las palabras mágicas Option Explicit y trata de ejecutarla. • Option Explicit • • Public Sub Sumas() • • Numero1 = Val(InputBox("Dame un número")) • Numero2 = Val(InputBox("Dame otro número")) • • Suma = Numero1 + Numero2 • • MsgBox "La suma es: " & Format(Suma) • • End Sub • ¿Que paso?, ¿no te dejo?, ¿porque?, ¿que te aparece?... efectivamente, nos muestra un bonito mensaje, que dice.. • Y no solo eso, también nos colorea de amarillo la macro donde esta el error y nos selecciona la palabra que esta mal, mejor dicho, la variable, déjame repetirlo, la variable que NO hemos declarado. • Ahora tenemos una nueva palabra, variable ya sabes que tienes que hacer, presionar F1, buscar esta palabra para encontrar... Variable Un lugar de almacenamiento con nombre que puede contener cierto tipo de datos. Cada variable tiene un nombre único que la identifica. Nombres de variable deben comenzar con un carácter alfabético, deben ser únicos dentro del mismo ámbito, no deben contener más de 255 caracteres y no pueden contener un punto Si leíste la ayuda, notaras que no esta todo lo que dice ahí, pues estoy haciendo un poco de trampita como diría un amigo, la trampita es que no transcribí todo, si no solo lo que a mi juicio, es relevante para este tema, así que vamos por partes...
  • 16. Entonces, una variable es un lugar de almacenamiento con nombre, por ahora, es suficiente que recuerdes esto, es muy importante, y... ¿dónde esta es lugar de almacenamiento?, señoras y señores, les presento a la señora RAM, bueno, no hace falta, todos la conocemos y la usamos, siempre que prendemos nuestra maquina, ¿verdad?, si, esa cosa llamada memoria RAM que por cierto ha subido mucho de precio, pero en fin, ahí, en al memoria RAM es el lugar de almacenamiento de nuestras variables, pero tenemos que comunicarle al VBA que nos aparte un pedacito de memoria y que además le de un nombre para que sepamos donde esta, a la acción de reservar memoria para nuestras variables, se le denomina Declaración de variables o Dimencionar variables, para ello, usamos otra nueva palabrita mágica, la instrucción Dim, modifica la macro para que se vea así... • Option Explicit • • Public Sub Sumas() • Dim Numero1 • • Numero1 = Val(InputBox("Dame un número")) • Numero2 = Val(InputBox("Dame otro número")) • • Suma = Numero1 + Numero2 • • MsgBox "La suma es: " & Format(Suma) • • End Sub • Ejecutala y..., tampoco nos deja, y ahora ¿que paso?, se detuvo de nuevo, pero ahora en otra variable, pero nos muestra el mismo error, ¿no es así?, bueno, pues ni modo, vamos a declarar nuestras restantes variables.. • Option Explicit • • Public Sub Sumas() • Dim Numero1 • Dim Numero2 • Dim Suma • • Numero1 = Val(InputBox("Dame un número")) • Numero2 = Val(InputBox("Dame otro número")) • • Suma = Numero1 + Numero2 • • MsgBox "La suma es: " & Format(Suma) • • End Sub • ¿Y esta vez?, claro, ahora si funciona de nuevo, pero... ¿qué ventaja percibes al declarar las variables?, ¿no es teclear más solamente?, en este ejemplo manejamos tres variables y seria algo difícil el escribir mal alguna, pero cuando empiezas a manejar, diez, veinte, cincuenta variables y no se diga cuando empieza a combinar más de una macro, funciones y otras cositas que ya veremos, notaras todas las ventajas de Declarar explícitamente las variables pues el uso de Option Explicit nos evita que usemos variables que antes, no las hayamos declarado. • Si lees la ayuda acerca de la instrucción Dim, leerás que no solo es esta, sino que tiene muchas otras variantes, tantas que nos saldríamos del tema central de este articulo, pero te recomiendo que lo leas, analices y ponga en practica, lo que si veremos es algo de suma importancia, transcribo... Dim Declara variables y les asigna espacio de almacenamiento De esta definición, ya debes de tener comprendida la primer parte Declara variables, la segunda no es tan complicada asigna espacio de almacenamiento. Quedamos que nuestras variables quedan en la memoria RAM, como sabes esta memoria es limitada y conforme se usa, hay la posibilidad de que se acabe, lo cual es muy malo, así como dice la física, que materia es todo lo que ocupa un lugar en el espacio, aquí, diremos que toda variable ocupa un espacio en la memoria, la pregunta es ¿cuánto
  • 17. espacio?, la respuesta es, depende, nueva pregunta ¿de que depende?, nueva respuesta, del tipo de variable, (expresión de asombro), ¿pero que hay varios tipos de variables?, respuesta si, ¿cómo cuales?, aquí van algunos: Byte, Boolean, Integer, Long, Currency, Single, Double, Date, String, Object, Variant, cada uno de estos tipos, ocupa un lugar, tiene un tamaño y puede contener una cierta cantidad de información, ¿cuál es la mínima unidad de almacenamiento?, así es, 1(un) byte, entonces, las variables, dependiendo su tipo, usan desde un byte y ¿hasta?, esa es tu tarea... • Te estarás preguntando, ¿pero como le decimos que tipo de variable quiero usar?, y la respuesta es muy sencilla, solo usamos otra palabrita mágica, As, seguida del tipo de variable que queramos declarar, para muestra, declararemos correctamente nuestras variables... • Option Explicit • • Public Sub Sumas() • Dim Numero1 As Integer • Dim Numero2 As Integer • Dim Suma As Integer • • Numero1 = Val(InputBox("Dame un número")) • Numero2 = Val(InputBox("Dame otro número")) • • Suma = Numero1 + Numero2 • • MsgBox "La suma es: " & Format(Suma) • • End Sub • Todavía más preguntas, ¿qué pasa si no le indico de que tipo es?, en nuestro ejemplo anterior funciono bien, ¿entonces?, ¿cuál es la diferencia?, la respuesta a esta interrogante, esta en la ayuda, así que nuevamente, busca y lee un poquito, por lo pronto, acostúmbrate a declarar explícitamente tus variables, reitero, declara explícitamente TODAS tus variables y acostumbrate a que como primer línea, en cualquier módulo de código, tengas un Option Explicit, entre más variables uses y mas líneas de código tengas, notaras cada vez más, las grandes ventajas de esto. Descargar el código de este artículo. ¿Cómo puedo proteger un trabajo intelectual desarrollado en excel?. Por Héctor Miguel Orozco Díaz La pregunta anterior se hace con cierta frecuencia en los foros públicos de discusión y consulta (tanto en los de Microsoft como en los "independientes"). Las respuestas siempre serán en relación con el tipo y grado de protección "deseada". La forma más "fácil" de proteger en Excel (sin utilizar macros), es asignar una contraseña (ó "password") ya sea a la hoja, al libro, al archivo. Para los dos primeros casos, "basta" con usar el comando Herramientas | Proteger | Proteger hoja... o Proteger libro...
  • 18. Para proteger un archivo ("completo") contra apertura y/o escritura, usa el comando Archivo | Guardar como... | Herramientas (BOTÓN AL FINAL) | Opciones generales.... En los diálogos mostrados por estos comandos, podrás asignar la contraseña de tu preferencia y a los componentes que se habrán de incluir en la protección que creas más "convenientes" (se te solicitará una confirmación).
  • 19. Nota: Las contraseñas en Excel (y textos en VBA) son "sensibles" a la capitalización (mayúsculas ó minúsculas). NO ES LO MISMO "abc" QUE "aBc". Por lo tanto, si usas contraseñas para protección de tu trabajo... "¡ QUE NO SE TE OLVIDE... RECORDARLAS !!!" (EXACTAMENTE COMO Y EN DONDE LAS ASIGNASTE). Sin embargo, brincar (ó "crackear") las protecciones para la hoja y el libro (NO al archivo) es "sumamente fácil", mediante macros que pueden inclusive ser usadas "desde otro" libro cualquiera (ohh... desilusión !!!). Los siguientes códigos hacen el "trabajo sucio": Option Explicit '** Para quitar password en protecciones a hojas ... ** Public Sub RemoverPasswordEnHoja() ActiveSheet.Protect "", , , , True ActiveSheet.Range("a1").Copy ActiveSheet.Range("a1") End Sub '** Para quitar password en protecciones a libros ... ** Public Sub RemoverPasswordEnLibro() Dim Protecciones As Integer If ActiveWorkbook.ProtectStructure = True Then Protecciones = Protecciones + 1 If ActiveWorkbook.ProtectWindows = True Then Protecciones = Protecciones + 2 Select Case Protecciones Case 0: ActiveWorkbook.Protect "", False, False Case 1: ActiveWorkbook.Protect "", True, False Case 2: ActiveWorkbook.Protect "", False, True Case 3: ActiveWorkbook.Protect "", True, True End Select ActiveWorkbook.Unprotect End Sub
  • 20. Para quitar password en protecciones a archivos .... Esta protección "ya empieza" a ser difícil de brincar. Se requiere "apoyo" de algún software especializado (que generalmente cuesta dinero) cuyas "versiones de prueba" (léase gratis) "rompen" contraseñas con hasta un máximo de 4 caracteres. Te sugiero que utilices contraseñas "más largas", inclusive puedes usar "mezclas" de mayúsculas y minúsculas, números y caracteres especiales, como los que se obtienen de la combinación de las teclas {Alt} + teclado numérico como: {Alt}+174 = «, {Alt}+0140 = Œ, {Alt}+225 = ß, {Alt}+ (la_que_te_encuentres_simpática). Los caracteres que se "visualizan" dependen del tipo de letra que se usa. USO DE MACRO-CÓDIGOS CON APOYO DE VBA. Si quieres "llegar" a protecciones más "sofisticadas", tendremos que "echar mano" de las macros, para lo cual, enseguida se explicarán algunos "trucos" que, haciendo una "buena" combinación de ellos te podrás acercar a lo que pudiera considerarse como un "Sistema de Protección (casi) Perfecto". Requisito INDISPENSABLE: Asignar también al proyecto VBA (macros) una contraseña. SIGUE LAS SUGERENCIAS INDICADAS ANTERIORMENTE... Y ¡OJO! CON LOS ACENTOS. Toma en consideración que una de las tareas más "quema-neuronas" en cuestiones de programación es: o "Anticipar" (en la medida de lo posible) las acciones del usuario para poder. o "Evaluar" las consecuencias de ejecutar un código y finalmente. o "Diseñar" prevenciones o correcciones de errores "involuntarios" (o premeditados?). La técnica empleada para este ejemplo, es precisamente el uso combinado de varios "trucos", los cuales se irán explicando en el curso de estos textos y cuya base principal es: "Mantener" el archivo grabado (en la unidad de almacenamiento) SIEMPRE OCULTO Y CON CONTRASEÑA, para lo cual es imprescindible contar con el apoyo de los eventos de la aplicación para "detectar" algunas acciones del usuario y "actuar en consecuencia". ANALIZANDO LOS "INCONVENIENTES" (Y SOLUCIONES) DE USAR MACROS:> Dado que el usuario tiene la opción de decidir si un archivo se abre o no "con permiso" de usar macros ó puede inclusive "mantener inoperables" los eventos (esto NO lo puedes evitar), las primeras acciones "preventivas" serán: 1. Si se ha de abrir sin permiso de usar macros (por elección o alto nivel de protección) ó los eventos son "inoperables" (en ese momento), hemos de asegurarnos que el archivo "se mantiene" OCULTO y con "password" (en la unidad de almacenamiento). 2. Si las macros y los eventos "están en operación" (y se va a "permitir" su uso), hemos de EVITAR que pueda grabarse el archivo (a la unidad de almacenamiento) de la manera "convencional", ya que podría "volverse visible" y quedar completamente "desprotegido" para la siguiente vez que se abra (lo haremos por código mediante un procedimiento "especial"). 3. Hemos también de prevenir (y corregir en su caso) que durante el curso de la sesión los eventos sean "des-habilitados". Estas acciones nos permiten darle al usuario "permiso de usar" el archivo "prácticamente" sin restricciones y "tomar" el control de lo que podrá o no "hacer" con él (y en él). Algunas opciones que el usuario puede usar para "impedir" el uso de macros son: o "Tener" un nivel alto de protección "contra" archivos con macros. o "Elegir" NO ejecutar las macros del archivo (si el nivel es medio ó bajo). o "Mantener presionada" la tecla {Mayús} (al abrir el archivo y "permitir" las macros).
  • 21. En cualquiera de estos casos, las macros NO se ejecutan o "se omiten" las de apertura. Otra "forma" que podría emplearse es: abrir el archivo mediante macros (en otro archivo) usando previamente la instrucción Application.EnableEvents = False "Contra" estas (y otras) opciones, nuestra primer acción preventiva prevalecerá: el archivo (desde la unidad de almacenamiento) "permanece" OCULTO Y CON CONTRASEÑA. Ahora bien, cuando las macros "son permitidas" y los eventos "están operables", podemos verificar que "se cumplan" ciertas condiciones para permitir o no el uso de nuestro archivo. Tales condiciones pueden ser -entre otras- A. Que el archivo está ubicado en algún directorio específico -o uno "alterno"- B. El nombre del usuario C. Si existe algún archivo en ese u otro directorio D. La fecha del sistema E. El nombre mismo del archivo F. Etc., etc., etc. Podrás encontrar otras que "acomoden" mejor a tus necesidades. En caso de que las condiciones ("mínimas necesarias") estén cumplidas, se dará acceso al archivo, en caso contrario, se tomarán otras acciones (como permitirle "verlo sin usarlo" ó definitivamente cerrar el libro -entre otras-). Si se permite el acceso al libro (total ó "restringido") para evitar que lo grabe de la manera "tradicional" (segunda acción preventiva), "forzamos" a la aplicación para que los métodos "convencionales" de grabado "no funcionen" y le proveemos de un "comando especial" que se encargará de que el archivo se grabe (a la unidad de almacenamiento) SIEMPRE OCULTO Y CON CONTRASEÑA. Es por esto es que "nos tenemos que asegurar" de que los eventos estén "siempre operables" (tercera acción preventiva). ALGUNOS "TRUCOS" (COMBINABLES) POR CÓDIGO: Para continuar con la exposición de los ejemplos, "se dará por entendido" que se tiene al menos un conocimiento "esencialmente básico" en cuanto al uso del lenguaje Visual Basic para Aplicaciones (VBA) -la plataforma en la que "trabajaremos"-, así como de los objetos, propiedades, métodos, eventos, instrucciones y "otros". Para verificar que el archivo se encuentre ubicado en un directorio específico, usamos la propiedad Path de un objeto Workbook, que "devuelve" una cadena de texto indicando la ruta (unidad y directorio): If ThisWorkbook.Path = "C:Mis documentosOtro directorio" Then Para verificar el nombre del usuario, usaremos la propiedad UserName del objeto Application ("forzada" a minúsculas -ó mayúsculas-), que "devuelve" una cadena de texto con el nombre "registrado": If StrConv(Application.UserName, vbLowerCase) = "fulanito de tal" Then Para verificar si existe algún archivo en ese u otro directorio, existe el método Dir("Ruta_ Archivo"), que "devuelve" una cadena de texto con el nombre del archivo ó una cadena vacía ("") si no existe: If Dir("Unidad:Ruta1Ruta2NombreArchivo.ext") <> "" Then Para comparar dos fechas, primero "tendremos" que identificar el orden de los elementos con la propiedad International(xlDateOrder) del objeto Application, que "devuelve" un tipo de datos Long (0 = mes-día-año; 1 = día-mes-año; 2 = año-mes-día), de lo contrario, un dato de fecha podría "significar" FECHAS DISTINTAS (en sistemas "diferentes"). P.e.: La fecha "25 de Mayo de 2002" de un sistema "de origen" del orden 1 (día-mes-año) si se quiere comparar en un sistema "de destino" del orden 0 (mes-día-año) "indicando" la fecha como "25/5/02" significará "Mayo 2 de 2025". Una estructuración "confiable" sería: Dim Fecha_x As Date Select Case Application.International(xlDateOrder) Case 0: Fecha_x = DateValue("5/25/02")
  • 22. Case 1: Fecha_x = DateValue("25/5/02") Case 2: Fecha_x = DateValue("02/5/25") End Select If Now <= Fecha_x Then PRIMER PUNTO: TERCERA ACCIÓN "PREVENTIVA". Una vez que "obtuvimos permiso" de usar las macros y estando los eventos "operables", puesto que uno de ellos "detecta" la intención del usuario de grabar el archivo "de manera convencional", aseguramos que los eventos "permanezcan operables", utilizando para ello el método OnTime del objeto Application, haciendo una llamada "recursiva" al mismo método una y otra vez (por el tiempo que dure la sesión) para "monitorear" los eventos. PRECAUCIÓN !!! - La ejecución del método OnTime de manera recurrente y programada, NO ES CANCELADA "automáticamente" por la aplicación. Si el libro que la ejecuta es cerrado SIN CANCELAR LA SIGUIENTE "LLAMADA", Excel volverá a abrir el libro y continuará su ejecución. ¡ ES NECESARIO CANCELAR AL SALIR !!!. Para lograr el efecto de "re-llamado" al método, usaremos las variables Públicas: 'Para el "siguiente monitoreo" de los eventos Public MonitorEventos As Double 'Para monitorear los eventos cada 20 segundos (p.e.) Public Const IntervaloMonitor As String = "0:00:20" 'Es el nombre de la macro que mantiene activos los eventos Public Const MacroEventos = "MantenerEventos" En los siguientes procedimientos: 'Macro de "prevención" contra "suspensión" de eventos Public Sub MantenerEventos() 'Mantiene siempre Activos los eventos Application.EnableEvents = True '(Re)-Inicia un bucle de "Activación" cada "X" tiempo ComenzarLoopDeEventos 'Fin del procedimiento End Sub 'Macro de monitoreo "permanente" de Eventos Public Sub ComenzarLoopDeEventos() 'Se determina el "siguiente monitoreo" de los eventos MonitorEventos = Now + TimeValue(IntervaloMonitor) 'Una vez "llegado" el tiempo, "lanza" nuevamente el método OnTime haciendo referencia 'a la variable pública constante "MacroEventos" (macro "MantenerEventos") especificando 'que el siguiente "loop" se ejecute (Schedule:=True) Application.OnTime _ EarliestTime:=MonitorEventos, _ Procedure:=MacroEventos, _ Schedule:=True 'Fin del procedimiento End Sub 'Macro para "cancelar" el siguiente método OnTime 'Este procedimiento se llamará "al cierre" del libro. Public Sub DetenerLoopDeEventos()
  • 23. 'Necesariamente es igual al procedimiento de re-llamada, con excepción de que '"la siguiente vez" que el método debiera ejecutarse se especifica como Falso. MonitorEventos = Now + TimeValue(IntervaloMonitor) Application.OnTime _ EarliestTime:=MonitorEventos, _ Procedure:=MacroEventos, _ Schedule:=False End Sub Una vez definidos los procedimientos, los "llamamos" en alguna macro de evento como Auto_Open (ó Auto_Close) o los procedimientos de evento del objeto Workbook. 'Para iniciar (y mantener) el método: Private Sub Workbook_Open() MantenerEventos End Sub 'Para detener (y cancelar) el método: Private Sub Workbook_BeforeClose(Cancel As Boolean) DetenerLoopDeEventos End Sub SEGUNDO PUNTO: SEGUNDA ACCIÓN "PREVENTIVA". Ahora que los eventos "permanecerán" activos, vamos a "impedir" que el archivo se grabe (a la unidad de almacenamiento) de la manera "convencional" (ya sabemos que de esta manera podría "volverse visible" y quedar completamente "desprotegido" para la siguiente vez que se abra). Para esto será necesario declarar una variable pública del tipo Boolean (Verdadero ó Falso) como: PermisoParaGrabar, que será la que "impida" (ó "permita") que el archivo sea grabado y usaremos el evento Before_Save del objeto ThisWorkbook con una línea como: If Not PermisoParaGrabar = True Then Cancel = True Así le estamos "indicando" a Excel que siempre y cada vez que el usuario "pretenda" grabar el archivo, "NO se lo permita". La variable será usada como "candado" en el código de nuestro "comando especial" para "abrir" el permiso, grabar (de manera "correcta") y "cerrar" nuevamente el candado. TERCER PUNTO: PRIMER ACCIÓN "PREVENTIVA". Con los eventos activos y los comandos convencionales de grabación "fuera del alcance" del usuario, procederemos a "instruir" a Excel para que, a través de un comando especial nos asegure que el archivo SIEMPRE "permanecerá" OCULTO Y CON CONTRASEÑA. 'Macro para guardar los cambios (sólo por código) Public Sub GuardarEspecial() 'Congelamos la actualización de la pantalla Application.ScreenUpdating = False 'La variable que "permite" o "impide" grabar el archivo PermisoParaGrabar = True 'Ocultamos la ventana del libro protegido Windows(ThisWorkbook.Name).Visible = False 'Protegemos el libro con Contraseña '(inclusive su estructura y "arreglo" de ventanas) ThisWorkbook.Protect Password:="X_Contraseña", _ Structure:=True, Windows:=True 'Grabamos el libro (a la unidad de almacenamiento)
  • 24. ThisWorkbook.Save '"Cancelamos el permiso" que da la variable PermisoParaGrabar = False 'Fin del procedimiento. End Sub Una macro como la anterior hará "un excelente trabajo", sólo faltaría "detectar" si el libro "continúa en operación" (para volverlo a "presentar" al usuario ó cerrarlo si fuera el caso). El siguiente paso es: "Agregar" el comando a algún menú (o submenú), "aprovechando" el evento Open del objeto ThisWorkboook, agregando la siguiente línea: AgregarComando., que "hace referencia" a la siguiente macro: 'Macro para agregar el Comando "Especial" Public Sub AgregarComando() 'Se agrega un comando TEMPORAL en la posición # 8 del menú de "Archivo" y ... Set MiComando = CommandBars("File").Controls.Add _ (Type:=msoControlButton, Before:=8, Temporary:=True) With MiComando .BeginGroup = True .Style = msoButtonCaption .Caption = "Guardar &especial" .FaceId = 1 'Lo mandamos ejecutar la macro de "GuardarEspecial" .OnAction = "GuardarEspecial" End With 'Fin del procedimiento End Sub Finalmente (y sólo "por si las dudas"), al salir del libro eliminaremos este comando usando el evento Before_Close del objeto ThisWorkbook con la siguiente instrucción: If Application.CommandBars("File").Controls(8).Caption = "Guardar &especial" _ Then Application.CommandBars("File").Controls("Guardar &especial").Delete (True) NOMBRE Y POSICIÓN DE LOS OBJETOS. Generalmente se usan las propiedades Name ó Index (posición) para "referirnos" por código a las hojas de un libro, p.e. Worksheets("Resumen") Worksheets(3) Si el usuario "modifica" estas propiedades (cambiando nombre o posición), el código fallará lanzando "el temido" mensaje de: "Subíndice fuera del intervalo", ó estaremos "afectando" a la hoja que "quedó" en la posición #3 y "creíamos" que era... "la que estaba antes???". Para efectos "prácticos", es mejor el uso de la propiedad "Name", inclusive puedes "regresar" la hoja a su nombre "original" en algún evento (como Worksheet_Deactivate) con una línea como la siguiente: If Hoja3.Name <> "Resumen" Then Hoja3.Name = "Resumen" Habrás notado que se utiliza Hoja3.Name. Hoja3 es el nombre-código (propiedad CodeName) que cada objeto tiene en el proyecto de VBA (en este caso "verías" en la ventana de exploración del proyecto, un objeto Worksheet como - Hoja3 (Resumen) y en la ventana de propiedades, las propiedades: (Name) = Hoja3 y Name = Resumen. Pues bien, la propiedad CodeName es aún más "conveniente" que la "simple" propiedad "Name" para el caso de "asegurarnos" que no afecte al código si el usuario cambia las propiedades "Name" e "Index" de los objetos sobre los que necesitamos un "control total".
  • 25. PROTECCIONES "ADICIONALES" PARA "CELDAS ESPECIALES". Si ya has usado Herramientas | Proteger | Proteger hoja... y/o Proteger libro..., te habrás dado cuenta de que "se debe quitar" la protección cuando necesitas hacer modificaciones por código a las hojas "protegidas" por este comando. Otra manera de "evitar" que el usuario modifique "celdas importantes" es (aprovechando nuevamente los eventos y código), "detectar" si el usuario selecciona alguna de esas celdas y "pedirle una clave" (para "permitirle estar ahí" ó "remitirlo" a otra celda). El siguiente código en el evento SelectionChange de un objeto Worksheet le pedirá esa clave al usuario si selecciona alguna de las celdas que se indiquen como "especiales": Private Sub Worksheet_SelectionChange(ByVal Target As Range) Dim Permiso As String Select Case Target.Address 'Si el usuario selecciona "B6" ó "B18"... Case Range("B6").Address, Range("B18").Address 'Se le "pide" una clave. Permiso = InputBox("¿Cuál es tu clave?") 'Si la clave es "incorrecta" lo "mandamos" arriba. '(Podrías "avisarle" que... ¡ NO es la clave K !!!) If Permiso <> "Hocus Pocus" Then Target.Offset(-1, 0).Select End Select End Sub IMPEDIR QUE EL USUARIO UTILICE "ALGUNOS" COMANDOS. Habrá ocasiones en las cuales "quisieras" que el usuario no pueda "copiar | cortar | pegar" datos "de" ni "a" ciertas celdas, hojas o libros. 1. - Una manera sería "inhabilitar" el modo "Cortar/Copiar" de la aplicación ("imperceptible" para el usuario), usando algún evento (SelectionChange, Activate, Deactivate) de los objetos Worksheet ó Workbook con la siguiente línea: 2. Application.CutCopyMode = False para "simular" el efecto de presionar {Esc} ("al momento de" copiar ó cortar) "cancelando" de la memoria el contenido del "porta-papeles". 3. - Otra manera sería "inhabilitar" los "atajos de teclado" como {Ctrl}+C, {Ctrl}+X, {Ctrl}+V utilizando para ello el método OnKey del objeto Application en cualquiera (o varios) de los eventos mencionados en el párrafo anterior. La sintaxis del método es: Application.OnKey "Tecla", "Procedimiento" Donde: argumento Tecla es la tecla (o combinación de teclas) que al ser presionada(s) "ejecutará(n)" la macro especificada por el argumento Procedimiento. Si se omite el procedimiento, la(s) tecla(s) "vuelve(n)" a su acción natural. Por ejemplo, para impedir que se usen esas combinaciones de teclado en una hoja en específico, los siguientes códigos "trabajan" bien: 'Cuando el usuario "activa" la hoja (con el código)... Private Sub Worksheet_Activate() 'Los "atajos de teclado" {Ctrl}+C, {Ctrl}+X, {Ctrl}+V
  • 26. 'para "copiar", "cortar" y "pegar" quedan "inhabilitados" 'puesto que se especifica un argumento "vacío" para "la macro". Application.OnKey "^c", "" Application.OnKey "^x", "" Application.OnKey "^v", "" End Sub 'Cuando el usuario "des-activa" la hoja (con el código)... Private Sub Worksheet_Deactivate() 'Los "atajos de teclado" {Ctrl}+C, {Ctrl}+X, {Ctrl}+V 'para "copiar", "cortar" y "pegar" quedan "re-habilitados" Application.OnKey "^c" Application.OnKey "^x" Application.OnKey "^v" End Sub Nota: El método OnKey (usado de la manera anterior) NO IMPIDE el uso de los comandos (por menús o botones) para efectuar las mismas acciones de "copiar", "cortar" y "pegar". Si quieres "impedir" que se usen "también" comandos "integrados" de Excel, entonces... OPCIONES "AVANZADAS" PARA TRABAJAR CON MENÚS Y COMANDOS "Asegurar" un control de los comandos (sean barras de menús y/o herramientas) implica "averiguar" que tanto se han personalizado en el "entorno" de cada usuario. Considerando que los menús pueden contener submenús y éstos a su vez más submenús se debe desarrollar una macro que pueda "ir descendiendo" a todos los niveles de todos los elementos existentes. Una vez "detectados" los comandos "objetivo", una propiedad (Enabled o Visible) habrá de permitir (o no) su uso. Utilizaremos las siguientes variables Públicas: 'Declaramos las variables del tipo "necesario"... Public Barra As CommandBar, _ Comando As CommandBarControl, _ Contenedor As CommandBarControl, _ Siguiente As Integer En los siguientes procedimientos | funciones: 'Macro para "Des-Habilitar" comandos Private Sub DesHabilitarComandos() 'Por si existiera algún error On Error Resume Next 'Para buscar en TODAS las barras (Herramientas ó Menús) For Each Barra In Application.CommandBars 'Para buscar en TODOS los controles (Comandos ó Submenús) For Each Comando In Barra.Controls 'Inicia un "bucle" de búsqueda (a través de una función "recursiva") Siguiente = AtenuarProhibidos(Comando) '"Busca" en el siguiente botón Next Comando '"Busca" en la siguiente Barra de Comandos Next Barra 'Fin del procedimiento End Sub 'Función "recursiva" para "bajar" por los menús Private Function AtenuarProhibidos(Comando As CommandBarControl) As Integer
  • 27. 'Por si existiera algún error On Error Resume Next '"Inicializa" la variable del bucle Siguiente = 0 'Para "afectar" sólo a Comandos ó Menús Select Case Comando.Type Case 1, 2, 4, 6, 7, 13, 18 'Si es un botón de comando... Select Case Comando.ID '"Ver" cuál es Case 19, 21, 22 'Si es "copiar", "cortar" ó "pegar" Comando.Enabled = False 'Lo "DES-HABILITA" End Select Case Else 'Si es un Menú (ó Submenú) '... seguir buscando "más abajo" For Each Contenedor In Comando.Controls '... haciendo una "Re-Llamada" de la función Siguiente = Siguiente + AtenuarProhibidos(Contenedor) Next Contenedor '(continuar con el "bucle") Siguiente = Siguiente - 1 '(regresar al bucle en el mismo control) End Select 'y ... 'continuar "la llamada" a la función con "el siguiente" AtenuarProhibidos = Siguiente + 1 'Fin de la función End Function Aunque es posible que este procedimiento sea "auto-alternante" (podría cambiarse en la función la sentencia: Comando.Enabled = False por una que "auto-invierta" el estado del botón +/- así: If Comando.Enabled = True Then Comando.Enabled = False Else Comando.Enabled = True para un control "más estable" es mejor "definir" procedimientos "separados" (uno para inhabilitar y otro para re- habilitar los botones de comando). Dejo a tu criterio "la contra-parte". Complementariamente (y para NO "perjudicar" la interacción con el usuario) puedes usar los eventos WindowActivate y WindowDeactivate del objeto ThisWorkbook para que, los comandos queden inhabilitados "solamente" cuando la ventana "activa" sea "el libro". Private Sub Workbook_WindowActivate(ByVal Wn As Window) DesHabilitarComandos End Sub Private Sub Workbook_WindowDeactivate(ByVal Wn As Window) ReHabilitarComandos End Sub Puedes incluir además en los procedimientos, las opciones del usuario para "personalizar" las barras de menús y herramientas para que "sufran" el mismo efecto que lo botones. De esta manera, podrá agregar más barras (con los botones y menús que "no funcionan") siempre y cuando la ventana "activa" sea "otro libro", pero... al "regresar" a nuestro libro... ¡dejarán de "funcionar" también!!! Para mayor información acerca de las "ID's" (ó nombres) de otros comandos y menús que pudieras considerar como "necesarios" de inhabilitar para protección de tu trabajo, visita la página: http://support.microsoft.com/support/kb/articles/Q213/5/52.ASP Otra acción "conveniente" de controlar es el uso del comando "especial" de guardar, para lo cual puedes aprovechar los mismos eventos WindowActivate para "permitir su uso sólo en el libro" con la línea: Application.CommandBars("File").Controls("Guardar &especial").Visible = True y el evento WindowDeactivate para "inhabilitar" su uso "fuera del libro" con otra línea "inversa" como: Application.CommandBars("File").Controls("Guardar &especial").Visible = False Bueno... dejemos de momento tanta "palabrería", y pasemos a un...
  • 28. CASO "PRÁCTICO" DE LA COMBINACIÓN DE ALGUNOS TRUCOS El archivo "descargable" (al final de este artículo) contiene algunos ejemplos de cómo proteger (por código) los libros de Excel. Te explico "brevemente" como funciona y cuales son las condiciones, contraseñas y "opciones" consideradas. 1. Condiciones A. Con las macros "habilitadas" y los eventos "operables", el libro se abrirá "sin problemas" si se cumple cualquiera de las dos primeras condiciones siguientes: I. Que el directorio donde se encuentra sea: "C:Mis documentos" o... II. Que el directorio "alterno" sea: "D:Personales..." (el que yo utilicé). (Obviamente puedes definir tus propias condiciones como se explicó antes.) III. O, si se abre desde otro directorio, avisará que las condiciones de operación no se cumplen y sugerirá "No Continuar" (aunque da la opción de "seguir adelante", se abrirá en modo de "sólo lectura", y... NO "se puede" guardar). B. Si las macros NO están "habilitadas" (por elección o nivel alto de protección), o se "abre por código" pero los eventos NO están "operables" (Open, Change, etc.), el libro se abrirá, pero estará OCULTO y con Contraseña. Una vez abierto el libro "sin problemas", solo puede grabarse a través del comando que se agrega automáticamente ("Guardar especial" en el menú "Archivo"), de esta manera (aún cuando la PC "-???-...¡se apagó!!!") siempre queda "bien" guardado.
  • 29. 2. Contraseñas (Recuerda lo de mayúsculas, minúsculas, acentos y/o signos) A. Para el libro y la hoja "Protegida", la contraseña es: «Contraseña (el signo « es la combinación de teclas {Alt}+174). B. Para el proyecto de macros (VBA) es: «Contrase«Ñ«a (mismo signo). C. En la hoja "Protegida", algunas de las celdas "libres" requieren de un "Permiso especial" (con un formulario). La clave: Abrete Sésamo D. Existe una hoja oculta en el libro (podrías manejar ahí datos "Ultra-Secretos") que SOLO puede mostrarse mediante una imagen (con macro) en la hoja "Normal" y también requiere de un "Permiso especial". La clave: Abracadabra.
  • 30. 3. Como protección adicional, todos los códigos son Privados (no se pueden ver en la "lista de macros" menú Herramientas | Macro | Macros ó teclas {Alt}+{F8}. El método OnTime "monitorea" que los Eventos "permanezcan activos", por si a algún "vivillo" se le ocurriera des-habilitarlos para "ver como funciona". Puedes eliminar éste método si te resulta "engorroso" ver un ligero parpadeo del cursor cada 20 segundos (ó el tiempo que determines) ó si lo consideras no necesario. Sólo "asegúrate" de hacerlo "correctamente". 4. La estructura de códigos es "modulada" (y en orden de aparición) para que se puedan usar "interactivamente" y son "funcionales" (si los ejecutas desde la ventana del VBE). Cada línea está "comentada" para que sea entendible y clara su intención. Espero que no tengas problemas para entenderlo. 5. Nota 1.- Cuando la ventana activa es este libro, TODOS los comandos "peligrosos" se des-habilitan (se restablecen cuando el libro deja de ser la ventana activa). Nota 2.- Si creas nuevas barras con comandos "prohibidos" (o los agregas a las ya existentes), de cualquier forma al activar de nuevo la ventana del libro se des-habilitarán. 6. La lista que consideré como comandos "peligrosos" es la siguiente (puede modificarse a tu criterio): En el menú (o Sub-menú) Estos comandos SE INHIBEN DE TODAS LAS BARRAS "Edición"... Eliminar hoja; Copiar o mover hoja "Edición"... "Eliminar"... Eliminar (celdas); Eliminar filas; Eliminar columnas "Formato"... Formato de celdas (por la pestaña de "protección") "Formato"... "Hoja"... Cambiar nombre; Ocultar; Mostrar "Herramientas"... Ver Nota 2 Personalizar (por si creas barras con "más prohibidos") "Herramientas"... "Proteger"... Proteger hoja; Proteger libro; Proteger y compartir "Datos"... Ordenar; Validación "Ventana"... Ocultar; Mostrar La lista de barras "Toolbar List" (por aquello del comando "Personalizar") 7. Visita la página de Microsoft indicada anteriormente para ver una lista de otros comandos que pudieras considerar como "peligrosos". 8. Saludos cordiales, y espero "haber sido de utilidad" para tus propósitos. 9. Héctor Miguel Orozco Díaz. hemiordi@hotmail.com 10. 11. Descargar el archivo Proteger.zip que contiene el archivo Proteger.xls con todo el código mostrado en este artículo. 12. 13. Nota de Mauricio: Les agradeceria mucho a mis visitantes y como agradecimiento por el gran trabajo de Héctor, le notificaran a su correo, de cualquier error, duda, mejora, observación o comentario en relación con el presente artículo, GRACIAS Héctor... Variables y objetos, ¿como nombrarlos? • Supongamos una sencilla macro como la siguiente • Option Explicit • • Public Sub Preguntas() • Dim Nombre As String • Dim Edad As Integer • • Nombre = InputBox("¿Cuál es tu nombre?") • Edad = InputBox("¿Cuantos años tienes?") • • MsgBox "Hola " & Nombre & " tienes " & Edad & " años" • • End Sub • Public Sub Preguntas1() • Dim Coche As String • Dim Sol As Integer
  • 31. • Coche = InputBox("¿Cuál es tu nombre?") • Sol = InputBox("¿Cuantos años tienes?") • • MsgBox "Hola " & Coche & " tienes " & Sol & " años" • • End Sub • • Descargar el código de este artículo. Grabando mi primer macro en Excel Te sugiero que primero realices los pasos que menciono aquí y después, con toda libertad y confianza haz todas las pruebas que consideres pertinentes o Entra a Excel o Ve al menú Herramientas | Macro | Grabar nueva macro... o Te saldrá el siguiente cuadro de dialogo... Los datos que hay que introducir son: Nombre de la macro Con este nombre identificaremos a la macro, con este la podemos "ejecutar" y "llamar" desde otras macros, por default te saldrá Macro1 la primera vez y, si no cambias este nombre, a las sucesivas macros las ira nombrando Macro2, Macro3, Macro'n, etc, propongo que se llame Mi_Primer_Macro , las recomendaciones son: usa un nombre corto, pero suficientemente claro en relación con la tarea o tareas que hará la macro, NO uses espacios, por ejemplo, si tienes una macro que realiza un reporte, podrías llamarla: 1. hacerreporte 2. HACERREPORTE 3. hacer_reporte 4. HACER_REPORTE
  • 32. 5. Hacer_Reporte 6. HacerReporte Comúnmente, y lo veraz en estas páginas, uso la opción 5 o 6 pues me parecen mas claras de leer, pero no te detengas en hacer uso de tu libre derecho de usar el que te de la gana. Método abreviado Si sabes para que nos sirve Ctrl + C o Alt + F4 , entonces ya sabes para que es esta opción, así es, bien pensado, sirve para relacionar una combinación de teclas con la macro que estamos grabando y ejecutarla con solo presionar estas teclas, en lo personal no lo uso, pues ya tengo bastante con las decenas de métodos abreviados que tiene Windows, prefiero "asignarlas" a un botón o un menú (te enseñare a hacer esto), pero estas en todo tu derecho de usarla si así lo deseas. Guardar macro en Toda la información ocupa un lugar, verdad?, pues las macros son información y ocupan lugar y hay que guardarlas en algún lado, este lado, son los archivos de Excel, es decir, "dentro" del archivo, se guardan las instrucciones en un lugar especial que se llama modulo , que aprenderemos a dominar, si observas la imagen, tenemos un Cuadro de lista desplegable o ComboBox (así se llama este "objeto") que tiene tres opciones: Libro de macros personal, Libro nuevo y Este libro, como veras, los tres son libros o sea, archivos de Excel, las macros de Excel solo pueden estar dentro de archivos de Excel. Para nuestro ejemplo escogeremos Este libro. Descripción Creo que el nombre es bastante "descriptivo", aquí puedes poner toda la información que consideres conveniente acerca de tu macro, su función más útil, es comentar brevemente cual es el propósito de nuestra macro, algunos ponen la fecha y el nombre del autor. o Damos un clic en el Botón de Comando (CommandButton) ACEPTAR , a partir de este momento, casi cualquier acción, lo repito, casi cualquier acción que realices sobre la ventana de Excel, se grabará en nuestra macro, por eso las recomendaciones antes de grabar una macro son: 1. Planea lo que hara tu macro, las correcciones que hagas, también se grabaran. 2. Casi nunca una macro queda a la primera, no importa que repitas de nuevo los pasos, pero hazla bien, cuando aprendas a editarlas, veremos como quitar lo que no sirve. 3. Procura no grabar demasiadas instrucciones, es mejor grabar pequeñas macros y después llamarlas desde otras o entre si, esto, ya veremos como se hace. o Realiza los siguientes pasos tal cual... R Selecciona la celda A1 S Escribe "Esta es mi primer macro" (o lo que gustes). E Presiona Enter, si tu selección se movió abajo (normalmente), entonces vuelve a seleccionar la celda A1 c Dale formato de Negritas , Cursiva , cambia el tamaño de la fuente, el estilo de la fuente y por ultimo el color de la fuente d Al final se tiene que ver algo muy parecido a esto:
  • 33. o ο Da un clic en el botón Detener grabación , este botón (que aparece en la imagen de arriba) se encuentra dentro de la barra de herramientas Detener Grabación, esta barra se visualiza (o deberia de aparecer) en cuanto empiezas a grabar una macro, si no la vez, ve al menú Ver | Barra de Herramientas y activa la barra Detener Grabación o si lo prefieres, en el menú Herramientas | Macro veraz, en vez de Grabar Macro , la opción Detener Grabación , esto solo cuando tienes activada la grabadora de macros. ο Ahora, probemos la macro, borra o mejor, elimina la celda donde escribiste el texto Esta es mi primer macro, en nuestro ejemplo, se trata de la celda A1. ο Ve al menú Herramientas | Macro | Macros... o presiona el método abreviado de teclado Alt + F8 , por cualquiera de estos dos métodos, te saldrá el siguiente cuadro de dialogo. La imagen lo dice todo, tendras una lista de las macros que esten disponibles en los libros (archivos de Excel) abiertos, es decir, para que puedas ejecutar una macro, el libro que la contiene debe estar
  • 34. abierto. Este cuadro de dialogo tiene más opciones que el anterior, así que las que no se vean aquí, te dejo de "tareita" investigues para que sirven. ο Selecciona la macro que acabamos de grabar, si no le cambiaste el nombre debe decir Macro1 , si usaste el propuesto será Mi_Primer_Macro o en su defecto el que hayas escogido, si tienes más libros abiertos que tengan macros, aquí las veraz (no todas, ya te explicare por que), da un clic en el Boton de Comando (CommandButton) EJECUTAR . ο ¿Que pasó?, se ve bonito no?, ahora, con un solo paso, hacemos varias instrucciones de Excel, si fue así?, bien, ahora ya tenemos el 0.01 % de lo necesario para dominar las macros y no te estoy desanimando, al contrario, pretendo, con estas páginas, subir un poco mi 5% de dominio y también pretendo, que lo hagamos juntos, si estas de acuerdo sigue leyendo y sino también sigue leyendo. ο Este es un buen momento para guardar tu archivo, propongo que se llame Mis macros , pero, como antes, puedes usar el nombre que gustes ¿como podría impedírtelo?. ο Ahora van las preguntas, lo siento pero te tendrás que acostumbrar a ellas, aun cuando veas que trato a detalle los temas, no es así, por que el tema es bastante extenso y muchas cosas las tendrás que buscar, descubrir y mejor aun, razonar por tu cuenta. l ¿ Todo salió bien ? ¿ ¿ Que pasa si ahora pongo el cursor, o sea la selección en otra celda, por ejemplo la C15 y ejecuto la macro? e Prueba a grabar otra macro, pero activa el botón que aparece al lado del Detener grabación y que se llama Referencia relativa y haz la prueba anterior, ¿que pasa ahora? q Si cambias de hoja en el libro ¿puedes ejecutar la macro? S Y si cambias de libro ¿aun la puedes ejecutar? Y Prueba a grabar una macro que cambie a otras ventanas fuera de Excel o abra otros programas ¿es posible? p Graba una macro un poco mas larga y ejecútala ¿que observas?, ¿como se ve la pantalla cuando se esta ejecutando? ο Tal vez pienses que son muchas preguntas para la primera vez, ya veraz que solito te saldrán mas, ahora mismo yo tengo más preguntas que respuestas, pero no importa, sigue siendo muy divertido crear y grabar macros. Cuando tengas contestadas las preguntas anteriores y cuando hagas las "tareitas" que propongo, entonces, pasamos al siguiente punto. ο Esto es más interesante, veamos las instrucciones que graba Excel a estas instrucciones se le conoce como código fuente , para esto ve la menú Herramientas | Macro | Macros... o presiona el método abreviado de teclado Alt + F8 y ya sabes que sale ¿verdad?, si, el cuadro de dialogo Macro , de nuevo, selecciona la primer macro que grabaste y que ejecutaste, pero ahora, en vez de ejecutarla, presiona el Botón de Comando (CommandButton) MODIFICAR . Esta acción abrirá una nueva ventana (la notaras en la barra de tareas de Windows) y nos llevara a una ventana que tal vez nunca has visto, esta ventana se llama Microsoft Visual Basic y es una nueva aplicación, un programa, correctamente es un Editor, un Editor del lenguaje Visual Basic para crear nuestras macros, también puedes abrir esta ventana desde el menú Herramientas | Macro | Editor de Visual Basic o presiona el método abreviado de teclado Alt + F11 , este Editor tienes que dominarlo si quieres obtener más provecho de tus macros, más adelante veremos las partes principales de este Editor, por lo pronto y si grabaste la macro de ejemplo, veraz algo muy similar a la siguiente imagen.
  • 35. Las ventanitas que están a la derecha de la imagen, tal vez las tengas a la izquierda en tu ventana, pero no importa, estas ventanas las puedes mover como la mayoría de las ventanas de Windows (desde la barra de titulo) y posicionar donde gustes, te recomiendo dejarlas como en la imagen de arriba, para que nos entendamos mejor. ο Te pongo el código aquí por si en la imagen no se ve bien, además de que le faltan unas líneas abajo. ο Sub Mi_Primer_Macro() ο ' ο ' Macro1 Macro ο ' Macro grabada el 09/01/2002 por Tecnico1 ο ' ο Range("A1").Select ο ActiveCell.FormulaR1C1 = "Esta es mi primer macro" ο Range("A1").Select ο Selection.Font.Bold = True ο Selection.Font.Italic = True ο With Selection.Font ο .Name = "Arial" ο .Size = 20
  • 36. ο .Strikethrough = False ο .Superscript = False ο .Subscript = False ο .OutlineFont = False ο .Shadow = False ο .Underline = xlUnderlineStyleNone ο .ColorIndex = xlAutomatic ο End With ο With Selection.Font ο .Name = "Comic Sans MS" ο .Size = 20 ο .Strikethrough = False ο .Superscript = False ο .Subscript = False ο .OutlineFont = False ο .Shadow = False ο .Underline = xlUnderlineStyleNone ο .ColorIndex = xlAutomatic ο End With ο Selection.Font.ColorIndex = 5 ο End Sub Ya la viste bien, ¿verdad que hay líneas repetidas?, ¿porque crees que sea esto?, observa muy bien los colores, nos dicen mucho, pero lo primero que te enseñare de los colores es que las líneas que están en verde no se "ejecutan" , esto quiere decir, que el VBA se las salta olímpicamente, las ignora completamente, esas líneas verdes se llama comentarios y sirven para documentar nuestras macros para poner notas acerca del propósito o funcionamiento del código, algo muy importante, pues después de algunos cientos de líneas, ya ni sabes donde vas o para que servía determinada línea, por ejemplo, observa la primer línea después de la ultima verde, si quisiéramos comentarla, o sea, establecerla de modo que no se "ejecute", tenemos dos formas, agregando una comilla simple a la izquierda de la línea o escribiendo, también a la izquierda la palabra REM, me parece más fácil la comilla ¿no crees?. Sub Mi_Primer_Macro() ' ' Macro1 Macro ' Macro grabada el 09/01/2002 por Tecnico1 ' Range("A1").Select 'Range("A1").Select Rem Range("A1").Select Ahora que sabes como se comentan las líneas para que el VBA no las ejecute, te recomiendo que cuando estés probando código, no lo borres, mejor solo comenta la línea, pues algunas veces pasa que regresamos a la línea original y si la borramos en ocasiones ya no sabemos como iba, así que te pregunto, ¿que líneas de este código fuente, se podrían comentar, de modo que no se ejecuten, pero que la macro siga haciendo lo mismo?... muy bien, podría quedar así... Sub Mi_Primer_Macro() ' Macro grabada el 09/01/2002 por Tecnico1 ' Range("A1").Select ActiveCell.FormulaR1C1 = "Esta es mi primer macro" Range("A1").Select Selection.Font.Bold = True Selection.Font.Italic = True 'With Selection.Font
  • 37. ' .Name = "Arial" ' .Size = 20 ' .Strikethrough = False ' .Superscript = False ' .Subscript = False ' .OutlineFont = False ' .Shadow = False ' .Underline = xlUnderlineStyleNone ' .ColorIndex = xlAutomatic 'End With With Selection.Font .Name = "Comic Sans MS" .Size = 20 .Strikethrough = False .Superscript = False .Subscript = False .OutlineFont = False .Shadow = False .Underline = xlUnderlineStyleNone .ColorIndex = xlAutomatic End With Selection.Font.ColorIndex = 5 End Sub Pero todavía se puede mejorar más, prueba a comentar las líneas que terminen en la palabra False para que nuestro código quede así: Sub Mi_Primer_Macro() ' Macro grabada el 09/01/2002 por Tecnico1 ' Range("A1").Select ActiveCell.FormulaR1C1 = "Esta es mi primer macro" Range("A1").Select Selection.Font.Bold = True Selection.Font.Italic = True 'With Selection.Font ' .Name = "Arial" ' .Size = 20 ' .Strikethrough = False ' .Superscript = False ' .Subscript = False ' .OutlineFont = False ' .Shadow = False ' .Underline = xlUnderlineStyleNone ' .ColorIndex = xlAutomatic 'End With With Selection.Font .Name = "Comic Sans MS" .Size = 20 ' .Strikethrough = False ' .Superscript = False ' .Subscript = False ' .OutlineFont = False ' .Shadow = False .Underline = xlUnderlineStyleNone .ColorIndex = xlAutomatic End With Selection.Font.ColorIndex = 5 End Sub
  • 38. Sigue haciendo lo mismo la macro?, si?, pues entonces vamos bien, con esto te darás cuenta que, la mayoría de las veces, la grabadora de macro nos escribe mucha "basura", es decir, código de más, código innecesario para nuestra macro, lo complicado es saber que quitar y que no, incluso que agregar y que no, ojalá que con todos los ejemplo que haya aquí, te sea más leve esta tarea. Por ultimo, te escribiré una segunda versión de esta macro, la llamaremos Mi_Primer_Macro2 , regla, no puede tener dos macros en el mismo modulo de código, que tengan el mismo nombre , no lo olvides, esta segunda versión, esta basada completamente en la original, tu "tareita" es decirme cuales son las diferencias, claro, aparte del número de líneas, hice lagunas "trampitas", observa las primeras líneas, observa las líneas que se quitaron y las que se modificaron, las que se movieron y las que se dejaron tal cual, ¿de acuerdo?... Sub Mi_Primer_Macro2() ' Macro modificada por mi ActiveCell.FormulaR1C1 = "Esta es mi primer macro, claro, con algunos cambios" With Selection.Font .Bold = True .Italic = True .Name = "Comic Sans MS" .Size = 20 .ColorIndex = 5 End With End Sub Se me pasaba comentarte que puedes hacer todas las macros que quieras dentro de un mismo modulo, lo único que tienes que hacer es procurar separarlas por una línea, como se que eres observador, habrás notado que todas las macros empiezan con Sub y terminan con End Sub , pues así son las macros, por ejemplo, podrías tener esto: Sub CopiarDatos() ' Aqui va el código de esta macro End Sub Sub HacerReporte() ' Aqui va el código de esta macro End Sub Sub HacerGrafico() ' Aqui va el código de esta macro End Sub ο Ahora hagamos algo muy interesante, grabaremos nuestra segunda macro, pero con una pequeña variante, iremos viendo como es que Excel, va grabando las instrucciones dentro de un modulo en el Editor de Visual Basic, para lograrlo abramos el Editor de Visual Basic, ya sabes como ¿verdad?, redimensiona y manipula las ventanas, tanto de Excel como del Editor, para que ocupen, aproximadamente la mitad de la pantalla cada una, cuida , que la pantalla de Excel quede en primer plano y en segundo plano el Editor de Visual Basic, cuidado , si en la ventana del Editor, no esta visible el MODULO donde se están grabando las macros no veraz nada, tienes que poner el cursor dentro del modulo actual para que veas la grabación, para que no haya duda, ve la siguiente imagen:
  • 39. Observa como Excel esta en primer plano y el Editor en segundo plano, si estas en la misma sesión de trabajo, donde grabaste Mi_Primer_Macro , entonces solo deja el cursor dentro del modulo donde está, esta macro, si estas usando otra sesión de trabajo, te grabara esta segunda macro, dentro de un segundo modulo y tal vez no lo veas, en resumen, el modulo visible debe ser el actual, donde veas que Excel esta grabando actualmente tus macros. Descargar el código de este artículo. Escribiendo mi primer macro en Excel Esta vez no usaremos la grabadora de macros, esta vez escribiremos nuestra propia macro desde cero, para este tema, considero que ya sabes entrar al EditorVBA y que ya sabes ejecutar cualquier macro, ¿estas listo?... o Entramos a Excel o Aquí podemos usar un nuevo libro o si lo prefieres abre tu libro de pruebas favorito. o Entra el Editor de Visual Basic Alt + F11 . o Puedes usar, si ya lo tienes, un modulo existente, o mejor aun, agregamos uno, esto lo hacemos desde el menú Insertar | Modulo , nuestro Explorador de Proyectos se tiene que ver así.
  • 40. o El cursor de escritura debe de quedar dentro de la ventana de código, observa que estoy usando el mismo archivo que hice en el tema anterior Grabando mi primer macro, pero reitero, puedes usar cualquier otro que gustes, observa la barra de título, observa si tengo alguna nueva barra de herramientas, observa la Ventana de Propiedades, en fin, observa lo más que puedas. o El siguiente paso es importante, ¿qué hará nuestra macro?, bueno, realmente al entrar al EditorVBA ya "deberíamos" de haber tenidos resuelta esta cuestión, pero debes de recordar que esta es la primera y más importante pregunta que debemos hacernos, cuando empecemos a crear una macro, para nuestro ejemplo, como estamos considerando que será nuestra primera macro, tendremos que escoger algo sencillo, se me ocurre hacer una macro que nos solicite nuestro nombre y el nombre de algún mes, después solicitaremos los importes de algunos conceptos "predefinidos" como: transporte, alimentos, diversión, por ultimo sumar estos importes, entonces, los pasos que hará nuestra macro son:  Solicitar nuestro nombre  Escribirlo en una celda  Solicitar el nombre de algún mes  Escribirlo en alguna celda  Solicitar un importe para el gasto de Transporte  Escribirlo en alguna celda  Solicitar un importe para el gasto de Alimentos  Escribirlo en alguna celda  Solicitar un importe para el gasto de Diversión  Escribirlo en alguna celda  Introducir la formula que sume estos conceptos o Esto que acabamos de hacer es muy importante, siempre que te sea posible y repito, siempre, procura tratar de escribir la secuencia de pasos necesarios para lograr el proposito establecido, detras de esto, hay miles de líneas de teoría, así que puedes investigar los siguientes temas: Analisis de
  • 41. sistemas, algoritmos, seudocódigo, entre más domines estos temas y entre más claros sean estos pasos, más fácil te será, pasarlos el lenguaje que quieras, en nuestro caso, al VBA. o Vamos a la ventana de código y escribimos, ojo, no lo copies, quiero que lo teclees en la ventana de código... o Public Sub Gastos_Mes() o o End Sub o Puntos importantes: Toda macro tiene un nombre, para este caso, decidí que se llamará Gastos_Mes, pero si tu consideras que otro nombre es adecuado, adelante, no dejes de usarlo, ¿observaste que paso, cuando finalizaste con la línea Public Sub Gastos_Mes() y presionaste la tecla Enter?, ayudas como esta, nos la da el EditorVBA, en este caso, solito agrego el final de la macro, End Sub, y poco a poco te mostrare y te iras dando cuenta de que el EditorVBA, nos da muchas otras ayudas más, que hacen un poco más fácil la escritura de código, si observas alguna otra, durante el proceso de esta macro, no dejes de comentarla, también observa que después del nombre de la macro, terminamos la línea con un abriendo y cerrando un par de paréntesis, más adelante, veremos que podemos introducir dentro de estos paréntesis, por lo pronto, las macros que haremos deben de terminar con estos. o Recuerda que todo lo que escribamos de aquí en adelante, será entre las lineas Public Sub y End Sub, y de acuerdo a los pasos que establecimos, debemos de solicitar un nombre y escribirlo en una celda ¿verdad?... o Public Sub Gastos_Mes() o Dim strNombre As String 'Declaramos nuestra variable o o strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre o Range("A1").Value = strNombre 'Lo escribimos en la celda A1 o o End Sub o Esta muy fácil ¿verdad?, conforme vayamos esribiendo nuestra macro, ve la probando, y, por ahora, te sugiero proporcionarle todos los datos que solicitamos, ya veremos que pasa cuando no es así. Ahora trata de solicitar un nombre de mes y escríbelo en la celda A2, como se que no harás trampa, aquí esta la solución... o Public Sub Gastos_Mes() o Dim strNombre As String 'Declaramos nuestra variable o Dim strMes As String 'Declaramos otra variable o o strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre o Range("A1").Value = strNombre 'Lo escribimos en la celda A1 o o strMes = InputBox("¿Cual es el mes?") 'Preguntamos el mes o Range("A2").Value = strMes 'Lo escribimos en la celda A2 o o End Sub o Que fácil esta esto, ahora solicitaremos el importe de cada uno de los conceptos, en este caso son tres y estos, los escribiremos en las celdas B5, B6 y B7 respectivamente, ¿por qué ahí?, bueno, ya lo notaras más adelante, sigue, sigue leyendo por favor, veamos como quedaría para el primer caso... o Public Sub Gastos_Mes() o Dim strNombre As String 'Declaramos nuestra variable o Dim strMes As String 'Declaramos otra variable o Dim sngImporte As Single 'Declaramos la variable para los Importes o o strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre o Range("A1").Value = strNombre 'Lo escribimos en la celda A1 o o strMes = InputBox("¿Cual es el mes?") 'Preguntamos el mes o Range("A2").Value = strMes 'Lo escribimos en la celda A2 o o 'Preguntamos por el importe para el concepto Transporte o sngImporte = InputBox("¿Cual es el importe para Transporte?")
  • 42. o Range("B5").Value = sngImporte 'Lo escribimos en la celda B5 o o End Sub o Solo nos resta solicitar los restantes dos importes, de las restantes categorías, y esta es mi pregunta, ¿declararemos otras dos variables para "guardar" los valores de estos importes?, ¿o podemos usar la misma?, y tu, ¿qué crees?... o Public Sub Gastos_Mes() o Dim strNombre As String 'Declaramos nuestra variable o Dim strMes As String 'Declaramos otra variable o Dim sngImporte As Single 'Declaramos la variable para los Importes o o strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre o Range("A1").Value = strNombre 'Lo escribimos en la celda A1 o o strMes = InputBox("¿Cual es el mes?") 'Preguntamos el mes o Range("A2").Value = strMes 'Lo escribimos en la celda A2 o o 'Preguntamos por el importe para el concepto Transporte o sngImporte = InputBox("¿Cual es el importe para Transporte?") o Range("B5").Value = sngImporte 'Lo escribimos en la celda B5 o o sngImporte = InputBox("¿Cual es el importe para Alimentos?") o Range("B6").Value = sngImporte 'Lo escribimos en la celda B6 o o sngImporte = InputBox("¿Cual es el importe para Diversión?") o Range("B7").Value = sngImporte 'Lo escribimos en la celda B7 o o End Sub o Y por ultimo, introducimos la formula que nos sume el importe de estas tres categorías, esto lo haremos en la celda B8 o Public Sub Gastos_Mes() o Dim strNombre As String 'Declaramos nuestra variable o Dim strMes As String 'Declaramos otra variable o Dim sngImporte As Single 'Declaramos la variable para los Importes o o strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre o Range("A1").Value = strNombre 'Lo escribimos en la celda A1 o o strMes = InputBox("¿Cual es el mes?") 'Preguntamos el mes o Range("A2").Value = strMes 'Lo escribimos en la celda A2 o o 'Preguntamos por el importe para el concepto Transporte o sngImporte = InputBox("¿Cual es el importe para Transporte?") o Range("B5").Value = sngImporte 'Lo escribimos en la celda B5 o o sngImporte = InputBox("¿Cual es el importe para Alimentos?") o Range("B6").Value = sngImporte 'Lo escribimos en la celda B6 o o sngImporte = InputBox("¿Cual es el importe para Diversión?") o Range("B7").Value = sngImporte 'Lo escribimos en la celda B7 o o 'Sumamos las celdas B5 a B7, pero introduciendo una formula o Range("B8").FormulaLocal = "=SUMA(B5:B7)" o o End Sub
  • 43. o En sentido estricto, lo que tenemos hasta ahora, realiza el propósito para lo que fue creada, pero... (siempre hay un pero), ¿como la vez?, ¿te gusta?, ¿qué le agregamos?, ¿qué le quitamos?, ¿siempre funciona, en cualquier libro y hoja? (ya sabes a donde contestar estas preguntas). La primer mejora, será agregar algunos encabezados para identificar cada valor y la segunda, será darle un poco de formato a los datos... o Public Sub Gastos_Mes() o Dim strNombre As String 'Declaramos nuestra variable o Dim strMes As String 'Declaramos otra variable o Dim sngImporte As Single 'Declaramos la variable para los Importes o o strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre o Range("A1").Value = strNombre 'Lo escribimos en la celda A1 o o strMes = InputBox("¿Cual es el mes?") 'Preguntamos el mes o Range("A2").Value = strMes 'Lo escribimos en la celda A2 o o 'Preguntamos por el importe para el concepto Transporte o sngImporte = InputBox("¿Cual es el importe para Transporte?") o Range("B5").Value = sngImporte 'Lo escribimos en la celda B5 o o sngImporte = InputBox("¿Cual es el importe para Alimentos?") o Range("B6").Value = sngImporte 'Lo escribimos en la celda B6 o o sngImporte = InputBox("¿Cual es el importe para Diversión?") o Range("B7").Value = sngImporte 'Lo escribimos en la celda B7 o o 'Sumamos las celdas B5 a B7, pero introduciendo una formula o Range("B8").FormulaLocal = "=SUMA(B5:B7)" o o 'Agregamos los encabezados necesarios o Range("A4").Value = "Concepto" o Range("B4").Value = "Importe" o Range("A5").Value = "Transporte" o Range("A6").Value = "Alimentos" o Range("A7").Value = "Diversión" o Range("A8").Value = "Total" o o 'Le damos formato a las celdas o Range("A1:A2").Font.Bold = True 'Negritas o Range("A4:B4").Font.Bold = True o Range("A8:B8").Font.Bold = True o Range("A4:B4").HorizontalAlignment = xlCenter 'Alineacion horizontal central o Range("B5:B8").NumberFormat = "#,##0.00" 'Formato númerico o o End Sub o Muy importante , como mencionamos, por lo pronto, proporciónale, a la macro, todos los datos que pedimos, no dejes nada vacío, teclea texto donde te pida texto y números donde te pida números, la tareita es: modifica la macro, de modo que se vea como la siguiente imagen...
  • 44. o Por ultimo, y como preparación para la segunda parte de este tema, prueba, ahora sí, a NO darle todos los valores a la macro, a darle texto donde deberían ir números y ver que es lo que hace la macro, se muy observador, el EditorVBA, de nuevo nos va a ayudar mucho, LEE la ayuda, investiga más acerca de la función InputBox y ve investigando para que sirve la función Val, todo esto, lo encuentras en la ayuda, así que solo es cuestión de leer, razonar y comprender un poquito, nos vemos... o Como se que hiciste tu tarea, aquí esta la solución a la macro, si no te resulto, verifica en donde están las diferencias, recuerda que esto es solo una propuesta... o '***************************************** o 'Esta es la función que TU tenias que hacer o Public Sub Gastos_Mes_2() o Dim strNombre As String 'Declaramos nuestra variable o Dim strMes As String 'Declaramos otra variable o Dim sngImporte As Single 'Declaramos la variable para los Importes o o strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre o Range("B3").Value = strNombre 'Lo escribimos en la celda A1 o o strMes = InputBox("¿Cual es el mes?") 'Preguntamos el mes o Range("B4").Value = strMes 'Lo escribimos en la celda A2 o o 'Preguntamos por el importe para el concepto Transporte o sngImporte = InputBox("¿Cual es el importe para Transporte?") o Range("B7").Value = sngImporte 'Lo escribimos en la celda B5 o o sngImporte = InputBox("¿Cual es el importe para Alimentos?") o Range("B8").Value = sngImporte 'Lo escribimos en la celda B6 o o sngImporte = InputBox("¿Cual es el importe para Diversión?") o Range("B9").Value = sngImporte 'Lo escribimos en la celda B7 o o 'Sumamos las celdas B5 a B7, pero introduciendo una formula o Range("B10").FormulaLocal = "=SUMA(B7:B9)" o o 'Agregamos los encabezados necesarios o Range("A1").Value = "Reporte de gastos" o Range("A3").Value = "Nombre" o Range("A4").Value = "Mes" o Range("A6").Value = "Concepto" o Range("B6").Value = "Importe" o Range("A7").Value = "Transporte" o Range("A8").Value = "Alimentos" o Range("A9").Value = "Diversión"
  • 45. o Range("A10").Value = "Total" o o 'Le damos formato a las celdas o Range("A1").Font.Bold = True 'Negritas o Range("A3:A4").Font.Bold = True o Range("A6:B6").Font.Bold = True o Range("A10:B10").Font.Bold = True o Range("A1:B1").HorizontalAlignment = xlHAlignCenterAcrossSelection o Range("A3:A4").HorizontalAlignment = xlRight 'Alineacion horizontal derecha o Range("A6:B6").HorizontalAlignment = xlCenter 'Alineacion horizontal central o Range("B7:B10").NumberFormat = "#,##0.00" 'Formato númerico o o End Sub o Descargar el código de este artículo. Escribiendo mi primer macro en Excel II Para este tema doy por entendido que has leido y comprendido la primer parte de este articulo, que, como recordaras, la dejamos trabajando perfectamente, la ultima versión quedo así... '***************************************** 'Esta es la función que TU tenias que hacer Public Sub Gastos_Mes_2() Dim strNombre As String 'Declaramos nuestra variable Dim strMes As String 'Declaramos otra variable Dim sngImporte As Single 'Declaramos la variable para los Importes strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre Range("B3").Value = strNombre 'Lo escribimos en la celda A1 strMes = InputBox("¿Cual es el mes?") 'Preguntamos el mes Range("B4").Value = strMes 'Lo escribimos en la celda A2 'Preguntamos por el importe para el concepto Transporte sngImporte = InputBox("¿Cual es el importe para Transporte?") Range("B7").Value = sngImporte 'Lo escribimos en la celda B5 sngImporte = InputBox("¿Cual es el importe para Alimentos?") Range("B8").Value = sngImporte 'Lo escribimos en la celda B6 sngImporte = InputBox("¿Cual es el importe para Diversión?") Range("B9").Value = sngImporte 'Lo escribimos en la celda B7 'Sumamos las celdas B5 a B7, pero introduciendo una formula Range("B10").FormulaLocal = "=SUMA(B7:B9)" 'Agregamos los encabezados necesarios
  • 46. Range("A1").Value = "Reporte de gastos" Range("A3").Value = "Nombre" Range("A4").Value = "Mes" Range("A6").Value = "Concepto" Range("B6").Value = "Importe" Range("A7").Value = "Transporte" Range("A8").Value = "Alimentos" Range("A9").Value = "Diversión" Range("A10").Value = "Total" 'Le damos formato a las celdas Range("A1").Font.Bold = True 'Negritas Range("A3:A4").Font.Bold = True Range("A6:B6").Font.Bold = True Range("A10:B10").Font.Bold = True Range("A1:B1").HorizontalAlignment = xlHAlignCenterAcrossSelection Range("A3:A4").HorizontalAlignment = xlRight 'Alineacion horizontal derecha Range("A6:B6").HorizontalAlignment = xlCenter 'Alineacion horizontal central Range("B7:B10").NumberFormat = "#,##0.00" 'Formato númerico End Sub o También quedamos que en esta ocasión, no le vamos a proporcionar los datos esperados, si no que pondremos a prueba la "solidez" de nuestra macro, asignándole valores incorrectos o simplemente cancelando la operación, esto ultimo muy importante, en la mayoría de los casos, tienes que proporcionarle al usuario una forma de cancelar la macro en ejecución... o Como primer prueba le pasaremos una cadena vacía en donde nos solicite un dato, veamos que hace la macro y que mejores le podemos hacer, empecemos... o Cuando nos solicite el primer dato, prueba a; directamente dar un clic en el botón Aceptar o a introducir puros espacios con la tecla Barra espaciadora, observa como en la imagen siguiente el cursor esta unos caracteres adelante, pues se introdujeron algunos espacios. o Al dar clic en el botón Aceptar, la macro continua como si nada, es decir, nos muestra el siguiente cuadro donde nos solicita el siguiente dato, ¿pero?, ¿es esto correcto?, no verdad, el dato Nombre es un dato (lo pondré en mayúsculas) REQUERIDO, esta palabra es muy importante, nos indica que el valor que estamos solicitando es OBLIGATORIO proporcionarlo para que nuestra macro haga el trabajo encomendado, si un dato es o no REQUERIDO es algo que Tu tienes que decidir y que es muy fácil determinar, tan solo pregúntate; ¿la macro puede resolver el trabajo sin este dato?, si la respuesta es NO, entonces es REQUERIDO, si la respuesta es SI, entonces es OPCIONAL, para nuestro caso, el dato Nombre es un dato REQUERIDO, por lo que tenemos que garantizar que el usuario proporcione este valor, la pregunta del millón ¿cómo lo hacemos?... o Como sabes (y si no lo sabes aquí te lo dijo), la función InputBox "siempre", lo repito, "siempre", nos devuelve un String, es decir, una cadena de texto y esta cadena de texto, será de longitud cero, cuando: presione inmediatamente el botón Aceptar o cuando presione el botón Cancelar, aun cuando ya haya introducido algún texto en el cuadro, con este conocimiento, solo tenemos que medir el número de caracteres para saber si el usuario escribió algo en el cuadro de texto, para eso, usamos la función Len, que nos devuelve un Long, un número con el número de caracteres de una cadena... o Dim Largo As Long
  • 47. o o strNombre = InputBox("¿Cual es tu nombre?") 'Preguntamos el nombre o Largo = Len(strNombre) o En la variable Largo, tenemos el número de caracteres que el usuario escribió, si este valor es cero, entonces ya sabes que significa ¿verdad?, ¿pero, como sabemos si es o no cero?, para esto lo preguntamos de esta manera o If Largo = 0 Then o MsgBox "El dato Nombre es requerido" o End If o Lo que acabamos de hacer, es crear una estructura condicional, o sea, que dependiendo de una condición, podemos ejecutar determinado código, en esta caso, nuestra condición es: Largo = 0, que, como observas, esta entre las palabras If y Then, es decir, entre estas dos palabras claves de VB, pondremos la condición necesaria, como condición, puedes usar "cualquier expresión que se pueda evaluar como VERDADERA o FALSA", esta estructura tiene muchas variantes, pero empezaremos por su forma más sencilla, en nuestro ejemplo, si la condición es VERDADERA, entonces se ejecuta la línea o líneas inmediatas a la condición, en este caso la línea: MsgBox "El dato Nombre es requerido", que tan solo le notifica al usuario que no proporciono un dato, pero si continuamos, la macro sigue como antes, es decir, nos muestra el siguiente mensaje, lo cual no es correcto, pues buscamos obligar al usuario a introducir el dato, para esto, podemos volver a preguntar, pero con esto corremos el riesgo de que vuelva a proporcionar una cadena de longitud cero, con este inconveniente, decidimos mejor, salir de la macro con la instrucción Exit Sub, con la cual el código quedaría así... o If Largo = 0 Then o MsgBox "El dato Nombre es requerido" o Exit Sub o End If o Pruébala y verifica como, cuando presionas Cancelar o inmediatamente presionas Aceptar, efectivamente nos informa de ello y termina la macro, la instrucción Exit Sub hay que usarla con mesura, no abuses mucho de ella, ya aprenderemos otras alternativas para minimizar su uso. o Bien, muy bien, ahora prueba a introducir espacios cuando te solicite el nombre, ¿qué paso?, nos deja continuar ¿verdad?, esto es por que recuerda que aunque nosotros no veamos los espacios, para la computadora son un carácter más, así que cuando evalúa el largo de la cadena, esta devuelve el número de espacios vacíos que el usuario tecleo, pero esto también debemos de preverlo con una función llamada Trim que elimina los espacios en blanco que tenga una cadena al principio y al final de esta... o strNombre = Trim(strNombre) en este ejemplo, primero le quitamos los espacios a la variable strNombre y después reasignamos el valor resultante a ella misma, también podríamos haber usado la función Trim directamente en la función InputBox de la siguiente manera... strNombre = Trim (InputBox("¿Cual es tu nombre?")) solo para que lo notaras, puse en negritas la función Trim, puedes usar cualquiera de las dos, al final el resultado es el mismo. Vuelve a hacer las pruebas pertinentes. o Como siguiente paso, realizamos la misma evaluación para el dato Mes, garantizaremos que el usuario introduzca un dato. o strMes = Trim(InputBox("¿Cual es el mes?")) o Largo = Len(strMes) o If Largo = 0 Then o MsgBox "El dato Mes es requerido" o Exit Sub o End If o Una muy buena pregunta; ¿podremos lograr evaluar que el usuario introduzca un nombre de Mes válido, es decir, garantizar que el usuario introduzca Enero, Febrero... Diciembre o cualquier mes correcto?, te queda de tareita tratar de hacerlo, al fin y al cabo solo son doce meses, pero recuerda que la respuesta más obvia no siempre es la mejor.
  • 48. o El siguiente dato que tenemos que garantizar que el usuario introduzca es un valor, un número, ya no una cadena, esto es importante, más atrás se dijo la función InputBox "siempre", lo repito, "siempre", nos devuelve un String, es decir, una cadena de texto, entonces, ¿como es que podemos asignar un String (cadena de texto) a una variable de tipo Single (número simple) como en la línea siguiente?... o sngImporte = InputBox("¿Cual es el importe para Transporte?") La respuesta es simple, cuando VB encuentra que queremos hacer una asignación de un Tipo de dato a otro Tipo de dato, si le es posible hace la conversión necesaria, si no le es posible ocurre un error (mejor dicho un horror por que nuestro código se detiene), veamos un ejemplo... o En la imagen anterior, cuando se nos solicita un importe, en vez de un número, introducimos un texto, al presionar el botón Aceptar nos muestra un lindo e interesante mensaje, un mensaje de ERROR, nos muestra el número de error (13) y nos muestra la causa del error (No coinciden los tipos), a que tipos... o Si presionamos el botón Finalizar simplemente la ejecución de la macro termina, pero si presionamos el botón Depurar pasa algo muy interesante, se abre la ventana del Editor del VBA y una línea se colorea de un forma bastante llamativa, ¿para que será?...
  • 49. o Así es, como lo imaginaste en esa línea ocurrió el error (¡¡que brillante eres Mauricio...!!) y en ese momento, podemos modificarla, pero antes, quiero que seas muy observador, aparte de la línea amarilla, hay otra cosa que quiero que observes, esta es, la barra de titulo del Editor, obsérvala y ve lo que nos va mostrando conforme cambiamos y usamos el Editor VBA, por ahora, detén la ejecución de la macro, ¿como?, ve al menú Ejecutar | Restablecer o presiona el botón que encerré en un circulo rojo (ya vieron que bien dibujo a mano alzada). o Entonces, el error fue que VB no pudo convertir el valor tipo String al tipo Single, pero nuestro trabajo es garantizar que si pueda hacerlo, pues si a un usuario le sale el mismo mensaje de "horror" que acabamos de ver, ten por seguro que se acordara de ti, pero para que no pase esto, veamos como solucionarlo. o Como casi siempre, hay más de una manera de resolverlo, probemos una de las más sencillas, haciendo uso de la función Val, que convierte "si le es posible" una cadena de texto en un número, pero si no le es posible, ya no ocurre un error, sino que lo convierte en cero, su uso es simple... o sngImporte = Val(InputBox("¿Cual es el importe para Transporte?")) o Ahora, en la variable sngImporte tendremos el valor en "número" si fue posible hacer la conversión, y tendremos un cero, si no fue posible hacer la conversión, pregunta; ¿cómo evalúas entonces que el dato este correcto?... o sngImporte = Val (InputBox("¿Cual es el importe para Transporte?")) o If sngImporte = 0 Then o MsgBox "El dato Transporte es requerido" o Exit Sub o End If o Muy bien, veo que si estas aprendiendo, pero... ¿qué crees?, pues si, tienes otra tareita, es sencilla, solo tienes que responder la pregunta ¿cómo solucionarías el caso, cuando un usuario introduzca un número negativo?, más fácil no es posible... o Ahora solo te resta hacer lo mismo para los restantes datos, pero... ¿por qué siempre sales con un pero?, observa la siguiente imagen, obsérvala muy bien...
  • 50. o En este cuadro, se nos esta solicitando el dato Importe (en rojo), que como sabemos debe ser un número, pero le estamos proporcionando una cadena de texto (en azul), como ya previmos esto, la macro simplemente nos avisara que no es un número válido y se detendrá, ¿pero que pasa?, en el fondo (en naranja) ya introdujimos por código, los valores de las dos variables anteriores, pero al cancelarse mi macro por la introducción de un dato erróneo, estos valores son obsoletos, es decir, inservibles, inútiles, están de más ¿verdad?, solución uno, los borramos antes de salir, solución dos (mejor), los escribimos hasta después de haber evaluado todas las variables, pero... ¿otro? (ya me estoy cansando de los pero's...), esto es válido para las dos primeras variables, pero en el caso de los tres importes, estamos usando una sola variable para los tres, para resolver este pequeño inconveniente, usaremos una variable para cada dato y te podrás preguntar ¿y si mis datos a introducir son muchos, tendré que declarar una variable para cada dato?, muy buena pregunta, más adelante veremos casos como ese, por lo pronto hazme caso y declara una variable para cada concepto o cuéntame que otras alternativas que se te ocurren. o Bien, nuestro código completo se vera así... o Option Explicit o o Public Sub Gastos_Mes_2() o 'Declaramos las variables a usar o Dim strNombre As String o Dim strMes As String o Dim sngTransporte As Single o Dim sngAlimentos As Single o Dim sngDiversion As Single o Dim Largo As Long o o 'Solicitamos cada uno de los datos requerido y verificamos que sean correctos o strNombre = Trim(InputBox("¿Cual es tu nombre?")) o Largo = Len(strNombre) o If Largo = 0 Then o MsgBox "El dato Nombre es requerido" o Exit Sub o End If o o strMes = Trim(InputBox("¿Cual es el mes?")) o Largo = Len(strMes) o If Largo = 0 Then o MsgBox "El dato Mes es requerido" o Exit Sub
  • 51. o End If o o sngTransporte = Val(InputBox("¿Cual es el importe para Transporte?")) o If sngTransporte = 0 Then o MsgBox "El dato Transporte es requerido" o Exit Sub o End If o o sngAlimentos = Val(InputBox("¿Cual es el importe para Alimentos?")) o If sngAlimentos = 0 Then o MsgBox "El dato Alimentos es requerido" o Exit Sub o End If o o sngDiversion = Val(InputBox("¿Cual es el importe para Diversion?")) o If sngDiversion = 0 Then o MsgBox "El dato Diversion es requerido" o Exit Sub o End If o o 'Escribimos los valores ya correctos o Range("B3").Value = strNombre o Range("B4").Value = strMes o Range("B7").Value = sngTransporte o Range("B8").Value = sngAlimentos o Range("B9").Value = sngDiversion o o 'Sumamos las celdas B5 a B7, pero introduciendo una formula o Range("B10").FormulaLocal = "=SUMA(B7:B9)" o o 'Agregamos los encabezados necesarios o Range("A1").Value = "Reporte de gastos" o Range("A3").Value = "Nombre" o Range("A4").Value = "Mes" o Range("A6").Value = "Concepto" o Range("B6").Value = "Importe" o Range("A7").Value = "Transporte" o Range("A8").Value = "Alimentos" o Range("A9").Value = "Diversión" o Range("A10").Value = "Total" o o 'Le damos formato a las celdas o Range("A1").Font.Bold = True 'Negritas o Range("A3:A4").Font.Bold = True o Range("A6:B6").Font.Bold = True o Range("A10:B10").Font.Bold = True o Range("A1:B1").HorizontalAlignment = xlHAlignCenterAcrossSelection o Range("A3:A4").HorizontalAlignment = xlRight 'Alineacion horizontal derecha o Range("A6:B6").HorizontalAlignment = xlCenter 'Alineacion horizontal central o Range("B7:B10").NumberFormat = "#,##0.00" 'Formato númerico o o End Sub o Bien, muy bien, ahora nuestra macro es un poco más profesional, los posibles usuarios "casi" no se acordaran de nosotros y estamos contentos de saber un poco más, recuerda que no es la única solución, puede y hay más, una de ellas la veremos en el próximo capitulo, no te despegues...
  • 52. Descargar el código de este artículo. Escribiendo mi primer macro en Excel III Para este tema doy por entendido que has leido y comprendido la primer y segunda parte de este articulo, la ultima versión es la siguiente... Option Explicit Public Sub Gastos_Mes_2() 'Declaramos las variables a usar Dim strNombre As String Dim strMes As String Dim sngTransporte As Single Dim sngAlimentos As Single Dim sngDiversion As Single Dim Largo As Long 'Solicitamos cada uno de los datos requerido y verificamos que sean correctos strNombre = Trim(InputBox("¿Cual es tu nombre?")) Largo = Len(strNombre) If Largo = 0 Then MsgBox "El dato Nombre es requerido" Exit Sub End If strMes = Trim(InputBox("¿Cual es el mes?")) Largo = Len(strMes) If Largo = 0 Then MsgBox "El dato Mes es requerido" Exit Sub End If sngTransporte = Val(InputBox("¿Cual es el importe para Transporte?")) If sngTransporte = 0 Then MsgBox "El dato Transporte es requerido" Exit Sub End If sngAlimentos = Val(InputBox("¿Cual es el importe para Alimentos?")) If sngAlimentos = 0 Then MsgBox "El dato Alimentos es requerido" Exit Sub End If sngDiversion = Val(InputBox("¿Cual es el importe para Diversion?")) If sngDiversion = 0 Then MsgBox "El dato Diversion es requerido" Exit Sub
  • 53. End If 'Escribimos los valores ya correctos Range("B3").Value = strNombre Range("B4").Value = strMes Range("B7").Value = sngTransporte Range("B8").Value = sngAlimentos Range("B9").Value = sngDiversion 'Sumamos las celdas B5 a B7, pero introduciendo una formula Range("B10").FormulaLocal = "=SUMA(B7:B9)" 'Agregamos los encabezados necesarios Range("A1").Value = "Reporte de gastos" Range("A3").Value = "Nombre" Range("A4").Value = "Mes" Range("A6").Value = "Concepto" Range("B6").Value = "Importe" Range("A7").Value = "Transporte" Range("A8").Value = "Alimentos" Range("A9").Value = "Diversión" Range("A10").Value = "Total" 'Le damos formato a las celdas Range("A1").Font.Bold = True 'Negritas Range("A3:A4").Font.Bold = True Range("A6:B6").Font.Bold = True Range("A10:B10").Font.Bold = True Range("A1:B1").HorizontalAlignment = xlHAlignCenterAcrossSelection Range("A3:A4").HorizontalAlignment = xlRight 'Alineacion horizontal derecha Range("A6:B6").HorizontalAlignment = xlCenter 'Alineacion horizontal central Range("B7:B10").NumberFormat = "#,##0.00" 'Formato númerico End Sub o Esta versión funciona bien, pero como habrás notado, cuando el usuario no proporciona un dato correctamente, la macro, si bien informa de esta falta, lo que hace es simplemente terminar la ejecución, no le da la oportunidad al usuario de intentarlo nuevamente, dicen por ahí que -todos merecemos una segunda oportunidad-, así que implementaremos una forma de que el usuario pueda intentarlo nuevamente, para ello usaremos una nueva estructura condicional, veamos el ejemplo y después lo explicamos... o 'Iniciamos la estructura condicional o Do o 'Solicitamos el dato requerido quitandole los espacios sobrantes o strNombre = Trim(InputBox("¿Cual es tu nombre?")) o 'Verificamos que exista el dato o If strNombre = "" Then o 'Notificamos en caso de que no haya dato o MsgBox "El dato Nombre es requerido" o End If o 'Volvemos a la línea inmediata a Do si el dato es vacio o Loop While strNombre = "" o Estos cambios, ya lo habrás notado, los haremos para solicitar el primer dato, para entender esta nueva estructura, te pondré las instrucciones pero le agregare su interpretación en español... o 'Iniciamos la estructura condicional o Do(Hacer) o 'Solicitamos el dato requerido quitandole los espacios sobrantes o strNombre = Trim(QuitaEspacios)(InputBox(SolicitaDato)("¿Cual es tu nombre?")) o 'Verificamos que exista el dato
  • 54. o If(Si) strNombre = "" Then(Entonces) o 'Notificamos en caso de que no haya dato o MsgBox(MuestraMensaje) "El dato Nombre es requerido" o End If(Fin Si) o 'Volvemos a la línea inmediata a Do si el dato es vacio o Loop While(Hacer Mientras) strNombre = "" o La estructura condicional Do...Loop... While, nos sirve para repetir una serie de instrucciones mientras o hasta que se cumpla una condición, fíjate como es muy sencillo, solo hay que iniciar la estructura con un Do y terminarla con un Loop While condicion, con esta estructura el código se ejecutara mientras la condición sea verdadera, la otra variante es que el código se ejecute hasta que la condición sea verdadera, veamos este ultimo ejemplo... o 'Iniciamos la estructura condicional o Do o 'Solicitamos el dato requerido quitandole los espacios sobrantes o strNombre = Trim(InputBox("¿Cual es tu nombre?")) o 'Verificamos que exista el dato o If strNombre = "" Then o 'Notificamos en caso de que no haya dato o MsgBox "El dato Nombre es requerido" o End If o 'Volvemos a la línea inmediata a Do si el dato es vacio o Loop Until strNombre <> "" o El cambio fue realmente simple, observa la siguiente línea que fue la que se modifico... o Loop Until strNombre <> "" o Solo sustituimos While por Until e invertimos la condición strNombre <> "" , esto es muy importante, es decir, que la condición la establezcas de manera correcta, sino, nuestra estructura no cumplira su proposito. Esta estructura tiene otras variantes, por ejemplo, que la condición la realices al principio de la estructura, en la misma línea del Do, pero como este no es un curso de programación, te dejo de tareita que investigues más de esta estructura, en la ayuda del VBA, viene, creo yo, suficientemente explicada, lo que si veremos más adelante son ejemplos de su uso, pues es muy versátil y muy poderosa esta estructura. o Solo nos resta complementar los restantes datos, para que queden en la misma estructura de la siguiente manera, siéntete en libertad de usar cualquier de las dos formas vistas... o Option Explicit o o Public Sub Gastos_Mes_3() o 'Declaramos las variables a usar o Dim strNombre As String o Dim strMes As String o Dim sngTransporte As Single o Dim sngAlimentos As Single o Dim sngDiversion As Single o Dim Largo As Long o o o 'Iniciamos la estructura condicional o Do o 'Solicitamos el dato requerido quitandole los espacios sobrantes o strNombre = Trim(InputBox("¿Cual es tu nombre?")) o 'Verificamos que exista el dato o If strNombre = "" Then o 'Notificamos en caso de que no haya dato o MsgBox "El dato Nombre es requerido" o End If o 'Volvemos a la línea inmediata a Do si el dato es vacio o Loop While strNombre = "" o
  • 55. o Do o strMes = Trim(InputBox("¿Cual es el mes?")) o If strMes = "" Then o MsgBox "El dato Mes es requerido" o End If o Loop While strMes = "" o o Do o sngTransporte = Val(InputBox("¿Cual es el importe para Transporte?")) o If sngTransporte = 0 Then o MsgBox "El dato Transporte es requerido" o End If o Loop While sngTransporte = 0 o o Do o sngAlimentos = Val(InputBox("¿Cual es el importe para Alimentos?")) o If sngAlimentos = 0 Then o MsgBox "El dato Alimentos es requerido" o End If o Loop While sngAlimentos = 0 o o Do o sngDiversion = Val(InputBox("¿Cual es el importe para Diversion?")) o If sngDiversion = 0 Then o MsgBox "El dato Diversion es requerido" o End If o Loop While sngDiversion = 0 o o 'Escribimos los valores ya correctos o Range("B3").Value = strNombre o Range("B4").Value = strMes o Range("B7").Value = sngTransporte o Range("B8").Value = sngAlimentos o Range("B9").Value = sngDiversion o o 'Sumamos las celdas B5 a B7, pero introduciendo una formula o Range("B10").FormulaLocal = "=SUMA(B7:B9)" o o 'Agregamos los encabezados necesarios o Range("A1").Value = "Reporte de gastos" o Range("A3").Value = "Nombre" o Range("A4").Value = "Mes" o Range("A6").Value = "Concepto" o Range("B6").Value = "Importe" o Range("A7").Value = "Transporte" o Range("A8").Value = "Alimentos" o Range("A9").Value = "Diversión" o Range("A10").Value = "Total" o o 'Le damos formato a las celdas o Range("A1").Font.Bold = True 'Negritas o Range("A3:A4").Font.Bold = True o Range("A6:B6").Font.Bold = True o Range("A10:B10").Font.Bold = True o Range("A1:B1").HorizontalAlignment = xlHAlignCenterAcrossSelection o Range("A3:A4").HorizontalAlignment = xlRight 'Alineacion horizontal derecha
  • 56. o Range("A6:B6").HorizontalAlignment = xlCenter 'Alineacion horizontal central o Range("B7:B10").NumberFormat = "#,##0.00" 'Formato númerico o o End Sub o CONCLUSIONES  Casi siempre, hay más de una forma de programar una solución.  Las diferentes estructuras no están para complicarnos el trabajo, al contrario, son para adaptarlas a nuestras diferentes necesidades y sobre todo nuestras diferentes forma de razonar una respuesta.  Estas estructuras tienen muchas variantes, por ejemplo, la capacidad de usar más de una condición, si no se vio a fondo es por varias razones; la ayuda del lenguaje viene bastante bien explicado y con buenos ejemplos de su uso, si no te gusta mucho la ayuda, en la red hay cientos (y no exagero), cientos de páginas que te enseñan a programar en el VB, busca, busca un poquito y veras que así es.  En esta versión de nuestra macro, "obligamos" al usuario a introducir "algo", pero en el artículo anterior, mencionamos que es importante, tratar de proporcionarle al usuario una forma de cancelar la operación o macro en proceso, de tareita te invito a que trates de hacer las siguientes variantes... 1. Una versión de esta macro, que le de la oportunidad al usuario de cancelar el proceso, OJO, que no sea la vista en la parte dos de este artículo, sino una combinación digamos de las dos, mira, sin querer ya casi te dije como hacerlo. 2. Otra versión de esta macro, que le demos, digamos, tres oportunidades de introducir su dato y salga al llegar a este limite, claro, informando en todo momento al usuario de que es lo esta pasando. Descargar el código de este artículo. Escribiendo mi primer función en Excel Para obtener el mejor provecho de esta sección, estoy asumiendo que manejas con soltura el uso de las funciones incorporadas de Excel, como SUMA, MAX, BUSCARV, entre otras, recuerda que Excel tiene mas de 300 funciones incorporadas y que también has usado el EditorVBA, sino lo has hecho te recomiendo leer la Introducción a esta página, bien, entonces, conoces la estructura de cualquier función, veamos cual es: Las funciones personalizadas, "deben" seguir la misma estructura, si eres observador, notaras que los argumentos están separados por ";" (punto y coma), pero en la descripción dice que debe ser "," (comas), ¿porque?, ¿cual es la correcta? (esto te queda de tareita ). Nuestras funciones "deben" de responder de la misma manera que las incorporadas, DEVOLVIENDO VALORES , esto me parece la parte más importante que algunos olvidan, ¿has visto que alguna función de Excel te de algún mensaje?, no, lo que hace, cuando no puede hacer resolver la operación, es darnos un error como #¡NULO!, #¡DIV/0!, #¡VALOR!, #¡REF!, #¿NOMBRE?, #¡NÚM!, #N/A, pero nada más. Entonces ya conocemos los siguiente términos, Función y Argumentos, ¿verdad?, otro punto importante es saber que una función puede o no llevar argumentos como la función ALEATORIO y AHORA, una función puede requerir argumentos de un Tipo y devolver valores de otro Tipo, como las funciones: Función Tipo de ARGUMENTO requerido Tipo de VALOR devuelto
  • 57. LARGO Texto Numero VALOR Texto Numero FILA Rango Numero ESNUMERO Numero Booleano Tareita: Excel, dentro de sus formulas, maneja diferentes Tipos de datos, como fechas y números, ¿que otros TIPOS DE DATOS conoces que usen las funciones de Excel?, ¿que otros ejemplos de funciones, podrías dar, que devuelvan un tipo de dato diferente del de su o sus argumentos?. Como habrás notado, el nombre es importante, el nombre de la función nos sirve para en primera instancia sepamos que hace o que valor o valores nos devuelve, entonces, una parte importante es saber QUE HARA NUESTRA FUNCION es decir, que trabajo realizara, cual es su finalidad. Resumiendo: • Conocer los términos FUNCION, ARGUMENTO, VALOR DEVUELTO y TIPO DE DATO • Conocer la estructura de cualquier función • Conocer que trabajo realiza una función • TODA función devuelve un valor • Una función puede o no, tener argumentos • Una función puede devolver valores de diferente tipo del de sus argumentos • Los argumentos se separan por "comas" o "punto y coma", depende de??. Ahora que sabemos lo que necesitamos, hagamos nuestra primer función, como ya dijimos, lo primero es saber, que queremos que haga nuestra función, como ejemplo, haremos la superarchidificilisima formula para calcular el ¡rea de un triángulo: • Entramos a Excel • Entramos el EditorVBA • Insertamos un nuevo Módulo y escribimos lo siguiente: • • Option Explicit • • Function AreaTriangulo(Base, Altura) • AreaTriangulo = (Base * Altura) / 2 • End Function • Pruébala..., ¿como?, como cualquier función de Excel, que ya lo sabes, si usas el Asistente para funciones, veras una nueva categoría, al final de la lista que se llama, Definidas por el usuario, ahí encontraras nuestra función. • Ahora, comparemos la formula tradicional con nuestra función:
  • 58. Bueno, nuestra formula funciona, pero no esta optimizada, es decir, estamos cometiendo omisiones "técnicas", es decir, no estamos escribiendo nuestra función como lo mandan los "santos cánones" de la programación y esto, si bien, no es obligatorio, es muy, muy conveniente hacerlo y más aun, saberlo, veamos cuales son esas omisiones... • Si no se especifica otra cosa, toda función es Publica, pero procura hacerlo explícitamente... • Public Function AreaTriangulo(Base, Altura) • AreaTriangulo = (Base * Altura) / 2 • End Function • No le estamos diciendo de que TIPO son nuestros argumentos, en nuestro ejemplo, nuestra función debe poder manejar números grandes y con decimales, por lo tanto el Tipo de dato más conveniente es el Single (busca en la ayuda, los tipos de datos que se puedes usar en el VBA y me dices cuales son), por lo tanto nuestra función quedaría así: • Public Function AreaTriangulo(Base As Single, Altura As Single) • AreaTriangulo = (Base * Altura) / 2 • End Function • Tampoco le estamos diciendo que tipo de valor es que nos devolverá nuestra función, es muy importante, escoger este tipo de dato muy bien, la recomendación es, debe ser lo suficientemente grande para contener el resultado de nuestra función, en la misma ayuda, encontraras cuando espacio ocupa (en memoria) y que valores pueden contener los diferentes tipos de datos, para nuestro caso, si estamos multiplicando un Single por un Single y aunque estemos dividiendo, el más conveniente es un Double, para que nuestra función quede así: • Public Function AreaTriangulo(Base As Single, Altura As Single) As Double • AreaTriangulo = (Base * Altura) / 2 • End Function • Por ultimo, hay que agregarlo otra palabrita, que en otros ejemplos veremos a detalle, por lo pronto, solo te menciono que sirve para que los valores que tengan los argumentos, no se puedan modificar desde nuestra función y en la mayoría de los casos se usa, esta palabrita se llama ByVal y me gustaría que buscaras ayuda de esta palabra, ya sabes donde... • Public Function AreaTriangulo(ByVal Base As Single, ByVal Altura As Single) As Double • AreaTriangulo = (Base * Altura) / 2 • End Function • Y ahora sí, estarás de acuerdo conmigo, que se ve mucho más bonita y presentable, pero sobre todo, esta eficientemente codificada. Para terminar, te mostrare una variante, que te servirá como ejemplo para la tareita que te dejare. • Public Function AreaTriangulo(ByVal Base As Single, ByVal Altura As Single) As Double • Dim Area As Double • • Area = Base * Altura • Area = Area / 2 • AreaTriangulo = Area • • End Function
  • 59. Lo que te he querido decir con esta variante, es que "casi nunca", obtenemos el resultado de nuestra función en una línea, "casi siempre" se hace uso del proverbio que dice -divide y vencerás-, ¿recuerdas lo que decía Descartes?, puedes hacer uso de VARIABLES intermedias, observa muy bien esta línea Dim Area As Double te encontraras con líneas como esta muy seguido, lo que le estamos diciendo al VBA es -oye, apártame un cachito de memoria (recuerda que todo lo que hagas con tu maquina encendida, usa memoria) para que la use-, estamos DECLARANDO UNA VARIABLE. Como se que eres una personita muy observadora, notaras que es "casi" igual que con los argumentos, solo que aquí usamos la palabra reservada (¿que es eso de palabra reservada?) Dim, pero para decirle el tipo de datos es igual As Tipo_Dato • Ahora si, esta es la tareita , como sabes, tenemos los pelos de los griegos por cualquier lado que mires, allá por el año 500 a.C., vivia el señor Herón que no se conformo con la función que hicimos un poco más arriba, así que se puso a investigar como obtener el área, pero de cualquier triángulo con solo conocer la longitud de sus lados, para llegar a deducir la siguiente formula... En donde a, b y c, son los lados del triángulo y S es el Semiperímetro o sea, la mitad del perímetro y hasta te voy a ayudar un poco más, en VBA para obtener la raíz cuadrada de un número, se usa la función Sqr (número), en donde número es el número del cual queremos obtener la raíz cuadrada, adelante, empieza a codificarla que con gusto la revisaré... • Como siempre, pruébala, si tenemos el famoso triángulo 3,4,5 y le pasamos estos datos a nuestra primer función, Base = 4 y Altura = 3, el área obtenida sería 6, si le pasamos estos mismos datos, más el largo del tercer lado, a la función que escribas, te tiene que dar el mismo resultado, el poder de la segunda, como ya se menciono, esta en que se puede obtener el área de cualquier triángulo, tan solo conociendo la longitud de sus lados. • Después de haber recibido todas las pruebas que han hecho, aquí esta una de varias posibles soluciones, pruébala y verifica si esta correcta o cuéntame que es lo que no te gusta o que otras variantes podría tener... • 'Función que obtiene el área de cualquier triangulo, conociendo • 'la longitud de sus lados, usando la formula de Herón • Public Function AreaTrianguloHeron(ByVal LadoA As Single, _ • ByVal LadoB As Single, _ • ByVal LadoC As Single) As Double • Dim Semi As Double • Dim Area As Double • • 'Obtenemos el semiperimetro • Semi = (LadoA + LadoB + LadoC) / 2 • 'Obtenemos los productos • Area = Semi * (Semi - LadoA) * (Semi - LadoB) * (Semi - LadoC)
  • 60. 'Obtenemos la RAIZ CUADRADA • Area = Sqr(Area) • 'Asignamos el valor obtenido al nombre de nuestra función • AreaTrianguloHeron = Area • • End Function • • Recuerda que debes de probar las dos funciones, de modo que verifiques que te de el mismo resultado, en la siguiente imagen, puedes observar los valores asignados a cada función, así mismo, en rojo, están las funciones que hemos creado... Descargar el código de este artículo. Complementos... ¿que son? Complemento Componentes que pueden instalarse en el equipo para agregar comando o funciones a Excel Esto es lo que nos dice la ayuda, en otros términos, un complemento es un archivo de Excel, con ciertas características especiales (que veremos) en el cual podemos crear macros o funciones que extiendan las posibilidades de Excel, veamos primero un complemento de los que incluye Excel y después crearemos el nuestro... • Entramos a Excel • Seleccionamos el menú Herramientas | Complementos... • Nos mostrara el siguiente cuadro de dialogo
  • 61. Observa la lista y selecciona Autoguardar. Nota: estos complementos se pueden instalar y desinstalar, tal vez la lista no sea igual o tal vez no este instalados en tu equipo, para instalarlos checa la ayuda. • Después de seleccionar el complemento Autoguardar y claro, después de que hayas leído la leyenda que aparece en la parte inferior del cuadro de dialogo, para que te des una idea de lo que hace, presionas el botón Aceptar • Si eres observador y si tu maquina no es muy rápida, observa la barra de estado de Excel, notaras que dirá Abriendo Autosave.xla... y como es común al abrir libros, mostrara una barra de progreso, al terminar "aparentemente" no notaras ningún cambio, pero ve al menú Herramientas y este tendrá una nueva opción, como se ve en la siguiente imagen. • Selecciona esta nueva opción y te saldrá el siguiente cuadro de dialogo... • Como este articulo no es para explicar el uso de este complemento, pues te queda de tarea probarlo, que como imaginaras, te permite guardar cada X minutos el libro activo o todos los libros, además de que si esta bien instalado, también se instala la ayuda de los complementos. • Ahora, quiero que regreses a los complementos y busques en la lista uno que se llama Solver, selecciónalo y de nuevo te agregara una nueva opción al menú Herramientas, esto es solo como prueba de otro complemento y también como tarea te queda investigar como quitar estos complementos.
  • 62. Observa como la herramienta de Autoguardar NO esta implementada en Excel, sino que se agrego esta funcionalidad con un complemento o Add-ins como también se les conoce, esto no lo pierdas de vista, los complementos son para agregar nuevas funciones o herramientas a Excel, no para repetir las ya existentes. • Ahora viene lo interesante, como creo mi propio complemento, antes de continuar, no pierda de vista lo comentado en el punto anterior y veamos paso a paso como crear un sencillo complemento. Para lo que veremos a continuación, estoy suponiendo que ya trabajas, aunque sea muy básico, con macros y funciones, si no es así, te recomiendo los siguientes temas vistos en estas páginas:  Introducción donde vemos como empezar desde cero con las macros y a familiarizarnos con el Editor VBA  Grabando mi primer macro en Excel  Escribiendo mi primer función en Excel  Y los primeros tres temas de la sección Articulos  Como ya se dijo, vamos a usar los complementos para agregar funcionalidades inexistentes en Excel, para nuestro ejemplo, implementaremos la posibilidad de cambiar el contenido de las celdas de MAYÚSCULAS a minúsculas y viceversa.  Entramos a Excel.  Si tenemos más de una hoja (normalmente 3) dejamos solamente una hoja, esto no es indispensable, pero dado que no se van a ocupar, las eliminamos para que el complemento resultante sea de menor tamaño.  Guardamos nuestro archivo, por ahora, guárdalo como cualquier archivo de Excel y después veremos como hacerlo como complemento.  Entramos al Editor VBA, método abreviado Alt + F11  Agregamos un módulo de código Estándar desde el menú Insertar | Módulo  Escribimos o copiamos las siguientes macros...  Option Explicit   Public Sub Mayusculas()  Dim c As Range   For Each c In Selection  c.Value = StrConv(c.Value, vbUpperCase)  Next c   End Sub   Public Sub Minusculas()  Dim c As Range   For Each c In Selection  c.Value = StrConv(c.Value, vbLowerCase)  Next c   End Sub   'NOTA la funcion StrConv solo esta disponible de Excel 2000 en adelante  'para versiones anteriores hacerlo de esta forma   Public Sub Mayusculas()  Dim c As Range   For Each c In Selection  c.Value = UCase(c.Value)  Next c   End Sub   Public Sub Minusculas()  Dim c As Range  For Each c In Selection
  • 63. c.Value = LCase(c.Value)  Next c   End Sub  Comprobamos que trabajen bien, probándolas desde el Editor VBA o desde la interfaz de Excel desde el menú Herramientas | Macro | Macros... o con el método abreviado de teclado Alt + F8  Estas macros las declaramos Publicas (para detalles de este tema lee el articulo Publica o Privada, ¿cual usar?), pero al guardar nuestro archivo como Complemento, estas macros no las podrás ver y por consiguiente ejecutar, desde la interfaz de Excel, es como si las macros pasaran a ser Privadas, entonces, para poder ejecutarlas tienes que asignarlas a alguna elemento de la pantalla, un menú, un botón o algún control, como notaste en los Complementos Autoguardar y el Solver, estos agregaban una nueva opción al menú Herramientas, esto no es obligatorio, ya que puedes agregar una opción en cualquier parte de los menús o submenús existentes o de plano crear un nuevo menú propio, para nuestro ejercicio agregaremos un submenú al menú Herramientas que se llame Utilidades y dentro de este las opciones Mayúsculas y Minúsculas, para ello usaremos el siguiente código...  Public Sub PonerMenu()  Dim NuevoMenu As Object  Dim OpcionMenu As Object  Dim MenuHerr As Object   ' Busca si el menú ya esta existe  Set NuevoMenu = CommandBars.FindControl(Type:=msoControlPopup, Tag:="Utilidades")  ' Si no lo encuentra la variable es Nothing  If NuevoMenu Is Nothing Then  ' Busca el menú Herramientas y devuelve una referencia a el  Set MenuHerr = CommandBars.FindControl(ID:=30007)  ' La posibilidad de que sea Nothing es remota pero hay que considerarla  If Not MenuHerr Is Nothing Then  ' Agrega un sunmenú al menú Herramientas  Set NuevoMenu = MenuHerr.Controls.Add(Type:=msoControlPopup, Temporary:=True)  With NuevoMenu  ' Le ponemos Titulo  .Caption = "&Utilidades"  ' Usamos esta propiedad como utilidad para la busqueda  .Tag = "Utilidades"  'Garantizamos que este visible  .Visible = True  End With   Set OpcionMenu = NuevoMenu.Controls.Add(Type:=msoControlButton, _  Temporary:=True)  With OpcionMenu  .Caption = "Mayusculas"  'Le asignamos la macro que queramos ejecutar  .OnAction = "Mayusculas"  End With   Set OpcionMenu = NuevoMenu.Controls.Add(Type:=msoControlButton, _  Temporary:=True)  With OpcionMenu  .Caption = "Minusculas"  .OnAction = "Minusculas"  End With   End If  End If   'Liberamos la memoria  Set MenuHerr = Nothing
  • 64. Set NuevoMenu = Nothing  Set OpcionMenu = Nothing   End Sub   Public Sub QuitarMenu()  Dim Menu As Object   'Busca el menu, si lo encuentra lo borra, si no, no hace nada  Set Menu = CommandBars.FindControl(Type:=msoControlPopup, Tag:="Utilidades")  If Not (Menu Is Nothing) Then  Menu.Delete  End If   End Sub  Ahora, para que la macro PonerMenu se ejecute de forma automática al abrir el Complemento y la macro QuitarMenu se ejecute automáticamente al cerrar el Complemento, las "llamamos" desde los eventos Open y BeforeClose del libro, respectivamente...  Desde el Editor VBA selecciona el objeto ThisWorkbook  Ve al menú Ver | Código o presiona la tecla F7  Copia o escribe el siguiente código.  Option Explicit   Private Sub Workbook_BeforeClose(Cancel As Boolean)  QuitarMenu  End Sub   Private Sub Workbook_Open()  PonerMenu  End Sub  Ahora, antes de guardarlo como un Complemento, guarda el archivo con estos últimos cambios de modo que siempre tengas un "respaldo" de tu complemento como un libro normal XLS.  Ve al menú Archivo | Guardar Como... y del cuadro de lista desplegable (ComboBox) Guardar como tipo, buscas y seleccionas Complemento de Microsoft Excel (*.xla)
  • 65. Establece el nombre del Complemento, normalmente será el mismo de mi archivo XLS, pero antes de aceptar y cerrar este cuadro de dialogo, observa como Excel, al decirle que queremos guardarlo como Complemento, solito nos cambia la ruta de acceso, da un clic en el cuadro de lista desplegable (ComboBox) Guardar en, y observa la ruta donde lo dejara, la cual normalmente es C:WINDOWSApplication DataMicrosoftComplementos claro, en este momento, si lo deseas, puedes cambiar esa ruta y guardar tu complemento donde gustes.
  • 66. En este momento ya tienes dos archivos, uno XLS y otro XLA, aunque el XLA (el Complemento) no queda abierto en estos momentos, hay que cargarlo para probarlo y es lo que haremos a continuación.  Cierra y vuelve a entrar a Excel, esto es con la finalidad de que reconozca el nuevo complemento, NO es indispensable, pero ya te iras dando cuenta, cuando es conveniente hacerlo y cuando no.  Ve al menú Herramientas | Complementos, la lista de complementos esta en orden alfabético, así, que si has usado los nombres propuestos, desplázate hasta la letra U y debe de aparecer el Complemento Utilidades como se ve en la siguiente imagen, en caso de que hayas guardado tu complemento en otro lugar, tienes que usar el botón de comando (CommandButton) Examinar... para localizarlo...  Ve al menú Herramientas y observa como tenemos nuestro menú personalizado, agregado automáticamente al cargar nuestro complemento y que será eliminado automáticamente al cerrarse o descargarse.
  • 67. Pruébalo, llena algunas celdas con texto y conviértelas a MAYUSCULAS o minúsculas, prueba a hacerlo en cualquier otro libro, prueba a cargar y descargar el complemento para verificar que se elimina el menú correctamente.  Por ultimo, habrás notado en los complementos instalados que al seleccionar en la lista de Complementos, en al parte inferior aparece una breve descripción del propósito de dicho complemento, si bien esto no puede sustituir a la documentación que debe de acompañar a todo código o programa, es útil para de primera mano, saber la utilidad del complemento, agreguémosle esta propiedad a nuestro complemento, para esto, descarga el complemento y abre el archivo XLS original.  Ve al menú Archivo | Propiedades... y selecciona la ficha Resumen, en esta, puedes llenar todos los campos que quieras, pero los importantes son: Titulo y Comentarios, el campo Titulo será lo que aparezca en el cuadro de lista Complementos y el campo Comentarios se verá en la parte inferior de dicho cuadro, complétalos a tu gusto, te muestro lo que yo escribí...
  • 68. Vuelve a realizar el proceso de guardar como Complemento, por supuesto, al querer guardarlo con el mismo nombre, te preguntara si quieres reemplazarlo, respondes que si y cierras y vuelves a entrar a Excel, vas al menú Herramientas | Complementos buscas tu complemento y veras que corresponde lo que escribiste en los campos de las propiedades del archivo, con lo que ves aquí... • Muy bien hecho, cierto, todavía puede tener muchas mejoras y las tiene, sobre todo en lo que respecta a controlar errores, pero eso se verá en otro capitulo, por lo pronto con esto basta...
  • 69. La mayoría de las macros y funciones que hagamos, son susceptibles de usarse desde un modulo estándar y un libro común como macro o incorporarse a un Complemento, con el uso y la experiencia, tu mismo discernirás cuando es conveniente lo uno y cuando lo otro. • Para los miembros de la lista, el archivo original XLA esta disponible en el área de archivos. Descargar el código de este artículo. Exportador de macros Este complemento, extrae de todos los libros abiertos, las macros o funciones que contenga, con la posibilidad de Exportarlas a cualquir otro libro abierto, al cargarlo, te agrega una nueva opción al menú Herramientas, llamada Exportar Macros... el cual, al ejecutarlo, te muestra el siguiente cuadro de dialogo Su uso de detallará en esta página, aunque realmente es muy sencillo, el complemento esta disponible en el área de ficheros de la lista, o puedes descargarlo desde aqui, te aclaro que para que puedas ver el código, el archivo esta guardado como XLS, pero puedes guardarlo como complemento, pues esta pensado para que funcione como tal... Descargar el Complemento Exportar Macros de este artículo.