domingo, 27 de noviembre de 2011

Antes de empezar

Dale un vistazo a mi “política sobre las consultas” que puede resultar útil de conocer.

Ahora si, empecemos

¿Visual Basic desde cero? ¿y en unas pocas lecciones simples que cualquiera puede seguir?. Yo creo que se puede. De hecho la mayoría aprendemos a programar así, lo que cuesta es la partida y eso es lo que pretendo entregar en este pequeño curso.

Primero, para hacer programas en Visual Basic necesitamos el entorno de programación en cualquiera de sus versiones. Pero si tenemos el Office 97 también podemos hacer programas sin necesidad de comprar el Visual Basic. Basta con entrar desde el Word 97 y tendremos el entorno del VB5.0 practicamente completo. Para efectos prácticos eso es lo que usaremos para aprender a programar en VB.

Así abriremos el Word 97 y escogeremos Herramientas, Macros, Editor de Visual Basic y aparecerá lo siguiente:

Explorador de proyectos
El explorador de proyectos es una herramienta de exploración y gestión que muestra una lista jerárquica de cada proyecto abierto. También muestra cada una de las componentes asociadas con los proyectos, como los documentos de Word, formularios, módulos de clase y referencias.
En palabras sencillas hay que dejarlo tal como está. A medida que agreguemos objetos a nuestro progranma irán apareciendo en el explorador y nos servirá para movernos de un componente a otro.

Ventana de propiedades
La ventana de Propiedades muestra las propiedades para el objeto activo (Formulario de usuario o control). Ofrece una manera visual de configurar y modificar propiedades. En la ventana de propiedades , las propiedades se pueden listar alfabéticamente o por categorías.
En palabras sencillas, cuando agregamos un objeto este tiene varias “propiedades” como su color, tamaño, tipo de letra, etc. En esta ventana podemos cambiar las propiedades del objeto “activo” (iluminado) en ese momento.

Barra de herramientas
Es donde aparecen los botones para las funciones mas usadas, esta justo abajo de la Barra de menús que tiene los menús con todas las opciones del Visual BAsic

Area de trabajo
Es donde colocamos nuestros objetos (Formularios o controles) y les agregamos código

Como se hacen los programas en Visual Basic:

Los programas en Visual Basic se hacen en dos etapas
a) Se dibujan las pantallas
b) Se coloca código a los objetos
Así de simple, con esto tenemos toda la teoría necesaria para programar en VB

Cuando estudié computación por primera vez (fin de los 70, época del Fortran) mi primer programa fue uno de conversión de dólares a pesos. Siempre que he aprendido un lenguaje comienzo haciendo eso ya que permite aprender las funciones basicas más usadas en la mayoría de los programas de la vida real, ingreso de datos, cálculo, despliegue (salida) de datos. Así, nuestro primer programa sera un CONVERTIDOR DE DOLARES A PESOS.

Manos a la obra con el paso a) dibujaremos las pantallas. Las pantallas en VB se llaman Formularios de Usuario, asi es que procedemos a Insertar, UserForm (usando la barra de menús), nos aparece lo siguiente:


Aparece en nuestra Area de trabajo un formulario llamado UserForm1 (nombre por defecto) y abajo una caja de herramientas con los componentes que podemos colocar dentro de ese formulario.

Fijense que la barra superior de UserForm1 está de color azul (iluminada) lo que indica que es el componente activo en este momento.

Ahora experimentemos con las propiedades de la UserForm1. Primero hagamos click en la propiedad “Caption” y cambiemos el valor por defecto (UserForm!) escribiendo encima de eso “Convertidor de Dolares a Pesos)”. Vean como cambia el título de nuestro formulario.

Seguidamente cambiemos la propiedad “Back color” haciendo click en ella y luego un click sobre el botón con flecha que aparece a la derecha. Aparecerá una paleta de colores. Haga click sobre cualquier color y verá como cambia el fondo de nuestro formulario. Busque más propiedades que le parezcan obvias y cambie sus valores. Si no nota ningún efecto restaure la propiedad a su valor original (con el tiempo se familiarizará con cada una de las propiedades).

Si, por esas cosas de la vida se le pierde la caja de herramientas, la podrá recuperar fácilmente con “Ver” “Caja de Herramientas” de la barra del menú. Si no encuentra alguna propiedad (por ejemplo “Name” recuerde que la ventana de propiedades las muestra en orden alfabetico y por categorías, busque en ambos lados pulsando en la ventana correspondiente.

Ahora hay tres clases de controles que usaremos en nuestro proyecto: labels (etiquetas), textboxes (cajas de dialogo o de texto) y un commandbutton (botón de comando), todas estos controles se sacan de la caja de herramientas de abajo del formulario.

Los labels son los marcados con la letra “A” en la caja de herramientas, haga click sobre el icono y luego coloquese sobre el formulario y dibuje arrastrando el mouse el tamaño en que desea que aparezca su label. Luego en la ventana de propiedades cambia la propiedad “Caption” del primer label escribiendo “Dolares” en lugar de label1. También puede cambiar la propiedad “Name” a ldolares (por labeldolares). Repita el procedimiento creando otro label con caption “Pesos” y nombre lpesos (por labeltpesos).

Luego escoja un textbox del la caja de herramientas (el icono con “ab”) y dibujelo al lado del label ldolares, borrele la propiedad “Caption” (que quede en blanco) y cambie la propiedad “name” a tdolares. Con el mismo procedimiento cree un textbox llamado tpesos al lado del label lpesos.

Luego arrastre un boton de la caja de herramientas (el rectangulo sin nombre) y dibujelo en el formulario, luego cambiele la propiedad “Caption” a “Borrar”. Si ha llegado hasta el punto que muestra la figura ya tiene la mitad del programa listo.


Note que en éste ejemplo cambié la propiedad “Backcolor” del formulario y la propiedad “Font” de los labels a “Bold” y “10 pt”.

Aquí tenemos nuestra pantalla rudimentariamente dibujada. Ahora nos falta poner el código, para ello debemos pensar “que es lo que queremos que haga el programa”. En éste caso yo deseoque “cuando escriba una cifra en el textbos de dolares aparezca su equivalencia en el textbox pesos y viceversa”.

O sea que el programa debe actuar cada vez que escribamos algo en uno de los textbox y luego de presionar Enter.

En otras palabras tenemos que poner un código a cada uno de los textbox indicando que deseamos que ocurra cada vez que escribimos algo y apretamos Enter. Para poner código en el textbox de “tdolares” simplemente hacemos doble click sobre él y aparecerá la “ventana de códigos” con dos ventanillas en la parte superior; la de la izquierda dirá ldolares (el nombre del objeto) y en la derecha una lista deplegable con todos los “eventos” permitidos para ese objeto (change, click, mousedown, etc…). De esa lista escogemos el evento “Exit” (que significa que presionamos la tecla Enter) y escribimos en la ventana el siguiente código:

Private Sub tdolares_Exit(ByVal Cancel As MSForms.ReturnBoolean)
tpesos.text = Val(tdolares.text) * 500
End Sub

(la primera y la última línea las escribe solo el sistema, hay que escribir nada más que el texto de en medio)

Es decir que cuando escribimos algo en el textbox llamado tdolares y luego presionamos Enter se calculará el varol equivalente en pesos. Nótese que lo que escribimos en el textbox llamado tdolares queda almacenado en la propiedad “tdolares.text”,, le extraemos su valor con val(tdolares), multiplicamos este valor por 500 y lo asignamos como propiedad “text” al textbox llamado “tdolares”. Al principio puede parecer enredado pero una vez que nos acostumbramos a los objetos a los que les cambiamos sus propiedades esto se convierte en pan comido. Para salir de la ventana de códigos y volver al formulario simplemente hacemos click en “UserForm1″ del explorador de proyectos (ventana superior izquierda)

Para el otro textbox (tpesos) también hacemos doble click, escogemos el evento “exit” y escribimos:

Private Sub tpesos_Exit(ByVal Cancel As MSForms.ReturnBoolean)
tdolares.text = Val(tpesos.text) /500
End Sub

Finalmente volvemos al formulario y programamos (agregamos código) al botón “Borrar” haciendo doble click sobre él y escribiendo ¿adivinan que?…claro:

Private Sub CommandButton1_Click()
tdolares.Text = “”
tpesos.Text = “”
End Sub

Nuestro primer programa está listo y nuestra ventana de códigos debe verse más o menos así:

Private Sub CommandButton1_Click()
tdolares.Text = “”
tpesos.Text = “”
End Sub

Private Sub tdolares_Change()

End Sub

Private Sub tdolares_Exit(ByVal Cancel As MSForms.ReturnBoolean)
tpesos = Val(tdolares) * 500
End Sub

Private Sub tpesos_Exit(ByVal Cancel As MSForms.ReturnBoolean)
tdolares = Val(tpesos) / 500
End Sub

Si está todo correcto no sería mala idea que lo grabaran, haciendo click sobre el icono del diskette.

¡Y llegó el momento de probar nuestra primera obra de arte!. Si se fijan en la barra de herramientas hay tres botones similares a los de una grabadora. Para que parta el programa simplemente presionen el boton correspondiente al “Play” o bien presionen F5 (da lo mismo).

¡Disfrutenlo!, y si les da error o no les funciona como es debido entretenganse buscando donde está la falla. Ese ha sido mi pasatiempo de los últimos 5 años con el VB.

Otra aplicación muy simple

Imaginen que tenemos una gran hoja de cálculo como la de este ejemplo, con datos sobre las universidades chilenas, y nos reculta complicado comparar los datos de dos universidades porque tenemos que hacer gran desplazamineto en la plantilla. Basta que hagamos un formulario como este


Con tres ComboBox, dos TextBox y dos CommandButtom y le agregamos códico al evento Form_Activate para que lea y llene los ComboBox al cargar el formulario, luego programamos el CommandButtom1 para que ubique los datos que queremos comparar y los muestre en los TextBox correspondientes. Lo bueno de este ejemplo es que nos muestra como usar los índices de los ComboBox y como referenciar celdas específicas de una planilla Excel, el código es el siguiente

Más adelante entenderán como funciona, por mientras pueden copiarlo y usarlo como ejercicio, son apenas 22 líneas de código

APRENDER HACIENDO


También podrían entretenerse haciendo algunos Prototipos en Visual Basic

Ahora en serio: de que se trata el asunto

El Visual Basic para Aplicaciones VBA, es un subconjunto casi completo de VB 6.0 Profesional Edition, que viene incluido GRATIS en los componentes de Microsoft Office 97; Word, Excel, Power Point y Acces. Practicamente cualquier cosa que se pueda programar en VB6.0 se puede hacer también dentro de un documento de Office, con la sola limitación que el producto final no se puede compilar separadamente del documento, hoja o base de datos en que fue creado. Es decir que se convierte en una macro (super macro mas bien) que se puede instalar o distribuir con solo copiar el documento, presentación o base de datos.

¿Suena enredado? veamos con un ejemplo (solo muestro los resultados, no como hacerlo). Yo tengo una plantilla de Word llamada “egresos.doc”. Al abrirlo se ve como un escrito común y corriente pero que solo tiene un encabezado y una tabla vacia. Pero si miramos la barra de herramientas veremos un botón con el icono “cara sonriente”. Al hacer click sobre ese icono aparece un programa en Visual Basic dentro del documento.

La figura siguiente muestra como vemos el documento al abrirlo:


Si hacemos click sobre el botón de “cara sonriente” aparece la siguiente pantalla dentro del documento



Para los que conocen Visual Basic esta pantalla les parecera familiar; es una form, con textbox para entrada de datos y con un botón de comando. La diferencia es que está codificada DENTRO de un documento de Word y nos permitirá crear un comprobante contable de manera muy sencilla para el operador

Y al terminar de ingresar los datos se generará un comprobante de egreso como se muestra a continuación


¿Se va entendiendo?. Como pueden ver el potencial es enorme, ya que se programan aplicaciones con las que prácticamente todos los usuarios están familiarizados. Adicionalmente la programación en si es sencillísima para cualquiera que conozca el Visual Basic.

¿Y como se hace?. Bueno, como se programa en VBA será el tema de las siguientes lecciones de éste curso rápido


Comenzando a programar en VBA

Nota Preliminar: Al abrir macros en Word97 aparece una pantalla de advertencia sobre la posibilidad de virus (como VBA es un lenguaje completo, ahora se puede encapsular facilmente un virus dentro de un documento de Office), les recomiendo que hagan caso omiso de esta advertencia y coloquen el botón para permitir la ejecución de macros para este documento.

Para hacer un programa en VBA necesitas desde el Office 97 en adelante. En este ejemplo programaremos un documento de Word. Para ello solo debemos abrir un nuevo documento de Word y escoger Herramientas, Macros, Editor de Visual Basic, con lo que aparecerá una pantalla como esta:


Para los que conocen el VB 6.0 esta pantalla les resultará muy familiar, para los que conocen versiones anteriores es lo mismo, solo que el mapa del proyecto y la ventana de propiedades están a la izquierda siempre visibles.

La primera diferencia con VB esta en el mapa del proyecto que aparece en la ventana superior izquierda y muestra un árbol de directorios con Normal, Project(Documento1), Referencia a Microsoft Word, etc..(a veces aparecen más ramas según la instalación del Office). En esta ventana nosotros escogemos donde se va a guardar nuestro proyecto y tenemos dos alternativas; si nos ubicamos en Normal nuestro macro será accesible para cualquier documento que abramos en Word. Si nos ubicamos en Project(Documento 1) el macro solo estará disponible para el documento específico que estamos creando. En nuesto ejemplo grabaremos un macro solo en nuestro documento, por lo que nos colocamos en Project(Documento 1).

El primer paso al crear un macro en VBA es darle un nombre, para ello tenemos que ir a Insertar, Modulo del menú con lo cual aparecerá en el mapa de proyecto un Modulo1. Nos vamos a la ventana de propiedades (abajo izquierda) y le cambiamos la propiedad (Name) a Prueba1 (podemos colocar cualquier nombre por supuesto). Este será el nombre de llamada del macro. Hacemos doble click sobre el y aparecerá la ventana para ingresar el código de la macro. En nuestro ejemplo (así como en la mayoría de los casos) queremos que nuestro programamuestre una Form al iniciarse así es que escribimos:

Sub prueba1()
UserForm1.show
End Sub

Luego tenemos que crear nuestra form, usando Insertar, UserForm, con lo que aparecerá lo siguiente:


Con las herramientas de la caja arrastramos las textbox, labels y CommandButtom para obtener una form del tipo


colocar Enter. Para ello hacemos doble click sobrte las textbox, nos cambiamos a Exit y ponemos

Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
TextBox1.Text = UCase(TextBox1.Text)
End Sub

Nota para los que conocen versiones anteriores al VB5.0: En las versiones anteriores si queríamos que el foco pasara hacia el textbox de abajo al colocar Enter usabamos Keypress y luego hacíamos un If Keyascii=13 then….

En la versión 5.0 se usa Exit y el foco pasa automáticamente hacia abajo. Otra importante diferencia con las versiones anteriores es que el órden en que pasa el foco al colocar Enter puede ser especificado usando Ver, Orden de Tabulación. Así puedes colocar el orden como quieras pasando hacia arriba o abajo los distintos elementos del UserForm. Para poder usar esta opción tiene que estar la UserForm visible (no la ventana de códigos).

Bueno, hasta aquí no hay ninguna novedad con respecto a VB5.0. La programación específica de VBA la colocaremos en el botón OK (CommandButton1). Hacemos doble click sobre este botón y escribimos:

Private Sub CommandButton1_Click()
With Selection
. Font.Size = Val(10)
. ParagraphFormat.LineSpacingRule = wdLineSpaceSingle
. TypeParagraph
. Font.Name = “arial black”
. ParagraphFormat.Alignment = wdAlignParagraphCenter
. TypeText Text:=vbTab & “Programa de Prueba”
. ParagraphFormat.Alignment = wdAlignParagraphLeft
. TypeParagraph
. TypeParagraph
. Font.Name = “Arial”
.TypeText Text:=vbTab & “NOMBRE ” & vbTab & TextBox1.Text
.TypeParagraph
.TypeText Text:=vbTab & “DIRECCION” & vbTab & TextBox2.Text
. TypeParagraph
. TypeText Text:=vbTab & “TELEFONO ” & vbTab & TextBox3.Text
. TypeParagraph
. TypeParagraph
End With
End Sub

¡Y ya tenemos listo nuestro primer programa!. ahora lo grabamos haciendo click en el icono del diskette de la barra de herramientas del VBA y le colocamos un nombre (en este caso yo lo grabé como Prueba 1 VBA) Luego cerramos todo..

Para ejecutarlo ingresamos abrimos el documento Prueba 1 VBA.doc y escogemos Herramientas, Macros, Macros, iluminamos el macro prueba1 y hacemos doble click. Deberá aparecer la pantalla siguiente:


Para hacerlo rápidamente usamos las opciones Copiar, Pegar, Formato, Alinear a la izquierda, Espacio Horizontal, Igualar, etc..

Una vez que tenemos creada nuestra UserForm pasamos a programarla, primero haremos click sobre cada text box para que las entradas se conviertan automáticamente a mayúsculas al Al ingresar los datos y hacer click en el botón Ok, se creará el documento. Este ejemplo es muy básico por su propósito didáctico. Después de pulsar el Botón Ok tendremos que cerrar la UserForm1 Clickeando en la X de la esquina superior, posteriormente veremos que prácticamente todo puede ser automatizado.

Lo más bonito de todo esto es que si copian el documento “prueba 1 de VBA.doc” en un pendrive USB y lo colocan en CUALQUIER computador que tenga Office 97, el programa funciona igual sin importar cuan complejo sea siempre y cuando no use componentes especiales como veremos más adelante. Es decir CERO trabajo de instalación. Les adjunto este primer documento programado, para que lo examinen y lo comparen con el que han hecho ustedes mismos en este ejercicio. Eso si cambienle el nombre si lo van a grabar en el mismo directorio del disco duro donde escribirán la prueba, para evitar regrabarlo..

Bueno, ya hicimos un programa y seguramente tendrán serias dudas por los “chorizos” de código del tipo “.ParagraphFormat.Alignment = wdAlignParagraphCente” y otras lindezas que colocamos en el botón Ok. La pregunta del millón es ¿tendré que aprenderme ESOS comandos antes de programar en VBA?, la respuesta es que afortunadamente no es necesario. No hay que saber nada de la “Microsoft Foundation Classes” para programar pues hay un truco muy sencillo que nos entrega de manera automática todos los comandos que necesitemos.

Pero eso será tema de la próxima sesión. Espero que todo les resulte Ok y no se hayan aburrido

Como programar en VBA sin conocer el modelo de objetos

La complejidad del código en VBA (entendiendo por complejidad el uso de instrucciones larguísimas y muy estructuradas en lugar de instrucciones simples) nace de la decisión de Microsoft de convertir sus programas en modelos de objetos permitiendo “un código más limpio con una síntaxis y semántica más consistente”. Una elección poco afortunada para los programadores ‘antiguos’ que nos complica la codificación, en fin, las nuevas generaciones se sentirán más confortables con esto supongo..

La idea de estudiar el modelo de objetos de Microsoft (la Microsoft Foundation Classes) me parece una tontería para un programador casual (como yo), más aún considerando que cuando se llega a dominar algo tan especializado, esto ya comienza a caer en desuso por obsolecencia.

Todo este largo preámbulo para indicarles un truco que les permitirá conocer el código para programar cualquier cosa en VBA sin necesidad de estudiar nada (que rico ¿no?). Un ejemplo práctico: en nuestro ejercicio anterior abrimos una form que nos permitió ingresar nombre, dirección y apellido y luego los escribió en un formulario del Word. Ahora vamos a colocar un encabezado con el nombre y un pie de página con la leyenda “página # de #”. Para conocer el código hacemos lo siguiente:

Abrimos una página en blanco y nos vamos a Herramientas, Macros, Grabar nueva macro y Aceptar (quedará con el nombre por defecto Macro1). Aparecerá una imagen de “grabadora” que indica que estamos grabando la macro. Entonces nos vamos a Ver, Encabezados y pies de página, escribimos el encabezado y el pie de la manera deseada y apretamos el botón que detiene la grabadora.

Luego nos vamos a Herramientas, Macros, Macros, Editar y allí tenemos TODO el codigo, listo para ser cortado y pegado en nuestra aplicación, que en éste caso es:

Sub Macro2()
‘ Macro2 Macro
‘ Macro grabada el 24-12-98 por TOMAS BRADANOVIC
If ActiveWindow.View.SplitSpecial <> wdPaneNone Then
ActiveWindow.Panes(2).Close
End If
If ActiveWindow.ActivePane.View.Type = wdNormalView Or ActiveWindow. _
ActivePane.View.Type = wdOutlineView Or ActiveWindow.ActivePane.View.Type _
= wdMasterView Then
ActiveWindow.ActivePane.View.Type = wdPageView
End If
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
Selection.TypeText Text:= _
“Tomás Bradanovic, Consultoría en Proyectos de Inversión Públ”
Selection.TypeText Text:=”ica”
Selection.TypeParagraph
Selection.HeaderFooter.Shapes.AddLine(72#, 93.6, 540#, 93.6).Select
If Selection.HeaderFooter.IsHeader = True Then
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageFooter
Else
ActiveWindow.ActivePane.View.SeekView = wdSeekCurrentPageHeader
End If
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldNumPages
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldNumPages
Selection.Fields.Add Range:=Selection.Range, Type:=wdFieldPage
NormalTemplate.AutoTextEntries(“Página X de Y”).Insert Where:=Selection. _
Range
ActiveWindow.ActivePane.View.SeekView = wdSeekMainDocument
End Sub

¿Que tal?, ahora podrían por ejemplo sustituir el string “Tomás Bradanovic….” por TextBox1.Text o cualquier otra variable y el asunto funciona igual.

Como ejercicio (y entretención) les recomiendo que obtengan con éste método el código para colocar doble espacio, para imprimir, para modificar el tamaño de papel, el tipo y seteo de la impresora, los tipos de letra…en fin todo lo que se les ocurra, luego pueden cortar y pegar el código en el ejercicio de la clase anterior a ver como les queda.

Bueno, con este dato yo creo que tienen entretención para rato y además es una manera indolora de aprenderse el modelo de objetos de Microsoft, practiquen y diviertanse

Código para tareas usuales

Del feedback recibido (y que agradezco mucho) he notado que incluso personas que no conocen el Visual Basic pueden beneficiarse del VBA usando sus características básicas. Para ellos les incluyo un resumen de códigos que pueden cortar y pegar en sus programas para las tareas que se usan frecuentemente. Aquí van:

1. Para que el form desaparezca del documento después de clickear un botón. Al final del código del botón se agrega lo siguiente:

Unload UserForm1 (o, el nombre de la form que estan usando, si lo han cambiado)

2. Para que un documento se imprima automáticamente después de clickear un botón. Se agrega el siguiente código:

Application.PrintOut FileName:=”Permiso.doc”, Range:=wdPrintCurrentPage, Item:= _
wdPrintDocumentContent, Copies:=1, Pages:=”", PageType:=wdPrintAllPages, _
Collate:=True, Background:=True, PrintToFile:=False
Selection.WholeStory
Selection.Delete Unit:=wdCharacter, Count:=1
Unload UserForm1

(en este caso el documento se llama permiso.doc, en lugar de ese nombre se coloca el nombre del documento que estén usando)

3. Para cambiar el tamaño y tipo de font

Selection.Font.Size = 10

Selection.Font.Name=”Arial”

4. Para colocar espacio simple, doble, etc.

Selection.ParagraphFormat.LineSpacingRule = wdLineSpaceSingle

5. Para alinear a izquierda, derecha, centro o justificado completo

Selection.ParagraphFormat.Alignment = wdAlignParagraphJustify (justificado completo)

Selection.ParagraphFormat.Alignment = wdAlignParagraphRight (justificado derecha)

etc..

6. Para escribir una linea de texto (con wordwrap automático)

Selection.TypeText Text:=”este texto” (imprime la palabra “este texto”, si la palabra es muy larga hace el wordwrap automáticamente)

Selection.TypeText Text:=TextBox1.Text (escribe el contenido de TextBox1.Text)

7. Para pasar a la línea siguiente (equivale a poner “enter”)

Selection.TypeParagraph

En general, para saber cualquier código basta con grabar una macro, hacer lo que deseamos codificar y luego examinar la macro en “editor de Visual Basic” ¡El código aparecerá solito!

8. Para no escribir “selection” a cada rato

Si se fijan, muchas instrucciones especificas del VBA empiezan con “Selection”, para no repetirlo a cada rato se puede usar with… end with así:

(ojo con los puntitos antes de Font.Size, Font.Name, etc, en esta pantalla no se notan muy bien, pero deben escribirse)

With Selection
.Font.Size = 10
.Font.Name=”Arial”
End With

9. Como cambiar las propiedades (solo para principiantes)

Para los que no manejan el Visual Basic, pero ya han hecho el primer ejemplo, les propongo que exploren la ventana de “propiedades” que aparece en la esquina inferior izquierda. Cada vez que seleccionamos un objeto de nuestra form (por ejemplo una textbox, un commandbutton, a la propia userform) cambia la lista de propiedades. Modificando valores de esta lista también podemnos modificar el aspecto y comportamiento de los objetos. Por ejemplo si hacemos doble click en la propiedad “backcolor” podemos cambiar el color de fondo del objeto. Con “forecolor” cambiamos el color del texto, con “font” cambiamos el font y sus características, etc.

Yo mismo aprendí a programar en Visual Basic jugando con las propiedades, es muy fácil e interesante explorar lo que significa cada propiedad.

En Visual Basic cada objeto tiene “propiedades” (colores, altura, posición, visible o invisible, y otras que dependen del objeto) y “eventos”. Los eventos aparecen cuando hacemos doble click sobre un objeto. En la parte superior derecha de la ventana de programación aparece la lista de eventos. Al hacer doble click aparece el evento por defecto (p.ej si es un botón el evento por defecto es “click”, si es un textbox, el evento por defecto es “change”, etc.).

Para programar un objeto escogemos el evento de la lista y luego escribimos el código en la pantalla. Por eso en nuestro primer ejemplo programamos el Commandbutton1 con el evento “click” (es decir “cuando se haga click con el mouse sobre este objeto, ejecute el siguiente código”)

Tal vez ya es tiempo de revisar unas pocas Buenas Prácticas de Programación

Un Ejemplo Sencillo de Programación en Excel

Siguiendo el esquema de introducir el VBA mediante ejemplos simples y fáciles de reproducir, esta vez les presento una macro que permite crar un documento tipo factura en una hoja de cálculo. Se trata de un ejemplo rudimentario al que se le han sacado todos los detalles para hacer más fácil su comprensión y se puede programar con facilidad en un rato.

Primero que nada abrimos el Excel y entramos al editor de Visual Basic con Alt-F11 (esta es una forma abreviada que nos evita usar Herramienta, Macro, Editor de Visual Basic). Luego insertamos un nuevo modulo (mantenemos el nombre por defecto Módulo1) y escribimos en el:

Sub ejemplo()
UserForm1.Show
End Sub

Enseguida insertamos un nuevo formulario (mantenemos el nombre por defecto UserForm1) y le creamos 6 textbox, 6 labels y 1 botón de comando como muestra la figura:


Esta vez me pondre un poco más ordenado para colocar los nombres, a los labels les coloco los siguientes nombres: fecha, cliente, direccion, RUT, articulo, precio, cantidad (modificando su propiedad “Name” en la ventana de propiedades abajo a la izquierda). A los textbox les coloco los nombres de : tfecha, tcliente, tdireccion, trut, tarticulo, tprecio, tcantidad.

Luego usando Formato, Igualar Tamaño, Ambos, dejo a todos los textbox del mismo tamaño y usando Formato, Alinear, Izquierda los dejo bien alineados. También puedo usar Espaciado Vertical, Igualar para que queden bien espaciados.

Enseguida usando Ver, Orden de tabulación me aseguro que cada vez que coloco enter el foco se corra correctamente al textbox que corresponda. Asi el ordern de tabulación debe quedar: tcliente, tdireccion, trut, tarticulo, tcantidad y luego todos los demás en cualquier orden.

Ahora haciendo doble click sobre el commandbutton1 lo programo (evento click) de manera que quede así:

Private Sub CommandButton1_Click()
Hoja1.Cells(linea, 2) = tarticulo.Text
Hoja1.Cells(linea, 3) = Val(tprecio.Text)
Hoja1.Cells(linea, 4) = Val(tcantidad.Text)
Hoja1.Cells(linea, 5) = Val(tprecio.Text) * Val(tcantidad.Text)
Range(“E19″).Select
ActiveCell.FormulaR1C1 = “=SUM(R[-10]C:R[-1]C)”
Range(“E20″).Select
tarticulo.Text = “”
tprecio.Text = “”
tcantidad.Text = “”
linea = linea + 1
End Sub

Como se ve en el código anterior, para llenar la celda A1 por ejemplo usamos Hoja1.Cells(1,1)=”texto”, para la A2 Hoja1.Cells(2,1) etc. Noten que podemos llenar no solo la hoja activa en este momento sino que culquiera del libro activo (recuerden que en excel un “libro” puede tener varias “hojas” simultaneamente). La variable “linea” la inicializo cuando se carga el UserForm1 al valor 9 pues los datos deben escribirse a partir de la linea 9.

Luego tenía que calcular el total sumando la columna de los subtotales. Como yo no sabia el código para programar una suma, simplemente me fui a Herramientas, Macro, Grabar Macro y luego hice la operación de forma manual (escribiendo la fórmula en la celda deseada). Luego volví a Herramientas, Detener Grabación y examiné el código que apareció en un nuevo módulo, que era el siguiente:

Range(“E19″).Select
ActiveCell.FormulaR1C1 = “=SUM(R[-10]C:R[-1]C)”
Range(“E20″).Select

Lo corté y lo pegue donde correspondía. Finalmente agregué el código que limpia los textos de los textbox tarticulo, tprecio y tcantidad e incrementé la variable “linea” en una unidad (para que los siguientes datos se graben una linea más abajo)

Enseguida hice doble click sobre el UserForm1 y programé algunos valores para cuando se cargue el Form (initialize), colocando lo siguiente:

linea = 9
cliente.Caption = “Nombre”
direccion.Caption = “direccion”
articulo.Caption = “Articulo”
precio.Caption = “precio”
cantidad.Caption = “cantidad”
RUT.Caption = “RUT”
Columns(“B:B”).ColumnWidth = 8
Columns(“B:B”).ColumnWidth = 45
Columns(“C:C”).ColumnWidth = 10
Columns(“D:D”).ColumnWidth = 10
Columns(“E:E”).ColumnWidth = 10

Inicializé el valor de linea=9, coloqué los valores caption a los label (también podría haberlo hecho directamente modificasndoles la propiedad, usé esta forma solo para mostrarla) y definí los anchos de las columnas.

Luego borré el macro recientemente creado Iluminando Modulo2, Archivo, quitar Modulo 2 y No exportar, volví a Herramientas, Macros, Grabar Macro y Escribí los títulos, coloqué los cuadriculados, centrados, negrita, etc. Luego Herramientas, Macros, Detener Grabación y corté y pegué a continuación el código resultante que fue el siguiente:

‘ Macro grabada el 15-08-99 por TOMAS BRADANOVIC
Range(“C1″).Select
ActiveCell.FormulaR1C1 = “FACTURA”
Range(“A3″).Select
ActiveCell.FormulaR1C1 = “Fecha”
Range(“A4″).Select
ActiveCell.FormulaR1C1 = “Cliente”
Range(“A5″).Select
ActiveCell.FormulaR1C1 = “Rut”
Range(“A6″).Select
ActiveCell.FormulaR1C1 = “Dirección”
Range(“B8″).Select
ActiveCell.FormulaR1C1 = “Artículo”
Range(“C8″).Select
ActiveCell.FormulaR1C1 = “Precio Unitario”
Range(“D8″).Select
ActiveCell.FormulaR1C1 = “Cantidad”
Range(“E8″).Select
ActiveCell.FormulaR1C1 = “Subtotal”
Range(“B8″).Select
Range(“A3:B6″).Select
Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
With Selection.Borders(xlEdgeLeft)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideVertical)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideHorizontal)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
Range(“B8:E18″).Select
Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
With Selection.Borders(xlEdgeLeft)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideVertical)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlInsideHorizontal)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
Range(“E19″).Select
Selection.Borders(xlDiagonalDown).LineStyle = xlNone
Selection.Borders(xlDiagonalUp).LineStyle = xlNone
With Selection.Borders(xlEdgeLeft)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeTop)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeBottom)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
With Selection.Borders(xlEdgeRight)
.LineStyle = xlContinuous
.Weight = xlThin
.ColorIndex = xlAutomatic
End With
Range(“D19″).Select
ActiveCell.FormulaR1C1 = “Total”
Range(“D2″).Select
Range(“B3″).Select
With Selection
.HorizontalAlignment = xlLeft
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.IndentLevel = 0
.ShrinkToFit = False
.MergeCells = False
End With
Range(“C8:E8″).Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.ShrinkToFit = False
.MergeCells = False
End With
Range(“B8:E8″).Select
Selection.Font.Bold = True
Range(“A3:A6″).Select
Selection.Font.Bold = True
Range(“B1″).Select
With Selection
.HorizontalAlignment = xlCenter
.VerticalAlignment = xlBottom
.WrapText = False
.Orientation = 0
.ShrinkToFit = False
.MergeCells = False
End With
Selection.Font.Bold = True
¡Como nos ahorra trabajo la grabadora de macros!. Con Archivo, Quitar Módulo, borramos el macro recién creado (para que nos quede un código limpio)

En fin, el ejemplo está casi completo, solo falta declarar la variable “linea” como global para que pueda traspasar su valor desde initialize hasta el CommandButton1 sin problemas. Para ello creamos un módulo y escribimos

global linea

También podemos aprovechar de colocar algunos comentarios con propaganda o lo que se nos ocurra en éste módulo. Y ya tenemos listo nuestro ejemplo, solo falta programar un atajo para lanzarlo de manera rápida. En el Excel nos vamos a Herramientas, Macros, Macros, Opciones y programamos las teclas Ctrl-E para lanzar el macro. Cada vez que pulsemos Ctrl-E el macro parte.

Ahora les dejo las siguientes tareas para la casa:

agregar validaciones tales como largo total permitido, tipo (caracter o numerico), formatear los datos numéricos, etc., grabar cada una de las entradas en una base de datos Acces, para esto supongo que solo hay que agregar algo de código de inicialización al Modulo2 y ajustar las propiedades ControlSource y ControlTipText.

El que las haga que me la mande y se hace famoso pues lo publicamos acá mismo.

Algunos trucos de Microsoft para VBA con Excel

En algunos detalles el VBA para Excel no es muy obvio que digamos. Buscando en el help de Microsoft me encontré con estos datos que me fueron bastante útiles en mi trabajo. En algunos adjunto un comentario de con mi aplicación práctica:

