Jump to content

Recommended Posts

Posted

Estou a desenvolver um programa de registo de valores.

Como era urgente a sua implementação, estou a registar os valores em ficheiro csv, um por dia com 1760 linha (1 por minuto).

Quando o programa arranca, lê (dos ficheiros) todos os dados relativos ao ano corrente, e a partir daí actualiza o minuto actual com dados provenientes de um OPC Server e calcula os valores da hora, dia e mês.

Para isso criei 4 arrays:

    Friend DadosMinuto(1 + 12, 1 + 31, 24, 60) As stuDados
    Friend DadosHora(1 + 12, 1 + 31, 24) As stuDados
    Friend DadosDia(1 + 12, 1 + 31) As stuDados
    Friend DadosMes(1 + 12) As stuDados

O utilizador tem a hipótese de consultar em qualquer momento os valores do Dia, Mês ou Ano em 3 forms diferentes.

Estava a funcionar muito bem, até hoje ter percebido que não estava a permitir ao utilizador a consulta de anos anteriores, então criei mais 4 arrays:

    Dim HistóricoMinuto(1 + 12, 1 + 31, 24, 60) As frmMain.stuDados
    Dim HistóricoHora(1 + 12, 1 + 31, 24) As frmMain.stuDados
    Dim HistóricoDia(1 + 12, 1 + 31) As frmMain.stuDados
    Dim HistóricoMes(1 + 12) As frmMain.stuDados

e se o ano que o utilizador for o actual faço:

                HistóricoMinuto = frmMain.DadosMinuto
                HistóricoHora = frmMain.DadosHora
                HistóricoDia = frmMain.DadosDia
                HistóricoMes = frmMain.DadosMes

Se não for, leio para o HistóricoXXX os valores relativos ao ano, calculo etc...

O problema!

Se o utilizador escolher um ano sem valores, naturalmente que o HistóricoXXX fica a zero, mas os DadosXXX também, já  :wallbash: e não encontro a justificação.

Ricardo Timóteo

Posted

Não percebo, estou farto de  :wallbash:

Tenho 4 forms criadas.

Na form principal crio os arrays principais com Friend que são carregado no arranque do programa e actualizados periodicamente.

Depois criei em cada form de consulta crio novos array como Private.

Quando corro a rotina e ponho os arrays da form de consulta a zero -> fico com os array principais a zero (entretanto depois continuam a ser actualizados, mas os dados anteriores já eram)

Não consigo perceber o que se está a passar.

Já mudei os nomes da variáveis, já não sei o que fazer mais.

Ricardo Timóteo

Posted

Se a ideia é teres as arrays acessíveis anytime anywhere porque não as declaras num módulo ?  👍

Sérgio Ribeiro


"Great coders aren't born. They're compiled and released"
"Expert coders do not need a keyboard. They just throw magnets at the RAM chips"

Posted

Arrays para tanta informação!

Porque não usas uma DataTable() em vez de arrays ? Podes carregar as colunas que queres e é simples de filtrar usando um DataView.

Mas eu não quero filtrar.

A ideia é criar um DataLog e registar vários valores de minuto a minuto, para depois fazer alguns cálculos: para alguns valores é uma soma de tempo para outros é uma média do valor e para outros é uma soma de tempo em que a média do valor este a cima de um setpoint.

É verdade que os arrays são grandes, cada hora tem 60 minutos, cada dia tem 24 horas, cada mês tem 31 dias e o ano tem 12 meses.

Quando o cliente só quer ver o histórico do dia, só necessito minutos e horas, mas quando o cliente quer ver o histórico do ano tenho que ter os dados todos, apesar de só apresentar 12 linhas correspondentes aos 12 meses.

O problema é quando faço:

A=B

estou a passar o valor de B para A, isto é claro.

Só que não sei o porque, se no momento seguinte se fizer:

A=0

então também fico com:

B=0 (sem haver nenhuma instrução para isso)

e isto não faz sentido.

Ricardo Timóteo

Posted

Se a ideia é teres as arrays acessíveis anytime anywhere porque não as declaras num módulo ?  👍

Ok, declarei na form principal, e as privadas em modulos ou forms secundárias, mas porque foi crescendo assim, nunca tinha pensado nisso, é capaz de ser boa política em questões de organização.

Ricardo Timóteo

Posted

Não sei se percebi a pergunta:

Crio o array principal assim:

