En los anteriores post vimos como guardar el estado de las entradas/salidas del PLC en el PC. Hoy vamos a leer estos archivos y generar una tabla que nos muestre de una forma clara como se han producido los cambios. La técnica empleada para esto es leer texto separado por “;”. En el anterior proyecto añadiremos un botón que nos abra un nuevo formulario. A este botón lo llamaremos buAnalizar y en la propiedad texto le pondremos Analizar. Doble click en el botón y nos genera el evento donde pondremos el siguiente código.

También podríamos utilizar el siguiente código para abrir el formulario, este código nos permite abrir múltiples estancias del mismo formulario:

Como podemos ver en el código, en el segundo caso se crea una nueva estancia del formulario cada vez que presionamos el botón.
En el explorador de soluciones, click con el derecho y añadir nuevo elemento:


Y este es el aspecto de nuestro formAnalizar:

He previsto tres posibilidades para elegir el archivo, las dos primera (IN, OUT), son RadioButon y tienen la peculiaridad de que solo podrá estar marcada una. Cuando marcamos IN se desmarca Out y viceversa. La última posibilidad es un CheckBoxy la función es abrir un cuadro de dialogo para elegir el archivo a analizar. Aunque los tres podrían ser RadioButon he considerado poner un Checkbox para que podáis apreciar la diferencia entre los dos primeros y el tercero. Por último ponemos un botón para proceder a la lectura del archivo.
El cuadro blanco situado a la derecha es un ListView. Podríamos configurar las columnas directamente pero yo prefiero hacerlo por código. Hacemos doble click en el formAnalizar y nos genera el gestor de eventos del FormAnalizar.Load. Lo que quiere decir que será el código que primero leerá cuando se abra el formulario. Aprovechamos este evento para configurar la tabla en el listView. Aunque es un poco largo porque hay muchas columnas, es fácil y prácticamente es copiar pegar, puesto que la diferencia entre las columnas de la tabla son los nombres, bit0, bit1, etc
Private Sub FormAnalizar_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load ListView1.View = View.Details ListView1.BackColor = Color.GhostWhite ListView1.GridLines = True ListView1.Columns.Add("Fecha / Hora") ListView1.Columns(0).Width = 150 ListView1.Columns.Add("bit.0") ListView1.Columns(1).Width = 40 ListView1.Columns.Add("bit.1") ListView1.Columns(2).Width = 40 ListView1.Columns.Add("bit.2") ListView1.Columns(3).Width = 40 ListView1.Columns.Add("bit.3") ListView1.Columns(4).Width = 40 ListView1.Columns.Add("bit.4") ListView1.Columns(5).Width = 40 ListView1.Columns.Add("bit.5") ListView1.Columns(6).Width = 40 ListView1.Columns.Add("bit.6") ListView1.Columns(7).Width = 40 ListView1.Columns.Add("bit.7") ListView1.Columns(8).Width = 40 ListView1.Columns.Add("bit.8") ListView1.Columns(9).Width = 40 ListView1.Columns.Add("bit.9") ListView1.Columns(10).Width = 40 ListView1.Columns.Add("bit.10") ListView1.Columns(11).Width = 40 ListView1.Columns.Add("bit.11") ListView1.Columns(12).Width = 40 ListView1.Columns.Add("bit.12") ListView1.Columns(13).Width = 40 ListView1.Columns.Add("bit.13") ListView1.Columns(14).Width = 40 ListView1.Columns.Add("bit.14") ListView1.Columns(15).Width = 40 ListView1.Columns.Add("bit.15") ListView1.Columns(16).Width = 40 End Sub
Bien, tenemos el formulario gráficamente terminado, ahora vamos a leer los archivos y a llenar la tabla con datos. El primer paso es seleccionar el archivo con el que queremos trabajar:
Agregamos un componente, que nos hará el trabajo de abrir un cuadro de diálogo para seleccionar un archivo. OpenFileDialog.

Lo arrastramos hasta el formulario, y automáticamente se pasará a la barra gris situada debajo del formulario.