Algunas funciones de hoja de cálculo no tienen utilidad en Visual Basic. Por ejemplo, la función Concatenar no se necesita, ya que en Visual Basic puede usar el operador & para unir varios valores de texto.
Dim miRango As Range
Set miRango = Worksheets(“Hoja1″).Range(“A1:C10″)
Llamar a una función de hoja de cálculo desde Visual Basic:
En Visual Basic, las funciones de hoja de calculo de Microsoft Excel pueden ejecutarse mediante el objeto WorksheetFunction.

El siguiente procedimiento Sub usa la función Mín para obtener el valor más pequeño de un rango de celdas. En primer lugar, se declara la variable miRango como un objeto Range y, a continuación, se establece como el rango A1:C10 de la Hoja1. Otra variable, respuesta, se asigna al resultado de aplicar la función Mín a miRango. Por último, el valor de respuesta se muestra en un cuadro de mensaje.

Sub UseFunction()
respuesta = Application.WorksheetFunction.Min(miRango)
MsgBox respuesta
End Sub

Comentario: el sentido común nos diría que podemos incluír la función de Excel en nuestro programa VBA sin más pero no es así, hay que definir primero el rango (Set miRango en este ejemplo) y luego colocar la función usando Application.WorksheetFunction. Por ejemplo con:

