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 nuovo libro


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

Normal.dot & NewMacros, questi sconosciuti

Normal.dot & NewMacros, questi sconosciuti

Confessiamolo: noi utenti (in prevalenza) di Excel + VBA ragioniamo quasi sempre in termini di modelli, intesi come singoli file .xls e, con Excel 2007, .xlsm (macro enabled), dotati di valenza applicativa, ciascuno con proprie routine e funzioni. E anche per quanto riguarda queste ultime il più delle volte escogitiamo funzioni ad hoc, valide per quel caso più o meno particolare. Un esempio che mi riguarda è una funzione di conversione da cifre a lettere creato in anni piuttosto lontani per un modello didattico Excel. Valeva la pena di incorporarla in qualche add-in per il suo ri-uso in altri casi? Forse ma non lo feci.

Le funzioni personalizzate o UDF, User Defined Function, meritano comunque di essere incluse in qualche libreria, per arricchire il già ragguardevole insieme che il convento Excel ci passa e qui ricordo che l’operazione può essere compiuta in due modi:

  • Creando un file con codice VBA di estensione xls, o rispettivamente xlsm nel mondo 2007, salvandolo poi come xla o xlam, rispettivamente;
  • Addirittura, tramite Visual Basic standard 6 o .NET non col VBA vulgaris, creando librerie .DLL.

Il caso Word: il template Normal...

Poiché il primo modo, oltre che più facile e diretto è anche ragionevolmente sicuro, checché se ne dica (°) non mi vergogno a dire che l’ho sempre privilegiato. Non ne richiamo le modalità, perché i principianti possono scoprirle facilmente da soli, mentre i bene informati potrebbero offendersi.

Nota (°) La protezione di un add-in xla o xlam da sguardi indiscreti si fa, come è noto, assegnando una password al progetto, nell’Editor VBA e leggende metropolitane sostengono che il cracking della stessa è possibile, mediante utility che abbondano sul Web. Vero solo a metà, ossia se la password è corta, ma se usiamo una dozzina o più di caratteri le celebri utility falliscono... (Inoltre Microsoft deve aver migliorate le cose, con Office 2007).

La situazione in Word presenta delle analogie con Excel, per quanto riguarda gli add-in. In questo quadro si parla più specificatamente di template, che poi sono file .dot e, in Word 2007, .dotm. Per dirla tutta, c’è anche il template di estensione .dotx privo di macro, avente lo scopo di definire particolari modelli di formato (per lettere commerciali e quant’altro: Microsfot stesso ne fornisce una caterva anche on line) che qui non ci interessano.

Questi template sono parenti degli add-in di Excel e analoghe sono le manovre per arruolarli, ma qui si ha una particolarità:

Il modello Normal.dot è presente in tutti i documenti vecchi e nuovi, ed è tale da conservare tutte le macro dei moduli in esso contenuti.

La situazione, di regola, si presenta come segue nella finestra Project:

Normal

   Microsoft Word oggetti

         ThisDocument

   Moduli

         NewMacros

   Project(Miodoc.doc)

         Microsoft Word oggetti

             ThisDocument

Si tratta di un albero di oggetti la cui radice è Normal (espresso senza .dot) avente come nipote, sotto la cartella-figlia Microsoft Word oggetti, l’oggetto ThisDocument, un modulo VBA parente del ThisWorkbook di Excel e come quello destinato a ospitare macro di eventi (come Open e Close per citarne solo due). Notare subito un altro ThisDocument in fondo all’albero, nipote stavolta di un Project(Miodoc.doc) ossia del documento corrente. Vale la seguente distinzione, che qui accenniamo solo a memoria futura, perché qui ci occupiamo del modulo NewMacros:

Mentre il secondo ThisDocument è inerente al documento corrente, il primo è relativo a tutti i documenti vecchi e nuovi.

Di conseguenza la routine Open nell’uno e nell’altro caso si dovrebbe scatenare quando si apre quel preciso documento e, rispettivamente, quando se ne apre uno qualsiasi.

Nota Il condizionale deriva da mie esperienze negative al riguardo. Nell’augurare miglior fortuna a chi legge, osservo che l’evento New ha senso solo se dotato di codice nel primo dei due... compari. O no?

... e il modulo NewMacros

Come sanno quanti almeno una volta in vita loro hanno registrato una macro ospita appunto le routine che rispecchiano le azioni dell’utente. I principianti le utilizzano anche più volte, ma appena diventano più bravi le perfezionano e magari le trasferiscono in nuovi moduli Modulo1, Modulo2 eccetera, posti in una cartella Moduli relativa al documento corrente. La qual cosa è corretta se creaiamo un documento come applicazione in analogia con quel che (più frequentemente) si fa con Word.

Ma probabilmente la maggior parte dimentica, come accaduto finora a chi scrive, che Normal gode di due peculiarità, cui ne aggiungo una terza alla quale forse quasi nessuno pensa:

1)      Tutte le macro ivi contenute operano in qualunque documento, vecchio e nuovo;

2)      Soltanto alle macro ospitate in NewMacros è possibile associare una scorciatoia di tastiera (escluse quelle già impegnate nell’uso manuale);

3)      Il punto 1 vale anche per i moduli inseriti allo stesso livello di NewMacros!

