Worksheet Selectionchange

  • Worksheet_selectionchange di Valentina
    Per un foglio excel (foglio1) ho scritto nel modulo1 dell’editor vb una routine che viene attivata dall’evento worksheet_selectionchange che ho scritto nel modulo di codice associato al foglio1. ora, per implementare le funzionalità del mio foglio excel, ho scritto un’altra routine (anch’essa nel modulo1) sempre attivata dall’evento worksheet_selectionchange e che ho pure scritto nel modulo di codice associato al foglio 1 e, praticamente, sotto al precedente worksheet_selectionchange.
    nel modulo di codice associato al foglio1 ho quindi 2 worksheet_selectionchange. visual basic fa apparire un messaggio di errore “nome non univoco”. a cosa si riferisce? che cosa devo modificare in sostanza? ringrazio anticipatamente coloro che vorranno aiutarmi. -- valentina

    di Apoben64
    L'errore potrebbe derivare dall'utilizzo del medesimo codice in un stesso modulo. prova invece usare due moduli e sub con nomi diversi.

    di Mauro
    Ciao valentina, nello stesso modulo hai definito 2 routine con lo stesso nome e questo non è permesso!
    non ti è possibile raggruppare le azioni eseguite nei 2 moduli in un modulo unico?

    di Valentina
    Nel codice associato al foglio1 ho due routine (diverse) ma che iniziano entrambe con:
    worksheet_selectionchange(byval traget as range). e’ forse questa “intestazione comune” a creare problemi? nel modulo1, invece, ho due normali routine completamente diverse, anche nel nome.
    ciascuna di queste due ultime routine viene richiamata, sotto opportune condizioni, da una delle due worksheet_selectionchange di cui ho detto.
    se il problema fosse la comune intestazione delle routine nel codice associato al foglio1, non vedo in quale modo posso differenziarle.
    quanto alle altre due, create nel modulo1, esse sono di per sè assolutamente diverse in tutto, nome compreso.
    dov’è il problema? ciao a tutti -- valentina

    di Big ronnie
    Ciao valentina, l'unico modo è cercare di raggruppare il codice in una sola macro worksheet_selectionchange.se il codice non è molto scrivilo nel post e se possibile lo sistemiamo.ciao

    di Valentina
    Ringrazio mauro e big ronnie per la disponibilità offerta. il codice che segue è tratto dalla rielaborazione di alcuni post apparsi di recente nel sito. in un primo tempo (prima versione) ho scritto questo codice nel foglio1:

    private sub worksheet_selectionchange(byval target as range)
    indirizzo = "j" & range("bh2").text
    if activecell.address(rowabsolute:=false, columnabsolute:=false) = indirizzo then
    application.run ("macro1")
    end if
    end sub

    e poi nel modulo1 ho scritto il codice:

    sub macro1()
    a = range("at35").value
    dim i as integer
    for i = 1 to 4
    cells(35, 46) = a
    call macro2
    next i
    end sub
    private sub macro2()
    a = range("at35").value
    dim n as byte, start as variant
    for n = 1 to 10
    start = timer
    do while timer < start + 1 / 10
    loop
    if n mod 5 = 0 then cells(35, 46) = ""
    next n
    range("at35").formula = "=at33*(ao5)^2+av33*ao5+ax33"
    end sub

    e tutto ciò funziona perfettamente senza problemi. vengo al mio problema e quesito.
    seguendo il suggerimento che mi avete dato ho modificato questa procedura così (vedi spazio codice).
    quest’ultima procedura esegue tutto correttamente ma rallenta notevolmente qualsiasi operazione sul foglio. persino il semplice spostamento con i tastini direzionali da una cella all’altra o l’immissione di un valore in una cella richiede tempi di attesa. perchè non accadeva con la prima versione? come posso ottenere lo stesso risultato senza rallentamenti? grazie di cuore ad entrambi --
    valentina

     
    Nel codice del Foglio1:
    
    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Indirizzo = "J" & Range("BH2").Text
    If ActiveCell.Address(RowAbsolute:=False, ColumnAbsolute:=False) = Indirizzo Then
    Application.Run ("Macro1")
    ElseIf Range(“L17”).Value <> “” Then
    Application.Run(“Macro3”)
    End If
    End Sub
    
    Nel modulo1:
    
    
    
    
    Sub Macro1()
    a = Range("L17").Value
    Dim i As Integer
    For i = 1 To 4
    Cells(17, 12) = a
    Call Macro2
    Next i
    End Sub
    Private Sub Macro2()
    a = Range("L17").Value
    Dim n As Byte, Start As Variant
    For n = 1 To 10
    Start = Timer
    Do While Timer < Start + 1 / 10
    Loop
    If n Mod 5 = 0 Then Cells(17, 12) = ""
    Next n
    Range("L17").Formula = "=BK4"
    End Sub
    
    Sub Macro3()
    a = Range("AT35").Value
    Dim i As Integer
    For i = 1 To 4
    Cells(35, 46) = a
    Call Macro4
    Next i
    End Sub
    Private Sub Macro4()
    a = Range("AT35").Value
    Dim n As Byte, Start As Variant
    For n = 1 To 10
    Start = Timer
    Do While Timer < Start + 1 / 10
    Loop
    If n Mod 5 = 0 Then Cells(35, 46) = ""
    Next n
    Range("AT35").Formula = "=AT33*(AO5)^2+AV33*AO5+AX33"
    End Sub
    

    di Big ronnie
    Il codice che hai creato va benissimo,forse è troppo macchinoso.per esempio assegni alla variabile "a" la cella "l17" e subito dopo assegni alla cella "l17" la variabile "a". ma questo è la stessa cosa cioè "l17" è "l17".ho provato a semplificare un pò il tuo codice in modo da farti un esempio diverso di scrittura.a me funziona tutto perfettamente.per il rallentamento, ad ogni cambiamento nel foglio devi attendere i lampeggi per poi poter fare qualsiasi altra operazione.
    ciao valentina.
     
    Nel Foglio1
    
    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Indirizzo = "J" & Range("BH2")
    If ActiveCell = Indirizzo Then Macro1
    If Range("L17") <> "" Then Macro3
    End Sub
    
    Nel Modulo1
    
    Sub Macro1()
    Dim i As Integer
    For i = 1 To 4
    Call Macro2
    Next i
    End Sub
    Private Sub Macro2()
    Dim n As Byte, Start As Variant
    For n = 1 To 10
    Start = Timer
    Do While Timer < Start + 1 / 10
    Loop
    If n Mod 5 = 0 Then Cells(17, 12) = ""
    Next n
    Range("L17").Formula = "=BK4"
    End Sub
    Sub Macro3()
    Dim i As Integer
    For i = 1 To 4
    Call Macro4
    Next i
    End Sub
    Private Sub Macro4()
    Dim n As Byte, Start As Variant
    For n = 1 To 10
    Start = Timer
    Do While Timer < Start + 1 / 10
    Loop
    If n Mod 5 = 0 Then Cells(35, 46) = ""
    Next n
    Range("AT35").Formula = "=AT33*(AO5)^2+AV33*AO5+AX33"
    End Sub
    
    

    di Valentina
    Ciao big ronnie! grazie per il tempo e l'attenzione che mi stai dedicando.
    ho copiato e trascritto scrupolosamente il tuo codice. funziona tutto ma il rallentamento persiste immutato anche quando il lampeggiamento non è in atto. fai questa prova. passando al foglio excel, prova a spostarti velocemente da una cella all'altra con i tastini direzionali.
    il rallentamento è notevole al punto che non è possibile lavorare normalmente con il foglio.
    fammi sapere. ciao ronnie.

    di Apoben64
    Ciao a tutti , penso che per poter velocizzare il lavoro quando si usano degli eventi sia necessario affidarsi anche un pò alla teoria.
    personalemnte ho trovato utile queste informazioni in questo link:
    http://ennius.altervista.org/mike/procedure/mikevba100.htm
    in particolare l'uso di "application.enableevents" per evitare le continue attivazioni dell'evento change . potrebbe essere una soluzione ai rallentamenti !
    un saluto luca

    di Big ronnie
    Ciao valentina, a me il rallentamento è dato solo dal lampeggiare delle celle "l17" e "at35".prova ad accorciare i tempi del lampeggio diminuendolo da 1/10 ad 1/100 per esempio.un'altra possibile causa forse potrebbero essere le caratteristiche del computer.ciao e fammi sapere.

    di Valentina
    Ciao big ronnie.
    hai provato a spostarti velocemente con i tastini direzionali in assenza delle condizioni per far lampeggiare una delle due celle? dovresti vedere che il rallentamento persiste ugualmente. ho provato a scrivere il programma su altri computer: stesso risultato. e' normale che durante il lampeggiamento non si possano eseguire altre operazioni fino a che esso non termina, ma perchè deve rallentare anche quando non ci sono le condizioni che richiedono il lampeggio? una cosa che mi lascia perplessa è che nella prima stesura del programma (prima versione, vedi post precedenti) il rallentamento non c'è. e ancora, esistono programmi vba ben più complessi di questo e che nonostante ciò non danno problemi del genere. credo che apoben64 stia individuando la strada giusta: manca qualcosa al programma, ma cosa? un saluto a tutti. -- valentina

    di Apoben64
    Ciao valentina, mi chiedo del perchè non provi ad inserire l'istruzione pplication.enableevents che serve proprio diminuire il rallentamento,o comunque stabilizza l'evento change; certo è, che come dice big ronnie potrebbe essere anche colpa del computer considernado che excel contrariamente ad access per funzionare utilizza la memoria disponibile nel computer.
    dimenticavo per l'inserimento dell'istruzione guarda il post "avvio macro - evento change ". spero che sia quello che cerchi !
    un saluto luca

    di Big ronnie
    Ciao valentina,sono ripartito dal tuo primo codice e devo dirti che così comè digitato non fa funzionare il lampeggiamento,quindi tutte le azioni che fai sono a velocità normale.l'errore sta nella sintassi di activecell.address nel foglio1.se tu togli tutto ciò che sta all'interno delle parentesi(comprese le parentesi) allora tutto funziona come vorresti e cioè avviene il lampeggiamento in determinate condizioni e purtroppo per te anche il rallentamento.
    p.s.: nel secondo codice da te digitato ci sono degli apici(vedi scritta "l17" x esempio) che non fanno funzionare il codice facendo dare messaggio di errore.ciao,aspetto notizie.

    di Valentina
    Penso che con un esempio molto semplificato riusciamo ad inquadrare meglio (e forse risolvere) il problema. hai questa situazione:
    nel foglio1 di excel hai la cella a1 con la formula =d1; nella cella d1 hai la formula =se(f1=1;"pippo";" "); la cella f1 è vuota ed è destinata all'immissione di numeri (1, 2, ...).
    il codice del foglio1 è:
    private sub worksheet_selectionchange(byval target as range)
    if range("a1").value <> "" then
    call lampeggio
    end if
    end sub
    nel modulo1, invece, hai il codice riportato sotto (vedi spazio).
    orbene, in questa situazione si ottiene il lampeggio ogni volta che digiti "1" in f1 e subito dopo selezioni un'altra cella qualsiasi.
    tutto ok, dunque. se provi però a spostarti da una cella all'altra con i tastini direzionali (anche non durante il lampeggio) si osserva il notevole rallentamento. io credo che se riusciamo a risolvere il problema in una situazione così semplificata sarà poi possibile risolvere situazioni più complesse. apoben aveva suggerito di utilizzare l'istruzione enableevents. bene, proviamo a inserirla nella situazione semplificata, ma dove?. fammi sapere se non ho chiarito sufficientemente il problema. ciao -- valentina

     
    Sub lampeggio()
    a = Range("a1").Value
    Dim i As Integer
    For i = 1 To 3
    Cells(1, 1) = a
    Call Flash_Sequence
    Next i
    End Sub
    Private Sub Flash_Sequence()
    a = Range("a1").Value
    Dim n As Byte, Start As Variant
    For n = 1 To 10
    Start = Timer
    Do While Timer < Start + 1 / 15
    Loop
    If n Mod 5 = 0 Then Cells(1, 1) = ""
    Next n
    Range("A1").Formula = "=D1"
    End Sub

    di Big ronnie
    Ciao valentina,
    ho constatato che ciò che da fastidio è la formula in "a1" che non permette ad excel il riconoscimento della cella vuota e quindi il lampeggiamento(di nulla) avviene comunque ritardando le azioni.potresti ovviare a questo scrivendo in d1 =se(f1=1;"pippo";se(f1=1;a1=d1;"")),togliere la formula in a1 e lasciare il codice che hai scritto così com'è.ciao


    di Valentina
    Ciao ronnie! certamente hai avuto una felice intuizione riguardo alla formula in a1. purtroppo, però, non è possibile eliminarla perchè in a1 arrivano messaggi dipendenti dal parametro esistente in f1. in pratica, ad ogni parametro configurato in f1, a1, collegata con f1, espone un "messaggio" di diverso tipo (che auspicabilmente dovrebbe lampeggiare). cosi come proponi di modificare le celle, il messaggio dovrebbe essere posto in a1 direttamente dall'utente mentre in realtà dovrebbe andarci in automatico in base, come ho detto, la parametro di f1. ciao ronnie. fammi sapere - valentina

    di Big ronnie
    Ciao valentina,
    dal tuo esempio si capiva che "a1" dipendeva dalla cella "d1",comunque sto cercando di interpretare il tutto e forse credo di aver capito cosa cerchi di fare.ti invio del codice con 3 esempi di cosa potrebbe valere "f1",eventualmente fossero di più sitemalo aumentando i case.poi ho modificato l'ultima riga della macro flash_sequence per evitare di inserire di nuovo la formula in "a1".se anche questa volta non ci siamo,fai l'esempio reale di cosa ti serve, evitiamo così la confusione.ciao.
     
    nel foglio1
    
    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Dim F1 As Range
    Set F1 = Worksheets(1).Range("f1")
    If F1 >= 1 And F1 < 4 Then
    Select Case F1
    Case 1
    Worksheets(1).Range("a1") = "A"
    Case 2
    Worksheets(1).Range("a1") = "B"
    Case 3
    Worksheets(1).Range("a1") = "C"
    End Select
    lampeggio
    End If
    End Sub
    nel modulo1
    
    Sub lampeggio()
    a = Range("a1").Value
    Dim i As Integer
    For i = 1 To 3
    Cells(1, 1) = a
    Call Flash_Sequence
    Next i
    End Sub
    Private Sub Flash_Sequence()
    a = Range("a1").Value
    Dim n As Byte, Start As Variant
    For n = 1 To 10
    Start = Timer
    Do While Timer < Start + 1 / 15
    Loop
    If n Mod 5 = 0 Then Cells(1, 1) = ""
    Next n
    Range("A1") = Range("d1")
    End Sub

    di Valentina
    Ciao big ronnie. ho avuto modo di testare il tuo codice e...sei big davvero. funziona tutto e senza rallentamenti. una domanda. e' proprio necessaria la condizione if f1>=1 and f1<4 ?
    poichè io non ho queste limitazioni, posso evitarla senza problemi? ed ancora, ho provato a sostituire worksheet_selectionchange con worksheet_change (che per me sarebbe più comodo) ma ottengo la segnalazione "stack di memoria esaurito". ti viene in mente qualcosa?

    di Big ronnie
    Ciao valentina,
    il ciclo "if" serve per non chiamare la macro lampeggio in ogni case, comunque ti invio il codice senza "if".per quanto riguarda l'evento change ti da errore perchè ogni lampeggio è un "change",quindi entri in un ciclo infinito non avendo più la possibilità di fare nilla fino all'esaurimento della memoria.
     
    Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    Dim F1 As Range
    Set F1 = Worksheets(1).Range("f1")
    Select Case F1
    Case 1
    Worksheets(1).Range("a1") = "A"
    lampeggio
    Case 2
    Worksheets(1).Range("a1") = "B"
    lampeggio
    Case 3
    Worksheets(1).Range("a1") = "C"
    lampeggio
    End Select
    End Sub
    

    di Valentina
    Capisco. un grazie di cuore, alla prossima! ciao very big ronnie -- valentina