Ir al contenido principal

Importación de archivos de texto (log) a una base de datos Access

Introducción

A partir de la pregunta de un usuario de todoexpertos.com, voy a intentar poner en limpio un método para hacer importaciones de datos log.
Se trata de leer un archivo de texto con información, tratarla y escribirla en una base de datos.
En este caso voy a hacerlo con Access, por dos motivos:

  • El usuario lo pregunta en este lenguaje
  • Es lo más rápido y cómodo que tengo a mano
Cada caso es distinto, es decir, cada archivo es distinto, porque cada archivo contiene una información determinada, y quien diseñó la exportación a log, decidió la estructura de datos que quería exportar y el formato en que se escribiría tal exportación.
Por tanto, lo primero que hay que hacer es estudiar esa estructura de datos y ver como plasmarla en una o más tablas de datos. Lo segundo es crear las tablas correspondientes.
Siempre puede haber errores en la estructura, porque siempre pueden aparecer datos imprevistos que no existen en los primeros archivos log vistos, por tanto, hay que tener presente que el código debe ser legible y bien estructurado para poder modificarlo en caso necesario.

Planteamiento

Los pasos a seguir son:
  1. Creación de un módulo para la importación. Por higiene, vale más la pena hacer un módulo que se dedique a la importación.
  2. Crear los tipos de datos necesarios. Es útil para escribir la información de forma más clara en las tablas de datos
  3. Crear un SUB que lea la información.
  4. Crear un SUB que formatee y escriba la información.

Detalle

Módulo de importación

Es importante que las primeras líneas del módulo sean:
Option Compare DatabaseOption Explicit
Esto hace que estemos obligados a declarar cada variable antes de poder usarla.
Aunque VBA admite que podamos usar variables sin declaración, bajo mi punto de vista, es bueno acostumbrarnos a declararlas cada vez.

Tipos de datos

Veremos más adelante porque son tan útiles.
Su declaración se hace justo después de las primeras dos líneas y depende en cada caso, en cada tipo de importación. Asumimos que siempre tenemos el mismo tipo de importación.
Voy a usar dos campos como ejemplo.
Doy por supuesto que:

  • La información del archivo contiene los datos que se muestran en la estructura
  • Se ha creado una tabla a tal efecto y con los mismos campos

La declaración de un tipo se hace del siguiente modo:

Type MiTipo
    Campo1 As Long
    Campo2 As String
End Type

De este modo hemos definido una variable de variables que usaremos como un todo, es decir, que podremos definir variables de tipo MiTipo.
Esta estructura nos facilitará mucho la gestión de los datos.

Lectura de la información

La lectura de la información se hace en un SUB. Esquemáticamente lo que hace es:
  • Abrir el archivo
  • Leer el archivo de forma secuencial (de arriba a abajo, línea a línea)
  • Pasar cada línea leída a una función que la descompone y la organiza según el tipo definido anteriormente, y que posteriormente la pasa a otra que lo escribe en la tabla.
Evidentemente, la organización puede variar.

Abrir el archivo

Supondremos que el archivo se llama archivo.log, para simplificar, y que está en la misma carpeta que la aplicación.
Veremos en otro post cómo hacer que el usuario pueda seleccionar un archivo mediante las utilidades del sistema.
El código a añadir a nuestro módulo sería:

Public Sub Importador(NombreArchivo As String)
    Dim linea as String

    Open NombreArchivo For Input As #1
    Do While Not EOF(1)
        Line Input #1, linea
        GrabarDatos linea, Separador
    Loop
    Close #1
End Sub

Analicemos el código:
  • Se pasa como parámetro de entrada una cadena con el nombre del archivo. Veremos en otro post porqué y como se gestiona.
  • La sentencia Dim declara los dos datos que necesitamos, linea, que contendrá la información que leamos de cada línea del archivo log.
  • La orden Open abre el archivo para lectura y le asigna un número
  • Mientras no se llegue a final de fichero, se lee una línea del archivo y se almacena en la variable linea, se pasa al SUB GrabarDatos
  • Cuando se llega al final del archivo, se cierra.
