Prime novità di Office 2007: CommandBar e nuova proprietà Range di oggetti vari
Non ho qui intenzione esaurire il tema delle nuove funzionalità di Office 2007. La medicina va presa a piccole dosi, con qualche prudente sguardo alle novità delle macro, peraltro non proprio sconvolgenti, almeno a prima vista.
Barre strumenti personali: addio?
Da più di un visitatore è pervenuto un grido di dolore, più o meno del tenore seguente: Che fine hanno fatto le mie belle barre personalizzate, coi loro bravi pulsanti e controlli che scatenano le mie macro in qualunque punto del foglio o del documento?
Risposta: non sono sparite, il timore che qualcuno potrebbe nutrire viene presto fugato. Di che timore parlo? Del fatto che ora tutte le barre strumenti non personali sono assorbite dal nuovo Ribbon, (mal) tradotto in Barra multifunzione nell’edizione italiana (ma, ohibò, non andava benone Nastro?). Anticipo che anche questo si può personalizzare anche a fondo, mediante opportuni file XML (v. http://blog.shareoffice.it/giannigiaccaglini/articles/8979.aspx )
La cosa curiosa è che le vecchie barre non sono state “uccise”, anzi si possono ancora trattare in VBA. Eccone subito alcuni esempi, relativi alle CommandBar File e Task Pane, che poi – chi non lo sapesse – corrispondono al menu File e al riquadro delle attività.
Application.CommandBars("File").Visible = True 'oppure = False
Application.CommandBars("Task Pane").Visible = True 'oppure = False
Application.CommandBars("File").Enabled = False 'Disabilita il menu File?
‘sì in Word o Excel 2003, niente affatto in Word o Excel 2007
Application.CommandBars("Task Pane").Enabled = False 'idem c.s.
Office 2007 accetta senza fare una piega tali comandi, che però purtroppo non hanno nessun effetto e si continua a vedere l’intero Ribbon, di cui le vecchie barre (o, forse più esattamente, i loro comandi e controlli) dovrebbero pur continuare a far parte. Si scopre inoltre che i valori default della proprietà Visible sono False, mentre gli Enabled sono True, ma la modifica a False lascia le cose immutate. Verrà così delusa qualche anima spericolata, avvezza a disabilitare comandi o interi menu, per inibirne l’uso all’utente finale, così impara ad essere, anzi a non essere, così cattivo…
Le barre personali fanno eccezione (in parte)
Il timore dell’angosciante domanda in apertura viene fugato, come anticipato. Infatti presto si scopre che esse vanno, automaticamente, a far parte della zona Componenti aggiuntivi del Ribbon. Meno male, però si evidenzia pure un limite di questa faccenda (che così risulta consolatoria solo parzialmente):
- Se si clicca su una diversa sezione (Tab) del Ribbon scompare, così funziona il Ribbon, quella dei Componenti aggiuntivi e, con essa, pure le barre personali;
- Legata a questa c’è la pratica impossibilità di farle fluttuare sul foglio o documento.
La cosa ha un risvolto anche in VBA:
Application.CommandBars("MiaBellaBarra").Floating = msoFloating
La precedente istruzione non viene rifiutata, ma non ha effetto. Idem con le altre opzioni della proprietà Floating, come msoTop, msoBottom, msoLeft ecc, che, lungi dal porre la barra in cima, in fondo o altrove, la lasciano custodita nel girone dei, stavo per dire dannati, Componenti aggiuntivi. Insomma, dobbiamo continuamente cliccare lì per vederla e usarla.
Sempre alle barre personali si applicano e funzionano invece le proprietà Visible ed Enabled
Nota – Questi discorsi, nel bene e nel male, valgono anche per le barre e controlli che certi programmi, come Adobe, hanno aggiunto in precedenza a Word o Excel 2003. Sono regolarmente ereditati dai corrispondenti membri della famiglia 2007.
Dimenticavo di dire che, come d’altronde anticipato nel titolo di questo paragrafo:
- Creare manualmente nuove barre personali come avveniva nel mondo 2003 è impossibile; inutile fare clic destro sul Ribbon, non si vedono né si possono modificare barre di sorta né tantomeno crearne di nuove; il clic destro apre solo due opzioni relative alla barra di accesso rapida;
- in tale nuova barra, che diamo per nota, si possono solo inserire comandi standard (quelli d’uso più comune per ciascuno) ed è vano ogni tentativo di incorporarvi icone o pulsanti cui associare macro, anzi non sembra proprio che non faccia in nessun modo parte delle combriccola delle CommandBar, ergo escluderei che si possa programmare in VBA (se qualcuno mi può smentire si faccia vivo)
- lo si può però fare mediante codice VBA e anche in questo caso la neonata barra personale si colloca nel calderone dei Componenti aggiuntivi.
Ed ecco del codice (senza commenti) atto a creare una barra personale formata da tre generici menu e ad aggiungervi altrettanto generiche voci, associando con OnAction - per brevità alla sola seconda voce - tre ridicole macro.
Sub CreaMenu(PBarra, VettMenu)
'Crea una barra personale temporanea di nome PBarra,
'formata da menu attinti da un array VettMenu
Dim i As Integer
Set Bar = CommandBars.Add(Name:=PBarra, temporary:=True)
Bar.Visible = True
For i = 0 To UBound(VettMenu)
Bar.Controls.Add Type:=msoControlPopup
With Bar.Controls(i + 1)
.Caption = VettMenu(i)
End With
Next
End Sub
Sub ProvaCreaMenu()
'Crea tre generici menu in una "MiaBarra"
CreaMenu PBarra:="MiaBarra", _
VettMenu:=Array("Menu1", "Menu2", "Menu3")
End Sub
Sub AggiungiVoci(PBarra, NumContr, VettVoci, VettMacro)
'Aggiungi al menu NumContr di una barra personale PBarra,
'comandi attinti da un array VettVoci, associando a
'ciascun commando una macro attinta da un VettMacro
Dim i As Integer
With CommandBars(PBarra).Controls(NumContr)
For i = 0 To UBound(VettVoci)
With .Controls
.Add
.Item(i + 1).Caption = VettVoci(i)
.Item(i + 1).OnAction = VettMacro(i)
End With
Next
End With
End Sub
Sub ProvaAggiungiVoci()
'Aggiungi voci e relative macro al secondo menu
'della “MiaBarra”
AggiungiVoci PBarra:="MiaBarra", NumContr:=2, _
VettVoci:=Array("Voce1", "Voce2", "Voce3"), _
VettMacro:=Array("Mac1", "Mac2", "Mac3")
End Sub
'Seguono tre macro-del-cavolo evocate dalle
'predette Voce1, Voce2 e Voce3...
Sub Mac1
MsgBox "Ciao, sono la macro 1"
End Sub
Sub Mac1
MsgBox "Ciao, sono la macro 2"
End Sub
Sub Mac1
MsgBox "Ciao, sono la macro 3"
End Sub
Programmabilità del Ribbon? Sì e multiforme, ma tramite XML
I tradizionalisti incalliti si accorgeranno che, benché la nuova barra multifunzione rassomigli vagamente a una barra menu non si comporta allo stesso modo per un aspetto: la seconda, una volta selezionato un menu, permette di spostarsi da un menu all’altro trascinando il cursore del mouse o semplicemente le fredde destra e sinistra, mentre il Ribbon esige dei clic per passare da una Tab all’altra. Pazienza, ci faremo il callo.
Quel che invece è bene sottolineare fin d’ora è che la barra multifunzione non si può programmare almeno direttamente in VBA.
La pratica non applicabilità di codice VBA alle vecchie barre strumenti ne è un indizio, cui se ne possono aggiungere altri due:
- Se si prova ad accendere il Registratore delle macro, sull’operazione manuale della selezione di una sezione del Ribbon non si ottiene nulla;
- Idem se si cerca nella Guida un qualche oggetto Ribbon, con specifiche proprietà e metodi.
Che cosa è successo? Navigando con pazienza nella Guida si scopre che il Ribbon è un oggetto interamente XML! Pertanto lo si può modificare adattandolo a tutte le esigenze modificando lo schema XML o creando un proprio schema del genere. E il bello è che si possono anche inserire nuovi tipi di controlli ai quali sono associabili macro On Action (in modo, si direbbe, concettualmente simile a quanto avviene già coi controlli delle vecchie barre personali.
L’argomento apre nuovi orizzonti su cui ci proponiamo di dare qualche lume appena possibile, dicendo fin d’ora che documentazione adeguata è reperibile sul sito MSDN di Microsoft, mentre la Guida VBA comprende l’argomento anche con esempi vari, ma… non brilla per chiarezza, almeno per chi inizia. Vedremo.
La proprietà Range applicabile a nuovi oggetti
Concludiamo con questa semplice ma utile novità di Excel 2007, che consiste nella possibilità di applicare la proprietà Range a una varietà di oggetti, restituendone l’intervallo associato. Per entrare in medias res, forniamo due esempi relativi all’oggetto Autofilter, ovvero all’elenco del foglio cui è applicato il Filtro automatico (altrimenti si ha errore…):
Sub SegnalaZonaFiltroAutom()
With ActiveSheet.AutoFilter.Range
MsgBox .Address
If MsgBox("Seleziono l'intervallo del Filtro?", vbYesNo) = _
vbYes Then .Select
End With
End Sub
Sub SpostaFiltroAutom()
'Sposta l’elenco filtrate in F4
ActiveSheet.AutoFilter.Range.Cut Range("F4")
End Sub
Nel primo caso vengono segnalati i riferimenti dell’elenco, poi questo viene selezionato se l’utente accetta la proposta. Già questo fa capire che l’oggetto Range restituito non è read-only (se qualcuno lo temeva) ma può essere ulteriormente manipolato, come mostra la seconda più “audace” routine.
Per finire due esempi relativi all’oggetto Hyperlink, che anch’esso ora gode della proprietà Range.
Sub ProvaHypRange()
Set hr = ActiveSheet.Hyperlinks(1).Range
ActiveWindow.ScrollRow = hr.Row
ActiveWindow.ScrollColumn = hr.Column
If MsgBox("Torno all'ovile?", vbYesNo) = vbYes Then
ActiveCell.Select
End If
End Sub
In questo caso il primo legame ipertestuale del foglio viene visualizzato nell’angolo in alto a sinistra della finestra portandone lo scroll orizzontale e quello verticale a livello della riga e colonna del link, senza, si badi bene, che cambi la cella corrente. Pertanto forzando la selezione di questa la si fa tornare in primo piano.
La Sub seguente va testata dopo aver sparso qua e là nel foglio di versi legami ipertestuali locali (diciamo che puntano a celle di altri fogli).
Sub EsploraLink()
Dim Lnk As Hyperlink, hr As Range, AttW As Window
'Dim Ovile As Range
Set AttW = ActiveWindow
Set Ovile = ActiveCell
For Each Lnk In ActiveSheet.Hyperlinks
Set hr = Lnk.Range
AttW.ScrollRow = hr.Row
AttW.ScrollColumn = hr.Column
If MsgBox("Lancio l'hyperlink?", vbYesNo) = vbYes Then
ActiveCell.Select
Lnk.Follow
Exit For
End If
Next
ActiveCell.Select
End Sub
Anche in questo caso ogni link spazzolato dal ciclo For Each Lnk ... Next viene messo in evidenza ponendo all’utente la richiesta di lanciarlo o meno, cosa che viene fatta in caso affermativo con lnk.Follow.
?>
?>