UNA APLICACION PRACTICA EN VBA

En el siguiente ejemplo veremos como un documento en VBA puede ser llamado desde un programa en Visual Basic. Como puede leer datos almacenados con ese programa y generar un formulario que lea estos datos desde el disco.

a) El programa en Visual Basic

Tenemos el programa que se muestra a continuacion, que almacena fichas de datos personales en un archivo ascii plano del disco duro:

La idea es que al pinchar el botón "Word" se cargue un documento programado en VBA que traspase y utilice los datos de la persona elegida para elaborar un documento como el que se muestra a continuación:

b) Como se carga el documento desde Visual Basic y como se pasan los datos

Para realizar de manera sencilla estas dos tareas se programa el icono "Word" con el siguiente código:

Private Sub Image7_Click()
Open "TEMPORAL" For Random As 1
tem.codigo = codigo.Text
Put 1, 1, tem
Close
file = "C:\Archivos de programa\Microsoft Office\OFFICE\WINWORD.EXE CRS.doc"
X = Shell(file, 3)
End Sub

Las primeras cuatro lineas graban el codigo de la persona seleccionada en un archivo llamado "TEMPORAL" y las dos siguientes abren el documento que contiene el macro en VBA. Un problema usual al hacerlo de esta manera el el error "File not found" ya sea desde el programa o bien desde el Word que no encuentra el documento. La manera mas expedita de solucionar estos problemas es colocar el archivo .EXE de Visual Basic y el documento .doc de VBA en el mismo directorio en que Word busca por defecto sus archivos, en este caso c:\Mis documentos.

Al pinchar el botón de "Word" se cargará el Word y también automáticamente el documento llamado CRS.doc. Al hacer click sobre el botón de macro aparece como se muestra a continuación:

Noten como se han traspasado de manera automática los datos desde el programa en VB a nuestra aplicación VBA. Esto se ha logrado porque al cargarse la Form, se le ha agregado el siguiente código a la sección "Initialize":

Private Sub UserForm_Initialize()
TextBox1.Text = Date
Open "c:\mis documentos\temporal" For Random As 1
Get 1, 1, TEM
Close
codigoinicio = Val(Mid(TEM.codigo, 2))
If codigoinicio > 1 Then
Open "c:\mis documentos\maestro crs" For Random As 1 Len = 600
Get 1, codigoinicio, MOV
Close
TextBox2.Text = MOV.nombre
TextBox6.Text = MOV.rol
TextBox4.Text = MOV.materia
TextBox3.Text = MOV.tribunal
TextBox11.Text = MOV.delegado
TextBox12.Text = MOV.fechasent
End If
End Sub

La primera instrucción carga el textbox con la fecha, las cuatro siguientes leen el registro único del archivo "TEMPORAL" y lo convierten en la variable codigoinicio.

Si codigoinicio es mayor que 1 (es decir si hay grabado un código válido) se cargarŽçan las textbox correspondientes con los datos. En caso contrario apareceran en blanco para que las llene el digitador.

Como yo soy un programador anticuado y algo obsoleto, siempre he preferido para archivos pequeños y medianos, usar archivos ascii planos en lugar de bases de datos (que necesitan menos instrucciones pero que también tienen sus inconvenientes) Para definir la estructura de los archivos ascii hay que insertar un nuevo modulo, al que yo le coloco el nombre de "globales", en el declaro las estructuras de datos, las variables globales y la información del programa como se muestra a continuación:

'******************************************************************
' Tomás Bradanovic Computación
'
' Programa para emisión de presentacion de delegado
' Gendarmería de Chile, CRS Arica
'
' Nombre del proyecto : CRS
'
' Ultima modificación : 27-12-98
'*******************************************************************