Con la dovuta pazienza, magari aiutandosi col drag ‘n drop, si potrà avere la situazione seguente:

Normal

   Microsoft Word oggetti

         ThisDocument

   Moduli

         NewMacros

         MacroA

         MacroB

         eccetera

Il bello è che anche il codice inserito o digitato in moduli come MacroA e MacroB resta in vita con tutti i documenti (N.B. – anche se non salviamo il documento corrente! Provare per credere).

In fondo è questo il mio piccolo segreto. Se qualcuno ci ha già pensato, buon per lui. Sia come sia, a valle di queste riflessioni la ricetta è ovvia:

Coi moduli a livello Normal si possono ottenere macro (e funzioni, se occorrono, e magari classi) che agiscono su tutti i documenti senza bisogno di caricare particolari template. I vari MacroA, MacroB permettono di suddividere le macro classificandole (evitando di avere NewMacros come calderone omnicomprensivo).

In Excel non c’è nulla di equivalente, se occorrono funzioni particolari si deve caricare lo specifico componente aggiuntivo (add-in), che ovviamente può rimanere attivo per tutte le sessioni. Resta però la noia di scaricarlo se non serve più, ricaricandolo quando occorre di nuovo... Con NewMacros tutte le Sub e Function restano in vita e la gestione si presenta più “rozza” ma del tutto immediata. Credo poi che, a parità di istruzioni, il “peso” di questa aggiunta normale (come altro chiamarla?) sia assai minore dei file xla / xlam, dot /dotm o, peggio, delle equivalenti DLL (inaccessibile, queste ultime, ma laboriose da ristudiare e modificare...).

Concludo la ricetta con due osservazioni.

a)      Il modulo NewMacros potrebbe non esistere (ad esempio nel PC di un absolute beginner) ? Forse sbaglio, ma in tale ipotesi basterà accendere una volta il Registratore.

b)      Solo in NewMacros si possono inserire macro attivate da combinazioni di tasti (che in Word non vanno spregiate, ad es. se si vuole che quella certa azione si scateni mentre l’utente sta digitando). Peggio ancora, tali combinazioni si possono assegnare solo in sede di registrazione. Anche qui il rimedio è semplice. Supponiamo che nel modulo MacroA si trovi una Sub DaCifreALettere. basta registrare una macro, diciamo LancioCifrLett assegnandole diciamo la combinazione CTRL+ m, bloccare quasi subito il Registratore e, infine modificare il tutto come segue:
Sub LancioCifrLett
   DaCifreALettere
End Sub

Detto di passaggio, DaCifreALettere è proprio (grossomodo) il nome di una macro commissionatami da un visitatore per far sì che, accanto a una stringa numerica come “12.034” compaia su pressione di CTRL+M “(dodicimilatrentaquattro)”.  E questo, si badi bene, deve essere possibile su tutti o quasi i documenti di quel professionista.

Ne riparlerò.

E la funzione-chicca per Excel?

Eccola, con la sua brava routine di prova:

Function Sequenza(Inizio, passo, Lung) As Variant

  ReDim S(Lung)

  S(0) = Inizio

  For i = 1 To Lung

    S(i) = S(i - 1) + passo

  Next

  Sequenza = S

End Function

 

Sub p()

  MiaS = Sequenza(5, 2, 10)

  For i = 0 To UBound(MiaS)

    MsgBox MiaS(i)

  Next

End Sub

Come dovrebbe essere evidente, Sequenza restituisce in una Variant un array contenente una serie di interi con inizio e passo definiti dagli argomenti. Per utilizzarla nel foglio di lavoro occorre:

  1. Selezionare un intervallo orizzontale (con quelli verticali non funziona);
  2. Supponendo di aver preliminarmente denominato tre celle-paramentro Iniz, passo e Lung, inserire la funzione =Sequenza(Iniz;passo;Lung);
  3. Concludere con Maiusc+Ctrl+Invio.

L’ultimo passo è cruciale. Se si fosse usato in semplice Invio avremmo visto un unico valore, pari a Iniz, in tutte le celle, mentre con la mossa Maiusc+Ctrl+Invio si ottiene una formula matriciale evidenziata con delle graffe: {=Sequenza(Iniz;passo;Lung)} e il risultato è del tipo 5, 7, 9 ... coi valori della Sub di prova.

Questa curiosità dovrebbe piacere, no? Ammesso che ci interessi poterla utilizzare in ogni spreadsheet ecco una tentazione che potrebbe venire, dopo l’esperienza con Normal.dot in Word. Infatti si può constatare la presenza, in cima alla finestra degli oggetti VBA, di un tal FUNCRES.XLAM sotto il quale, in Excel 2007, c’è una cartella Moduli con un modulo RibbonX_Code (palesemente dedicato alla barra multifunzione eXtensible...). La tentazione è allora quella di agire in conformità a quanto visto con Word, inserendovi un nostro Modulo1 contenente le nostre funzioni personali. Speranza delusa, come si constata.

Ma poco male, la via di un normale add-in .xla o .xlam richiamata in apertura e che diamo per nota è solo un po’ meno immediata ma agevole e sicura.

 

?>

?>

?>

posted on lunedì 15 settembre 2008 16.18