2015-07-03 5 views
5

Voglio monitorare un valore e ricevere notifiche via email quando determinate condizioni sono soddisfatte. Ho una macro in questo modo:Come ottenere VBA Macro per eseguire continuamente in background?

Do While True 

    Worksheet.Calculate 

    If Value > 10 Then 
     SendEmail 
    End If 

    Sleep 60*CLng(1000) 

Loop 

Tuttavia, quando si esegue questo, intasa l'intero programma e si accende non risponde se cerco di fare qualsiasi cosa.

Esiste comunque lo scopo di farlo funzionare in background o almeno non arrestare il programma?

Quello che stavo facendo prima era usare VBScript per aprire un foglio di calcolo non visibile e VBScript funzionava continuamente in background, monitorando la condizione e funzionava bene, ma il mio cliente vuole davvero una GUI e che sia nel programma stesso .

Qualche idea?

+0

Se è necessario monitorare il valore di una cella di quanto non sia necessario eseguire continuamente un codice, ma utilizzare l'evento di modifica del foglio di lavoro. –

+0

@ MátéJuhász Non penso che il valore cambierà da solo. Deve essere richiesto a. Aggiornerò il codice di esempio. Posso ancora utilizzare l'evento di modifica del foglio di lavoro? –

+0

Dai un'occhiata qui: http://www.mrexcel.com/forum/excel-questions/79144-automatically-update-time-date.html, potrebbe esserti utile. –

risposta

6

Utilizzare il metodo Application.OnTime per pianificare il codice che verrà eseguito in un minuto.

Il codice sarà simile a questa (non testata):

Sub CreateNewSchedule() 
    Application.OnTime EarliestTime:=DateAdd("n", 1, Now), Procedure:="macro_name", Schedule:=True 
End Sub 

Sub macro_name() 

    If Value > 10 Then 
     SendEmail 
    Else 
     CreateNewSchedule 
    End If 

End Sub 

Si potrebbe desiderare di memorizzare l'ora del prossimo programma in una variabile globale in modo che l'evento Workbook_BeforeClose può annullare il programma successivo. In caso contrario, Excel riaprirà la cartella di lavoro.

Public nextScheduledTime As Date 

Sub CreateNewSchedule() 
    nextScheduledTime = DateAdd("n", 1, Now) 
    Application.OnTime EarliestTime:=nextScheduledTime , Procedure:="macro_name", Schedule:=True 
End Sub 

Sub macro_name() 

    If Value > 10 Then 
     SendEmail 
    Else 
     CreateNewSchedule 
    End If 

End Sub 

Private Sub Workbook_BeforeClose(Cancel As Boolean) 
On Error Resume Next 
    Application.OnTime EarliestTime:=nextScheduledTime, Procedure:="macro_name", Schedule:=False 
End Sub 

È quindi possibile continuare a utilizzare Excel tra gli orari pianificati.

+0

Grazie. La tua funzione 'CreateNewSchedule' funziona perfettamente. Non sapevo di quella funzione –

1

Penso che sia necessario elaborare in modo specifico lo stack di eventi dell'applicazione con una chiamata DoEvents. Ciò consente alle interazioni dell'utente con il foglio di calcolo di verificarsi, dove normalmente la macro avrebbe la precedenza. È il codice sarebbe simile:

Do While True 

    If Value > 10 Then 
     SendEmail 
    End If 

    Sleep 60*CLng(1000) 

    DoEvents 
Loop 

Si potrebbe anche costruire una GUI con HTA se si voleva rimanere con VBScript.

+2

Un altro modo sarebbe quello di impostare una macro da eseguire ogni volta che il foglio di calcolo cambia. –

+0

Sì, questa è una soluzione migliore per essere onesti, perché in questo caso si otterrà ancora il blocco dell'applicazione come risultato del comando di sospensione, credo. Ti suggerisco di postarlo come risposta a questa domanda - lo svalutarei :-). L'unico problema sarebbe venuto se non si fosse verificata un'interazione con l'utente, ma era necessario inviare una mail. In tal caso, se il comando sleep non sta effettivamente cronometrando qualcosa, potresti ridurlo a 33ms o qualcosa di non percepibile. – Orphid

+0

@ HolmesIV, vedere la mia risposta nei commenti sopra. –