Discussione:
Option Button: pulsanti di opzione in moduli.SOLUZIONE!
(troppo vecchio per rispondere)
RE.MOTO
2021-02-09 07:46:51 UTC
Permalink
Norman Joans facendo riferimento a questo tuo contributo in questo link https://groups.google.com/g/microsoft.public.it.office.excel/c/F2AeqHhdwuA/m/MUK3IjDGyaMJ ho provato a ragionarci subito ed in poche righe rintracciate ho compreso chiaramente che il tuo contribuito del 2007 sollecitato da Solaris faceva (e fa!) al caso mio. Già Paganini non si ripete ma .... sarebbe possibile avere un tuo nuovo contributo su uno stesso tema suonato con diverse corde?
te ne sarei davvero grato:

1) E' possibile, sempre in modo dinamico, chiedere a VBA, una volte che ha creato degli oggetti, (in questo caso 3 pulsanti di opzione ed una casella di gruppo), di creare un raggruppamento degli stessi creati dinamicamente all'interno della routine?

2) E' possibile modificare la routine facendo si che se viene ri-eseguita non venga eseguita sulle righe dove ha già svolto la sua funzione?

Questa è la routine che ho modificato partendo dalla sua postata nel link:
Public Sub Test_Control_OptBtn()
'
Dim WB As Workbook
Dim SH As Worksheet
Dim Rng As Range
Dim rCell As Range
Dim arrCaption As Variant
'
Set WB = Workbooks("HPP.xlsm") '<<======= da CAMBIARE
Set SH = WB.Sheets("INSERIMENTO") '<<===== da CAMBIARE
Set Rng = SH.Range("C2:C25") '<<========= da CAMBIARE
'
Application.ScreenUpdating = False
'
For Each rCell In Rng.Cells
If rCell <> "" Then
'
'CASELLA DI GRUPPO
With ActiveSheet.GroupBoxes.Add(rCell.Left + 10, rCell.Top + 7, 460, 57)
.Caption = "Prestazione n° " & rCell.Row - 1
End With
'
'PIANIFICAZIONE
With ActiveSheet.OptionButtons.Add(rCell.Left + 300, rCell.Top + 30, 14, 9)
.Caption = "P" & rCell.Row - 1
.LinkedCell = "$G$" & rCell.Row
End With
'
'PRENOTAZIONE
With ActiveSheet.OptionButtons.Add(rCell.Left + 360, rCell.Top + 30, 14, 9)
.Caption = "!"
.LinkedCell = "$G$" & rCell.Row
End With
'
'ESECUZIONE
With ActiveSheet.OptionButtons.Add(rCell.Left + 420, rCell.Top + 30, 14, 9)
.Caption = "E"
.LinkedCell = "$G$" & rCell.Row
End With
End If
'
rCell.Font.Color = vbBlack
'
Next rCell
Application.ScreenUpdating = True
'
End Sub

Grazie

.G.R.
Norman Jones
2021-02-09 13:19:24 UTC
Permalink
Post by RE.MOTO
Norman Joans facendo riferimento a questo tuo contributo in questo link https://groups.google.com/g/microsoft.public.it.office.excel/c/F2AeqHhdwuA/m/MUK3IjDGyaMJ ho provato a ragionarci subito ed in poche righe rintracciate ho compreso chiaramente che il tuo contribuito del 2007 sollecitato da Solaris faceva (e fa!) al caso mio. Già Paganini non si ripete ma .... sarebbe possibile avere un tuo nuovo contributo su uno stesso tema suonato con diverse corde?
Ciao G.R.,
Post by RE.MOTO
1) E' possibile, sempre in modo dinamico, chiedere a VBA, una volte che ha creato degli oggetti, (in questo caso 3 pulsanti di opzione ed una casella di gruppo), di creare un raggruppamento degli stessi creati dinamicamente all'interno della routine?
Non ho capito questa richiesta: ogni set di tre pulsanti di opzione è già raggruppato nella propria casella di gruppo
Post by RE.MOTO
2) E' possibile modificare la routine facendo si che se viene ri-eseguita non venga eseguita sulle righe dove ha già svolto la sua funzione?
Nel codice, sostituisci l'istruzione
Post by RE.MOTO
Application.ScreenUpdating = False
con:
Application.ScreenUpdating = False
With SH
.OptionButtons.Delete
.GroupBoxes.Delete
End With