Más código. Veamos en procedimiento GrabarDatos:

Private Sub GrabarDatos(Linea As String)
    Dim Registro As MiTipo, Posicion as Integer, Longitud as Integer
    Dim Car as String, Campo As Integer
    Dim sqlAccion as String

    Longitud = Len(Linea)
    Posicion = 1
    Campo = 1
    While Posicion <= Longitud
      Car = Mid(Linea,i,1)
      If Car =;" Then
          Campo = Campo + 1
      Else
          Select Case Campo
            Case 1
              Registro.Campo1 = Registro.Campo1 * 10 + Val(Car)
            Case 2
              Registro.Campo2 = Registro.Campo2 & Var 
          End Select
      End If
      Posicion = Posicion + 1
    Wend


    sqlAccion = "INSERT INTO Tabla (Campo1, Campo2) " & _
                "VALUES (" & Datos.Campo1 & ", " & _
                        "'" & Datos.Campo2 & "')"
    CurrentDB.Execute (sqlAccion)


End Sub

Analicemos el código precedente:
  • Así como en el procedimiento Importador hemos recorrido el archivo log de arriba a abajo, en GrabarDatos recorremos cada línea de izquierda a derecha.
  • En ambos casos necesitamos saber cuando acaba el archivo o la línea. 
  • El archivo acaba cuando EOF (End Of File) es cierto, en el caso de la línea cuando hemos llegado al final.
  • Para saber cuando hemos llegado al final usamos las variables Posicion y Longitud.
  • La variable Posición es un número entero, inicialmente 1, que es el primer carácter de la línea, y que va cambiando para cada uno de los caracteres que iremos leyendo. Recordemos que la línea es una cadena de caracteres, un String. 
  • El recorrido es también secuencial, es decir, en cada paso del bucle se lee y se trata un carácter.
  • La variable Longitud es la longitud de la cadena Len(Linea), por tanto, empezamos en el primer campo, Campo=1, y vamos leyendo un carácter:
Car = Mid(Linea,i,1)
  • Car contiene uno a uno cada valor incluido en el parámetro de entrada.
  • Si el carácter leído es punto y coma (;), es decir, es el separador de campos, hacemos que salte al campo siguiente.
  • Si el carácter no es el separador de campos, se entiende que es el contenido del campo correspondiente, por lo que ese valor se colocará donde corresponda. Si se trata del primer campo, es un número, por ejemplo 3, y ya se había entrado otro número, por ejemplo 2, se multiplica 2*10 y se suma, es decir, 2*10=20 y 20+3=23, que es el resultado final. Si se trata del segundo campo es una cadena de texto, por lo que se concatena el contenido actual con el nuevo carácter.
  • Una vez se ha añadido el nuevo valor de Car al campo correspondiente, se actualiza el valor de Posicion para seguir leyendo hasta que el valor de i sea la longitud de la cadena completa, momento en el cual ha acabado la lectura de la línea.
  • Una vez se ha leído la línea entera y se han separado los datos en los campos correspondientes se pasa a escribir en la tabla con la sentencia SQL Insert Into.

Consideraciones finales

  • Se ha supuesto que cada línea del archivo log tiene un solo carácter de separación de campos.
  • Se ha supuesto que el carácter separador es un punto y coma (;), siempre.
  • La diferenciación entre campos se podría haber hecho sin tener que acumular en un contador. Sí, es cierto, pero se trata de un ejemplo, y se deja preparado para que cualquier archivo log tenga más de dos campos.
  • No se han añadido más campos, evidentemente porque es un ejemplo. Se entiende que a partir de este código es el programador quien debe investigar y completar como extenderlo a más campos, sean del tipo que sean.
  • Se ha supuesto que cada dato leído se entra a la tabla de datos tal cual.

Bueno, hasta aquí el pequeño tutorial de importación de datos de un archivo log.
Espero que os haya gustado y que haya servido para aclarar algo.

Comentarios