Forzare in ordine numerico delle caselle combinate tramite VBA

di il
32 risposte

32 Risposte - Pagina 2

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    13/01/2026 - @Alex ha scritto:

    In questi casi si può usare una Collection

    Ciao Alex! :-)

    Giusto, ma per popolarla ed evitare il ciclo (motivo per il quale è nata la discussione) dovrebbero essere inseriti uno ad uno i controlli nella Collection.

    Quindi a questo punto tanto vale passare il tempo a rinominarsi i controllli! :-D

    Ovviamente è una battuta e, comqunque alla fine, dipende dal numero di controlli di cui stiamo parlando... Se sono solo 8, probabilmente le prestazioni si equivalgono in tutti i casi.

    TheTruster

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    13/01/2026 - TheTruster ha scritto:

    13/01/2026 - @Alex ha scritto:

    In questi casi si può usare una Collection

    Ciao Alex! :-)

    Giusto, ma per popolarla ed evitare il ciclo (motivo per il quale è nata la discussione) dovrebbero essere inseriti uno ad uno i controlli nella Collection.

    Quindi a questo punto tanto vale passare il tempo a rinominarsi i controllli! :-D

    Ovviamente è una battuta e, comqunque alla fine, dipende dal numero di controlli di cui stiamo parlando... Se sono solo 8, probabilmente le prestazioni si equivalgono in tutti i casi.

    TheTruster

    Ciao Mirko, si se rinomini i controlli indicizzandoli come hai suggerito è sicuramente più semplice e funzionale.

    Se non puoi rinominarli invece, e la collection Controls è sostanziosa, qualche centinaio di controlli, allora come mi è capitato di dover gestire con i limiti grafici di Access, la differenza è estremamente importante e visibile, e lavorare con le collection Custom con i raggruppamenti rende molto veloce l'iterazione per le operazioni grafiche in particolare.

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    Ciao, grazie soprattutto dei vostri suggerimenti, sono utili in tutti i sensi e nel caso le caselle ComboBox siano rinominati progressivamente è più che sufficiente ciò che aveva suggerito TheTrueter

    Dim I As Long
    
    For I = 1 To 8   '-> Oppure il numero massimo dei tuoi controlli
        With Me.Controls("cbo" & I)
            .Requery
            If .ListCount <= 1 Then .Value = .ItemData(0)
        End With
    Next I

    Questo è perché vengono inserite automaticamente tutti gli altri valori nella ComboBox altrimenti inserisco manualmente se ci sono più voci.

    Inoltre anche nel caso non volessi rinominare perché ormai sono già strutturati si potrebbe usare attraverso i TAG numerati progressivamente.

        For Each ctl In Me.Controls
        
        For I = n To 8
            If ctl.Tag = I Then
                If ctl.ControlType = acComboBox Then
                    ctl.Requery
                    If ctl.ListCount <= 1 Then ctl = ctl.ItemData(0)
                End If
            End If
        Next I
        
        Next
        Set ctl = Nothing

    In entrambi i casi vanno bene.

    Grazie anche a tutti gli altri che mi avete suggerito.

    Antonio

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    13/01/2026 - BLUES ha scritto:

    ComboBox siano rinominati progressivamente è più che sufficiente ciò che aveva suggerito TheTrueter

    Almeno finché non hai l'esigenza di una combo intermedia... Combo3,5... Combo2,75....

    Come ha suggerito Alex, meglio ridefinire la collection (o un alias).

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    13/01/2026 - @Alex ha scritto:

    In questi casi si può usare una Collection, se non si usa la Key in fase di Add(Item), ovviamente poi per puntare all'item specifico va ciclato ma con i controlli direi che è inutile, è discretamente più performante di un Array.

    Option Compare Database
    Option Explicit
    
    Dim mCCombo As Collection
    
    Private Sub Form_Load()
        Set mCCombo = New Collection
        With mCCombo
            .Add Me!Combo1
            .Add Me!Combo2
            .Add Me!Combo3
            .Add Me!Combo4
        End With
    End Sub

    Poi per usarla:

    Private Sub TestCollection()
        Dim mCbo As Access.Combo
        For Each mCbo In mCCombo
            Debug.Print mCbo.Name
        Next
    End Sub

    Ciao Alex, ho provato anche con questi codici ed è OTTIMO, funziona perfettamente, veloce e anche molto comodo.

    Non so se hai copiato a mano o copia/incolla ma ho dovuto correggere che mi dava l'errore:

    Dim mCbo As Access.ComboBox

    Grazie ancora.

    Antonio

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    13/01/2026 - @Alex ha scritto:

    In questi casi si può usare una Collection, se non si usa la Key in fase di Add(Item), ovviamente poi per puntare all'item specifico va ciclato ma con i controlli direi che è inutile, è discretamente più performante di un Array.

    Option Compare Database
    Option Explicit
    
    Dim mCCombo As Collection
    
    Private Sub Form_Load()
        Set mCCombo = New Collection
        With mCCombo
            .Add Me!Combo1
            .Add Me!Combo2
            .Add Me!Combo3
            .Add Me!Combo4
        End With
    End Sub

    Poi per usarla:

    Private Sub TestCollection()
        Dim mCbo As Access.Combo
        For Each mCbo In mCCombo
            Debug.Print mCbo.Name
        Next
    End Sub

    Ciao Alex, ho notato che viene ciclato SEMPRE dal primo ComboBox, se ad esempio cancello il valore dalla quarta ComboBox non si cancella anzi viene rimesso lo stesso valore di prima allora ho pensato di far partire dalla quinta ComboBox usando la stringa ListIndex (mCbo.ListIndex) ma dal Debug viene restituito sempre i valori 0 e -1 mentre ciò che vorrei sono i numeri da 1 in poi, ti sarei grato se hai qualche suggerimento.

    Antonio

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    Devi resettare da quella selezionata in poi.

    Questo significa che potresti creare una routine di reset, a cui passare come parametro la combo che subisce la modifica.

    Private Function getRequery(actCombo As Access.ComboBox)
    
    	Dim ctl As Variant
    	Dim bRequery As Boolean
    
        For Each ctl In mCbo
        	If bRequery Then
        		ctl.Value = Null
        		ctl.Requery
        		If ctl.ListCount = 1 Then ctl = ctl.ItemData(0)
        	End If
    		If ctl.Name = actCombo.Name Then bRequery = True
        Next
        Set ctl = Nothing
    End Function

    Quindi se nell'evento AfterUpdate della cmbCascata1, ad esempio:

    getRequery cmbCascata1

    e dovrebbe effettuare il rquery dalla cmbCascata2 in poi, secondo l'ordine dei controlli caricati nella Collection

    Il codice l'ho scritto direttamente qui, senza testarlo, quindi potrebbe esserci qualche errore, ma il senso si dovrebbe comprendere.

    TheTruster

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    14/01/2026 - BLUES ha scritto:

    Ciao Alex, ho notato che viene ciclato SEMPRE dal primo ComboBox, se ad esempio cancello il valore dalla quarta ComboBox non si cancella anzi viene rimesso lo stesso valore di prima allora ho pensato di far partire dalla quinta ComboBox usando la stringa ListIndex (mCbo.ListIndex) ma dal Debug viene restituito sempre i valori 0 e -1 mentre ciò che vorrei sono i numeri da 1 in poi, ti sarei grato se hai qualche suggerimento.

    probabilmente sono io ma non capisco cosa intendi per  "cancello il valore dalla quarta ComboBox" e "viene rimesso lo stesso valore di prima".

    considerazioni:

    1) stai ciclando le combobox secondo un ordine stabilito dalla collection

    2) If ctl.ListCount <= 1 Then ctl.value = ctl.ItemData(0) 

         significa: se la combo ha 1 o zero elementi allora il valore deve essere il primo della lista

    la combo è una textbox associata ad una lista (una combinata appunto). se cancelli il testo della texbox non stai cancellando la lista che resta ferma al suo ultimo indice. 

    soluzione:

    la lista la popoli aggiungento il valore "" in modo che se cancelli il valore visualizzato la combo si posiziona sul valore della lista che vale "" 

    in questo caso l'indice 0 sarà associato alla voce della lista con valore ""

    qualunque sia il testo che scrivi sulla combo che non è presente nella lista non farà cambiare l'indice della lista.

    se nella combo hai le voci "pippo" e "pluto"  e selezioni pluto (indice 1) ma poi scrivi "clarabella" la lista resta sull'indice 1.

    se magari spieghi cosa vuoi ottenere e perchè devi necessariamente ciclare le combo in quell'ordine, possiamo trovare una soluzione più stabile e lineare.

    potresti al cambio del valore mettere in quell'array i valori in sequenza delle combo (il valore non l'indice) ed eventualmente mettere l'indice 0 come valore null o "".

    sicuramente sono io che non ci arrivo e vado per tentoni.

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    14/01/2026 - sihsandrea ha scritto:

    non capisco cosa intendi per  "cancello il valore dalla quarta ComboBox" e "viene rimesso lo stesso valore di prima".

    Io l'ho interpretato nei termini in cui se nella Combo4 viene eliminato (o cambiato) il valore, quelli successivi (dal 4 all'8 immagino) devono effettuare il requery sulla base dell'eliminazione/cambiamento del valore.

    E' ovvio che se vengono effettuati tutti i requery a partire dal primo e viene impostata la voce principale di ogni lista, quando viene fatto il Requery del Combo3 anche il combo "cancellato" (4) riprende un valore (evidentemente il primo della lista).

    Effettuando un requery dei soli combo successivi a quello modificato, il problema dovrebbe cessare.

    TheTruster

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    Io non ho capito l'esigenza specifica esposta nell'ultima parte...!

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    14/01/2026 - TheTruster ha scritto:

    Io l'ho interpretato nei termini in cui se nella Combo4 viene eliminato (o cambiato) il valore, quelli successivi (dal 4 all'8 immagino) devono effettuare il requery sulla base dell'eliminazione/cambiamento del valore.

    14/01/2026 - TheTruster ha scritto:

    (evidentemente il primo della lista).

    mah! un collegamento in cascata delle combo non era più intuitivo? se serve solo il primo risolve: cambia la 4 e si adegua la 5 che adegua la 6 e così via... 

    se non spiega bene cosa deve fare rischia di ritrovarsi con i problemi in... cascata. ogni soluzione comporta un errore al successivo.

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    14/01/2026 - TheTruster ha scritto:

    Devi resettare da quella selezionata in poi.

    Questo significa che potresti creare una routine di reset, a cui passare come parametro la combo che subisce la modifica.

    Private Function getRequery(actCombo As Access.ComboBox)
    
    	Dim ctl As Variant
    	Dim bRequery As Boolean
    
        For Each ctl In mCbo
        	If bRequery Then
        		ctl.Value = Null
        		ctl.Requery
        		If ctl.ListCount = 1 Then ctl = ctl.ItemData(0)
        	End If
    		If ctl.Name = actCombo.Name Then bRequery = True
        Next
        Set ctl = Nothing
    End Function

    Quindi se nell'evento AfterUpdate della cmbCascata1, ad esempio:

    getRequery cmbCascata1

    e dovrebbe effettuare il rquery dalla cmbCascata2 in poi, secondo l'ordine dei controlli caricati nella Collection

    Il codice l'ho scritto direttamente qui, senza testarlo, quindi potrebbe esserci qualche errore, ma il senso si dovrebbe comprendere.

    TheTruster

    Passando l'oggetto nella Function byref come è, il confronto potrebbe essere fatto direttamente sull'oggtto, è pignoleria lo so ma sono 2 classi... 

    If ctl Is actCombo Then bRequery = True
    ' o meglio ancora
    bRequery=ctl Is actCombo

    il codice tuttavia mi lascia qualche ombra che non riesco bene a decifrare... ma forse non ho compreso a pieno la logica io.

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    14/01/2026 - sihsandrea ha scritto:

    14/01/2026 - BLUES ha scritto:

    Ciao Alex, ho notato che viene ciclato SEMPRE dal primo ComboBox, se ad esempio cancello il valore dalla quarta ComboBox non si cancella anzi viene rimesso lo stesso valore di prima allora ho pensato di far partire dalla quinta ComboBox usando la stringa ListIndex (mCbo.ListIndex) ma dal Debug viene restituito sempre i valori 0 e -1 mentre ciò che vorrei sono i numeri da 1 in poi, ti sarei grato se hai qualche suggerimento.

    probabilmente sono io ma non capisco cosa intendi per  "cancello il valore dalla quarta ComboBox" e "viene rimesso lo stesso valore di prima".

    considerazioni:

    1) stai ciclando le combobox secondo un ordine stabilito dalla collection

    2) If ctl.ListCount <= 1 Then ctl.value = ctl.ItemData(0) 

         significa: se la combo ha 1 o zero elementi allora il valore deve essere il primo della lista

    la combo è una textbox associata ad una lista (una combinata appunto). se cancelli il testo della texbox non stai cancellando la lista che resta ferma al suo ultimo indice. 

    soluzione:

    la lista la popoli aggiungento il valore "" in modo che se cancelli il valore visualizzato la combo si posiziona sul valore della lista che vale "" 

    in questo caso l'indice 0 sarà associato alla voce della lista con valore ""

    qualunque sia il testo che scrivi sulla combo che non è presente nella lista non farà cambiare l'indice della lista.

    se nella combo hai le voci "pippo" e "pluto"  e selezioni pluto (indice 1) ma poi scrivi "clarabella" la lista resta sull'indice 1.

    se magari spieghi cosa vuoi ottenere e perchè devi necessariamente ciclare le combo in quell'ordine, possiamo trovare una soluzione più stabile e lineare.

    potresti al cambio del valore mettere in quell'array i valori in sequenza delle combo (il valore non l'indice) ed eventualmente mettere l'indice 0 come valore null o "".

    sicuramente sono io che non ci arrivo e vado per tentoni.

    Allora mi spiego meglio, sulla Form ho 8 ComboBox in gerarchia e con i tuoi codici funzionano bene se inserisco il valore nel primo ComboBox vengono inseriti automaticamente tutti gli altri, fin qui tutto ok ma se volessi cancellare il valore dalla seconda ComboBox ciò non mi fa proprio cancellare ed è perché fa il suo ciclo sempre dalla prima ComboBox e sto cercando di risolvere ciò che mi ha consigliato TheTruster che sembrerebbe ciò che fa per me ma dopo tante prove non sembra che faccia il suo lavoro come dovrebbe ma sto ancora testando...

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    Si comincia a vedere terra all'orizzonte...

    14/01/2026 - BLUES ha scritto:

    funzionano bene se inserisco il valore nel primo ComboBox vengono inseriti automaticamente tutti gli altri, fin qui tutto ok ma se volessi cancellare il valore dalla seconda ComboBox ciò non mi fa proprio cancellare ed è perché fa il suo ciclo sempre dalla prima ComboBox

    Se da codice imponi che la combo 2 che popoli in funzione dalla combo1 e ne prendi il primo valore che senso ha andarlo a cambiare?

    Un tipico esempio di combo dipendenti è:

    Combo1: regioni

    In base alla regione selezionata popoli la combo2 con le provincie di quella regione selezionata.

    La combo3 elenca i comuni di quella provincia di quella regione... 

    Cancelli la provincia ok ma cosa vuoi che mostri la combo comuni?

    Soprattutto, visto che hai selezionato Abruzzo (prendi il primo della lista da codice) e la prima provincia dell'Abruzzo, nonché il primo comune della prima provincia dell'Abruzzo (tutto suppongo in ordine alfabetico).

    Poi cancelli la prima provincia mantenendo il comune ma stai prendendo i valori da codice .

    Sorvolo sulla ratio di quello che stai facendo, sarà sicuramente giusto anche se non riesci a spiegarti, magari perché la mia mente considera la combo come un range di valori da inserire a margine di errore pari a zero.

    La combo nasce per essere usata dall'utente non dal programmatore da codice.

    Chiusa parentesi.

    Fai un controllo per uscire dal loop e azzerare i successivi.

    Se combo.text="" stop, fermati.

    Setti una variabile "spia" dove la inizializzi prima del ciclo a false e la setti a true se devi fermare il ciclo.

    Quindi:

    A inizio funzione 

    Spia=false

    Prima di attribuire il valore verifica che combo.text<>"" 

    Se combo.testo='' allora spia=true

    Poi alla fine che assega l'item aggiungi 

    And not (spia)

     esegue finché spia=false se spia=true

     i successivi cicli vengono saltati

  • Re: Forzare in ordine numerico delle caselle combinate tramite VBA

    Rieccomi, dopo tante prove con DEBUG alla fine sono riuscito a individuare gli errori anche per una mia piccola svista e soprattutto perché non mi facevano cancellare i valori semplicemente avendo rinominato in VBA un DOPPIONE (appunto una mia svista) nella lista .Add di With mCCombo e ciò mi ha reso una vita dura.

    Comunque grazie ad Alex e anche TheTruster ho trovato ciò che cercavo e funziona tutto perfettamente.

    Private Function getRequery(actCombo As Access.ComboBox)
    Dim mCbo As Access.ComboBox
    Dim bRequery As Boolean
    
        For Each mCbo In mCCombo
               
               If bRequery Then
                    mCbo.Value = Null
                    mCbo.Requery
                    If mCbo.ListCount <= 1 Then mCbo = mCbo.ItemData(0)
                Else
                    If mCbo.Name = actCombo.Name Then bRequery = True
                End If
        'Next I
        
        Next
        Set mCbo = Nothing
        
    End Function

    Antonio

Devi accedere o registrarti per scrivere nel forum
32 risposte