Il blog di Gianni Giaccaglini

Blog su VBA e VSTO
Gianni Giaccaglini

My Links

News

NB - V. anche gli ARTICOLI (in fondo a questa barra)
Solo quesiti validi a: giannigiac@tin.it
Il mio Best seller su VBA
(v. www.hoepli.it)


Il mio ultimo libro su Open XML
(v. www.FAG.it):



La mia nipotina ELISA

Foto con dedica a ME di
Bill Gates giovanissimo
nei mitici anni 80!

Categorie Post

Categorie Articoli

Archivio

Immagini

Blog Stats

Caselle di testo dinamiche inserite in un UserForm

Caselle di testo dinamiche inserite in un UserForm

Recentemente mi è stata posta questa domanda: “Si può inserire in una UserForm un numero variabile, fissato a run-time (magari tramite opportuna macro VBA) di caselle di testo?” La richiesta è inusuale, visto che il più delle volte una UserForm viene definita al tempo di progetto. Con un po’ di pazienza, frugando nella Guida dell’Editor VBA, ho trovato la risposta, di cui riporto un tipico esempio in fondo a questo post. Adattandolo al caso che tormentava il nostro amico ho escogitato una prima macro di test, sull’evento Click dell’unico pulsante di una UserForm1, per il resto vuota di altri controlli:

Private Sub CommandButton1_Click()

    Dim miaTxtBox As Control

    Set miaTxtBox = Controls.Add("Forms.TextBox.1", "miaCasella", True)

    With miaTxtBox

      .Left = 18

      .Top = 150

      .Width = 175

      .Height = 20

    End With

    Me.Controls("miaCasella").Value = InputBox("Scrivi...")

End Sub

 

L’istruzione basilare, grassettata, ha la seguente sintassi:

