Contatore automatico macro vba excel 2007



  • Contatore automatico macro vba excel 2007
    di Dukati996 data: 02/08/2012

    Contatore automatico macro vba excel 2007

    un saluto a tutti.
    vorrei realizzare una macro in excel che al modificarsi del valore presente in una cella che può avere un valore di 0 o 1 vada automaticamente (senza che io debba avviare di nuovo la macro) a sommare in un'altra cella il valore della prima.
    per essere più chiaro se nella cella a1 in una giornata per 5 volte si passa dal valore di 0 a quello di 1 nella cella b1 quella con il contatore a fine giornata dovrei avare 5.
    sicuramente per chi è esperto è un gioco da ragazzi ma per me che non ne capisco e che diverse ore (non dico quante per non farmi prendere in giro) non ci sono ancora riuscito e per questo chiedo aiuto sul forum.
    vorrei sapere anche se è possibile avere un contatore di tempo che conti per quanti secondi in tutta la giornata nella cella a1 c'è stato il valore 1.
    grazie in anticipo a chi mi risponderà.
    ciao



  • di Vecchio frac data: 03/08/2012

    Chi modifica il valore? un evento esterno o c'è qualcuno che apre excel (o lo tiene sempre aperto) e modifica il dato ad ogni cambiamento? questa seconda situazione è già più gestibile, e non serve nemmeno tenere sempre aperto excel.
    comunque dovrai tener traccia delle rilevazioni temporali, magari nello stesso foglio, per calcolare il tempo trascorso tra una rilevazione e l'altra e vedere così quanto tempo ha resistito lo "zero" e quanto tempo l' "uno".

    quindi devi costruire un foglio molto semplice, che in pratica ti permetta di inserire solo zero o uno in una cella: al resto ci pensa lui, ad ogni cambiamento del valore in questa cella, senza che tu debba far ripartire la macro. esiste un evento apposta nei fogli per intercettare il cambiamento del contenuto di una cella.

    nessuno ti prende in giro per i tentativi che fai, anzi mostra pure il codice che hai prodotto e la logica sottostante. ti aiuteremo sia ad affrontare il problema, sia a realizzarlo. ti invito comunque a pensarci ancora e a mostrare i risultati raggiunti.
    prima di postare la mia soluzione (che ho testato e funziona) attendo anche che ci provi qualcun altro, altrimenti sembro sempre troppo prepotente ;)






  • di Vecchio frac data: 06/08/2012

    Gosh, nessuno ci vuol provare? :)
    sono impaziente di postare il mio modellino con la mia soluzione :d





  • di xxx (utente non iscritto) data: 06/08/2012 18:35:15

    ciao vecchio frac

    ti rispondo io, dato che Dukati996 a gia' avuto 2 soluzioni su un altro forum da parte di gente di mia conoscenza, ma a tutt'ora non ha dato nessuna risposta in merito al metodo che abbia utilizzato, quindi aspettiamo con pazienza una risposta, sperando che Dukati non sia partito per le ferie mentre noi siamo rimasti a casa a lavorare

    ciao da xxx



  • di xxx (utente non iscritto) data: 06/08/2012 18:35:55

    ciao vecchio frac

    ti rispondo io, dato che Dukati996 a gia' avuto 2 soluzioni su un altro forum da parte di gente di mia conoscenza, ma a tutt'ora non ha dato nessuna risposta in merito al metodo che abbia utilizzato, quindi aspettiamo con pazienza una risposta, sperando che Dukati non sia partito per le ferie mentre noi siamo rimasti a casa a lavorare

    ciao da xxx



  • di Vecchio frac data: 06/08/2012

    Grazie per il feedback mister "xxx" (più anonimo di così ^_^), visto che l'amico si gode le meritate ferie, domani posterò la mia proposta di soluzione. allegherò anche il file.





  • di Vecchio Frac data: 06/08/2012 22:05:59

    Per intanto godetevi l'anteprima nell'immagine allegata :)





  • di HarryBosch data: 06/08/2012 23:25:01

    L'anteprima è già molto interessante...



  • di Vecchio Frac data: 07/08/2012 11:20:11

    Allego il file contenente la mia proposta.
    Ditemi cosa ne pensate.





  • di xxx (utente non iscritto) data: 07/08/2012 16:56:45

    ciao vecchio frac
    ti posto una nota data da dukati nell'altro post, dove dice che il dato in A1 viene fatto da una funzione SE() in base a dei dati ricevuti da una DDE, quindi non puoi utilizzare come hai fatto l'evento >Worksheet_Change< dato che la cella in questione non ha nessun cambiamento con la funzione SE() quindi non fa nessun calcolo a riguardo, Prova con un'altra cella e metti un se in cella A2 e vedrai.

    Il valore in A1 passa da 0 ad 1 in base ad una funzione "SE" che ho impostato sul foglio excel che si basa su dei valori che excel riceve dall'esterno tramite DDE, quindi tutto avviene in automatico come in automatico vorrei che la macro conti il numero di volte che nella cella compare 1 ed il numero di secondi in cui nella cella dura l'1 prima che il valore nella cella torni a 0, in base ai dati ricevuti dal DDE che va a modificare il risultato della funzione "SE", a 0.Vorrei che questi due conteggi mi diano a fine giornata la somme con il numero di volte uno e con il numero di secondi l'atro in cui c'è stato 1 nella cella A1.

    quindi bisognerebbe utilizzare un altro tipo di evento, o un contatore di tempo, i quali vanno a verificare ogni secondo i cambiamenti della cella, nel tuo caso la A2.
    manca anche un contatore di secondi, dalle note messe, che dica quanti secondi in totale il valore 1 e stato presente quel giorno

    tutto questo non vuol essere un demerito, ma una semplice nota come quando si va a provare un programma in versine Beta e vengono riscontrate le falle di esso e in base a questi si aggiustano le macro

    ciao da xxx



  • di Vecchio Frac data: 07/08/2012 19:29:58

    Grazie "xxx", non prendo affatto queste tue osservazioni come critiche: hai introdotto dati nuovi che non erano stati esposti all'inizio, quindi se ora lo scenario cambia, di conseguenza cambia anche la soluzione.





  • di HarryBosch data: 07/08/2012 19:54:56

    Ciao Ragazzi
    questa cosa interessa molto anche a me, che vengo da una "preparazione" completamente autodidatta.
    L'evento _change non lo posso quindi sfruttare, perché la variazione del dato della cella A1 (o quel si voglia) deriva da una formula che prende i riferimenti da altre celle o addirittura da dati esterni.
    Se il riferimento è relativo ad altre celle mi vien da dire che sposterei su tali celle l'evento _Change, in modo da intercettare i cambiamenti delle celle che producono la variazione della formula.
    Ma se l'evento deriva da un database esterno, come avverti la variazione della cella A1?
    Mi rivolgo a Francesco che sicuramente ha già una valida idea.

    Comunque il file è ben fatto e mi sembra proprio che restituisca anche i secondi... (però sbaglio ho conta il tempo anche quando risulta 0?)

    Ciao, Vanni




  • di Vecchio Frac data: 07/08/2012 20:55:15

    Mi viene in mente l'utilizzo di un timer.
    Si può realizzare qualcosa di efficace con le API (SetTimer e KillTimer), ma qualcosa di nativo c'è già in Excel ed è l'evento OnTime.
    Da sistemare ovviamente nell'evento Open del Workbook, così da far partire il timer da subito.
    Posto un po' di codice di esempio nel riquadro apposito.
    Tutto a grandi linee e da testare... non mi son mai piaciuti gli eventi legati al timer soprattutto in Windows :)
    (comunque io preferisco SetTimer e KillTimer)

    Rispondo all'ultima domanda di Vanni...
    Conservo anche il momento in cui viene inserito un valore zero perchè il quesito iniziale voleva conoscere quanto tempo passa tra un "uno" e il successivo, e questo implica anche conoscere per quanto tempo abbiamo una situazione di "zero". E probabilmente l'informazione è anche più completa :)





     
    Public RunWhen As Double
    Public Const cRunIntervalSeconds = 120 ' in secondi, due minuti
    Public Const cRunWhat = "TheSub"  ' nome della procedura da far partire
    
    'crea la sub myTimer, programmata per partire 120 secondi dopo l'orario corrente
    Sub StartTimer
        RunWhen = Now + TimeSerial(0, 0, cRunIntervalSeconds)
        Application.OnTime EarliestTime:=RunWhen, Procedure:=cRunWhat, Schedule:=True
    End Sub
    
    'la procedura che sarà chiamata da OnTime
    Sub TheSub()
        ''''''''''''''''''''''''
        ' Il resto del codice qui 
        ''''''''''''''''''''''''
        StartTimer  ' Rischedula la procedura
    End Sub
    
    'Quando l'evento schedulato deve essere fermato si può utilizzare StopTimer
    Sub StopTimer()
        On Error Resume Next
        Application.OnTime EarliestTime:=RunWhen, Procedure:=cRunWhat, Schedule:=False
    End Sub






  • di xxx (utente non iscritto) data: 07/08/2012 23:50:21

    ciao ragazzi

    infatti avevo gia' pensato ad una soluzione del tipo che vi espongo dandovi i codici in VBA
    dove si intende questa e' una semplice bozza di macro, la quale macro che va posta nel foglio1 va elaborata per dare i risultati che si vogliono ottenere, adesso registra solamente il numero dei secondi che in cella A1 e' presente il valore 1 su cella F1

    ciao da xxx
     
    '' In ThisWorkbook
    Option Explicit
    Private Sub workbook_open()
      Foglio1.Select          ''seleziona foglio 1
      Call Conto_Tempo        ''avvia orologio e contatore
    End Sub
    
    ------------------------------------
    '' In un Modulo
    Sub Conto_Tempo()
      DoEvents
      ThisWorkbook.Worksheets("Foglio1").Verifico_Presenza ''Macro di scrittura
      Application.OnTime Now + TimeSerial(0, 0, 1), "Conto_Tempo"
    End Sub
    
    ------------------------------
    ''Nel Foglio1
    Option Explicit
    Sub Verifico_Presenza()
       DoEvents
        If ThisWorkbook.Worksheets("Foglio1").Range("A1").Value = 1 Then
          ThisWorkbook.Worksheets("Foglio1").Range("F1").Value = [F1] + 1
        End If
    End Sub



  • di Vecchio Frac data: 08/08/2012 09:39:41

    Sì "xxx", lo schema da utilizzare è quello.
    Ho visto anche la discussione su iprogrammatori.it e la risposta del grande Alex, al quale però sfugge che Excel dispone di OnTime, poco male :)

    Per gestire al meglio gli eventi legati al tempo, è preferibile affidarsi al sottosistema delle API: se sto editando una cella l'evento OnTime di Excel, per quanto schedulato, non funziona e si accoda. Le API non risentono (a quanto mi risulta) di questa limitazione.

    In workbook_open creo un timer ("timerID" nel codice qui sotto).
    In workbook_close lo uccido (è sempre meglio farlo esplicitamente).
    Nella "timer_routine" infilo il codice da eseguire periodicamente (controllare la cella che mi interessa, tener traccia dei cambiamenti, registrare data e ora, calcolare i totali parziali, ecc.)

    Nel mio modellino di ieri per fare le statistiche ho utilizzato una tabella pivot che a quanto pare è passata inosservata ma che io trovo carina :)
     
    'rendi disponibile la funzione
    Declare Function SetTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long, ByVal uElapse As Long, ByVal lpTimerFunc As Long) As Long
    
    'uccidi il timer
    Declare Function KillTimer Lib "user32" (ByVal hwnd As Long, ByVal nIDEvent As Long) As Long
    
    'inserisci qui il codice da eseguire
    Public Sub TimerRoutine(ByVal hwnd As Long, ByVal uMsg As Long, ByVal idEvent As Long, ByVal SysTime As Long)
    .
    .
    .
    End sub
    
    'per attivare il timer ogni 500 millisecondi
    timerID = SetTimer(0, 0, 500, AddressOf timer_routine)
    
    'per disattivare il timer
    KillTimer 0, timerID