Disabilitare una voce di menù

Ultima modifica: 27-05-2016

 

A volte possiamo desiderare di proteggere da manovre devastanti o comunque errate i dati inseriti con tanta fatica in un foglio di Excel.

Possiamo adottare alcune delle protezioni tra cui c'è quello che ci offre lo stesso Excel: Strumenti / Protezione / Proteggi foglio..., proteggere le celle. Oppure potremo nascondere alcune o tutte le barre degli strumenti e/o dei menù, oppure crearne di nuove costruite ad hoc (cosa che sento di consigliare di evitare in quanto potrebbe sconvolgere ambienti di lavoro che taluni utenti si sono costruiti con tanta fatica).

Per questi ed altri motivi questa volta ho deciso di mostrarvi come proteggere un foglio di lavoro semplicemente inibendo alcuni comandi indesiderati dalla barra dei menù o dalle barre degli strumenti.

Sia ben chiaro, comunque, che, per quanto ci riguarda, questo lavoro supplementare non mira ad ottenere una protezione inespugnabile al nostro lavoro. Chiunque, con un minimo di conoscenza di programmazione, può eludere le nostre protezioni e distruggere comunque tutto il nostro lavoro. Questo ed altri tipi di protezione, almeno quelli da me presentati, sono rivolti ad utenti corretti e servono solo a facilitargli il lavoro ed evitare di compiere accidentalmente delle manovre errate.

Prima di cimentarci in questa operazione dobbiamo vedere come viene visto un menù dal VBA.

Negli esempi che seguono cerchiamo di torturare le voci: Strumenti / Protezione / Proteggi foglio...

Questo è un esempio di menù che ci viene mostrato da Excel.

Come vedete, per arrivare alla voce che ci interessa, dobbiamo seguire la strada: Strumenti / Protezione / Proteggi foglio...

Anche il VBA, per arrivare a delle voci di menù più interne deve percorrere la stessa strada.

Grazie a questa particolare struttura possiamo decidere a quale livello possiamo disabilitare una voce di menù:

Vediamo brevemente i tre casi.

Disabilitare tutto il menù

Per disabilitare l'intera voce di menù (Strumenti) usiamo la sintassi:

Application.CommandBars("Worksheet menu bar").Controls("strumenti").Enabled = False

Disabilitare una voce del sottomenù

Per disabilitare una voce del sottomenù non è sufficiente specificare semplicemente la voce di menù da disabilitare, ma è necessario specificare l'intero percorso che occorre fare per raggiungere tale voce. Per questo se vogliamo che tutte o parte delle voci comprese nel menù Strumenti siano selezionabili eccetto una o più voci dobbiamo specificarne il percorso:

Strumenti / Protezione

Strumenti / Ricerche...

Di conseguenza l'istruzione sarà:

Application.CommandBars("Worksheet menu bar").Controls("strumenti").Controls("Protezione").Enabled = False

Oppure, in quest'altro modo:

With Application.CommandBars("Worksheet menu bar")
.Controls("strumenti").Controls("Protezione").Enabled = False
End With

Disabilitare voci sempre più basse di un menù

Penso che sia intuitivo, a questo punto, che per raggiungere la voce di menù che ci interessa ad un livello più basso dobbiamo specificarne tutto il percorso:

Strumenti / Protezione / Proteggi foglio... (compresi i punti)

per cui avremo:

Application.CommandBars("Worksheet menu bar").Controls("Strumenti").Controls("Protezione").Controls("Proteggi foglio...").Enabled = False

o, se più ci piace quest'altra versione di codice:

With Application.CommandBars("Worksheet menu bar")
.Controls("Strumenti").Controls("Protezione").Controls("Proteggi foglio...").Enabled = False
End With

Una nota

Invece dei nomi dei menù, racchiusi tra i doppi apici, possiamo riferirci ad essi usando i loro indici (Item):

Application.CommandBars("Worksheet menu bar").Controls.Item(6).Enabled = False
' oppure
Application.CommandBars("Worksheet menu bar").Controls(6).Enabled = False
' o ancora
Application.CommandBars("Worksheet menu bar").Controls.Item(6).Controls.Item(9).Controls.Item(1).Enabled = False

Per lavorare sulle altre Barre degli Strumenti

Lo stesso discorso vale per disabilitare i pulsanti di controllo presenti nelle varie Barre degli Strumenti ma qui ci troviamo di fronte ad un'altra difficoltà: reperire il nome o l'indice del controllo.

Se ci è noto il nome della Barra dei menu (Worksheet Menu Bar), non altrettanto potrebbe esserci noto il nome delle altre barre e dei relativi pulsanti. Per ovviare a questo ho messo a punto una routine che riesce a restituirmi tutti i nomi di cui ho bisogno.

In questa routine, tra le dichiarazione delle variabili che userò si distinguono le due dichiarazioni:

Dim Bar As CommandBar
Dim Ctrl As CommandBarControl

Infatti, nei due cicli approntati, con la variabile Bar intendo indicare le CommandBar e con Ctrl i controlli in esse disposti. Debbo confessare che la scelta di quest'ultima associazione è stata abbastanza sofferta in quanto durante la sperimentazione non potevo usare

Dim Ctrl As Control

oppure

Dim Ctrl As CommandBar.Control

perchè non supportati nel seguito della routine di prova.

Un'altra peculiarità del test che sto presentando è che, invece di usare delle MsgBox o scrivere su celle del foglio di Excel, scrivo le notizie nella finestra immediata dell'editor VBA (Visualizza / Finestra immediata).

