Condividi tramite

Worksheet_Calculate() Application.OnTime TimeValue

Anonimo
2011-12-15T01:08:23+00:00

Buon giorno. Ho un quesito interessante. Un programma riceve dati in continuo e li elabora per fini statistici, ogni tot secondi ho la necessità di prendere i risultati degli elaborati e tramite una routine VB di copiarli, o trasferirli, in un foglio. Per fare questo ho utilizzato il seguente codice:

Private Sub Worksheet_Calculate()

'Application.EnableEvents = False Non attivo

If Range("Z49") = 1 Then

Dim x As Date

x = Range("Z51").Value

Application.OnTime TimeValue(x), "Intermittenza"

End If

'Application.EnableEvents = True Non attivo

End Sub

Per chiarire, il codice si attiva al sopraggiungere della condizione 1 nella cella Z49 e ad ogni nuovo orario nella cella Z51 lancia la routine Intermittenza.

Agendo manualmente il sistema funziona ma non ho fatto i conti con il fatto che l'attivazione della routine avviene tramite la Sub Worksheet_Calculate() che ad ogni ricalcolo lancia la routine con il risultato che all'ora indicata da Application.OnTime TimeValue ho un numero di esecuzioni equivalenti ai ricalcoli avvenuti nell'intervallo di tempo.

Ho fatto la prova con 'Application.EnableEvents, che non funziona. Aggiungendo un secondo controllo con Else

Private Sub Worksheet_Calculate()

If Range("Z49") = 1 Then

Dim X As Date

X = Range("Z51").Value

Application.OnTime TimeValue(X), "Intermittenza"

Else: Range("Z49") = 2

Application.OnTime TimeValue(X), "Pausa"

End If

End Sub

che attiva una seconda routine Pausa che abbinata ad un controllo sul foglio blocca la ripetizione delle routine ma, a differenza della prima, non si attiva automaticamente al sopraggiungere dell'ora obbligando la presenza dell'operatore che la lancia tramite un pulsante, non indicato. Questa è la sosluzione poco professionale utilizzata un anno fà con al posto dell'ora un segnale cadenzato. Ho fatto un altro tentativo spostando la seconda parte della routine su un altro foglio ma hanno continuato a non attivarsi con l'inizio dei calcoli.

Penso che il problema sia nella struttura del Private Sub Worksheet_Calculate() che da quanto ho letto e provato non è possibile obbligarlo a considerare un solo segnale ogni intervallo di tempo anche se vi sono stati due o più ricalcoli.

Se esiste un controllo, anche solo su Excel 2010, è molto gradita la sua conoscenza.

Grazie.

Microsoft 365 e Office | Excel | Per la casa | Windows

Domanda bloccata. Questa domanda è stata eseguita dalla community del supporto tecnico Microsoft. È possibile votare se è utile, ma non è possibile aggiungere commenti o risposte o seguire la domanda.

0 commenti Nessun commento

7 risposte