Set miRango = Worksheets(“Hoja2″).Range(“B11:B21″)
Hoja2.Cells(22, 2) = Application.WorksheetFunction.Sum(miRango)
Set miRango = Worksheets(“Hoja2″).Range(“C11:C21″)
Hoja2.Cells(22, 3) = Application.WorksheetFunction.Sum(miRango)

Se suman las celdas C11 a la C21 y el resultado se coloca en la celda(22,3)

miVar = Application.WorksheetFunction _

Si usa una función de hoja de cálculo que requiere como argumento una referencia de rango, deberá especificar un objeto Range. Por ejemplo, puede usar la función de hoja de cálculo Coincidir para efectuar una búsqueda en un rango de celdas. En una celda de hoja de cálculo, podría introducir una fórmula como =COINCIDIR(9;A1:A10;0). No obstante, en un procedimiento de Visual Basic, para obtener el mismo resultado debe especificar un objeto Range.

Sub FindFirst()
. Match(9, Worksheets(1).Range(“A1:A10″), 0)
MsgBox miVar
End Sub

Nota Las funciones de Visual Basic no usan el calificador WorksheetFunction. Una función puede tener el mismo nombre que una función de Microsoft Excel y, sin embargo, dar otros resultados. Por ejemplo, Application.WorksheetFunction.Log y Log dan resultados diferentes.

Insertar una función de hoja de cálculo en una celda
Para insertar una función de hoja de cálculo en una celda, especifique la función como el valor de la propiedad Formula del objeto Range correspondiente. En el siguiente ejemplo, la función ALEATORIO (que genera un número aleatorio) se asigna a la propiedad Formula del rango A1:B3 de la Hoja1 del libro activo.

Sub InsertFormula()
Worksheets(“Hoja1″).Range(“A1:B3″).Formula = “=ALEATORIO()”
End Sub

Puede identificar las hojas por su nombre, utilizando las propiedades Worksheets y Charts. Las siguientes instrucciones activan varias hojas del libro activo.

Worksheets(“Hoja1″).Activate
Charts(“Gráfico1″).Activate
DialogSheets(“Diálogo1″).Activate

Puede utilizar la propiedad Sheets para devolver una hoja de cálculo, de gráficos, de módulo o de cuadro de diálogo, incluidos todos en el conjunto Sheets. El siguiente ejemplo activa la hoja denominada “Gráfico1″ del libro activo.

Sub ActivarGráfico()
Sheets(“Gráfico1″).Activate
End Sub

Nota Los gráficos incrustados en una hoja de cálculo son miembros del grupo ChartObjects, aunque los gráficos que poseen sus propias hojas pertenecen al conjunto Charts.

Puede hacer referencia a una celda o rango de celdas del estilo de referencia A1 utilizando el método Range. El siguiente procedimiento Sub cambia el formato de las celdas A1:D5 a negrita.

Sub FormatoRango()
Workbooks(“Libro1″).Sheets(“Hoja1″).Range(“A1:D5″) _Font.Bold = True
End Sub

La siguiente tabla muestra algunas referencias de estilo A1 utilizando el método Range.

Referencia Significado
Range(“A1″) Celda A1
Range(“A1:B5″) Celdas de la A1 a la B5
Range(“C5:D9,G9:H16″) Selección de varias áreas
Range(“A:A”) Columna A
Range(“1:1″) Fila uno
Range(“A:C”) Columnas de la A a la C
Range(“1:5″) Filas de la uno a la cinco
Range(“1:1,3:3,8:8″) Filas uno, tres y ocho
Range(“A:A,C:C,F:F”) Columnas A, C y F

Al utilizar Visual Basic, con frecuencia necesitará ejecutar el mismo bloque de instrucciones en cada una de las celdas de un rango. Para ello, combine una instrucción de repetición y uno o más métodos para identificar cada celda, una a la vez, y ejecutar la operación.

Una manera de ejecutar un bucle en un rango es utilizar el bucle For…Next con la propiedad Cells. Al utilizar la propiedad Cells, puede sustituir el contador del bucle, u otras variables o expresiones, por el número de índice de las celdas. En el siguiente ejemplo se sustituye la variable contador por el índice de fila. El procedimiento ejecuta un bucle en el rango C1:C20, estableciendo en 0 (cero) cualquier número cuyo valor absoluto sea menor que 0.01.

Sub RedondeoACero1()
For contador = 1 To 20
Set Celda_a = Worksheets(“Hoja1″).Cells(contador, 3)
If Abs(Celda_a.Value) < 0.01 Then Celda_a.Value = 0
Next contador
End Sub

Otra manera sencilla de ejecutar un bucle en un rango es utilizar el bucle For Each…Next en el conjunto de celdas devuelto por el método Range. Visual Basic establece automáticamente una variable de objeto para la siguiente celda cada vez que se ejecuta el bucle. El siguiente procedimiento realiza un bucle en el rango A1:D20, estableciendo en 0 (cero) cualquier número cuyo valor absoluto sea menor que 0.01.

Sub RedondeoACero2()
For Each c In Worksheets(“Hoja1″).Range(“A1:D10″).Cells
If Abs(c.Value) < 0.01 Then c.Value = 0
Next
End Sub

Comentario: esto sirve, por ejemplo para programar la suma de dos columnas (B y C, desde la fila 11 a la 22 en este ejemplo) así

Dim miRango As Range
For contador = 11 To 22
Set celda_a = Worksheets(“Hoja2″).Cells(contador, 2)
Set celda_b = Worksheets(“Hoja2″).Cells(contador, 3)
Hoja2.Cells(contador, 4) = celda_a +celda_b
Next contador

Si no conoce los límites del rango en que desea ejecutar el bucle, puede utilizar la propiedad CurrentRegion para devolver el rango que rodea la celda activa. Por ejemplo, el siguiente procedimiento, cuando se ejecuta desde una hoja de cálculo, ejecuta un bucle en el rango que rodea la celda activa, estableciendo en 0 (cero) todos los números cuyo valor absoluto sea menor que 0.01.

Sub RedondeoACero3()
For Each c In ActiveCell.CurrentRegion.Cells
If Abs(c.Value) < 0.01 Then c.Value = 0
Next
End Sub

Al aplicar la propiedad Cells a una hoja de cálculo sin especificar un número de índice, el método devuelve un objeto Range que representa todas las celdas de la hoja de cálculo. El siguiente procedimiento Sub borra el contenido de todas las celdas de la Hoja1 del libro activo.

Sub BorrarHoja()
Worksheets(“Hoja1″).Cells.ClearContents
End Sub

Una manera de trabajar con una celda relacionada con otra es utilizar la propiedad Offset. El siguiente ejemplo asigna un formato de doble subrayado al contenido de la celda situada una fila más abajo y a tres columnas de la hoja de cálculo activa.

Sub Subrayar()
ActiveCell.Offset(1, 3).Font.Underline = xlDouble
End Sub

Nota Puede grabar macros que utilicen la propiedad Offset en lugar en referencias absolutas. En el menú Herramientas, señale Grabar macro y, a continuación, haga clic en Usar referencias relativas.

Para ejecutar un bucle en un rango de celdas, utilice en el rango una variable con la propiedad Cells. El siguiente ejemplo rellena las primeras 20 celdas de la tercera columna con valores entre 5 y 100, en incrementos de 5. La variable contador se utiliza como índice de fila para la propiedad Cells.

Sub BucleAtravés()
Dim contador As Integer
For contador = 1 To 20
Worksheets(“Hoja1″).Cells(contador, 3).Value = contador * 5
Next contador
End Sub

Si establece una variable de objeto para un objeto Range, puede manipular fácilmente el rango utilizando el nombre de la variable.

El siguiente procedimiento crea la variable de objeto miRango y, a continuación, asigna la variable al rango A1:D5 de la Hoja1 del libro activo. Las instrucciones posteriores modifican las propiedades del rango, sustituyendo el nombre de la variable por el objeto del rango.

