Una famiglia di software per fogli di calcolo Microsoft con strumenti per l'analisi, la creazione di grafici e la comunicazione dei dati.
Ciao Fabio,
Ho una macro gemella e funziona benissimo, invece questa mi segnala l'errore ( metodo 'range' dell'oggetto I_worksheet' non riuscito.
Inananzitutto, una routine evento non è equivalente ad una macro in un modulo standard!
Vedo diversi problemi con la tua procedura e, con il massimo rispetto possibile, credo che tu abbia fornito un insegnamento di quanto non scrivere tale codice!
Quindi, prima di suggerire una versione funzionante e riveduta del codice, mi permetto di fare i seguenti suggerimenti:
Ti consiglierei di non scrivere mai un comando del genere:
[...]
Set Target = Sheets("INTELLIGENZA").Range("BF75")
[...]
Target è una parola riservata la quale rappresenta un oggetto range che, in questo caso, è l'intervallo modificato dall'utente o da altro codice.
Il modo convenzionale sarebbe qualcosa del genere:
If Not Intersect(Me.Range("BF75"), Target) Is Nothing Then
...
...
End if
With Application
.Calculation = xlCalculationManual
End With
Se si modifica una qualsiasi delle impostazioni di ambiente, ritengo che ci sia un obbligo implicito di utilizzare un gestore di errori al fine di garantire il corretto ripristino della impostazione nel caso di un errore imprevisto.
Mentre la struttura With ... End With spesso rappresenta una forma di codice elegante ed efficiente, in questo caso penso sia ridondante e inefficiente. Meglio sarebbe il semplice
Application.Calculation = xlCalculationManual
If Target = "SI" Then Sheets("OBBIETTIVI").Range("M73") = Sheets("OBBIETTIVI").Range("M73") - Sheets("INTELLIGENZA").Range("BF77")
Vorrei suggerire che, nonostante il fatto che mettendo l'istruzione If ...Then
su una singola riga rende il codice più breve e compatta, a mio modesto parere, lo renda meno leggibile e più difficile per il debug in caso di problemi con il codice.
Inoltre, ti consiglio sempre di enunciare esplicitamente la proprietà intesa, piuttosto che affidarsi alla proprietà predefinita dell'oggetto di interesse. Quindi, nel caso in questione, suggerirei:
With Me.Range("M73")
If UCase(Target.Value) = "SI" Then
.Value = .Value - Sheets("INTELLIGENZA").Range("BF77").Value
End If
End With
Tuttavia, e di importanza preponderante, è la questione di sopprimere eventuali chiamate ricorsive a questa o ad altre procedure evento.
Più in particolare, se, come in questo caso, l'evento Worksheet_Change modifichi uno o più valori sul foglio di interesse, è molto importante che gli eventi di Excel siano soppressi. In caso contrario, la modifica apportata dal codice darà luogo a ripetute chiamate ricorsive alla procedura evento Worksheet_Change. È inoltre fondamentale assicurarsi che gli eventi di Excel siano riabilitati, anche in caso di errori imprevisti. Insomma, in un tale scenario. si deve sfruttare la proprieta Appliction.EnableEvents.
Quindi, vorrei suggerire la seguente modificazione del tuo codice:
'=========>>
Option Explicit
'--------->>
Private Sub Worksheet_Change(ByVal Target As Range) ' Paga Forgiatura!
Dim srcSH As Worksheet
Dim Rng As Range
Const sFoglioDestinazione As String = "OBBIETTIVI"
Set srcSH = ThisWorkbook.Sheets(sFoglioDestinazione)
Set Rng = Me.Range("BF75")
On Error GoTo XIT
If Not Intersect(Rng, Target) Is Nothing Then
With Application
.EnableEvents = False
.Calculation = xlCalculationManual
End With
If UCase(Rng.Value) = "SI" Then
With srcSH
.Range("M73").Value = .Range("M73").Value - Me.Range("BF77")
End With
Me.Range("BD69:BD70").Value = "X"
End If
End If
XIT:
With Application
.Calculation = xlCalculationAutomatic
.EnableEvents = True
End With
End Sub
'<<=========
' Paga Forgiatura!
Non mi sognerei mai di farlo
In conclusione, e dovrei dirlo come avvertenza, non ho tentato troppo di seguire le azione intese del codice. Mi preoccupavo principalmente invece la struttura e la sintassi del codice.
Se tu dovessi avere ancora un problema, ti chiederei gentilmente di indicare la riga di codice che viene evidenziata in giallo al punto di riscontrare l'errore.
Postscriptum:
Nota che ho aggiunto l'istruzione essenziale, evidenziata in grassetto, qui sopra, ossia
.EnableEvents = True
===
Regards,
Norman