Ordina per: Più utili
  1. Anonimo
    2011-12-16T11:48:56+00:00

    Il sistema tipo è il seguente:

    In un foglio Excel collego i dati DDE che vengono trasmessi dalle 9.00 alle 17.30 in continuo, alle 17.50 vengono inviati i dati di chusura, dalle 18.00 alle 22.00 vengono nuovamente trasmessi i dati in continuo, alle 23.00 vengono trasmessi i dati relativi agli indici. Lo schema e gli orari dipendono dalla fonte dei dati trattati e quindi vengono determinati dall'operatore tramite dei controlli posti su un foglio che funge da interfaccia di settaggio. Il flusso dei dati in continuo è tale che un personal nell'elaborarli accumula un ritardo fra la fonte ed il segnale di uscita che ne vanifica l'utilizzo, per ovviare a questo ho interposto una routine, che si attiva fra gli orari inpostati, che trasferisce ad intervalli prestabiliti i valori rilevati in un preciso istante dalla fonte DDE al foglio di calcolo. Utilizzo la proprietà Value per non accumulare dati negli appunti.

    Ho elaborato il timer posto su un modulo nel seguente codice:

    <cut>

     

    Quello che hai postato lanciando mStart esegue il codice di mStart una sola volta se in mIntermittenza(che non so cosa sia) non c'è un Call mStart.

    Comunque, prova così:

    Public Sub mStart()

     On Error GoTo RigaErrore

         Dim wk1 As Workbook

         Dim sh1 As Worksheet

         Dim x As Date

         x = Range("Z47").Value '<<==== di quale foglio? non lo specifichi e sarà quello attivo

         With ThisWorkbook

             Set sh1 = .Worksheets("Comando")

         End With

        Call mIntermittenza

        Application.OnTime Now + TimeValue(x), "mSegnale"

    RigaChiusura:

         Set sh1 = Nothing

         Set wk1 = Nothing

         Exit Sub

    RigaErrore:

         MsgBox Err.Number & vbNewLine & Err.Description

         Resume RigaChiusura

     End Sub

    Public Sub mSegnale()

         If bln = True Then

         Call mStart

         End If

     End Sub

    Public Sub mStop()

        bln = False

     End Sub

    Public Sub mIntermittenza()

        'codice

    End Sub

    Ma sarebbe sufficiente mettere il codice che hai in mIntermittenza al posto di Call mIntermittenza nel codice che ho postato. E non capisco perchè fai il Set di un oggetto(sh1) senza mai utilizzarlo nel codice.

    La risposta è stata utile?

    0 commenti Nessun commento
  2. Anonimo
    2011-12-16T09:58:35+00:00

    Il sistema tipo è il seguente:

    In un foglio Excel collego i dati DDE che vengono trasmessi dalle 9.00 alle 17.30 in continuo, alle 17.50 vengono inviati i dati di chusura, dalle 18.00 alle 22.00 vengono nuovamente trasmessi i dati in continuo, alle 23.00 vengono trasmessi i dati relativi agli indici. Lo schema e gli orari dipendono dalla fonte dei dati trattati e quindi vengono determinati dall'operatore tramite dei controlli posti su un foglio che funge da interfaccia di settaggio. Il flusso dei dati in continuo è tale che un personal nell'elaborarli accumula un ritardo fra la fonte ed il segnale di uscita che ne vanifica l'utilizzo, per ovviare a questo ho interposto una routine, che si attiva fra gli orari inpostati, che trasferisce ad intervalli prestabiliti i valori rilevati in un preciso istante dalla fonte DDE al foglio di calcolo. Utilizzo la proprietà Value per non accumulare dati negli appunti.

    Ho elaborato il timer posto su un modulo nel seguente codice:

    Private bln As Boolean

    Public Sub mStart()

    On Error GoTo RigaErrore

        Dim wk1 As Workbook

        Dim sh1 As Worksheet

        Dim x As Date

        x = Range("Z47").Value

        With ThisWorkbook

            Set sh1 = .Worksheets("Comando")

        End With

        Application.OnTime Now + TimeValue(x), "mIntermittenza"

        bln = True

    RigaChiusura:

        Set sh1 = Nothing

        Set wk1 = Nothing

        Exit Sub

    RigaErrore:

        MsgBox Err.Number & vbNewLine & Err.Description

        Resume RigaChiusura

        Call mSegnale

    End Sub

    Public Sub mSegnale()

        If bln = True Then

        Call mStart

        End If

    End Sub

    Public Sub mStop()

       bln = False

    End Sub

    Attivando manualmente da mStart o da mSegnale la routine funziona ma non si riattiva come se Call mSegnale non fosse letto. Ricordo di aver visto un altro modo per far ritornare all'iizio la routine mStart che andrò a vedere.

    Per quanto riguarda l'attivazione e l'arresto, con il codice indicato, posso udare due pulsanti, comunque è un punto che devo ancora studiare.

    Grazie per tutto

    La risposta è stata utile?

    0 commenti Nessun commento
  3. Anonimo
    2011-12-16T08:07:03+00:00

    Buon giorno. Con il sistema connesso e il programma opportunamente settato l'evento Calculate() permettere alla fonte esterna DDE di gestire il programma anche se l'operatore è assente. Ho dato un occhiata alla routine che con le seguenti modifiche proverò ad utilizzarla. Attivazione, non presente, con un evento Worksheet. Possibile modifica della frequenza del segnale da controllo esterno. Ripetitività all'infinito del segnale.

    Grazie per ora, se avrò delle difficolta dovute alla mancanza di basi sul linguaggio VB le faro sapere.

    Non ho capito nulla(immagino sia colpa mia).

    Personalmente in programmi importanti(molto importanti) che estraggono dati da un db e ciclicamente li riportano su Excel, che lavorano 24 ore al giorno, 365 giorni all'anno, per n anni, senza essere mai fermati e in assenza di operatore, utilizzo questo schema:

    • una classe che fa il lavoro di recupero dati
    • un timer (quello postato, con le opportune modifiche)
    • il timer a intervalli prestabiliti istanzia un oggetto dalla classe
    • l'oggetto recupera i dati dal db
    • li restituisce ad Excel
    • libero la memoria eliminando l'oggetto
    • Excel compie alcune elaborazioni sui dati tramite funzioni preimpostate nelle celle
    • distribuisco copie del file a diversi utenti
    • una copia viene salvata in una cartella che contiene lo storico
    • elimino i dati importati
    • salvo il file

    Una cosa simile in altro contesto recupera i dati da un sito web. In entrambi i casi è gestito il fatto che la fonte dati o gli utenti a cui distribuisco le copie elaborate potrebbero non essere raggiungibili.

    Nessun evento è coinvolto.

    La risposta è stata utile?

    0 commenti Nessun commento
  4. Anonimo
    2011-12-16T07:17:22+00:00

    Buon giorno. Con il sistema connesso e il programma opportunamente settato l'evento Calculate() permettere alla fonte esterna DDE di gestire il programma anche se l'operatore è assente. Ho dato un occhiata alla routine che con le seguenti modifiche proverò ad utilizzarla. Attivazione, non presente, con un evento Worksheet. Possibile modifica della frequenza del segnale da controllo esterno. Ripetitività all'infinito del segnale.

    Grazie per ora, se avrò delle difficolta dovute alla mancanza di basi sul linguaggio VB le faro sapere.

    La risposta è stata utile?

    0 commenti Nessun commento
  5. Anonimo
    2011-12-15T08:16:43+00:00

    Buon giorno. Ho un quesito interessante. Un programma riceve dati in continuo e li elabora per fini statistici, ogni tot secondi ho la necessità di prendere i risultati degli elaborati e tramite una routine VB di copiarli, o trasferirli, in un foglio. Per fare questo ho utilizzato il seguente codice:

    Private Sub Worksheet_Calculate()

    <cut>

    Se esiste un controllo, anche solo su Excel 2010, è molto gradita la sua conoscenza.

    Grazie.

    Domanda stupida la mia: ma perchè utilizzi un evento e non una semplice macro?

    Qui trovi un esempio di come si gestisce un timer in Excel/vb:

    http://www.maurogsc.eu/comefareperexcel/timermacro.aspx

    La risposta è stata utile?

    0 commenti Nessun commento