Sub Aleatorio()
Dim miRango As Range
Set miRango = Worksheets(“Hoja1″).Range(“A1:D5″)
miRango.Formula = “=ALEATORIO()”
miRango.Font.Bold = True
End Sub

Utilice la función Array para identificar un grupo de hojas. El siguiente ejemplo selecciona tres hojas del libro activo.

Sub Varias()
Worksheets(Array(“Hoja1″, “Hoja2″, “Hoja4″)).Select
End Sub

Utilice la propiedad Rows o Columns para trabajar con filas o columnas enteras. Estas propiedades devuelven un objeto Range que representa un rango de celdas. En el siguiente ejemplo, Rows(1) devuelve la fila uno de la Hoja1. A continuación, la propiedad Bold del objeto Font del rango se establece en True.

Sub FilaNegrita()
Worksheets(“Hoja1″).Rows(1).Font.Bold = True
End Sub

La siguiente tabla muestra algunas referencias de fila y columna, utilizando las propiedades Rows y Columns.

Referencia Significado
Rows(1) Fila uno
Rows Todas las filas de la hoja de cálculo
Columns(1) Columna uno
Columns(“A”) Columna uno
Columns Todas las columnas de la hoja de cálculo

Para trabajar con varias filas o columnas al mismo tiempo, cree una variable de objeto y utilice el método Union, combinando varias llamadas a la propiedad Rows o Columns. El siguiente ejemplo cambia a negrita el formato de las filas uno, tres y cinco de la hoja de cálculo uno del libro activo.

Sub VariasFilas()
Worksheets(“Hoja1″).Activate
Dim miUnión As Range
Set miUnión = Union(Rows(1), Rows(3), Rows(5))
miUnión.Font.Bold = True
End Sub

Bueno, creo que con eso hay para entretenerse durante un tiempo, espero que practiquen y que les sirva, ¡Suerte!

Combinar macros con campos de formulario en Word

Hace poco tuve un problema práctico, necesitaba crear alrededor de 50 plantillas de Word y la sola idea de programar línea a línea usando Select.Typetext Text:= me daba dolor de estómago. ¿No sería mejor escribir las plantillas en Word e insertar los campos de formulario, que luego se conectaran con la una macro de entrada de datos?. Eso me ahorraría mucho trabajo y permitiría hacer una macro estándar que sirviese para varias plantillas con solo modificaciones menores.

Pero no encontraba la forma de hacerlo, finalmente se me ocurrió repasar el curso de un tal Tomás Bradanovic y ahi encontre la solución, ¿como lo hice? siguiendo mis propios consejos grabé un macro y luego estudié el código generado. Le saqué las líneas superfluas y listo.

Entrando en materia el procedimiento es el siguiente:

Abrir una plantilla con el documento que queremos crear, usando Ver, Barras de Herramientas, colocamos las barras Visual Basic y Formularios, luego escribí normalmente el documento y usando el botón para insertar campo de formulario, fui colocando los campos variables, aquí está el ejemplo. Noten las barras de Visual Basic y de formularios en la última fila, con el primer botón (ab) de la barra de formularios se insertan los campos:


Una vez escrito e insertados los campos le ponemos nombres, seleccionando cada campo, click con botón derecho, Propiedades, Nombre. Así los campos quedan con nombres descriptivos como: tribunal, ciudad, fecha, medico, proceso, fallecido, etc.
Luego hacemos click sobre la barra de Visual Basic para entrar al editor, y creamos la ventana estándar de ingreso de datos así

Luego programamos la form con el evento initialize con

Private Sub UserForm_Initialize()
UserForm1.Caption = “Autopsia”
Label1.Caption = “MEDICO” ‘combo1
Label2.Caption = “JUEZ” ‘combo2
Label3.Caption = “SECRETARIO” ‘combo3
Label4.Caption = “MOVIMIENTO” ‘combo4
Label5.Caption = “FECHA” ‘textbox1
Label6.Caption = “FALLECIDO” ‘textbox2
Label7.Caption = “ROL” ‘textbox3
Label8.Caption = “” ‘textbox4
Label9.Caption = “” ‘textbox5
Label10.Caption = “” ‘´textbox6
TextBox4.Visible = False
TextBox5.Visible = False
TextBox6.Visible = False
TextBox1.Text = Date
ComboBox4.Text = “SUM SOLICITA INF AUTOPSIA”
ComboBox1.AddItem “CARLOS VILLAVICENCIO SILVA”
ComboBox1.AddItem “ADRIANA BARRIENTOS ESPINOZA”
ComboBox2.AddItem “JORGE QUIÑONES GARAT”
ComboBox2.AddItem “HECTOR GUTIERREZ MASSARDO”
ComboBox3.AddItem “HECTOR GUTIERREZ MASSARDO”
ComboBox3.AddItem “JULIO MAZUELOS RAMOS”
ComboBox1.Text = ComboBox1.List(0)
ComboBox2.Text = ComboBox2.List(0)
ComboBox3.Text = ComboBox3.List(0)
End Sub
Y lo importante, en el botón de comando escribimos:
Private Sub CommandButton1_Click()
Selection.GoTo What:=wdGoToBookmark, Name:=”tribunal”
Selection.TypeText Text:=”PRIMER”
Selection.GoTo What:=wdGoToBookmark, Name:=”ciudad”
Selection.TypeText Text:=”ARICA”
Selection.GoTo What:=wdGoToBookmark, Name:=”fecha”
Selection.TypeText Text:=TextBox1.Text
Selection.GoTo What:=wdGoToBookmark, Name:=”medico”
Selection.TypeText Text:=ComboBox1.Text
Selection.GoTo What:=wdGoToBookmark, Name:=”rol”
Selection.TypeText Text:=TextBox3.Text
Selection.GoTo What:=wdGoToBookmark, Name:=”fallecido”
Selection.TypeText Text:=TextBox2.Text
Selection.GoTo What:=wdGoToBookmark, Name:=”juez”
Selection.TypeText Text:=ComboBox2.Text
Selection.GoTo What:=wdGoToBookmark, Name:=”secretario”
Selection.TypeText Text:=ComboBox3.Text
Selection.GoTo What:=wdGoToBookmark, Name:=”medico2″
Selection.TypeText Text:=ComboBox1.Text
Unload UserForm1
End Sub
Como pueden ver, todo se reduce a una instrucción Selection.GoTo What:=wdGoToBookmark, Name:=”nombre de variable” y luego escribimos en el campo con Selection.TypeText Text:=TextBox2.Text

Algunas precauciones al programar plantillas

Si están programando una plantilla (.dot) en lugar de un documento corriente hay que tener en cuenta que para modificarla debemos usar botón derecho y Abrir, si hacemos doble click no aparecerá la plantilla sino un Doc1.doc.

También hay que tener cuidado de no probar el programa cuando esté abierto como plantilla porque deesaparecerán los campos (serán reemplazados) y perderás el trabajo. Hay que cerrarla y luego abrirla con doble click para que aparezca como Doc1.doc.

Los detalles y adornos no los coloco para no enredarlos, solo les muestro a modo de idea, que se puede colocar alguna propaganda en el programa, en este caso al hacer click sobre “Tomás Bradanovic Computación” aparece la ventana de propaganda:

Un último dato, si abren la caja de herramientas y luego van a Herramientas, Controles Adicionales del menú, pueden agregar el control Microsoft MonthView 6.0 con lo que pueden dotar de un calendario a sus aplicaciones VBA para los programas que requieran cálculos con fecha, agendas, etc, miren que bonito es

El Modelo de Objetos: qué es y para qué sirve

En la primera parte del curso vimos como es posible programar en VBA sin saber nada acerca del Modelo de Objetos de Microsoft. Partimos de la base que éste era una complicación innecesaria y algo incomprensible para las personas comunes y corrientes.

Así lo era para mi al menos cuando comencé a trabajar en VBA, pero con el tiempo, las ideas subyacentes del Modelo de Objetos se terminan infiltrando y comienza la curiosidad por saber de que se trata y si realmente sirve para algo.

La clave para entender todo este asunto se encuentra en la ayuda del Word (asumire que estamos usando Word 2000, si no lo tiene no importa el ejemplo igual vale), vamos a Información de programación, Referencia de Visual Basic para Word y Objetos de Microsoft Word. Aparecerá un intrincado organigrama lleno de nombres mas o menos cripticos, partiendo en el tope de la jerarquía por el casillero llamado ‘Aplication’, y hacia abajo sale una gran cantidad de ramas (Microsoft dice que Word tiene “alrededor de 108 objetos”).

Al hacer click sobre un casillero (digamos, Document) aparecerá la explicación del objeto junto con los demás objetos de más baja jerarquía, como muestra la figura


Si todo esto todavía le resulta incomprensible, no se preocupe. Así me pareció también a mi y, de hecho todavía hay muchas ramas que no he explorado y no se para que sirven. Pero la razón de ser del Modelo de Objetos está en ese organigrama. Se supone que si alguien comprende el modelo no necesitará más ayuda que eso para programar cualquier cosa que necesite en VBA.

Se supone también que todas las capacidades del lenguaje están representadas allí, no habrán características “indocumentadas” como en los buenos viejos tiempos. A mi entender, ese es el objetivo esencial del Modelo de Objetos de Microsoft.

Una vez que entendemos “el secreto” de los números, podemos contar hasta el infinito sin necesidad de haberlo hecho nunca antes, igual cosa para multiplicar, sumar, etc. porque entendemos el modelo de los números decimales y los algoritmos respectivos. De manera similar, alguien que entiende el Modelo de Objetos no necesitará conocerlo en detalle (como los antiguos “expertos” que conocían todas las intrincadas sutilezas de un lenguaje de programación), bastará con que tenga a mano la referencia (el organigrama), para poder inferir cualquier procedimiento.

El haber modelado el lenguaje de manera lógica, permite además la programación automática, esa misma que cuando grabamos un macro nos escribe automáticamente el código correspondiente, y que nos permitió programar en la primera parte del curso sin saber nada acerca del Modelo de Objetos Todo esto es la explicación en términos generales, entremos ahora a los detalles específicos.

En beneficio de la comprensión seré algo liberal con la fraseología y tal vez a veces mis términos no sean los exactos, pero hay que tener en cuenta que es el rigor semántico lo que hace tan dificil de comprender el dichoso modelo, asi que me tomaré mis libertades sin mayor remordimiento. Para fines didácticos consideraremos los objetos del Word solamente. Word es una aplicacion de Microsoft, así como lo son Excel, Power Point, Access, etc.O sea que existe un objeto llamado Aplication, que representa al Word mismo, en general. Cuando queremos programar algo que tenga que ver con el Word en general, y no con un documento especifico, usamos el objeto Aplication.

Por ejemplo With Application .WindowState = wdWindowStateNormal .Height = 450 .Width = 600 End WithHace partir al Word en una ventana normal, con un tamaño de 450×500 pixeles Fijense bien: el objeto es Aplication y tiene métodos y propiedades como WindowState, Heigth y Width (acuerdense que en el curso anterior vimos que With…End With se usa para evitarnos tener que repetir palabras, en este caso la palabra Aplication) Así si nos vamos al organigrama de los objetos del Word y hacemos click en el cuadro Aplication, aparecerán todos los métodos y todas las propiedades que podemos usar con el objeto. En las lecciones siguientes iremos analizando los principales objetos con sus métodos más usados.

Los ejemplos de código los he obtenido del excelente artículo de Microsoft llamado Microsoft Word Objects.obtenido del Microsoft Office Developer Forum de Internet. Una referencia de primera que actualmente estoy traduciendo para mi uso personal

El Objeto Document

En la lección anterior vimos nuestro primer objeto Aplication, en el tope de la jerarquía, que representaba a la aplicación Word en general, de este objeto salen todos los demás y el segundo objeto que estudiaremos (en orden de utilidad) sera Document

Sin pensar mucho podemos intuir que Document es un documento que se abre usando la aplicación Word, como podemos tener varios documentos abiertos existe además la colección Documents (con s al final) que representa a todos los documentos abiertos en una sesión.
Para programar con el modelo de objetos usamos el objeto y su propiedad o método separado por puntos, como el nombre y los apellidos, cuando un objeto es una rama de inferior jerarquía también colocamos su objeto padre por ejemplo

Aplication.Document.Open

Pero el objeto Document es global, lo que significa que no es necesario que vaya antecedido por su objeto padre Aplication, así podemos escribir

Document.Open

Y no aparecerá ningún error. Podemos, por ejemplo abrir el documento TEXT.DOC (que esté en la carpeta actual) desde un programa usando

Set miDocumento = Documents.Open(FileName:=”TEST.DOC”)

Analizando el ejemplo anterior podemos ver como se programa en el modelo de objetos
Set miDocumento =

sirve para recuperar el documento, asignándolo a una variable, así cada vez que nos referimos a miDocumento estaremos accesando al documento abierto llamado TEST.DOC.
Con
Documents.Open(Filename=”TEXT:DOC”)
tenemos que de la colección Documents usamos el método Open con la constante Filename a la cual le hemos dado el valor de TEST.DOC

Ahora podemos modificar a miDocumento como por ejemplo:

miDocumento.PageSetup.TopMargin = InchesToPoints(1.25)

En este caso usamos el método PageSetup y la propiedad TopMargin para ajustar el margen superior a 1.25 pulgadas. A estas alturas creo que ya se puede ir comprendiendo las ventajas del modelo de objetos y la forma más o menos mecánica en que se puede programar sin necesidad de recurrir a trucos de ingenio como en los viejos tiempos.

Veremos a continuación algunos ejemplos de lo que podemos hacer usando el objeto Document, la colección Documents, sus métodos, propiedades y constantes

Ejemplo 1: Muestra el nombre del documento activo; si no hay documentos abiertos, el ejemplo muestra un mensaje

If Documents.Count >= 1 Then
MsgBox ActiveDocument.Name
Else
MsgBox “No documents are open”
End If

Ejemplo 2: Abre el archivo Test.doc (de la carpeta actual) y activa el control de los cambios
Set myDoc = Documents.Open(FileName:=”TEST.DOC”)
myDoc.TrackRevisions = True

Ejemplo 3: Muestra propiedades y métodos del objeto FileSearch para determinar si un archivo llamado “Test.doc” existe en la carpeta por defecto. Si el archivo es encontrado (FoundFiles.Count = 1), se abre, de otro modo se mostrará un mensaje
defaultDir = Options.DefaultFilePath(wdDocumentsPath)
With Application.FileSearch
.FileName = “Test.doc”
.LookIn = defaultDir
.Execute
If .FoundFiles.Count = 1 Then
Documents.Open FileName:=defaultDir & Application.PathSeparator & “TEST.DOC”
Else
MsgBox “Test.doc file was not found”
End If
End With

Ejemplo 4: Chequea el valor retornado por el método Display.Si el usuario hace click en OK para cerrar la dialog box, se retorna el valor -1 y el archivo, cuyo nombre esta almacenado en la variable fSelected, se abre.
Set dlg = Dialogs(wdDialogFileOpen)
aButton = dlg.Display
fSelected = dlg.Name
If aButton = -1 Then
Documents.Open FileName:=fSelected
End If

Ejemplo 5: Activa un documento llamado “Sample.doc” si ya está abierto; si no lo está, el ejemplo lo abre
docFound = True
For Each aDoc In Documents
If InStr(1, aDoc.Name, “sample.doc”, 1) Then
aDoc.Activate
Exit For
Else
docFound = False
End If
Next aDoc
If docFound = False Then Documents.Open _
FileName:=”C:DocumentsSample.doc”

Estos ejemplos, sacados de la documentación de Microsoft nos permiten ver como, de una manera bastante lógica podemos manipular desde un programa el objeto Document, en la próxima lección seguiremos investigando que más podemos hacer con las diferentes propiedades y métodos de este importante objeto

Más sobre el Objeto Document

Para imprimir un documento le aplicamos el método printout
Por ejemplo

ActiveDocument.Printout

También podrían usarse las opciones de impresión usando el objeto Options

Options.PrintHiddenText = True
ActiveDocument.PrintOut Range:=wdPrintFromTo, From:=”1″, To:=”3″

El objeto Close sirve para cerrar un documento, por ejemplo

Documents(“Prueba.doc”).Close

Se pueden agregar objetos, tales como notas al pie, comentarios o tablas a un documento usando el método Add con una colección de objetos accesada desde el objeto Document. La siguiente instrucción, por ejemplo, agrega una tabla de 3×3 localizada por la variable myRange (myRange es una variable de objeto que contiene un objeto Range).

ActiveDocument.Tables.Add Range:=myRange, NumRows:=3, NumColumns:=3

El siguiente ejemplo agrega una nota al pie en la localización especificada por la

variable myRange.
ActiveDocument.Footnotes.Add Range:=myRange, Text:=”The Willow Tree”

Para una lista de la colección de objetos que soportan el método Add, vea en la ayuda bajo el tópico “Add Method”

El objeto Range permite seleccionar un rango dentro del documento, para entender el objeto Range hay que saber que existen 11 diferentes wsStoryTye correspondientes a diferentes partes de un documento que son
wdCommentsStory, wdEndnotesStory, wdEvenPagesFooterStory, wdEvenPagesHeaderStory, wdFirstPageFooterStory, wdFirstPageHeaderStory, wdFootnotesStory, wdMainTextStory, wdPrimaryFooterStory, wdPrimaryHeaderStory, and wdTextFrameStory.
Además de objetos que pueden modificarse que son:

Words(index)

Range

Characters(index)

Range

Sentences(index)

Range

Paragraphs(index)

Paragraph

Sections(index)

Section

Algunos ejemplos de uso del objeto Range

