Mi permetto di suggerire un approccio simile a quanto fatto da Alfredo, ma probabilmente piu' semplice da adattare.
La scelta e' sempre fatta tramite ListBox, ma il tipo di listbox e gli elenchi di valori sono impostati direttamente dall'utente in Foglio2.
In dettaglio:
Creare in Foglio2 l'elenco delle voci di convalida colonna per colonna (si puo' usare un altro foglio, modificando una voce nel codice successivo):
-in riga 1 copia le intestazioni di Foglio1, come promemoria
-in riga 2 lasci vuoto se "nessuna convalida", metti 1 se convalida a 1 voce, metti 2 se convalida a piu' voci
-da riga 3 in avanti scrivi le voci di convalida ammesse per quella colonna
Poi vai in Foglio1
-cancellare tutte le Convalide (seleziona l'intervallo, avvia la Convalida, conferma che vanno cancellate tutte le convalide presenti, lascia Consenti Qualsiasi valore e premi Ok)
-disegnare una Casella di riepilogo: tab Sviluppo, Inserisci, scegli Casella di riepilogo tra i controlli ActiveX; vai sul foglio e traccia la casella. Assicurati che si chiami ListBox1 (con la casella selezionata, si vede il nome nella "Casella Nome", in genere visibile accanto alla barra della formula). Dimensione e posizione non sono importanti. Lascia invariate tutte le proprieta'.
Tornare su Foglio1, tasto dx sul tab col nome del foglio; scegli Visualizza codice per aprire l'editor delle macro nella posizione corretta; copiare il seguente codice e incollarlo nel frame vuoto di dx:
- Codice: Seleziona tutto
Dim tRange As Range 'DEVE Trovarsi in testa alle istruzioni
Private Sub ListBox1_Change()
Dim I As Integer, myTVal As String
'
If Not tRange Is Nothing And ListBox1.ListCount > 0 Then
Application.EnableEvents = False
For I = 0 To ListBox1.ListCount - 1
If ListBox1.Selected(I) = True Then
myTVal = myTVal & "; " & ListBox1.List(I)
End If
Next I
tRange.Value = Mid(myTVal, 3)
tRange.Select
Application.EnableEvents = True
End If
End Sub
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
Dim myArea As Range, tRow As Integer, tCol As Integer
Dim shList As String, myList(), sList As Range
'Debug.Print "Target= " & Target.Address(0, 0)
'
Set myArea = Range("A3:P20") '<<< L'intervallo su cui deve comparire la lista di scelta
shList = "Foglio2" '<<< Il nome foglio su cui sono state definite le liste
'
If Application.Intersect(Target, myArea) Is Nothing Then
ListBox1.Visible = False
Set tRange = Nothing
Exit Sub
End If
If Target.Count = 1 Then
tRow = Target.Row
tCol = Target.Column
If Sheets(shList).Cells(2, tCol) <> "" Then
Set tRange = Target
ListBox1.Width = Target.Width * 2
ListBox1.Height = Target.Height * 5
If ListBox1.Height > 100 Then ListBox1.Height = 100
ListBox1.ListFillRange = ""
If Sheets(shList).Cells(2, tCol) = 1 Then
ListBox1.MultiSelect = fmMultiSelectSingle
Else
ListBox1.MultiSelect = fmMultiSelectMulti
End If
DoEvents
'On Error Resume Next
ListBox1.ListFillRange = shList & "!" & Range(Cells(3, tCol), Cells(Sheets(shList).Cells(Rows.Count, tCol).End(xlUp).Row, tCol)).Address
'On Error GoTo 0
ListBox1.Top = Target.Top
ListBox1.Left = Target.Offset(0, 1).Left
ListBox1.ListStyle = fmListStyleOption
ListBox1.Visible = True
Else
Set tRange = Nothing
ListBox1.ListFillRange = ""
ListBox1.Visible = False
End If
Else
Set tRange = Nothing
ListBox1.ListFillRange = ""
End If
End Sub
Le due righe marcate <<< vanno personalizzate come da commento.
A questo punto torna su Foglio1 e prova a selezionare un po' di celle e vedi l'effetto che fa.
Deve essere chiaro pero' che in questo modo il meccanismo funziona come "aiuto" alla compilazione del foglio, non da controllore; cioe' l'utente puo' scegliere una voce dal listbox (o piu' voci per le colonne che lo prevedono), ma al contempo e' libero scrivere altre cose.
Se questo e' un problema reale allora faremo una modifica al codice per consentire solo la scelta da listbox.
Il tutto e' dimostrato nel file scaricabile qui:
https://www.dropbox.com/s/d2aec8k6ydhqc ... .xlsm?dl=0Ciao a tutti