===
Regards,
Norman
RE.MOTO
2021-02-10 08:37:28 UTC
Permalink
Post by Norman Jones
Post by RE.MOTO
Norman Joans facendo riferimento a questo tuo contributo in questo link https://groups.google.com/g/microsoft.public.it.office.excel/c/F2AeqHhdwuA/m/MUK3IjDGyaMJ ho provato a ragionarci subito ed in poche righe rintracciate ho compreso chiaramente che il tuo contribuito del 2007 sollecitato da Solaris faceva (e fa!) al caso mio. Già Paganini non si ripete ma .... sarebbe possibile avere un tuo nuovo contributo su uno stesso tema suonato con diverse corde?
Ciao G.R.,
Post by RE.MOTO
1) E' possibile, sempre in modo dinamico, chiedere a VBA, una volte che ha creato degli oggetti, (in questo caso 3 pulsanti di opzione ed una casella di gruppo), di creare un raggruppamento degli stessi creati dinamicamente all'interno della routine?
Non ho capito questa richiesta: ogni set di tre pulsanti di opzione è già raggruppato nella propria casella di gruppo
Si effettivamente è come tu dici, lo so però volevo avere un unico oggetto e soprattutto imparare a farlo. Questo mi consentirebbe una migliore operatività interna nella gestione e nel funzionamento della macro. Per questo motivo volevo capire come fare.
Post by Norman Jones
Post by RE.MOTO
2) E' possibile modificare la routine facendo si che se viene ri-eseguita non venga eseguita sulle righe dove ha già svolto la sua funzione?
Nel codice, sostituisci l'istruzione
Post by RE.MOTO
Application.ScreenUpdating = False
Application.ScreenUpdating = False
With SH
.OptionButtons.Delete
.GroupBoxes.Delete
End With
La soluzione proposta con il punto 2 è molto efficace. Se ti è possibile Norman volevo comprenderne il funzionamento oltre quello che mi pare di comprendere e cioè: questa porzione di codice non ne salta l'esecuzione di quello che lo comprende lì dove sono già presenti i controlli creati in una precedente esecuzione. Semplicemente, visto che la routine che ho modificato è impostata in un certo modo, la cosa più semplice è aggiungere un codice che elimina quanto creato in una precedente esecuzione e riscriverlo. All'operatore non sembrerà nulla. In effetti è un ottimo escamotage.

Ma anche se la mia lettura è corretta esiste comunque un modo per far fare uno o più giri a vuoto alla routine per le celle nelle quali è stata già eseguita? Anche perché in questo modo verranno generati una quantità enorme di oggetti anche se cancellati ed a tal proposito sai quali sono i limiti di Excel?
Post by Norman Jones
===
Regards,
Norman
Grazie Norman Jones
Norman Jones
2021-02-10 11:13:48 UTC
Permalink
Post by Norman Jones
Post by RE.MOTO
Norman Joans facendo riferimento a questo tuo contributo in questo link https://groups.google.com/g/microsoft.public.it.office.excel/c/F2AeqHhdwuA/m/MUK3IjDGyaMJ ho provato a ragionarci subito ed in poche righe rintracciate ho compreso chiaramente che il tuo contribuito del 2007 sollecitato da Solaris faceva (e fa!) al caso mio. Già Paganini non si ripete ma .... sarebbe possibile avere un tuo nuovo contributo su uno stesso tema suonato con diverse corde?
Ciao G.R.,
Post by RE.MOTO
1) E' possibile, sempre in modo dinamico, chiedere a VBA, una volte che ha creato degli oggetti, (in questo caso 3 pulsanti di opzione ed una casella di gruppo), di creare un raggruppamento degli stessi creati dinamicamente all'interno della routine?
Non ho capito questa richiesta: ogni set di tre pulsanti di opzione è già raggruppato nella propria casella di gruppo
Si effettivamente è come tu dici, lo so però volevo avere un unico oggetto e soprattutto imparare a farlo. Questo mi consentirebbe una migliore operatività interna nella gestione e nel funzionamento della macro. Per questo motivo volevo capire come fare.
Post by Norman Jones
Post by RE.MOTO
2) E' possibile modificare la routine facendo si che se viene ri-eseguita non venga eseguita sulle righe dove ha già svolto la sua funzione?
Nel codice, sostituisci l'istruzione
Post by RE.MOTO
Application.ScreenUpdating = False
Application.ScreenUpdating = False
With SH
.OptionButtons.Delete
.GroupBoxes.Delete
End With
La soluzione proposta con il punto 2 è molto efficace. Se ti è possibile Norman volevo comprenderne il funzionamento oltre quello che mi pare di comprendere e cioè: questa porzione di codice non ne salta l'esecuzione di quello che lo comprende lì dove sono già presenti i controlli creati in una precedente esecuzione. Semplicemente, visto che la routine che ho modificato è impostata in un certo modo, la cosa più semplice è aggiungere un codice che elimina quanto creato in una precedente esecuzione e riscriverlo. All'operatore non sembrerà nulla. In effetti è un ottimo escamotage.
Ma anche se la mia lettura è corretta esiste comunque un modo per far fare uno o più giri a vuoto alla routine per le celle nelle quali è stata già eseguita? Anche perché in questo modo verranno generati una quantità enorme di oggetti anche se cancellati ed a tal proposito sai quali sono i limiti di Excel?
Post by Norman Jones
===
Regards,
Norman
Grazie Norman Jones
Ciao G. R,