Crear un rango y almacenarlos en MiRango (las 10 primeras letras de un documento)
Set miRango = ActiveDocument.Range(Start:=0, End:=10)

Después podríamos ponerlo en cursiva con
miRango.Italics = True

También podríamos insertar una palabra antes de cierto rango con:
ActiveDocument.Range(Start:=0, End:=0).InsertBefore Text:=”Hola “

Si usamos Range.Select veremos el rango “pintado” tal como cuando seleccionamos con el mouse

Set miRango = ActiveDocument.Range(Start:=0,_ End:=ActiveDocument.Paragraphs(3).Range.End)
miRango.Select

Por ejemplo si queremos colocar varios atributos a un párrafo usamos

Set myRange = ActiveDocument.Paragraphs(1).Range
With myRange
.Bold = True
.ParagraphFormat.Alignment = wdAlignParagraphCenter
.Font.Name = “Arial”
End With

El objeto Selection permite también hacer muchas de las operaciones que se hacen con Range, por ejemplo

Para mostrar el nombre de cada marcador en un documento
For Each aBook In Selection.Bookmarks
MsgBox aBook.Name
Next aBook

Los objetos Find y Replace permiten, obviamente buscar y reemplazar texto, por ejemplo

Para buscar la palabra “Hola” dentro de un documento
With Selection.Find
.Forward = True
.Wrap = wdFindStop
.Text = “Hola”
.Execute
End With

Para reemplazar las palabras “uno” por “dos” dentro de un documento
With Selection.Find
.ClearFormatting
.Text = “uno”
.Replacement.ClearFormatting
.Replacement.Text = “dos”
.Execute Replace:=wdReplaceAll, Forward:=True, Wrap:=wdFindContinue
End With

Agregar y Editar campos en un documento
Para agregar campos a un documento se aplica el método Add a la colección Fields, por ejemplo para agregar el campo Fecha donde está la selección actual, usamos
ActiveDocument.Fields.Add Range:=Selection.Range, Type:=wdFieldDate
Luego de agregado el campo, se obtiene (o se asigna) el resultado de ese campo usando la propiedad Result o Code. El ejemplo siguiente cambia el código del primer campo de la selección actual, lo actualiza y muestra el resultado en el campo.

If Selection.Fields.Count >= 1 Then
With Selection.Fields(1)
.Code.Text = “CREATEDATE *MERGEFORMAT”
.Update
MsgBox .Result.Text
End With
End If

Modificar los Comandos del Word

Esta es una característica importantísima para el desarrollador en Vba en lugar de hacer lo que tienen predeterminado, ejecuten la macro que diseñemos

Por ejemplo podríamos escribir un macro llamado FileSave() que grabe una vez que este es cerrrado, así podríamos registrar los cambios que se le ha los documentos sin que el usuario se de cuenta (suponemos un usuario no también tendrán pensamientos malignos en este punto. En fin, la manera es:

1.
En el menú Herramientas, Macro, Macros

2.
En Macros en, escoger Comandos del Word

3.
En Nombre de Macro name, escoja el comando que quiere modificar (por ejemplo Archivo
Guardar Todo).

4.
En Macros en, seleccione la plantilla o ubicacion donde quiera guardar la macro. Si usa Normal.dot la macro funcionará en todos los documentos

5.
Crear

Se abrirá un módulo como por
ejemplo:
Sub FileSave()
‘ FileSave Mac
‘ Saves the a

ActiveDocument.Save
End Sub

En este módulo se pueden agregar comandos (para que además de grabar haga otras operaciones o también podría borrar la línea ActiveDocument.Save y programar
requiera

Eventos de Documento

Los eventos de documento que se pueden programar en el Word son:

Close: Ocurre cuando un documento es cerrado
New: Ocurre cuando una plantilla genera un nuevo documento y lo abre
Open: Ocurre cuando un documento es abierto

Por ejemplo, para maximizar un documento cada vez que es abierto usamos

Private Sub Document_Open()
End Sub

Eventos de Aplicación

DocumentChange: Occurre cuando se crea un nuevo documento, cuando se abre uno existente, o cuando otro documento se hace activo
Quit: Ocurre cuando el usuario sale del Word.

El siguiente ejemplo asegura que las toolbar Standard y Formatting sean visibles antes que el usuario salga del Word, para que queden visibles para el próximo uso

Private Sub App_Quit()
CommandBars(“Forma
End Sub
Los Macros Auto

Hay algunos nombres de macro especiales

AutoExec

Cada vez que parte el Word o se inicia con la plantilla Global

AutoNew

Cada vez que se crea un nuevo documento

AutoOpen

Cada vez que se abre un documento que ya existe

AutoClose

Cada vez que se cierra un documento

AutoExit

Cada vez que se sale del Word

El Modelo de Objetos Para Excel

Como creo que ya tenemos práctica en trabajar con el modelo de objetos, me limitaré a colocar los ejemplos y referencias entregadas por Microsoft respecto del Excel

Para el objeto Aplication tenemos por ejemplo:

Aplication.DisplayFormulaBar (True/False)

Aplication.ScreenUpdating (True/False)

Application.Calculate (recalcula todos los objetos de la aplicación)

El Objeto Workbook

El siguiente ejemplo abre la hoja “Libro1.xls” y muestra el valor de la celda A1 en una Msgbox

Sub OpenBook1()
Set myBook = Workbooks.Open(Filename:=”Libro1.xls”)
MsgBox myBook.Worksheets(1).Range(“A1″).Value
End Sub

Para guardar una plantilla Excell que contenga macros Micrososft recomienda hacerlo en el mismo directorio donde está el ejecutable de Excel, esto se recuperaría con

Sub OpenBook1()
EXEPath = Application.Path &_ Application.PathSeparator
fName = EXEPath & “BOOK1.XLS”
Set myBook = Workbooks.Open(Filename:=fName)
MsgBox myBook.Worksheets(1).Range(“A1″).Value
End Sub

Otra alternativa es guardarlo en un directorio que crea el Officce para estos efectos llamado Library, en este caso se recuperaría con:

Sub OpenBook1()
LibPath = Application.LibraryPath &_ Application.PathSeparator
fName = LibPath & “BOOK1.XLS”
Set myBook = Workbooks.Open(Filename:=fName)
MsgBox myBook.Worksheets(1).Range(“A1″).Value
End Sub

Para crear workbooks se usa el método Add para grabarlo por primera vez se usa SaveAs y para grabarlo las veces siguientes Save

Sub CreateAndSave()
Set newBook = Workbooks.Add
Do
fName = Application.GetSaveAsFilename
Loop Until fName <> False
newBook.SaveAs Filename:=fName
End Sub
Para cerrar un workbook se usa el método Close

Sub OpenChangeClose()
Do
fName = Application.GetOpenFilename
Loop Until fName <> False
Set myBook = Workbooks.Open(Filename:=fName)
‘ Hacer cambios a myBook
myBook.Close savechanges:=False
End Sub

El Objeto Range

Los diferentes métodos del objeto Range son:

ActiveCell
BottomRightCell
Cells
ChangingCells
CircularReference
Columns
CurrentArray
CurrentRegion
Dependents
DirectDependents
DirectPrecedents
EntireColumn
EntireRow
Next
Offset
PageRange
Precedents
Range
RowFields
RowRange
Rows
Selection
TableRange1
TableRange2
TopLeftCell
UsedRange
VisibleRange

Algunos ejemplos prácticos

Colocar el valor de la celda A1 en hoja1 Worksheets(“hoja1″).Range(“A1″).Value = 3

Colocar una fórmula en la celda activa Range(“B1″).Formula = “=5-10*RAND()”

Colocar el valor 6 en el rango C1:E3 de la hoja activa Range(“C1:E3″).Value = 6

Limpiar el contenido del rango A1:E3 en la hoja activa Range(“A1″, “E3″).ClearContents

Colocar el atributo font.bold en el rango llamado “miRango” Range(“miRango”).Font.Bold = True

Colocar un 3 en cada celda del rango llamado “miRango” de la hoja1 Range(“Sheet1!miRango2″).Value = 3

Establecer una variable de objeto para referir a un rango Set objRange = Range(“miRango”)

Usando Números de línea o columna

Colocar el valor de la celda A1 en Sheet1 Worksheets(“Sheet1″).Cells(1, 1).Value = 3

Colocar la fórmula en la celda B1 de la hoja activa Cells(1, 2).Formula = “=5-10*RAND()”

Colocar una variable de objeto Set objRange = Worksheets(“Sheet1″).Cells(1, 1)

Para selecciones multicolumna se usan loops, el ejemplo siguiente busca en el rango A1:D10 de la hoja Sheet1 y si encuentra un valor menor que 0.001 lo reemplaza por 0

Sub RoundToZero()
For rwIndex = 1 to 4
For colIndex = 1 to 10
If Worksheets(“Sheet1″).Cells(rwIndex, colIndex) < .01 Then
Worksheets(“Sheet1″).Cells(rwIndex, colIndex).Value = 0
End If
Next colIndex
Next rwIndex
End Sub