Comentaba en la primer parte del trabajo con archivos de texto plano algunas de las ventajas que nos presenta este tipo de métodos. Vimos el primero de los modos de acceder a ellos, denominado Secuencial, resultándonos de mucha utilidad a la hora de leer / escribir en dichos archivos, pero a la vez la gran desventaja que nos representaba el hecho de modificar algún dato.
Seguidamente detallaré el segundo modo disponible: el Aleatorio (Random). Recordemos que en el Secuencial, al abrirlo y en la primer línea de código, especificamos si nuestra operación será de lectura o escritura, lo que nos traía aparejado un problema: si estoy leyendo, no puedo modificar ningún dato, y si estoy escribiendo, no puedo leer. Con el Aleatorio las cosas cambian: simplemente le ordeno a VBA que abra el archivo y luego, según mis necesidades, leo o escribo en él. Y de ahí si nombre, Aleatorio, ya que una vez abierto cualquiera de las dos posibilidades son válida, sin la necesidad de avisarle previamente a VBA que es lo que voy a hacer. Pero cuidado, ya que esta forma de trabajar nos requerirá mayor planificación al momento de guardar los datos en un TXT. Y veremos mas adelante el por qué.
La sintaxis de la instrucción es casi (casi) igual a la Secuencial, con una leve pero importantísima modificación:
Open NombreDeArchivo For Random As #NúmeroDeArchivo Len = LongitudDelRegistro
La diferencia la encontramos al final de la línea: Len = LongitudDelRegistro
Si bien ahora no debemos especificar si voy a leer o escribir, nos encontramos en la obligación de indicarle a VBA que longitud (cantidad de bytes) tendrá la línea que voy a leer. Y es lógico: con las operaciones que nos permitirá realizar este modo, dentro de las instrucciones deberé indicar que posición leo / escribo / modifico.
trabajaremos con esta tabla de reducidas dimensiones, para escribir y leer datos en modo secuencial.
Mencionaba mas arriba la cuestión de la planificación. ¿Cómo me aseguro que todas las líneas insertas en el archivo de texto tengan la misma longitud de bytes? Por si no lo notaron, en nuestro trabajo sobre archivos Secuenciales la longitud de la cadena podía ser cualquiera.... pero aquí no. Y a esto lo solucionamos haciendo uso de los “tipos definidos por el usuario”, que no son mas que la creación de variables propias.
Un ejemplo dejará todo mas en claro: necesitamos almacenar en un TXT distintos datos sobre los empleados de la empresa: Legajo, Apellido, Edad y Estado Civil. Estos datos pueden tener en origen cualquier longitud, ya que un empleado de apellido Sebastianelli ocupará mas byte que Silva, y pero aún si el legajo de Sebastianelli es 115243 y el de Silva 845.
A esto lo solucionamos creando un “tipo definido por el usuario”, utilizando la siguiente sintaxis / estructura, la cual deberá ser colocada en un módulo de VBA
Type Persona Legajo As Integer Apellido As String * 20 Edad As Byte EstadoCivil As String * 2 End Type
Analicemos: en lugar de Sub o Function, usamos la palabra reservada Type (tipo) y a continuación el nombre que le daremos a nuestra nueva variable (en este caso, “Persona”).
Luego detallamos las variables que conformarán nuestro Type, especificando unívocamente que tipo de dato utilizarán cada una de ellas (byte, double, string, etc, etc). Y esto tiene un fundamento muy básico: recordemos que el modo Aleatorio mide la cantidad de Bytes de la cadena. Cada tipo de dato tiene una longitud de bytes fija (el long 4 bytes, el integer 2, el double 8, etc, etc), la única problemática aquí es la String, pero noten que usando el multiplicador le asigno una cantidad fija de caracteres. En los ejemplos arriba descriptos, Apellido nunca se guardará con mas de 20 caracteres y EstadoCivil tampoco tendrá mas de 2. Si el dato a guardar excede esa cantidad, VBA los truncará y solo almacenará los primeros 20, en el caso del Apellido.
Y todo armado de esta forma es mas sencillo. Vamos a los números, que no son redondos del todos, pero no quiero ponerme demasiado técnico y simplemente brindar un ejemplo compresible:
Legajo – Integer – 64 bits
Apellido – String – 20 caracteres * 8 bits c/u = 160 bits
Edad – Byte – 16 bits
EstadoCivil – String – 2 caracteres * 8 bits c/u = 16 bits.
Sumando los bits totales, obtendremos la longitud del registro.
Aclarado el tema de Type, volvamos al modo de acceso Aleatorio y como implementados todo lo leído hasta ahora en la práctica. Codifiquemos el ingreso al TXT de una tabla que tenemos en Excel:
Sub GrabarEnModoAleatorio() 'aquí dimensiono mi Type "Persona". Luego de 'ingresar la palabra reservada As, "Persona" aparece 'en la lista desplegable de variables. Dim Empleado As Persona Dim MiCadena As String Dim X As Integer 'y aqui la instrucción de apertura. Para definir el Len que me 'solicita, pongo la longitud de la variable Empleado, que a su 'vez contiene todos los datos del Type Persona definido previa 'mente. Open "R:\Compartido\txt_aleatorio.txt" For Random As #1 Len = Len(Empleado) For X = 1 To 5 'tomo los datos de la tabla y lo almaceno en cada 'variable: Empleado.Legajo = Cells(X + 1, 1) Empleado.Apellido = Cells(X + 1, 2) Empleado.Edad = Cells(X + 1, 3) Empleado.EstadoCivil = Cells(X + 1, 4) 'y con la instrucción Put escribo, utilizando a X 'para definir en que posicion colocaré cada registro: 'put_nroDeArchivo, posicion, registro: Put #1, X, Empleado Next X Close #1 End Sub
Y para recuperar los datos de un TXT
Sub LeerEnModoAleatorio() 'aquí dimensiono mi Type "Persona". Luego de 'ingresar la palabra reservada As, "Persona" aparece 'en la lista desplegable de variables. Dim Empleado As Persona Dim MiCadena As String Dim TotalRegistros As Integer Dim LongitudArchivo As Long 'y aqui la instrucción de apertura. para definir el Len que me 'solicita, pongo la longitud de la variable Empleado, que a su 'vez contiene todos los datos del Type Persona definido previa 'mente. Open "R:\Compartido\txt_aleatorio.txt" For Random As #1 Len = Len(Empleado) 'con la función LOF() calculo el tamñano de un archivo '(cuando se encuentra abierto) LongitudArchivo = LOF(1) 'si a la longitud del archivo lo divido por la longitud de 'cada registro... obtengo la cantidad total de registros 'existentes en el archivo, para luego usar esa variable 'el en bucle For... y recorrer todos los datos: TotalRegistros = Int(LongitudArchivo / Len(Empleado)) 'leemos con GET, especificando en este caso la posición 'del registro con un simple Bucle. noten que aqui usamos 'a TotalRegistros, producto de los dos calculos anteriores: For X = 1 To TotalRegistros 'get_nroDeArchivo_posicion_registro: Get #1, X, Empleado 'y vuelco esos datos a excel: Cells(X + 1, 1) = Empleado.Legajo Cells(X + 1, 2) = Empleado.Apellido Cells(X + 1, 3) = Empleado.Edad Cells(X + 1, 4) = Empleado.EstadoCivil Next X Close #1 End Sub
Hemos tratado las dos formas básicas de lectura / escritura, aunque lo suficientemente prácticas como para ponernos a trabajar en el tema. Lo mas interesante de este método es que, a diferencia del Secuencial, en donde para llegar al registro 2000 tengo que recorrer los 1999 previos, podemos ir directamente a uno en particular, indicando su posición. De la siguiente forma leo, sin mas, el registro que ocupa la posición 2000:
Open "R:\Compartido\txt_aleatorio.txt" For Random As #1 Len = Len(Empleado) Get #1, 2000, Empleado Close #1
Sigamos con tema que es de suma importancia, para aprovechar así a nuestro modo Random: modificar los registros existentes, tarea engorrosa y poco práctica en extremo si intentamos hacerlo a través del modo Secuencial.
Con lo aprendido hasta el momento podemos llevarlo a cabo sin problemas. El tema es sencillo: ubicamos el registro y sobrescribimos el campo que necesitamos cambiar.
Aquí surge una cuestión: como ubico el registro. Podríamos cargar los datos del TXT en un ListBox y luego, aprovechando la propiedad ListIndex de este objeto, ubicar el nro de línea en donde se encuentra el registro a modificar. O bien, como vimos en la entrada sobre el modo Aleatorio, ir línea x línea buscando los datos, utilizando la función Instr().
Uno de los “empleados” de nuestra supuesta empresa es “Sebastianelli”, legajo 356. Vamos a modificar algunos de sus datos:
Sub ModificarEnModoAleatorio() 'aquí dimensiono mi Type "Persona". Luego de 'ingresar la palabra reservada As, "Persona" aparece 'en la lista desplegable de variables. Dim Empleado As Persona Dim MiCadena As String Dim X As Integer 'aqui indico la posicion del empleado, la cual pudimos averi 'guar con alguna de las formas ya citadas: posicion = 2 'cambio el legajo. estos datos podrían 'venir de un textbox o alguna celda habilitada a los efectos Empleado.Legajo = 444 Open "H:\txt_aleatorio.txt" For Random As #1 Len = Len(Empleado) Put #1, posicion, Empleado.Legajo Close #1 End Sub
aqui vemos como quedó modificado el legajo. Obviamente que al estar en Excel la imagen del ejemplo, primero corrí el sub LeerEnModoAleatorio(), que migró los datos del TXT hacia la hoja de cálculos.
Como he mencionado con anterioridad, no duden en utilizar archivos de texto para el almacenamiento de datos, ya que VBA es muy poderoso a la hora de manipularlos. Desde ya que no reemplazarán a las prestaciones de una base de datos convencional, pero tienen sus ventajas, como por ejemplo las pocas líneas de código que necesitamos para manejarlos, los casi nulos requerimientos del sistema, el poco peso de los archivos resultantes, portabilidad y su fácil migración hacia otros medios de almacenamiento.
Nos restaría ver otra forma de apertura de archivos: Binario (Binary), la cual es muy poco utilizada para estos casos, ya que al leer byte x byte se aplica a los archivos de imagenes o ejecutables. Igualmente haré una entrada sobre el tema.
- Obtener enlace
- X
- Correo electrónico
- Otras aplicaciones
Etiquetas
Macros
Etiquetas:
Macros
- Obtener enlace
- X
- Correo electrónico
- Otras aplicaciones
hola damian: tus ejemplos son muy completos y pienso igual como el que escribio uqe hay cosas de excel que no sabia que existian. no soy programadora y solo grabo algunas macros y tengo un problema con un libro en el cual guardo datos en una tabla por hoja. necesito guardar esas tablas en un archivo de texto pero cuando voy a archivo ... guardar como ... archivo de texto me dice que libros de mas de una hoja no pueden guardarse. probe copiando y pegando en un libro nuevo y eliminando las hojas sobrantes y asi guardarlas y mi problema tambien es que son muchas hojas en mi libro. mas de 40. tardo mucho tiempo. necesitaria que me ayudes con esto gracias
ResponderEliminaranalía: no me olvido de tu consulta, pero tengo un pequenio problema a la hora de ejecutar la macro en distintas versiones de Excel. ahora estoy trabajando en un ejemplo mas complejo que se ejecute sin dificultades en cualquier versión.
ResponderEliminar