Una famiglia di software per fogli di calcolo Microsoft con strumenti per l'analisi, la creazione di grafici e la comunicazione dei dati.
Ciao Biagio Di Salvo,
Buongiorno Norman, grazie per la risposta.
Prego!
Sono nuovo della Community e quindi non so come inviare il file contenente la macro. Oppure posso tranquillamente fare un copia/incolla della macro qui?
Potresti caricare il file problematico, dopo averlo depurato dei dati sensibili, su un servizio di condivisione di file, per esempio Microsoft OneDrive o DropBox, e postare un link al file in una risposta qui.
Per caricare il file su Microsoft OneDrive, vedi qui
Nel caso di DropBox, vedi qui
Ad ogni modo la copio qui, spero di fare la cosa giusta.
All'interno di MODULO1 ho inserito:
Public Data_Iniziale_Globale As Date
In QUESTA CARTELLA DI LAVORO:
Sub Workbook_Open()
Dim Tempo As Long 'in secondi
Dim OpenForms
' Worksheets("Corso").Activate
Tempo = 180 ' tempo in secondi
Data_Iniziale_Globale = Now
Do Until DateDiff("s", Data_Iniziale_Globale, Now) >= Tempo
Application.StatusBar = "Se non verranno apportate modifiche questo file si chiuderà tra " & 180 - DateDiff("s", Data_Iniziale_Globale, Now) & " secondi salvando il contenuto"
OpenForms = DoEvents
Loop
Application.StatusBar = ""
Application.DisplayAlerts = False
ThisWorkbook.Close SaveChanges:=True
Application.DisplayAlerts = True
End Sub
In FOGLIO1 (che si chiama CORSO) ho inserito:
Private Sub CloseWithSave_Click()
Application.DisplayAlerts = True
Application.StatusBar = ""
ThisWorkbook.Close SaveChanges:=True
End Sub
Private Sub CloseWOutSave_Click()
Application.DisplayAlerts = True
Application.StatusBar = ""
ThisWorkbook.Close SaveChanges:=False
End Sub
Private Sub Crea_Appunt_Out_Click()
Dim Oggetto, Aula, DT_Inizio, DT_Fine As Excel.Range
Dim OutApp As New Outlook.Application
Dim appuntamento As Outlook.AppointmentItem
'aggiungere i riferimenti a Microsoft Outlook 16.0 object library
Set appuntamento = OutApp.CreateItem(olAppointmentItem)
Set Oggetto = [B4]
Set Luogo = [C8]
With appuntamento
.Body = Oggetto
.Subject = Oggetto
.Start = Range("B6").Value + Range("C6").Value 'DT_Inizio
.End = Range("B6").Value + Range("D6").Value ' DT_Fine
.Location = Luogo
.Display
End With
End Sub
Sub Worksheet_Change(ByVal Target As Range)
Application.EnableEvents = False
Data_Iniziale_Globale = Now
Application.EnableEvents = True
End Sub
Sub Worksheet_SelectionChange(ByVal Target As Range)
Application.EnableEvents = False
Data_Iniziale_Globale = Now
Application.EnableEvents = True
End Sub
Ho anche provveduto ad attivare (flag acceso) i seguenti riferimenti:
Visual Basic for Applications
Microsoft Excel 16.0 Object Library
OLE Automation
Microsoft Office 16.0 Object Library
Microsoft Forms 2.0 Object Library
Microsoft Scripting Runtime
Microsoft Outlook 16.0 Object Library
Avendo dato uno sguardo provvisorio al codice vorrei pensare che possiamo renderlo molto meno impegnativo. Ad esempio, come l'hai scritto, il codice esegue un'operazione di ciclo continuo circa 1000 volte al secondo - per dimostralo, nella procedura Workbook_Open, sostituisci:
Do Until DateDiff("s", Data_Iniziale_Globale, Now) >= Tempo
Application.StatusBar = "Se non verranno apportate modifiche questo file si chiuderà tra " & 180 - DateDiff("s", Data_Iniziale_Globale, Now) & " secondi salvando il contenuto"
OpenForms = DoEvents
Loop.
con qualcosa del genere:
Dim iCtr as Long
Do Until DateDiff("s", Data_Iniziale_Globale, Now) >= Tempo
iCtr = iCtr + 1
Application.StatusBar = _
"Se non verranno apportate modifiche questo file si chiuderà tra " _
& 180 - DateDiff("s", Data_Iniziale_Globale, Now) _
& " secondi salvando il contenuto"
Debug.Print Now & vbTab & iCtr
OpenForms = DoEvents
Loop
Dopo, diciamo un minuto, interrompi l'esecuzione del codice e controlla il valore della variabile iCtr nella finestra Immediata!
A prima achita, vorrei suggerire un approccio diverso del seguente genere:
Nel modulo di codice dell'oggetto ThisWorkbook (Questa_cartella_di_lavoro), incolla:
'=========>>
Option Explicit
'--------->>
Private Sub Workbook_Open()
Data_Iniziale_Globale = Now
Call StartTimer
Call UpdateStatusBar
End Sub
'--------->>
Private Sub Workbook_BeforeClose(Cancel As Boolean)
Call StopTimer
Call RestoreStatusbar
End Sub
'<<=========
Nel modulo di codice del foglio Foglio1, incolla il seguente codice:
'=========>>
Option Explicit
'--------->>
Private Sub Worksheet_Change(ByVal Target As Range)
Data_Iniziale_Globale = Now
Call CheckElapsedTime
End Sub
'--------->>
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Data_Iniziale_Globale = Now
Call CheckElapsedTime
End Sub
'--------->>
Private Sub CloseWithSave_Click()
Call RestoreStatusbar
ThisWorkbook.Close SaveChanges:=True
End Sub
'--------->>
Private Sub CloseWOutSave_Click()
Call RestoreStatusbar
ThisWorkbook.Close SaveChanges:=False
End Sub
'--------->>
Private Sub Crea_Appunt_Out_Click()
Dim Oggetto, Aula, DT_Inizio, DT_Fine As Excel.Range
Dim OutApp As New Outlook.Application
Dim appuntamento As Outlook.AppointmentItem
'aggiungere i riferimenti a Microsoft Outlook 16.0 object library
Set appuntamento = OutApp.CreateItem(olAppointmentItem)
Set Oggetto = [B4]
Set Luogo = [C8]
With appuntamento
.Body = Oggetto
.Subject = Oggetto
.Start = Range("B6").Value + Range("C6").Value 'DT_Inizio
.End = Range("B6").Value + Range("D6").Value ' DT_Fine
.Location = Luogo
.Display
End With
End Sub
'<<=========
In un modulo standard, incolla:
'=========>>
Option Explicit
'--------->>
Public RunWhen As Double
Public Const cRunIntervalSeconds = 2 '\ 2 Secondi
Public Const cRunWhat = "CheckElapsedTime"
Public Data_Iniziale_Globale As Double
Public dElapsedTime As Double
Public Const iMassimoNumeroDiSecondi As Long = 180 '\ 3 minuti
'--------->>
Public Sub StartTimer()
RunWhen = Now + TimeSerial(0, 0, cRunIntervalSeconds)
Application.OnTime EarliestTime:=RunWhen, _
Procedure:=cRunWhat, _
Schedule:=True
End Sub
'--------->>
Public Sub StopTimer()
On Error Resume Next
Application.OnTime EarliestTime:=RunWhen, _
Procedure:=cRunWhat, _
Schedule:=False
End Sub
'--------->>
Public Sub CheckElapsedTime()
dElapsedTime = DateDiff("s", Data_Iniziale_Globale, Now)
If dElapsedTime >= iMassimoNumeroDiSecondi Then
Call StopTimer
Call RestoreStatusbar
ThisWorkbook.Close SaveChanges:=True
End If
StartTimer
Call UpdateStatusBar
End Sub
'--------->>
Public Sub UpdateStatusBar()
Application.StatusBar = False
Application.StatusBar = _
"Se non verranno apportate modifiche questo file si chiuderà tra " _
& iMassimoNumeroDiSecondi - _
DateDiff("s", Data_Iniziale_Globale, Now) _
& " secondi salvando il contenuto"
End Sub
'--------->>
Public Sub RestoreStatusbar()
Application.StatusBar = False
End Sub
'<<=========
In questo modo, credo che si raggiunga i tuoi obiettivi originali ma con un clclo molto meno impegnato, ossia con un ciclo che viene ripetuto 30 volte per minuto anzichè molte centinaia di volte al secondo.
Potresti scaricare il mio file di prova BiagioDiSalvo220170515.xlsm
===
Regards,
Norman