Una Clase Para Archivos Ascii Planos

Como yo uso mucho los archivos Ascii planos para guardar información de volumen pequeño (digamos, bajo los 5.000 registros) no es raro que mi primera aplicación práctica de módulo de clases consista en encapsular los trozos de código usuales para grabar, leer y agregar registros en archivos de esta clase.

La verdad es que ya había intentado algo así hace algún tiempo en el artículo Programación Orientada a Objetos pero como no tenía muy claro el asunto el código no me quedó práctico aunque me sirvió para aprender y para efectos de demostración

 

El Módulo de Clase
Primero que nada usamos Proyecto, Agregar Módulo de Clase, con lo que se agrega un módulo en blanco. Le cambiamos el nombre a clsArchivo.cls (usando la notación recomendada con mayúsculas/minúsculas y las 3 primeras letras que indican de que se trata el objeto)

En éste módulo codificamos luego los procedimientos públicos grabar, leer, agregar y los privados abrir y cerrar como se muestra a continuación

Public archivo
Public pos

Public Sub Grabar()
     Abrir 
     Put 1, pos, Reg
     Cerrar
End Sub

Public Sub Leer()
     Abrir 
     Get 1, pos, Reg
     Cerrar
End Sub

Public Sub Agregar()
     Abrir 
     posi = LOF(1) / 80 + 1
     Put 1, posi, Reg
     Cerrar
End Sub

Private Sub Abrir()
      Open archivo For Random As 1 Len = 80
End Sub

Private Sub Cerrar()
       Close
End Sub

Con las instrucciones

Public archivo
Public pos

Le asignamos a la clase dos propiedades (archivo y pos) ¡así de simple!

Las demás propiedades que requieren operaciones públicas (grabar, leer, agregar) o privadas (abrir, cerrar) se escriben simplemente con el código correspondiente según sea el caso

Para agregar registros he sustituido el cavernario método de grabar la posición en el primer registro por 

posi = LOF(1) / 80 + 1

Que determina la posición donde deberá agregarse el último registro. Nótese que al abrir el archivo he indicado que los registros ocuparán un ancho máximo de 80 caracteres

Finalmente, para simplificar la clase en el procedimiento Cerrar he usado simplemente Close (lo que cierra todos los archivos abiertos) asumiendo que voy a trabajar solo con un archivo abierto a la vez como usualmente lo hago. Nótese también que cada vez que leo o escribo el archivo lo abro y lo cierro inmediatamente, esto elimina en gran medida los riesgos de corrupción de archivos por cortes de energía y problemas por el estilo

 

Un programa de ejemplo para probar la clase
Podemos crear una form como se muestra a continuación

 

Con un módulo .bas para declaraciones donde ponemos

Type Registro
     Nombre As String * 30
     Direccion As String * 30
     Telefono As String * 20
End Type

Public Reg As Registro           rem Con esto declaramos el registro como Reg
Public Ar As New clsArchivo   rem Con esto declaramos la clase como Ar

Y con los siguientes códigos en los elementos del form

Private Sub Command1_Click()
     rem Agregar

    
Reg.Nombre = txtNombre
     Reg.Direccion = txtDireccion
     Reg.Telefono = txtTelefono
     Ar.Agregar
End Sub

Private Sub Command2_Click()
     'rem Leer
     Ar.pos = Val(txtPos)
     Ar.Leer
     txtNombre = Reg.Nombre
     txtDireccion = Reg.Direccion
     txtTelefono = Reg.Telefono
End Sub

Private Sub Command3_Click()
     'rem Listar
     Open Ar.archivo For Random As 1
     ultimo = LOF(1) / 80
     Close
     For z = 1 To ultimo
          Ar.pos = z
          Ar.Leer
          List1.AddItem Reg.Nombre
     Next z
End Sub

Private Sub Form_Load()
     Ar.archivo = "prueba.tmp"
End Sub

¿Y si lo combinamos con el control OCX?
En el Artículo Creación de un Control OCX  mostraba como hacer un control que pidiera los datos de nombre, dirección y teléfono ¿por que no aprovecharlo entonces en este ejemplo?

Manos a la obra entonces, creamos un nuevo proyecto al que le agregamos la clase clsArchivo.cls que ya creamos en el ejemplo anterior (Proyecto, Agregar módulo de clase). También le agregamos el módulo .bas con las declaraciones Type...End Type y todo eso (Proyecto, Agregar módulo.

Luego con Proyecto, Componentes, Examinar agregamos el control OCX que ya tenemos compilado (en este caso se llama Ingreso.ocx) cerramos la ventana de proyecto y agregamos nuestro componente ocx y dos botones como muestra la figura siguiente:

Por último agregamos el código a los componentes como se muestra a continuación:

Private Sub Command1_Click()
     Rem Agregar
     Reg.Nombre = Mid(IngresoCtl1.StrSalida, 1, 30)
     Reg.Direccion = Mid(IngresoCtl1.StrSalida, 31, 30)
     Reg.Telefono = Mid(IngresoCtl1.StrSalida, 61, 20)
     Ar.Agregar
End Sub

Private Sub Command2_Click()
     'rem Listar
     Open Ar.archivo For Random As 1
     ultimo = LOF(1) / 80
     Close
     For z = 1 To ultimo
          Ar.pos = z
          Ar.Leer
          List1.AddItem Reg.Nombre
     Next z
End Sub

Private Sub Form_Load()
     IngresoCtl1.Titulo = "Ingrese los Datos"
     IngresoCtl1.Leyenda1 = "Nombre"
     IngresoCtl1.Leyenda2 = "Dirección"
     IngresoCtl1.Leyenda3 = "Teléfono"
     Ar.archivo = "prueba.tmp"
End Sub

A ver, probemos

 

Perfecto, todo funciona de acuerdo a lo esperado 

 

¿Y qué más podríamos hacer?

Bueno, podríamos por ejemplo compilar nuestra clase creando una DLL ActiveX, pero eso lo dejaremos para una próxima ocasión, creo que con estos ejemplos sencillos podemos darnos cuenta de las ventajas de crear objetos reutilizables

 

Créditos

El ejercicio presentado aquí lo hice con la ayuda del libro "Edición Especial, Visual Basic 6.0" de Brian Siler y Jeff Spotts, Editorial QUE (949 pgs)