Public Class frmMain
    ' Criação das estruturas
    Structure stuDados
        ' Estrutura dos dados recolhidos do autómato (tempos + valores actuais)
        Dim Ligado As Long
        Dim Funcionamento As Long
        Dim Emissão As Single
        Dim Concentração As Single
    End Structure

' ...

    Friend DadosMinuto(1 + 12, 1 + 31, 24, 60) As stuDados

Noutro módulo (de comunicação)

Transfiro os dados actuais para o array assim:

            frmMain.DadosMinuto(Now.Month, Now.Day, Now.Hour, Now.Minute).Emissão = TagsAutómato(0).Analog.AIT520.Value
            frmMain.DadosMinuto(Now.Month, Now.Day, Now.Hour, Now.Minute).Concentração = TagsAutómato(0).Analog.CO510.Value

Noutro módulo (relatórios ou histórico)

Crio um array assim:

 Private HistóricoMinuto(1 + 12, 1 + 31, 24, 60) As frmMain.stuDados

e a sseguir copio os valores de um para o outro e faço os cálculos todos com o array privado HistóricoMinuto:

    Private Sub CarregarValores()
        Try
            HistóricoMinuto = frmMain.DadosMinuto
            If dtpValores.Value.Year <> Now.Year Then
                ' 1º Limpa os valores actuais
                For mes As Integer = 1 To 12
                    For dia As Integer = 1 To 31
                        For hora As Integer = 0 To 23
                            For minuto As Integer = 0 To 59
                                HistóricoMinuto(mes, dia, hora, minuto).Concentração = 0
                                HistóricoMinuto(mes, dia, hora, minuto).Emissão = 0
                                HistóricoMinuto(mes, dia, hora, minuto).Funcionamento = 0
                                HistóricoMinuto(mes, dia, hora, minuto).Ligado = 0
                            Next
                            HistóricoHora(mes, dia, hora).Concentração = 0
                            HistóricoHora(mes, dia, hora).Emissão = 0
                            HistóricoHora(mes, dia, hora).Funcionamento = 0
                            HistóricoHora(mes, dia, hora).Ligado = 0
                        Next
                    Next
                Next

                ' 2º carrega os valores a partir do disco
                For Mes As Integer = 1 To 12
                    For Dia As Integer = 1 To 31
                        Dim filename As String = MainPath & "Valor\" & dtpValores.Value.Year.ToString & Format(Mes, "00") & Format(Dia, "00") & ".csv"
                        If My.Computer.FileSystem.FileExists(filename) = True Then
                            Dim Ficheiro As New System.IO.StreamReader(filename)
                            Dim Linha As String
                            Dim Valores() As String
                            Linha = Ficheiro.ReadLine ' A 1ª linha é´o cabeçalho (é lixo)
                            For hora As Integer = 0 To 23
                                For Minuto As Integer = 0 To 59
                                    Linha = Ficheiro.ReadLine
                                    Valores = Linha.Split(";") ' Delimeter
                                    HistóricoMinuto(Mes, Dia, hora, Minuto).Ligado = Valores(1)
                                    HistóricoMinuto(Mes, Dia, hora, Minuto).Funcionamento = Valores(2)
                                    HistóricoMinuto(Mes, Dia, hora, Minuto).Emissão = Valores(3)
                                    HistóricoMinuto(Mes, Dia, hora, Minuto).Concentração = Valores(4)
                                Next
                            Next
                            Ficheiro.Close()
                        End If
                    Next
                Next

                ' 3º Calcula os valores
                For Mes As Integer = 1 To 12
                    For Dia As Integer = 1 To 31
                        For Hora As Integer = 0 To 23
                            For Minuto As Integer = 0 To 59
                                ' Cálculo do relatório diário (de hora a hora)
                                HistóricoHora(Mes, Dia, Hora).Ligado = HistóricoHora(Mes, Dia, Hora).Ligado + HistóricoMinuto(Mes, Dia, Hora, Minuto).Ligado ' Total de minutos
                                HistóricoHora(Mes, Dia, Hora).Funcionamento = HistóricoHora(Mes, Dia, Hora).Funcionamento + HistóricoMinuto(Mes, Dia, Hora, Minuto).Funcionamento ' Total de minutos
                                HistóricoHora(Mes, Dia, Hora).Emissão = HistóricoHora(Mes, Dia, Hora).Emissão + HistóricoMinuto(Mes, Dia, Hora, Minuto).Emissão
                                HistóricoHora(Mes, Dia, Hora).Concentração = HistóricoHora(Mes, Dia, Hora).Concentração + HistóricoMinuto(Mes, Dia, Hora, Minuto).Concentração
                            Next
                            HistóricoHora(Mes, Dia, Hora).Emissão = HistóricoHora(Mes, Dia, Hora).Emissão / 60 ' Média
                            HistóricoHora(Mes, Dia, Hora).Concentração = HistóricoHora(Mes, Dia, Hora).Concentração / 60 ' Média
                        Next
                    Next
                Next
            End If
        Catch ex As Exception
            GravaErro("Erro #16 -> frmValoresDiários -> " & ex.Message)
        End Try
    End Sub

Nunca mais uso o array principal, mas fico sempre com ele a zero

Ricardo Timóteo

Posted

Não percebi o que se estava a passar, mas já dei a volta.

Uma vez que estou a consultar um histórico, passei a ler os valores todos a partir do disco para o histórico, acabei assim o copiar os valores de um array para o outro e ficou a funcionar (com a desvantagem de ficar ligeiramente mais lento)

Ricardo Timóteo

Posted

Encontrei um artigo em:

http://visualbasic.about.com/b/2005/10/29/when-is-a-copy-not-a-copy.htm

Que explica que em .NET, quando se copia um array, não se está a copiar os dados apenas a estrutura e que os dados de um array ficam referenciados ao outro, ou seja, quando apago 1 array, estou na realidade (via referência) a apagar o outro array.

A solução é fazer um clone:

ArrayDestino = ArrayOriginal.clone

Ricardo Timóteo

Posted

Porque para já, tenho uma quantidade substancial de dados.

Porque com o array é fácil de organizar os dados e é fácil de aceder e perceber

Por exemplo:

HistóricoMinuto(mes, dia, hora, minuto)

São dados raw, sem serem tratados, são dados internos que depois vou calcular e apresentar os resultados

Depois para cada array tenho várias variáveis:

HistóricoMinuto(mes, dia, hora, minuto).Concentração

HistóricoMinuto(mes, dia, hora, minuto).Emissão

HistóricoMinuto(mes, dia, hora, minuto).Funcionamento

HistóricoMinuto(mes, dia, hora, minuto).Ligado

HistóricoMinuto(mes, dia, hora, minuto).EmAlarme

Acho que com uma DataTable seria mais complicado, ou não se calhar.

Mas é capaz de comer mais recursos que um array, não?

Ricardo Timóteo

Posted

Bem, sinceramente nunca tentei usar uma DataTable com um GRANDE número de registos, mas que é muito mais simple de manipular, lá isso é.

Podes carregar a informação muito facilmente e filtrar pelo que queres (por qualquer campo), incluindo datas.

Vê este exemplo:

        ' Cria uma DataTable
        Dim dt As New DataTable("Teste")
        dt.Columns.Add("id", GetType(Byte)).AutoIncrement = True
        dt.Columns.Add("data", GetType(DateTime))
        dt.Columns.Add("campo1", GetType(String))
        dt.Columns.Add("campo2", GetType(String))
        dt.Columns.Add("campo3", GetType(Integer))

        Dim dr As DataRow = Nothing
        For x As Int16 = 0 To 999
            dr = dt.NewRow
            dr("data") = Now.AddDays(1)
            dr("campo1") = "C1_" & x.ToString.PadLeft(3, "0"c)
            dr("campo2") = "C2_" & x.ToString.PadLeft(3, "0"c)
            dr("campo3") = x
            dt.Rows.Add(dr)
        Next


        Stop ' DataTable criada e preenchida

        ' Filtra os resultados
        Dim dv As DataView = dt.DefaultView
        dv.RowFilter = String.Format("id <= 10 ")

        ' Mostra os resultados filtrados
        For Each row As DataRowView In dv
            Dim result As String = _
                    String.Format("ID:{0} Data:{1} Campo1:{2} Campo2:{3} Campo3:{4}", _
                    row.Item(0), row.Item(1), row.Item(2), row.Item(3), row.Item(4))
            Debug.WriteLine(result)
        Next

Precisas de filtrar os dados depois ? Também podias pensar um POO, porque sinceramente não gosto muito de usar arrays dessa forma. São faliveis, são muito lentos caso necessites de fazer um Redim, etc.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.