Controls.Add(“<Tipo ctrontrollo>”, “Nome”,

E ha l’effetto di aggiungere (metodo Add) all’insieme dei Controls una TextBox definita come “Forms.Textbox.1” – mentre analoghe sintassi valgono per altri controlli come il "MSForms.CommandButton.1” esemplificato dalla Guida e altri di pari eloquenza. Il terzo argomento va prudentemente posto a True assicurando la visibilità della neonata casella impostata nella MiaTxtBoz (di tipo Control, ovviamente). Dopo di che a MiaTxtBox sono assegnati, dinamicamente, proprietà relative al posizionamento e alle dimensioni e, infine, vi viene inserito il valore stabilito dall’utente in risposta a una InputBox.

Come i più svegli subito notano nell’ultima istruzione si ricorre, in alternativa a miaTextBox, al nome “miaCasella”, secondo nome facoltativo di Controls.Add.

Se poi si vuole lanciare la UserForm1 non resta che lanciare una macro bene nota come questa:

Sub UserFormDinamica()

   Load UserForm1

   UserForm1.Show

End Sub

 

Una variante appena un po’ più elaborata è la seguente, che crea ben due (“e regali..”, dicono a Livorno) casellineficcandovi due scemenze:

Dim CaselleAggiunte As Boolean

Private Sub CommandButton1_Click()

  If Not CaselleAggiunte Then

    Me.Controls.Add "Forms.TextBox.1", "Casella1", True

    Me.Controls.Add "Forms.TextBox.1", "Casella2", True

    With Me.Controls("Casella2")

      .Left = 50

      .Top = 50

    End With

    CaselleAggiunte = True

  End If

  Me.Controls("Casella1") = "ambarabà"

  Me.Controls("Casella2") = "Ciccì coccò"

End Sub

 

Il punto più rilevante è dato dalle istruzioni “creative” la cui sintassi è nata dalla scoperta che non occorre nessuna variabile per registrare il nuovo controllo, basta invocare il medoto Add  dell’insieme Controls dell’UserForm  corrente, ovvero Me.Controls.

Creazione dinamica di N casella all’apertura dell’UserForm

Dopo i precedenti esperimenti, torniamo all’esigenza iniziale ovvero, ricordate?, aggiungere un numero di TexBox definite di volta in volta. In tale prospettiva, si compiano le mosse seguenti:

1.       Creare un UserForm2

2.       Aggiungervi come prima un solo CommandButton1, magari dotato di Caption “Caselle dinamiche” in luogo del default “UserForm2”;

3.       Digitare la macro dell’evento Initialize:

Private Sub UserForm_Initialize()

  Dim i As Integer, N As Integer

  Dim NomeCasella As String

  Dim Cima As Integer

  N = Range("NumCaselle")

  Cima = 10

  Me.Height = N * 25 + 75

  CommandButton1.Top = Me.Height - 50

  ' If N > 10 Then N = 10 ' Limitazione num. caselle? Non serve col combo...

    For i = 1 To N

      NomeCasella = "Casella" & i

      Me.Controls.Add "Forms.TextBox.1", NomeCasella, True

      With Me.Controls(NomeCasella)

        .Left = 50

        .Height = 20

        .Width = 150

        .Top = Cima

      End With

      Cima = Cima + 25

    Next

End Sub

 

Commenti tacitiani. Il valore N è attinto da una cella del foglio di lavoro preliminarmente battezzata “NumCaselle”, ove l’utente dovrà stabilire appunto il desiato numero caselle. Il clou sta nel ciclo For i = 1 To N in seno al quale vengono via via fissato un NomeCasella pari a “ Casella” & i vale a dire “Casella1”, “Casella2” e così via. Il dimensionamento Me.Heigth dell’altezza del Form in modo da adeguarsi alle N caselle (ciascuna di altezza, Height, pari a 20) + 5 spazi tra le stesse è lasciato all’esegesi autogestita. Idem il posizionamento del Top del CommandButton1, sottostante alla N caselline ma senza sparire.

E la Sub dell’evento Click di quest’ultimo? Eccone una ipotetica, che segnala (MsgBox) i nomi delle N caselle create inserendovi man mano numeri casuali. Tanto per fare qualcosa, nei casi personali ognuno personalizzerà questa faccenda.

Private Sub CommandButton1_Click()

  Dim Ctrl As Control

  For Each Ctrl In Me.Controls

    If Left(Ctrl.Name, 7) <> "Command" Then

      Randomize

      Ctrl = Int(Rnd * 100000 + 100)

      MsgBox Ctrl.Name

    End If

  Next

End Sub

 

Concludo suggerendo, in luogo del controllo del numero massimo N = 10, un combo box sul foglio di lavoro associato alla predetta cella di nome”NumCaselle”.

Ultimissima variante

Consiste nell’omissione del secondo argomento di Controls.Add, nel qual caso la caselle di testo via via create assumono i nomi default o standard che dir si voglia “TextBox1 ,” TextBox2”, eccetera.

Private Sub UserForm_Initialize()

  Dim i As Integer, N As Integer

  Dim Cima As Integer

  N = Range("NumCaselle")

  Cima = 10

  Me.Height = N * 25 + 75

  CommandButton1.Top = Me.Height - 60

    For i = 1 To N

      Me.Controls.Add "Forms.TextBox.1", , True

      With Me.Controls(i)

        .Left = 50

        .Height = 20

        .Width = 150

        .Top = Cima

      End With

      Cima = Cima + 25

    Next

End Sub

 

L’esempio della Guida

Esempio dell'evento AddControl e del metodo Add

In questo esempio il metodo Add viene utilizzato per aggiungere un controllo a un form in fase di esecuzione. L'evento AddControl viene utilizzato per verificare se il controllo è stato aggiunto.

Per eseguire l'esempio, copiare il codice riportato di seguito nella sezione Dichiarazioni di un form. Verificare che il form contenga:

·         Un controllo CommandButton (CommandButton1).

·         Un controllo Label (Label1).

Dim Mycmd as Control

Private Sub CommandButton1_Click()

 

    Set Mycmd = Controls.Add("Forms.CommandButton.1") ', CommandButton2, Visible)

    Mycmd.Left = 18

    Mycmd.Top = 150

    Mycmd.Width = 175

    Mycmd.Height = 20

    Mycmd.Caption = "This is fun." & Mycmd.Name 

End Sub

 

Private Sub UserForm_AddControl(ByVal Control As _

    MSForms.Control)

    Label1.Caption = "Control was Added."

End Sub

 

Nota. Qui osservo, solamente, che a) definire a livello Dichiarazione la variabile Mycmd (o la mia Casella nel caso di una TextBox) non è indispensabile, come ho mostrato nei miei esempietti; b)  il secondo pulsante di comando Mycmd creato di fatto non serve quasi a nulla, non potendo associarvi routine d’evento (possibilità speciale ammessa in VB .NET). Lo stesso vale per le nostre caselle di cui però si può modificare il valore.

?>

posted on mercoledì 18 maggio 2011 16.37