Le he cambiado la propiedad Name por Ofd1. El siguiente extracto de código muestra la selección del nombre del archivo a leer, en función de los requerimientos del usuario:
'Borramos el listview ListView1.Items.Clear() 'Comprobamos si quiere ver In, Out o abrir un cuadro de dialogo Dim Filename As String = "" If ckMostrarDialogo.Checked Then Ofd1.ShowDialog() Filename = Ofd1.FileName Else If rdIn.Checked Then Filename = "In.csv" If rdOut.Checked Then Filename = "Out.csv" End If If Filename = "" Then MessageBox.Show("Error en parametros") Exit Sub End If
Declaramos la variable FileName donde almacenaremos el nombre del archivo a abrir. Si está marcado el Cheked.Box abre el cuadro de diálogo para que seleccionemos un archivo, una vez seleccionado pasa el nombre a la variable. De no ser así, se comprueba cual de los RadioButton está marcado para asignar el nombre del archivo como In.csv u Out.csv.
Como no sabemos a priori cuantas líneas tendrá el archivo que vamos a abrir, lo haremos en dos pasadas, en la primera pasada contamos las líneas, dimensionamos las variables que almacenaran los datos y en la siguiente pasada pasamos los datos a las variables. Realmente no es necesario almacenar los datos, puesto que como veremos más adelante, los datos se irán escribiendo en la tabla a medida que los leemos, pero esto no termina en una tabla, en la próxima entrada mostraremos los datos en un gráfico, por este motivo los guardamos en unas variables, para posteriormente poder visualizarlos en grafico.
¿Y cómo podemos leer un archivo de este tipo? Pues que lo diga el IDE. Pincha con el derecho dentro del evento buLeerDatos, insertar fragmento de código:




En nuestro caso quitamos la primera línea, ya que filename ya está declarada y cambiamos delimiter por “;”. El código completo del gestor de eventos leerdatos es este:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles buLeerDatos.Click 'Borramos el listview ListView1.Items.Clear() 'Comprobamos si quiere ver In, Out o abrir un cuadro de dialogo Dim Filename As String = "" If ckMostrarDialogo.Checked Then Ofd1.ShowDialog() Filename = Ofd1.FileName Else If rdIn.Checked Then Filename = "In.csv" If rdOut.Checked Then Filename = "Out.csv" End If If Filename = "" Then MessageBox.Show("Error en parametros") Exit Sub End If Dim i As Integer Dim fields As String() Dim delimiter As String = ";" Try 'Leemos para dimensionar las variables Using parser As New TextFieldParser(Filename) parser.SetDelimiters(delimiter) While Not parser.EndOfData ' Read in the fields for the current line fields = parser.ReadFields() ' Add code here to use data in fields variable. i += 1 End While End Using Catch ex As Exception MessageBox.Show("Error de parametros") Exit Sub End Try 'Dimensionamos las variables ReDim Momento(i - 1) ReDim Dato(i - 1) i = 0 'Leemos y asignamos a variables Using parser As New TextFieldParser(Filename) parser.SetDelimiters(delimiter) While Not parser.EndOfData ' Read in the fields for the current line fields = parser.ReadFields() ' Add code here to use data in fields variable. Momento(i) = fields(0) Dato(i) = DecToBin(fields(1)) Trace1(Momento(i), Dato(i), Color.Black) i += 1 End While End Using End Sub
Como podemos ver en el código, en la primera pasada sólo incrementamos i de manera que al final del bucle i = total filas. Redimensionamos las variables y volvemos a leer para asignar los valores a las variables, a la vez llamamos a la función Trace1, que es la encargada de rellenar la tabla de una manera especial.
Public Sub Trace1(ByVal Momento As String, ByVal ValorInt16 As String, ByVal ColorMsg As Color) Dim Texto(16) As String Texto(0) = Momento Dim i As Integer For i = 0 To ValorInt16.Length - 1 If DatoAnterior.Chars(i) <> ValorInt16.Chars(i) Then If ValorInt16.Chars(i) = "0" Then Texto(i + 1) = "OFF" Else Texto(i + 1) = "ON" End If Next Dim item As New ListViewItem(Texto) item.ForeColor = ColorMsg ListView1.Items.Add(item) DatoAnterior = ValorInt16 End Sub
Principalmente se trata de ir comprobando cada carácter de la variable string que contiene el valor binario, si es diferente de la vez anterior. De ser así, escribimos en la tabla. El resultado es este:

