Bueno, hay cosas que sigo sin entender, son detalles que sólo tu sabes.
No obstante eso no quita para te pueda indicar una línea de trabajo....
Yo te expongo un código que luego debes completar y adaptar a tus necesidades. Como no he podido descargar hasta hoy los otros 2 ficheros (tras descargar el fichero *.plf el 'gigasize' me indicó que alcancé el límite), ... pués no he visto que lo trabajas todo en excel.
Hay partes que está comentada y parte que tiene código, te lo meto todo en un archivo rar, lo abres y lo miras detenidamente, para hacerc cambios hazlos sobre una copia,a así quedando este intacto, podrás volver a ver el original cuando lo necesites. Obviamente tendrás que modificarlo bastante para adaptarlo a excel.... Sin embargo está bastante comentado, como para que puedas hacer un seguimiento casi completo sin perderte.
De todas formas te lo voy comentando por encima...
Tenemos un formulario, tiene 3 botoners, uno de iniciar y otro de detener, el tercero sólo aparece si ocurre aalgún error inesperado, el resto de la interfaz sólo tiene propósitos de aclarar el estado del proceso.
Los estados posibles son EnEspera de iniciarse(a fin de cuentas parado) , petición de inicio, inicio, petición de parada, parado.
Cuando el estado es petición de inicio, el timer se pone en marcha e invoca un método de una clase que es quien realiza todo el trabajo. Si tiene éxito dispara un evento 'procesando', entonces el estado pasa a ser iniciado. si ocurre un error el estado pasa a ser parado.
Cuando se pulsa el botón de parar, el estado se establece en petición de parada, la parada sólo ocurre cuando se termine de procesar los datos actuales. cuando esto ocurre se dispara un evento de terminado.
Estos botones 'fluctuan' , con el disparo de dichos eventos (procesando y terminado) habilitándose/desahbilitándose y cambio el color de fondo de los mismos, lo cual está controlado de modo general por el timer...
Cuando se inicia la aplicación se crea una instancia de la clse 'Trnsformar' y se invoca una función de ésta, la idea es que en esa función busquees el fichero inicial de entrada, debes también asignar las rutas a las variables de dichos archivos (entrada y salida)
El resto de la interfaz son el propio timer y 2 shapes, para indicar estados... adicional al estado que marcan los botones, para distinguir la fluctuación de los botones del estado global.
Como el código del formulario es bastante 'sencillo', creo que no necesita más comentario
El código del formulario es éste:
Private Procesando As Boolean
Private WithEvents Transforma As Transformar
Private Reintentos As Byte
Private Const Carmin As Long = &HE0E0F0
Private Const Verdin As Long = &HE0F0E0
' inicia un intento de paro o puesta en marcha del proceso
' la notificación de paro sólo sucederá cuando se termine el actual
' bloque de operaciones en curso.
Private Sub ComProceso_Click(Index As Integer)
' color de transición, tras un evento de transforma ya se cambiarán a su color adecuado
If Index = 0 Then
ComProceso(0).BackColor = Verdin
ComProceso(0).Enabled = False
ElseIf Index = 1 Then
ComProceso(1).BackColor = Carmin
ComProceso(1).Enabled = False
End If
Timer1.Enabled = (Index = 0)
ShaEnMarcha.Visible = Timer1.Enabled
End Sub
' regresa los cambios operados ante error al modo operativo normal
Private Sub ComResetError_Click()
ComResetError.Enabled = False
ComResetError.Visible = False
ShaError.Visible = False
ComProceso(0).Enabled = True
ShaEnMarcha.Visible = True
Timer1.Enabled = True
End Sub
' esto es lo primero que se va a ejecutar cuando se inicie la aplicación.
' prepara los controles y valores....
Private Sub Form_Initialize()
Set Transforma = New Transformar
Reintentos = 0
End Sub
' realiza hasta 12 intentos
Private Sub Form_Load()
Dim Ok As Boolean
Timer1.Enabled = False
Timer1.Interval = 30000
Do While Reintentos < 12
If Not (Transforma Is Nothing) Then
If Transforma.InicializarProceso = True Then
Ok = True
Exit Do
Else
' avisar, algo no está conforme a lo que necesitamos
' ver descripción de InicializarProceso
End If
Else
Reintentos = Reintentos + 1
' pausa de 3 segundos y reintentamos
Call Pausa(3)
Set Transforma = New Transformar
End If
Loop
Reintentos = 0
If Ok = False Then
MsgBox "Ocurrió un error, no se consiguió inicializar el proceso..."
Unload Me
Else
' el sistema está listo para comenzar.... sin embargo espera a que se pulse el botón de comienzo.
ComProceso(0).Enabled = True
ComProceso(1).Enabled = False
ComResetError.Enabled = False
ComResetError.Visible = False
ShaError.Visible = False
End If
End Sub
' antes de cerrar intentamos ver si es posible terminar el proceso actual (si estaba en marcha)
Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
If Timer1.Enabled = True Then
' petición de terminar
Call ComProceso_Click(1)
MsgBox "Hay una operación en curso intentaremos esperar a que termine... antes decerrar."
Me.Hide ' lo ocultamos para evitar que insista y al final recurra a medidas drásticas sin darle tiempo a terminar y guardar el resultado.
Do
DoEvents
Loop While Procesando = True
End If
Set Transforma = Nothing
End Sub
Private Sub Form_Terminate()
Timer1.Enabled = False
Set Transforma = Nothing
End Sub
Private Sub Timer1_Timer()
If Procesando = False Then
Procesando = True
Transforma.Procesar
End If
End Sub
'================================================
'======== eventos de el objeto Transforma =======
Private Sub Transforma_Procesando()
ComProceso(0).Enabled = False
ComProceso(0).BackColor = vbGreen
ComProceso(1).Enabled = True
ComProceso(1).BackColor = Carmin
Beep
Call Pausa(1)
Beep
End Sub
Private Sub Transforma_Terminado()
Procesando = False
ComProceso(1).Enabled = False
ComProceso(1).BackColor = vbRed
ComProceso(0).Enabled = True
ComProceso(0).BackColor = Verdin
Beep
Call Pausa(1)
Beep
End Sub
Private Sub Transforma_ParoError()
Timer1.Enabled = False
ShaEnMarcha.Visible = False
ShaError.Visible = True
ComResetError.Enabled = True
ComResetError.Visible = True
Call Transforma_Terminado
ComProceso(1).Enabled = False
MsgBox "Ha ocurrido un error inesperado..."
' otras acciones posibles
' acciones...
End Sub
' realiza una pausa con los segundos especificados antes de continuar
' esto es aproximado... no es un tiempo exacto. puede fluctuar 200 milisegundos
Private Sub Pausa(ByVal Segundos As Byte)
Dim t As Single
t = Timer
Do
DoEvents
Loop While Timer - t < Segundos
End Sub
La clase se compone de algunas enumeraciones, yo sólo he puesto la de 'eventos', que parece la más obvia y una matriz que se correponde indice a indice con esta enumeración. el resto de enumeraciones que precisares podrías tratarlas del mismo modo.
He tratado cada 'linea' como una estructura, supuse que tu idea inicial era guardarlo como fichero, te texto plano... Cyuando el timer entra en marcha, invoca una función de la clase que se dedica a procesar, hay bastante descripción detallada que señala los pasos que se deben seguir, naturalmente ni está completo ni es obligatorio, deberás añadir, quitar y modificar de acuerdo a tus necesidades, yo sólo te proveo una orientación...
Esa función determina si el fichero en seguimiento ha variado de tamaño, a fin de determinar si se debe seguir leyendo del mismo, intuyo que algo al final de un archivo debe ser indicador de que el archivo está completo, a falta de ello verificar el tamaño es una opción (más pobre pero que sirve). Si el fichero estuviera completo, se debe localizar el siguiente, se llama a una función que realiza esa labor.
Una vez localizado el fichero (si es otro distinto del anterior) se llama a una función que lee el contenido del actual archivo de entrada. Lo leemos todo de una vez (vb6 puede leer perfectamente incluso 10Mb. en menos de 1 sg.) y lo troceamos en líneas, asumimos que cada línea está separada de la siguiente por un retorno de carro y avande de línes (CR= CarryReturn , LF= Line Feed) ó vbCrlf en vb6. Esta función devuelve por referencia el número de líneas contenidas. Si el fichero no está al inicio se posiciona el cursor en la posición actual de lectura, antes de leerlo, lógicamente y guardamos el cursor de lectura tras tomar los datos, luego se cierra el archivo y se devuelve la matriz de líneas
Tras tomar la matriz de líneas si lineas -1 (error ocurruid) ó 0 (no hay texto ???) dispara un evento de error y sale de la función, en otro caso se invoca a otra función, la que va a realizar la transformación de estas líneas en las que tu quieres.
La función que formatea las líneas, está a medio codificar, hay datos que yo no tengo y lógicamente no se en base a que han detomar una u otra constante, a mi la línea, por ejemplo: '2009.05.04 15:42:28 MESSAGE PLY0023,23,3,~CM100GEN', no me dice gran cosa, es de asumir que el código de mensaje responde a un manual de operativa de la máquina , yo he tratado las fechas (sesupone que la fecha de inicio de una operación es la fecha de finalización de la anterior), y he calculado la duración usando una funcion de fecha, para totalizar segundos. El resto de esta función son sugerencias, por ejemplo verás un bloque 'select case', donde debes procesar la parte de 'mensaje', imagino que el resto de texto a la derecha se interpreta de modo uniforme de acuerdo a ese 'mensaje'.
finalmente en la misma función indicada anteriormente, te ofrezco 2 funciones de salida a fichero (es loque creía que tenías que hacen antes de descargar estos ficheros de excel). Nota que la salida en binario siempre será más rápida y cómoda pero ofrece un fichero ilegible a la vista si lo abres con el 'bloc de notas' (igual que sucede si abres un archivo excel con el mismo 'bloc de notas'), un 2º método te ofrece guardarlo en formato de cadena, es siempre más lento, porque tiene que hacerse a través de un bucle línea a línea.
No obstante esta (última) salida es aceptable para excel... excel permite importar ficheros de texto, interpretando como fila de excel cada línea de fichero e interpretando como columna cada dato separado de otro. con esto tienes pués 2 caminos a seguir para crear tus archivos excel, tomar todo el código y adaptarlo, completarlo a tu proyecto actual o crear un nuevo proyecto, completar este que ten envío y luego importar a excel el fichero ya elaborado, las 'fórmulas' que tengas en excel, te siguen valiendo... Sólo cambia el método de adquisición de datos.
El código de la clase es éste:
Private Enum EventosMaquinaIn
EVENTO_AVERIA = -1
EVENTO_ENTRADA = 0
EVENTO_PARADA = 1
EVENTO_MARCHA = 2
EVENTO_REDUCE_VELOCIDAD = 3
End Enum
Private Type LineaSalida
id As Long
Inicio As Date
Fin As Date
Duracion As Integer
' eventoEspecificado as string
Evento As String ' se toman de la matriz EventosMaquinaOut
Maquina As String
Motivo As String
End Type
' nótese que las cadenas se hacen coincidir en índices con EventosMaquinaIn
' los valores se generan al crear la clase: ver Class_Initialize
Private EventosMaquinaOut(-1 To 3) As String
Private s_LinAnterior As LineaSalida
Private p_FicheroEntrada As String
Private p_FicheroSalida As String
Private s_cursorEntrada As Long
Private s_CursorSalida As Long
Private s_TamañoEntrada As Long
Private s_Id As Long
Private s_Maquina As String
Public Event Procesando()
Public Event Terminado()
Public Event ParoError()
Public Property Get FicheroSalida() As String
FicheroSalida = p_FicheroSalida
End Property
Public Property Get FicheroEntrada() As String
FicheroEntrada = p_FicheroEntrada
End Property
' esto debería invocarse cuando se arranca el programa antes de ejecutarse nada
' para hacer esas cosas que sólo ocurrirán una única vez al principio.
Public Function InicializarProceso() As Boolean
' leemos de un fichero estado.txt
' si no existe se crea.
' pero si ya existe leemos
' donde quedamos la vez anterior, esto es si quedó un fichero sin terminar (suponiendo que esto interese)
' si estamos interesados en devolver algún estado devolvemos true, o false según convenga o cambiamos el tipo de devolución
' si queremos devolver otro tipo de dato.
' si deseamos decidir si empezar, o resetear el archivo de estado previo, deberíamos establecer un parámetro a la función.
' antes de devolver nos aseguramos de ver y asignar laos valores para las variables:
' p_ficheroentrada y p_ficherosalida
InicializarProceso = True
End Function
Public Function Procesar()
Dim Texto() As String
Dim Lineas As Long
' si existe p_ficheroEntrada luego
s_TamañoEntrada = FileLen(p_FicheroEntrada)
' si tamaño del fichero es mayor que p_cursorentrada luego (se ha escrito nuevo contenido)
'
' (continuamos con la lectura, esto es en el siguiente apartado)
' el tamaño es el mismo ' nada que procesar, se está esperando a que la máquina realice operaciones o está terminado ?
' (necesitamos saber cuando un fichero está terminado: ¿ obbsstop indica esto ?)
' si sabemos que está terminado luego (debemos buscar el siguiente fichero)
' localizado = llamar a función: BuscarSiguienteEntrada
' si localizado False luego ( no hay ficheros de entrada pendientes)
' raiseevent Terminado
' exit function
' fin condición: localizar siguiente fichero
' si sabemos que no está terminado (debemos esperar)
' raiseevent Terminado
' exit function
' fin condicion: de lo que sabemos
' fin condicion: Tamaño no varía
' no existe fichero entrada
' localizado = llamar a función: BuscarSiguienteEntrada
' si localizado False luego ( no hay ficheros de entrada pendientes)
' raiseevent Terminado
' exit function
' fin condición: localizar siguiente fichero
' fin condicion: existe fichero entrada
Texto = TomarContenidoFicheroEntrada(Lineas) ' ( llamar a función tomar contenido de fichero de entrada)
If Lineas < 1 Then ' -1= (ocurrió un error), 0= se leyó el fichero pero parece que no contiene texto ????
RaiseEvent Terminado
Exit Function
Else ' lineas es mayor que (hay líneas que procesar)
Call ConvertirLineas(Texto) ' llamamos a otra función para tratar las líneas (sólo por claridad y sencillez de modificar las funciones)
RaiseEvent Terminado
End If ' fin condición hay líneas de texto leídas
End Function
' localiza el siguiente fichero que genera la máquina para ser procesado
Private Function BuscarSiguienteEntrada() As Boolean
' si localiza un ficheo
' p_ficheroentrada= ElficheroEncontrado
' s_cursorentrada= 1
' cerramos ficherosalida
' s_cursorSalida=1
' creamos y abrimos nuevoFichero de salida
' p_Ficherosalida = ElNuevoficherosalida ' elegir el nombre y la ruta, supuestamente basado en el nombre y ruta del de entrada
'
' s_Maquina= "fiber-1" ' se supone que tú debes saber como obtener este dato.
'
' devuelve True
' no localiza un nuevo fichero (quizás la máquina esté parada, o está en medio de un largo proceso y no escribe hasta el ´termino)
' Devolver false
' fin condicion: localizar fichero
End Function
Private Function TomarContenidoFicheroEntrada(ByRef Lineas As Long) As String()
' abrimos el fichero
' posicionamos el crusor
' leemos hasta el final del archivo
' Troceamos el texto en líneas
' Devolvemos el texto
Dim ff As Integer
Dim Texto As String
Dim txt() As String
On Local Error GoTo ErrorTomar
Texto = String(s_TamañoEntrada - p_cursorentrada + 1, " ")
ff = FreeFile
Open p_FicheroEntrada For Binary As #ff
Get #ff, p_cursorentrada, Texto
Close #ff
Texto = Trim$(Texto)
If Texto <> "" Then
If InStr(1, Texto, vbCrLf) > 0 Then
txt = Split(Texto, vbCrLf)
Texto = "" ' liberamos memoria
Lineas = UBound(txt) + 1
TomarContenidoFicheroEntrada = txt
Erase txt ' liberamos memoria
Else
Lineas = 1
redim txt(0 to 0)
Txt(0)=texto
TomarContenidoFicheroEntrada = txt
Texto=""
erase txt
End If
Else
Lineas = 0
End If
Exit Function
ErrorTomar:
Close #ff
RaiseEvent ParoError
'MsgBox "Error al leer fichero de entrada: " & vbCrLf & _
'Err.Number & " " & Err.Description, vbCritical
Lineas = -1
End Function
Private Sub ConvertirLineas(ByRef Lineas() As String)
' iniciamos bucle
' procesamos línea a línea
' eventuualmente según la cantidad de parámetros de cada línea debe procesarse aparte
' terminamos bucle
' abrimos fichero de salida
' posicionamos el cursor de salida
' escribimos contenido
' cerramos fichero de salida
Dim k As Long, n As Long
Dim Salida() As LineaSalida
Dim Linea() As String
Dim txt As String
ReDim Salida(-1 To UBound(Lineas)) ' ojo: insertamos la línea usada la última vez del proceso anterior como la línea -1
Salida(-1) = s_LinAnterior
For k = 0 To UBound(Lineas)
Linea = Split(Lineas(k), " ") ' el divisor es un espacio
Salida(k).Maquina = s_Maquina ' se supone que al cargar el fichero siguiente se obtiene ese valor que presumiblemente es constante para el mismo fichero.
Salida(k).id = Salida(k - 1).id + 1
Salida(k).Fin = Replace(Linea(0), ".", "-") & " " & Linea(1) '
Salida(k).Inicio = Salida(k - 1).Fin
Salida(k).Duracion = DateDiff("s", Salida(k).Fin, Salida(k).Inicio)
' importante: al guardar el fichero en modo binario, resulta ilegible si abrimos luego el archivo para leerlo, si queremos
' que sea legible (a la vista) debemos hacerque todos los campos de la estructura sean cadenas de texto
' entonces deberíamos declarar al menos 2 datos de fecha a nivel de la función
' por ejemplo:
' estas 3 líneas iría antes del bucle
' Dim Ini As Date, Fin As Date, id As Long
' id = Val(Salida(-1).id)
' fin= salida(-1).Fin
' estas líneas irían dentro del bucle sustituyendo a las previas
' Ini = Fin
' Fin = Replace(Linea(0), ".", "-") & " " & Linea(1)
' Salida(k).Duracion = CStr(DateDiff("s", Fin, Ini))
' Salida(k).Fin = CStr(Fin)
' Salida(k).Inicio = CStr(Ini)
' id = id + 1
' Salida(k).id = CStr(id)
' estos datos se supone que tienes que interpretar las constantes que aparecen en las líneas
' podrían meterse enuna enumeración o no con y una matriz asociada con ello nos podríamos ahorramos el select case en algunos casos
Select Case Trim$(Linea(2))
Case "MESSAGE"
Salida(k).Evento = "?"
Salida(k).Motivo = "?"
Case "COMMENT"
Salida(k).Evento = "?"
Salida(k).Motivo = "?"
Case "MATERIALFP"
Salida(k).Evento = "?"
Salida(k).Motivo = "?"
' más casos
'Salida(k).Evento = "?"
'Salida(k).Motivo = "?"
' ................
End Select
Next
s_LinAnterior = Lineas(UBound(Lineas))
Erase Lineas ' liberamos memoria
redim preserve Salida(0 to ubound(salida)) ' eliminamos la línea previa -1 que añadimosprevio al bucle.
' qué queremos hacer con las salida ???.
' si sólo lo queremos escribir a fichero
' escribiendo en modo binario (ilegible a la vista).
Open p_FicheroSalida For Binary As #ff
'Loc(ff) = s_CursorSalida
'Put #ff, , Salida
Put #ff, s_CursorSalida, Salida ' tiene la ventaja de que escribe estructuras, matrices y matrices de estructura con 1 sola línea.
s_CursorSalida = Seek(ff)
Close #ff
' alternativamente puedes escribirlo como texto y usando un bucle (es totalmente legible a la vista)
Open p_FicheroSalida For Output As #ff
Loc(ff) = s_CursorSalida
With Salida(k)
For k = 0 To UBound(Salida)
Print #ff, .id, .Inicio, .Fin, .Duracion, .Evento, .Maquina, .Motivo
Next
End With
s_CursorSalida = Seek(ff)
Close #ff
Erase Salida ' liberamos memoria
End Sub
Private Sub Class_Initialize()
EventosMaquinaOut(-1) = "AVERIA"
EventosMaquinaOut(0) = "ENTRADA"
EventosMaquinaOut(1) = "PARADA"
EventosMaquinaOut(2) = "MARCHA"
EventosMaquinaOut(3) = "VELOCIDAD REDUCIDA"
End Sub
Considero que tienes bastante materia como para poder completar tu proyecto.
Si tienes alguna duda, consulta, pero sé explícito y no des por hecho que la ¿ troqueladora ? , ¿ torno ? , la hemos fabricado nosotros ni tampoco el programa que la maneja
?. Mejor si son preguntas concretas, las preguntas genéricas dispersan mucho la respuesta...
envío y luego edito para adjuntar el fichero: