nokPT Posted May 5, 2009 at 04:40 PM Report #261634 Posted May 5, 2009 at 04:40 PM 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á e não encontro a justificação. Ricardo Timóteo
nokPT Posted May 7, 2009 at 10:35 AM Author Report #262066 Posted May 7, 2009 at 10:35 AM Não percebo, estou farto de 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
jpaulino Posted May 7, 2009 at 10:41 AM Report #262067 Posted May 7, 2009 at 10:41 AM 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.
ribeiro55 Posted May 7, 2009 at 10:55 AM Report #262071 Posted May 7, 2009 at 10:55 AM 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"
nokPT Posted May 7, 2009 at 11:15 AM Author Report #262079 Posted May 7, 2009 at 11:15 AM 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
nokPT Posted May 7, 2009 at 11:16 AM Author Report #262080 Posted May 7, 2009 at 11:16 AM 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
jpaulino Posted May 7, 2009 at 11:19 AM Report #262081 Posted May 7, 2009 at 11:19 AM Mostra lá como registas os valores no array e como utilizas depois ?
nokPT Posted May 7, 2009 at 01:28 PM Author Report #262110 Posted May 7, 2009 at 01:28 PM 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
nokPT Posted May 7, 2009 at 02:18 PM Author Report #262131 Posted May 7, 2009 at 02:18 PM 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
nokPT Posted May 14, 2009 at 12:40 PM Author Report #264121 Posted May 14, 2009 at 12:40 PM 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
jpaulino Posted May 14, 2009 at 12:51 PM Report #264124 Posted May 14, 2009 at 12:51 PM Eu ainda não entendi muito bem porque estás a usar arrays e sinceramente não me parece um método nada seguro ou prático.
nokPT Posted May 14, 2009 at 04:04 PM Author Report #264169 Posted May 14, 2009 at 04:04 PM 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
jpaulino Posted May 15, 2009 at 08:44 AM Report #264297 Posted May 15, 2009 at 08:44 AM 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.
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now