Sub enumeraBarre()
Dim Bar As CommandBar
Dim Ctrl As CommandBarControl
Dim N, Nome1, Nome2, R
R = 1
For Each Bar In Application.CommandBars
If Bar.Visible = True Then ' senza questa IF verranno stampate tutte
R = R + 1
N = Bar.Controls.Count
Nome1 = Bar.Name
Cells(R, 1) = Nome1
For Each Ctrl In Bar.Controls
R = R + 1
Nome2 = Ctrl.Caption
Cells(R, 1) = Nome2
Next
R = R + 1
End If
Next
End Sub

Con questo test intendo esplorare solo le barre degli strumenti visibili al momento dell'utilizzo dell'applicativo. Se volessi passare in rassegna tutte le barre ci accorgeremmo di dover contarne ben 128 (nelle istruzioni appena presentate provate a togliere la "If Bar.Visible = True Then" e relativa "End If").

Con questo test, lavorando sul mio Excel, ottengo questo risultato:

Worksheet Menu Bar; &File, &Modifica, &Visualizza, &Inserisci, F&ormato, &Strumenti, &Dati, A&zione, Fi&nestra, &?,

Standard; &Nuovo, Apri, &Salva, Autorizzazione (Accesso illimitato), Dest&inatario posta, Stampa (Canon LBP-810), Antepri&ma di stampa, Controllo ortogra&fia..., Ricerc&he..., Tag&lia, &Copia, &Incolla, &Copia formato, &Annulla, &Ripristina, &Annotazioni a penna, Collegamento ipertest&uale..., &Somma automatica, Ordinamento &crescente, Ordinamento &decrescente, &Creazione guidata Grafico, &Disegno, &Zoom, Guida in li&nea Microsoft Excel ,

Formatting; &Tipo di carattere, &Dimensione carattere, &Grassetto, &Corsivo, &Sottolineato, Allinea a &sinistra, &Centra, Allinea a &destra, &Unisci e centra, &Valuta, Stile perce&ntuale, Stile se&paratore, &Aumenta decimali, &Diminuisci decimali, &Riduci rientro, &Aumenta rientro, B&ordi, Co&lore riempimento, Color&e carattere,

Forms; &Etichetta, &Casella di modifica, C&asella di gruppo, &Pulsante, &Casella di controllo, P&ulsante di opzione, C&asella di riepilogo, Ca&sella combinata, &Casella di riepilogo combinata, &Casella combinata a discesa, &Barra di scorrimento, &Casella di selezione, Proprietà di controllo, &Codice, Griglia, &Esegui finestra di dialogo,

Visual Basic; &Macro..., &Registra nuova macro..., Protezione..., &Visual Basic Editor, S&trumenti di controllo, &Modalità Progettazione, Microsoft Script Editor,

Control Toolbox; &Modalità Progettazione, &Proprietà, &Visualizza codice, &Casella di controllo, &Casella di testo, &Pulsante di comando, &Pulsante di opzione, &Casella di riepilogo, &Casella combinata, &Interruttore, &Pulsante di selezione, &Barra di scorrimento, Etic&hetta, I&mmagine, &Altri controlli...,

Drawing; Dise&gno, &Selezione oggetti, &Forme, Li&nea, &Freccia, Re&ttangolo, &Ovale, Cas&ella di testo, &WordArt..., Di&agramma, Cli&pArt..., &Da file..., &Disegno e scrittura a penna, Co&lore riempimento, &Colore linea, Color&e carattere, &Stile linea, &Stile tratteggio, &Stile freccia, &Ombreggiatura, &Stile 3D,

Su un altro computer o in altri contesti il risultato potrebbe essere diverso.

Un'ultima cosa da notare è che tra i nomi esposti dai vari comandi, a volte troviamo il carattere "&". Questo non è un errore ma è semplicemente una convenzione usata in VBA per impostare uno Shortcuts per tasti di scelta rapida (viene usato il carattere immediatamente a destra di questo carattere speciale) e non ha alcuna importanza indicarlo nell'istruzione che vorremmo usare nel codice.
Application.CommandBars("Formatting").Controls("Tipo di carattere").Enabled = True

Attenzione:

Quando usiamo gli indici possiamo usare sia la sintassi Controls.Item(6) sia la sintassi Controls(6).

Ma attenzione: nell'usare gli indici non sempre troviamo la voce nella locazione che immaginiamo per cui se vogliamo usare gli indici (Item) è consigliabile eseguire preventivamente dei test.

Negli esempi appena mostrati infatti volendo agire sul menù "Strumenti / Protezione / Proteggi foglio..." ci aspetteremmo di poter usare gli indici:

6 - per Strumenti che è la sesta voce nella barra dei menù

8 - che è la posizione occupata da Protezione nel menù Strumenti

1 - che è la posizione occupata da Proteggi foglio... nel sottomenù Protezione

invece ci troviamo la sequenza: 6 - 9 - 1 come mostrato nella terza istruzione appena presentata

Altro avviso importantissimo:

Per evitare malfunzionamenti o menù mutilati nei successivi riavvii di Excel occorre ricordarsi di porre a True le proprietà Enabled delle voci disabilitate con Enabled = False prima di uscire dall'applicazione.

Il modo migliore per rimettere tutto a posto è quello di ripristinare le modifiche apportate alle barre nel modulo ThisWorkbook usando uno degli eventi di chiusura (Workbook_Deactivate).

 

Buon lavoro