Y este es el código completo:
Imports Microsoft.VisualBasic.FileIO Public Class FormAnalizar Dim Dato(1) As String Dim Momento(1) As String Dim DatoAnterior As String = "0000000000000000" Private Sub FormAnalizar_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles MyBase.Load ListView1.View = View.Details ListView1.BackColor = Color.GhostWhite ListView1.GridLines = True ListView1.Columns.Add("Fecha / Hora") ListView1.Columns(0).Width = 150 ListView1.Columns.Add("bit.0") ListView1.Columns(1).Width = 40 ListView1.Columns.Add("bit.1") ListView1.Columns(2).Width = 40 ListView1.Columns.Add("bit.2") ListView1.Columns(3).Width = 40 ListView1.Columns.Add("bit.3") ListView1.Columns(4).Width = 40 ListView1.Columns.Add("bit.4") ListView1.Columns(5).Width = 40 ListView1.Columns.Add("bit.5") ListView1.Columns(6).Width = 40 ListView1.Columns.Add("bit.6") ListView1.Columns(7).Width = 40 ListView1.Columns.Add("bit.7") ListView1.Columns(8).Width = 40 ListView1.Columns.Add("bit.8") ListView1.Columns(9).Width = 40 ListView1.Columns.Add("bit.9") ListView1.Columns(10).Width = 40 ListView1.Columns.Add("bit.10") ListView1.Columns(11).Width = 40 ListView1.Columns.Add("bit.11") ListView1.Columns(12).Width = 40 ListView1.Columns.Add("bit.12") ListView1.Columns(13).Width = 40 ListView1.Columns.Add("bit.13") ListView1.Columns(14).Width = 40 ListView1.Columns.Add("bit.14") ListView1.Columns(15).Width = 40 ListView1.Columns.Add("bit.15") ListView1.Columns(16).Width = 40 End Sub Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles buLeerDatos.Click 'Borramos el listview ListView1.Items.Clear() 'Comprobamos si quiere ver In, Out o abrir un cuadro de dialogo Dim Filename As String = "" If ckMostrarDialogo.Checked Then Ofd1.ShowDialog() Filename = Ofd1.FileName Else If rdIn.Checked Then Filename = "In.csv" If rdOut.Checked Then Filename = "Out.csv" End If If Filename = "" Then MessageBox.Show("Error en parametros") Exit Sub End If Dim i As Integer Dim fields As String() Dim delimiter As String = ";" Try 'Leemos para dimensionar las variables Using parser As New TextFieldParser(Filename) parser.SetDelimiters(delimiter) While Not parser.EndOfData ' Read in the fields for the current line fields = parser.ReadFields() ' Add code here to use data in fields variable. i += 1 End While End Using Catch ex As Exception MessageBox.Show("Error de parametros") Exit Sub End Try 'Dimensionamos las variables ReDim Momento(i - 1) ReDim Dato(i - 1) i = 0 'Leemos y asignamos a variables Using parser As New TextFieldParser(Filename) parser.SetDelimiters(delimiter) While Not parser.EndOfData ' Read in the fields for the current line fields = parser.ReadFields() ' Add code here to use data in fields variable. Momento(i) = fields(0) Dato(i) = DecToBin(fields(1)) Trace1(Momento(i), Dato(i), Color.Black) i += 1 End While End Using End Sub #Region "Conversion binario decimal " Private Function BinToDec(ByVal ValorBin As String) As Decimal Dim Longitud As Integer = ValorBin.Length 'Debug.WriteLine("Entrar: " & ValorBin & "Longitud: " & Longitud) Dim i As Integer = 0 Dim ValorDec As Decimal = 0 For i = 0 To Longitud - 1 Dim _Char As Char = ValorBin.Chars(i) Dim ValorChar As Integer If _Char = "0" Then ValorChar = 0 Else ValorChar = 1 ValorDec += ValorChar * System.Math.Pow(2, ((Longitud - i) - 1)) Next Return (ValorDec) End Function Private Function DecToBin(ByVal ValorDec As Int32) As String 'Esta funcion convierte en binario tanto palabras INT como UINT. 'En caso de haber valores negativos se asume que es una palabra INT ' y hace la conversión con esta formula If ValorDec < 0 Then ValorDec = 65536 + ValorDec End If Dim Cociente As Int32 = ValorDec Dim Resto As Int32 = 0 Dim ValorBinMatriz(17) As Char Dim ValorBin As String = "" Dim i As Integer = 0 If ValorDec = 1 Then ValorBinMatriz(0) = "1" While Cociente > 1 Cociente = System.Math.DivRem(Cociente, 2, Resto) ValorBinMatriz(i) = Resto.ToString If Cociente < 2 Then ValorBinMatriz(i + 1) = Cociente.ToString i += 1 End While Dim j As Integer For j = 0 To 15 If ValorBinMatriz(j) = "1" Then ValorBin &= "1" Else ValorBin &= "0" Next Return (ValorBin) End Function #End Region Public Sub Trace1(ByVal Momento As String, ByVal ValorInt16 As String, ByVal ColorMsg As Color) Dim Texto(16) As String Texto(0) = Momento Dim i As Integer For i = 0 To ValorInt16.Length - 1 If DatoAnterior.Chars(i) <> ValorInt16.Chars(i) Then If ValorInt16.Chars(i) = "0" Then Texto(i + 1) = "OFF" Else Texto(i + 1) = "ON" End If Next Dim item As New ListViewItem(Texto) item.ForeColor = ColorMsg ListView1.Items.Add(item) DatoAnterior = ValorInt16 End Sub End Class
Añadir un comentario