Type registrohistorico
nombre As String * 30
fecha As String * 8
diapres As String * 8
horapres As String * 8
End Type
' LARGO TOTAL 54
Type REGISTROMOVIM
nombre As String * 40
sexo2 As String * 1
familiar As String * 40
rol As String * 15
materia As String * 50
situacion As String * 20
fechingreso As String * 8
fechegreso As String * 8
fechnacim As String * 8
domicilio As String * 40
tribunal As String * 2
tipomed As String * 40
escolaridad As String * 25
rut As String * 15
actividad As String * 40
tipegreso As String * 40
sexo As String * 1
capacitacion As String * 2
delegado As String * 30
fechasent As String * 8
End Type
Type registrotemp
codigo As String * 10
End Type
Global TIP As registrohistorico
Global TEM As registrotemp
Global MOV As REGISTROMOVIM
Global Const ARCHIVO = "c:\mis documentos\maestro.crs"
Global Const HISTORICO = "PRESENT.HIS"
Global indice As Double

En este código se comienza con comentarios de información sobre los programas y luego se defina la estructura de los tres archivos ascii que se usaran mediante nidos Type... End Type

Luego se declaran como variables globales TIP, TEM y MOV que serán las variables para grabar y recuperar los archivos de grabar histórico, temporal y lectura de datos de VB respectivamente. LAs demás lineas declaran variables globales que se usaran en distintas partes del programa.

Los archivos ascii graban sus registros a partir de la posición 2, ya que la primera posición se usa para guardar un índice con la cantidad de registros grabados. Al agregar un registro se lee el primer registro, se incrementa en uno y se graba en esa posición.. Ese código puede verse al principio del evento "click" del botón "Ok". El código completo del botón Ok es el siguiente:

Private Sub CommandButton1_Click()
'graba e imprime
Close
Open HISTORICO For Random As 1
Get 1, 1, TIP
ULTIMO = Val(TIP.nombre)
PUNTERO = ULTIMO + 1
If PUNTERO = 1 Then
PUNTERO = 2
End If
TIP.nombre = Str(PUNTERO)
Put 1, 1, TIP 'recupera puntero, lo incrementa y lo graba

TIP.fecha = TextBox1.Text
TIP.nombre = TextBox2.Text
TIP.diapres = TextBox7.Text
TIP.horapres = TextBox10.Text
Put 1, PUNTERO, TIP
Close

