Condividi tramite

Macro con errore !!!

Anonimo
2017-08-14T12:11:35+00:00

Ho una macro gemella e funziona benissimo, invece questa mi segnala l'errore ( metodo 'range' dell'oggetto I_worksheet' non riuscito.

Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range) ' Paga Forgiatura!

Set Target = Sheets("INTELLIGENZA").Range("BF75")

   With Application

      .Calculation = xlCalculationManual

   End With

If Target = "SI" Then Sheets("OBBIETTIVI").Range("M73") = Sheets("OBBIETTIVI").Range("M73") - Sheets("INTELLIGENZA").Range("BF77")

If Sheets("INTELLIGENZA").Range("BF75") = "SI" Then Sheets("INTELLIGENZA").Range("BD69") = "X"

If Sheets("INTELLIGENZA").Range("BF75") = "SI" Then Sheets("INTELLIGENZA").Range("BD70") = "X"

   With Application

      .Calculation = xlCalculationAutomatic

   End With

End Sub

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

Risposta accettata dall'autore della domanda

Anonimo
2017-08-14T15:10:02+00:00

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

La risposta è stata utile?

1 persona ha trovato utile questa risposta.
0 commenti Nessun commento

Risposta accettata dall'autore della domanda

Anonimo
2017-08-14T16:31:57+00:00

Ciao Fabio,

Apprezzo ENORMEMENTE la risposta datami e soprattutto le varie spiegazioni ma devo dirti che ho capito poco della tua lezione e la colpa è solo mia... io sono un PINCO.PALLINO che ha comprato OFFICE e si è trovato Excel davanti e ha detto "Vabbè proviamo ha fare qualcosa!?" , ho effettuato varie ricerche e domande in giro ma sono rimasto agli esordi, e non ho dimestichezza con parole tecniche.

Sul principio che una dimostrazione pratica vale mille parole, nel modulo di codice del foglio interessato fai clic nel margine a sinistra della intestazione della procedura Worksheet_Change per evidenziarla in marrone, In questo modo, ad ogni esecuzione della procedura, il codice si fermerà a questo punto e si continuerà alla pressione del tasto F5.

Inoltre, immetti un apostrofo iniziale sulla riga del comando 

            .EnableEvents = False

Ora, vedrai il codice così:

Adesso per vedere le chiamate ricorsive alla procedura, digita Si nella cella BF75. Sarai immediatamente portato al modulo di codice

Premi F8  per andare alla prima istruzione della procedura e poi premi il tasto F5 per eseguire la macro. Vedrai che, ripetutamente l'intestazione sarà  evidenziata in giallo, indicando una nuova esecuzione del codice.  In termine semplici, ogno volta che la macro viene eseguita, il codice scrive il valore  X nelle celle BD69:BD70 e, pertanto, si crea una nuova chiamata alla procedura  - insomma una chiamata ricorsiva!

Solo una cosa, dici che non ho chiuso la discussione precedente ,... ma ho segnato che ho risolto, cosa altro devo fare?

A causa dei problemi attualmente inerenti alla riorganizzazione di questo forum, non sono riuscito a vedere il tuo voto nel thread precedente! Ho pertanto cancellato la mia richiesta e ti ringrazio tardivamente.

Grazie veramente , con la tua risposta mi hai fatto capire quanto sono nessuno nel piccolo mondo VBA e figuriamoci nel complesso mondo informatico.

Prego! Non esitare a chiederci ulteriori delucidazioni.

Buon lavoro!

===

Regards,

Norman

La risposta è stata utile?

0 commenti Nessun commento

2 risposte aggiuntive

Ordina per: Più utili
  1. Anonimo
    2017-08-14T16:53:28+00:00

    Ciao Fabio,

    A costo di precisare un'ovvietà, dopo la 'dimostrazione', fai clic nel margine accanto alla intestazione della procedura,  per disabilitare il punto d'interruzione del codice, e togli l'apostrofo precedentamente inserito davanti l'istruzione:

                .EnableEvents = False

    ===

    Regards,

    Norman

    La risposta è stata utile?

    0 commenti Nessun commento
  2. Anonimo
    2017-08-14T15:39:55+00:00

    Apprezzo ENORMEMENTE la risposta datami e soprattutto le varie spiegazioni ma devo dirti che ho capito poco della tua lezione e la colpa è solo mia... io sono un PINCO.PALLINO che ha comprato OFFICE e si è trovato Excel davanti e ha detto "Vabbè proviamo ha fare qualcosa!?" , ho effettuato varie ricerche e domande in giro ma sono rimasto agli esordi, e non ho dimestichezza con parole tecniche.

    Solo una cosa, dici che non ho chiuso la discussione precedente ,... ma ho segnato che ho risolto, cosa altro devo fare?

    Grazie veramente , con la tua risposta mi hai fatto capire quanto sono nessuno nel piccolo mondo VBA e figuriamoci nel complesso mondo informatico.

    La risposta è stata utile?

    0 commenti Nessun commento