Penso che il codice per controllare ed escludere azioni precedenti sarebbe complesso e, soprattutto, non molto robusto.

Comunque, per rassicurarti sulla capacità di Excel di creare ed eliminare un gran numero di pulsanti di opzione e caselle di gruppo, ho eseguito il codice seguente:
'========>>
Public Sub TryIt()
Dim i As Long
For i = 1 To 1000
Debug.Print i
DoEvents
Call Test_Control_OptBtn
DoEvents
Next i
MsgBox "finito"
End Sub
'<<========

Questo codice ha creato e distrutto più di 75000 oggetti senza effetti negativi e con un minimo cambiamento nella dimensione del file.


===
Regards,
Norman
RE.MOTO
2021-02-10 12:16:33 UTC
Permalink
Ciao Norman Jones, grazie per la risposta.

Beh direi ottimo il risultato no e mi sento più tranquillo! Per quanto riguarda invece la realizzazione dinamica del raggruppamento degli oggetti la trovi davvero così inutile?
Norman Jones
2021-02-10 13:02:19 UTC
Permalink
Post by RE.MOTO
Ciao Norman Jones, grazie per la risposta.
Ciao G.R,
Post by RE.MOTO
Beh direi ottimo il risultato no e mi sento più tranquillo!
Bene!
Post by RE.MOTO
Per quanto riguarda invece la realizzazione dinamica del raggruppamento degli oggetti la trovi davvero così inutile?
Purtroppo, non ho capito questo requisito (:-


===
Regards,
Norman
RE.MOTO
2021-02-11 15:33:36 UTC
Permalink
Ciao Norman,
cerco di spiegarmi con un esempio creando una macro con il registratore di macro.
Sub Macro1()
ActiveSheet.OptionButtons.Add(519, 92, 58, 20).Select
ActiveSheet.OptionButtons.Add(638, 92, 60, 17).Select
ActiveSheet.GroupBoxes.Add(498, 81, 239, 60).Select
ActiveSheet.Shapes.Range(Array("Group Box 24", "Option Button 22", "Option Button 23")).Select
Selection.ShapeRange.Group.Select
Range("L14").Select
End Sub

Il registratore mi ha creato tre oggetti (2 pulsanti di opzione e 1 casella di gruppo) e poi con:
ActiveSheet.Shapes.Range(Array("Group Box 24", "Option Button 22", "Option Button 23")).Select
Selection.ShapeRange.Group.Select
crea un 4° oggetto che li contiene tutti e tre e cioè un Group 25. Bene io vorrei capire come può essere scritta questa istruzione su una macro non registrata che crea dinamicamente i miei tre oggetti (non so se ricordi, erano tre pulsanti di opzione ed una casella di gruppo). O meglio se dovessi usare la stessa sintassi riprodotta qui dovrei conoscere la numerazione degli oggetti creati di volta in volta, tipo il Me.controlls che si usa nelle useform. Leggendo un po' di documentazione sul web dovrei usare il metodo " .parent " ma non ho capito come si usa e la sua sintassi.
Credi che sia possibile?
RE.MOTO
2021-02-11 15:35:47 UTC
Permalink
Post by Norman Jones
Post by RE.MOTO
Ciao Norman Jones, grazie per la risposta.
Ciao G.R,
Post by RE.MOTO
Beh direi ottimo il risultato no e mi sento più tranquillo!
Bene!
Post by RE.MOTO
Per quanto riguarda invece la realizzazione dinamica del raggruppamento degli oggetti la trovi davvero così inutile?
Purtroppo, non ho capito questo requisito (:-
Ciao Norman,
cerco di spiegarmi con un esempio creando una macro con il registratore di macro.

Sub Macro1()
ActiveSheet.OptionButtons.Add(519, 92, 58, 20).Select
ActiveSheet.OptionButtons.Add(638, 92, 60, 17).Select
ActiveSheet.GroupBoxes.Add(498, 81, 239, 60).Select
ActiveSheet.Shapes.Range(Array("Group Box 24", "Option Button 22", "Option Button 23")).Select
Selection.ShapeRange.Group.Select
Range("L14").Select
End Sub

Il registratore mi ha creato tre oggetti (2 pulsanti di opzione e 1 casella di gruppo) e poi con:
ActiveSheet.Shapes.Range(Array("Group Box 24", "Option Button 22", "Option Button 23")).Select
Selection.ShapeRange.Group.Select
crea un 4° oggetto che li contiene tutti e tre e cioè un Group 25. Bene io vorrei capire come può essere scritta questa istruzione su una macro non registrata che crea dinamicamente i miei tre oggetti (non so se ricordi, erano tre pulsanti di opzione ed una casella di gruppo). O meglio se dovessi usare la stessa sintassi riprodotta qui dovrei conoscere la numerazione degli oggetti creati di volta in volta, tipo il Me.controlls che si usa nelle useform. Leggendo un po' di documentazione sul web dovrei usare il metodo " .parent " ma non ho capito come si usa e la sua sintassi.
Credi che sia possibile?

Grazie per la tua attenzione Norman Jones

.G.R.
Norman Jones
2021-02-11 17:40:08 UTC
Permalink
Post by RE.MOTO
Post by Norman Jones
Post by RE.MOTO
Ciao Norman Jones, grazie per la risposta.
Ciao G.R,
Post by RE.MOTO
Beh direi ottimo il risultato no e mi sento più tranquillo!
Bene!
Post by RE.MOTO
Per quanto riguarda invece la realizzazione dinamica del raggruppamento degli oggetti la trovi davvero così inutile?
Purtroppo, non ho capito questo requisito (:-
Ciao Norman,
cerco di spiegarmi con un esempio creando una macro con il registratore di macro.
Sub Macro1()
ActiveSheet.OptionButtons.Add(519, 92, 58, 20).Select
ActiveSheet.OptionButtons.Add(638, 92, 60, 17).Select
ActiveSheet.GroupBoxes.Add(498, 81, 239, 60).Select
ActiveSheet.Shapes.Range(Array("Group Box 24", "Option Button 22", "Option Button 23")).Select
Selection.ShapeRange.Group.Select
Range("L14").Select
End Sub
ActiveSheet.Shapes.Range(Array("Group Box 24", "Option Button 22", "Option Button 23")).Select
Selection.ShapeRange.Group.Select
crea un 4° oggetto che li contiene tutti e tre e cioè un Group 25. Bene io vorrei capire come può essere scritta questa istruzione su una macro non registrata che crea dinamicamente i miei tre oggetti (non so se ricordi, erano tre pulsanti di opzione ed una casella di gruppo). O meglio se dovessi usare la stessa sintassi riprodotta qui dovrei conoscere la numerazione degli oggetti creati di volta in volta, tipo il Me.controlls che si usa nelle useform. Leggendo un po' di documentazione sul web dovrei usare il metodo " .parent " ma non ho capito come si usa e la sua sintassi.
Credi che sia possibile?
Grazie per la tua attenzione Norman Jones
.G.R.
Ciao G. R.

Non sono ancora sicuro di cosa stai cercando di ottenere o del perché.

Detto questo, forse i seguenti punti e il codice allegato aiuteranno a chiarire le cose.

Un GroupBox dal menu dei moduli non contiene altri controlli. Potrebbero esserci altri controlli entro i suoi confini, ma non "in" esso. Se sposti la casella di gruppo, i pulsanti di opzione rimarranno posizionati. L'oggetto "genitore" di un GroupBox o di un pulsante di opzione è sempre il foglio pertinente.

Se vuoi controllare se un OptionButton si trova entro i confini di uno specifico GroupBox, è necessario testare la posizione di ogni controllo per vedere se si trova all'interno della Group Box.

Ho modificato la procedura Test_Control_OptBtn per denominare i GroupBox in sequenza 1,2,3..n e denominare gli OptionButtons 1,2,3..n. Di conseguenza, il primo GroupBox si chiamerà GroupBox 1 e gli OptionButton correlati si chiameranno OptionButton 1, OptionButton 2 e OptionButton 3; il secondo GroupBox si chiamerà GroupBox 2 e gli OptionButton correlati si chiameranno OptionButton 4, OptionButton 5 e OptionButton 6.

'========>>
Option Explicit

'-------->>
Public Sub Test_Control_OptBtn()
Dim WB As Workbook
Dim SH As Worksheet
Dim Rng As Range
Dim rCell As Range
Dim oGroupBox As GroupBox
Dim oOptionButton As OptionButton
Dim arrCaption As Variant
Dim ictr As Long, jCtr As Long
'
Set WB = ActiveWorkbook
Set SH = WB.Sheets("INSERIMENTO")
Set Rng = SH.Range("C2:C25")
'
Application.ScreenUpdating = False
With SH
.OptionButtons.Delete
.GroupBoxes.Delete
End With
For Each rCell In Rng.Cells
If rCell.Value <> "" Then
'
'CASELLA DI GRUPPO
Set oGroupBox = SH.GroupBoxes.Add(rCell.Left + 10, rCell.Top + 7, 460, rCell.EntireRow.Height - 10)
ictr = ictr + 1
With oGroupBox
.Caption = "Prestazione n° " & rCell.Row - 1
.Name = "GroupBox " & ictr
End With
'
'PIANIFICAZIONE
Set oOptionButton = SH.OptionButtons.Add(rCell.Left + 300, rCell.Top + 10, 14, 9)
jCtr = jCtr + 1
With oOptionButton
.Caption = "P" & rCell.Row - 1
.LinkedCell = "$G$" & rCell.Row
.Name = "OptionButton " & jCtr
End With
'
'PRENOTAZIONE
Set oOptionButton = SH.OptionButtons.Add(rCell.Left + 360, rCell.Top + 10, 14, 9)
jCtr = jCtr + 1
With oOptionButton
.Caption = "!"
.LinkedCell = "$G$" & rCell.Row
.Name = "OptionButton " & jCtr
End With
'
'ESECUZIONE
Set oOptionButton = SH.OptionButtons.Add(rCell.Left + 420, rCell.Top + 10, 14, 9)
jCtr = jCtr + 1
With oOptionButton
.Caption = "E"
.LinkedCell = "$G$" & rCell.Row
.Name = "OptionButton " & jCtr
End With
End If
'
rCell.Font.Color = vbBlack
'
Next rCell
Application.ScreenUpdating = True '
End Sub
'<<========

Per dimostrare come si potrebbe restituire i pulsanti di opzione che si riferiscono ad un dato GroupBox, prova qualcosa del genere:
'========>>
Option Explicit

'-------->>
Public Sub Demo()
Dim oOptionButton As OptionButton
Dim oGroupBox As GroupBox
Dim arrOptionButtons(1 To 3) As Variant
Dim sStr As String
Dim ictr As Long

Set oGroupBox = ActiveSheet.GroupBoxes("GroupBox 1")
For Each oOptionButton In ActiveSheet.OptionButtons
If oOptionButton.Name <> oGroupBox.Name Then
With oOptionButton
If oGroupBox.Top < .Top And .Top < oGroupBox.Top + oGroupBox.Height Then
If oGroupBox.Left < .Left And .Left < oGroupBox.Left + oGroupBox.Width Then
ictr = ictr + 1
arrOptionButtons(ictr) = oOptionButton.Name
End If
End If
End With
End If
If ictr = 3 Then Exit For
Next oOptionButton

If CBool(ictr) Then
sStr = Join(arrOptionButtons, vbNewLine)
Call MsgBox(Prompt:="Il GroupBox " & oGroupBox.Name _
& " circonda i seguenti OptionButton: " & vbNewLine & sStr, _
Buttons:=vbInformation, _
Title:="REPORT")
End If
End Sub
'<<========

Potresti scaricare il mio file di prova Moto20210211.xlsm:
https://1drv.ms/x/s!AmTW9HzZG8cqjWXVmQzq6MtayI3P?e=SmzMDH


===
Regards,
Norman

Loading...