TRIB = Val(TRI)
If TRB = 1 Then
tr = "PRIMER"
ElseIf TRIB = 2 Then
tr = "SEGUNDO"
ElseIf TRIB = 3 Then
tr = "TERCER"
ElseIf TRIB = 4 Then
tr = "CUARTO"
End If
'************************************************************************
With Selection
.Font.Name = "Arial"
.Font.Size = 10
.MoveUp Unit:=wdLine, Count:=21
.ParagraphFormat.LineSpacingRule = wdLineSpaceSingle
.ParagraphFormat.Alignment = wdAlignParagraphLeft
.TypeText Text:=" GENDARMERIA DE CHILE " & vbTab & vbTab & vbTab & "ORD.: Nº " & TextBox1.Text
.TypeParagraph
.TypeText Text:="CENTRO DE REINSERCION SOCIAL" & vbTab & vbTab & vbTab & "ANT.: Art. Nº 19 Ley 18,216"
.TypeParagraph
.TypeText Text:=" A R I C A " & vbTab & vbTab & vbTab & "MAT.: Comunica Presentación de"
.TypeParagraph
.TypeText Text:=" ------------------- " & vbTab & vbTab & vbTab & vbTab & "Beneficiario y Asignación"
.TypeParagraph
.TypeText Text:=" " & vbTab & vbTab & vbTab & vbTab & "de Delegado"
.TypeParagraph
.TypeText Text:=" " & vbTab & vbTab & vbTab & vbTab & "----------------------------------"
.TypeParagraph
.TypeText Text:=" " & vbTab & vbTab & vbTab & vbTab & " ARICA, " & TextBox1.Text
.TypeParagraph
.TypeParagraph
.TypeText Text:="DE : JEFE CENTRO DE REINSERCION SOCIAL DE ARICA"
.TypeParagraph
.TypeParagraph
.TypeText Text:="A : SEÑOR (A) MAGISTRADO (A)"
.TypeParagraph
.TypeParagraph
.TypeText Text:=vbTab & vbTab & vbTab & vbTab & "1.- En conformidad a lo dispuesto en el Antecedente, se informa "
.TypeText Text:="a Us., que el Usuario " & Trim(TextBox2.Text) & ", condenado (a) y beneficiado (a) con las Medidas "
.TypeText Text:="Alternativas a la Reclusión de Libertad Vigilada del Adulto en Causa Rol Nº " & Trim(TextBox6.Text)
.TypeText Text:=" por el delito de " & Trim(TextBox4.Text) & ", condena instruida en su contra por el "
.TypeText Text:=TRIB & " JUZGADO DEL CRIMEN DE ARICA el " & MOV.fechasent
.TypeText Text:=" se presentó el día " & TextBox7.Text & " a las " & TextBox10.Text & "Hrs., Registro Nº "
.TypeParagraph
.TypeParagraph
.TypeText Text:=vbTab & vbTab & vbTab & vbTab & "2.-Para hacer cumplir la sentencia impuesta al concurrente se le ha asignado a "
.TypeText Text:="como Delegado Libertad Vigilada del Adulto."
.TypeParagraph
.TypeParagraph
.TypeText Text:=vbTab & vbTab & vbTab & vbTab & "Saluda a Us.,"
.TypeParagraph
.TypeParagraph
.TypeParagraph
.TypeText Text:=vbTab & vbTab & vbTab & vbTab & "LUISA VALENZUELA VERA"
.TypeParagraph
.TypeText Text:=vbTab & vbTab & vbTab & vbTab & " Asistente Social"
.TypeParagraph
.TypeText Text:=vbTab & vbTab & vbTab & vbTab & " Jefe C.R.S. Arica"
.TypeParagraph
.TypeParagraph
.TypeParagraph
.TypeText Text:="LVV/alc"
.TypeParagraph
.TypeText Text:="DISTRIBUCION"
.TypeParagraph
.TypeText Text:="-Precitado"
.TypeParagraph
.TypeText Text:="-Exp.Individual"
.TypeParagraph
.TypeText Text:="-Arch.Unidad"
End With
'Application.PrintOut FileName:="citacion.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 form1
End Sub

Donde las primeras 16 líneas leen el puntero del archivo histórico, lo incrementan en uno, lo graban y luego agregan el nuevo registro.

Las siguientes 82 líneas generan el documento, llenando los campos variables. Debajo del End With hay 5 líneas de código desactivadas (colocadas como comentario) estas servirían para que el documento se imprima inmediatamente, sin esperar ser revisado.

El resto de la codificación es trivial y no se diferencia en nada a la del Visual Basic común y corriente. Para generar el documento mismo existen dos alternativas:

a) Grabar en el documento todos los textos fijos y dejar campos variables con la información que deseamos llenar. Esto simplifica mucho el código pero tiene la desventaja que el usuario podría modificar la parte fija del documento por equivocación.

b) Codificar todas las lineas del documento, tanto las fijas como las variables. Esta es la opción que yo he escogido, en que se carga una hoja en blanco y el programa escribe todas las líneas con mínima posibilidad de intervención del operador. En todo caso usando las funciones de cortar y pegar un programa de este tipo no debería demorar mas de una tarde en escribirse.

Finalmente conviene grabar estos documentos como plantillas protegidas, para que no se regraben por error los datos de documentos anteriores así como para evitar la manipulación del código de parte del operador.

Si se hubiese usado Acces para almacenar los datos la codificación se habría simplificado algo, en todo caso es cuestión de preferencias personales. Para ver el código completo pueden chequear el documento CRS.doc que les adjunto, solo hay que abrirlo en Word y usar "Herramientas" "Macros" "editor de Visual Basic" como es usual.

 

Autor: Tomás Bradanovic
http://members.spree.com/sip/tombrad

Entrega 1 - Entrega 2 - Entrega 3 - Entrega 4 - Entrega 5 - Entrega 6 - Entrega 7 - Entrega 8 - Entrega 9
Descargar