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

Nuovi eventi e nomi di range in ambiente VSTO

Nuovi eventi e nomi di range nei VSTO

 

Figura 1 [ http://bloggianni.altervista.org/Figura-01.jpg ]

 

Figura 2 [ http://bloggianni.altervista.org/Figura-02.jpg ]

 

Figura 3 [ http://bloggianni.altervista.org/Figura-03.jpg ]

 

Probabilmente la novità più importante nell'ambiente VSTO (Visual Studio Tools per Office System) è data dagli eventi, notevolmente potenziati sia in numero che per la loro varietà. Per entrare senza indugi in medias res ecco un'immagine che testimonia un tipo di evento del tutto inedito rispetto al classico mondo VBA (figura 1)

Per far meglio capire quel che segue a tutti (chi proviene dal VBA, soprattutto!), ricordo che per operare senza ammattire nel nuovo ambiente occorre tener presente alcune piccole cose.

  • Premere Maiusc+F7 per visualizzare l’IDE di Excel (o Word), ovvero i fogli, le celle e le barre strumenti incorporati in VB 2005 (infatti tale utilissima vista dio sa perché sovente NON ricompare, specie se si modifica un progetto).
  • Premere F7 (e non Alt + F11, come accade in VBA) per visualizzare il codice.
  • Premere F5 per lanciare il debug (ed evitare di usare F5 per portarsi su una certa cella: tale mossa funziona in Excel ma non nell’IDE!, ove F5 scatena il Debugger).
  • Salvare periodicamente il progetto corrente.
  • Prima di chiudere VB 2005 lanciare il comando Genera. Sovente ci si illude che le modifiche fatte manualmente sulla cartella che compare dopo il lancio del debug vengano accolte, ma al ritorno nell’IDE si resta delusi…

Nota – Esistono senz’altro sottili motivi di tale apparente stranezza, legati credo anche al fatto che la cartella di file del progetto è un “malloppo” composta da almeno due versioni del nostro ipotetico MioWorkbook.xls, in distinte sottocartelle, quella di debug e quella finale. Le ultime due raccomandazioni tagliano la testa al toro.

Lo strano controllo NamedRange

Si tratta di eventi associati a celle denominate. Per capire di cosa si tratta, si esaminino in figura le varie celle grigie e contenenti i valori da 1 a 9. Ebbene a ciascuna di esse è stato assegnato un nome default mediante le mosse seguenti:

  1. dare un clic sullo (strano) controllo NamedRange della Casella degli Strumenti, categoria Controlli Excel;
  2. trascinarlo il controllo nel foglio e inserirlo nella cella (o intervallo) da “battezzare”.
  3. Compare la finestrina ad hoc Aggiungi controllo NamedRange contenente una casella di testo contenente i riferimenti selezionati al passo 2. Questi si possono modificare (anche interattivamente) ma non il nome default, almeno in questa fase.

Aggiungi controllo NamedRange

Selezionare le celle da includere nel controllo

 

Named Range

 

 

 

 

 

 

 

 

 

 

$B$23

 

 

 

 

 

 

 

 

 

 

 

OK

 

Annulla

 

 

 

 

 

 

 

Il risultato è che alle diverse celle o intervalli così trattati vengono assegnati ma mano nomi standard, con numero progressivo finale: NamedRange1, NamedRange2, NamedRange3  e via di seguito. Grazioso e curioso, ma chi conosce Excel sa bene che il comando Inserisci > Nome ecc. è possibile anche assegnare nomi a piacere a celle e zone.

Nota – Chi ha voglia si cimenti con la modifica di un nome del genere, putacaso “NamedRange3” agendo nella casella Nomi. Ma, come anticipiamo, anche nei VSTO si può usare Inserisci > Nome, v. più avanti.

L’evento Select di un controllo NamedRange

Lasciamo per il momento in vita i nomi da NamedRange1 a NamedRange9 assegnati alle celle con le cifre da 1 a 9 più NamedRange10 destinato allo zero, e andiamo a esaminare il modulo Foglio1.Vb, con la pressione di F7 (v. figura 2).

Come si vede nella figura, nella casella dei vari oggetti incorporati figurano, accanto a vecchie conoscenze come il Button1 (che vedremo più avanti), i nostri range denominati. Selezionandone uno e cliccando sulla casella a discesa accanto se ne scoprono gli eventi. Questo è un articolo introduttivo, così limitiamoci all’evento Select, palesemente relativo alla selezione di quella tal cella e al quale è associata una specifica routine, come la seguente:

Private Sub NamedRange1_Selected(ByVal Target As

   Microsoft.Office.Interop.Excel.Range) Handles NamedRange1.Selected

 

End Sub

Per una prova idiota, inseriamo, tra Private Sub ed End Sub la solita finestrina di messaggio “Ciao Mondo!”:

MessageBox.Show("Ciao Mondo!")

(MessageBox.Show equivale suppergiù al vecchio MsgBox, che peraltro resta in vita)

Nessuno si sorprenderà se poi, ogni volta che si seleziona la cella “NamedRange1”, fuoriesce l’idiota annuncio.

A questo punto pensiamo a un semplice caso applicativo: usiamo le celle denominate in modo che sulla selezione di ciascuna le varie cifre vengano accodate in una data cella. Ne approfittiamo per denominare altre due celle, stavolta in modo tradizionale, ossia con Inserisci > Nome > Definisci..., la prima di nome Spazio servirà a immettere, volendo, un blank tra un carattere e l’altro, la seconda di nome CellaOut è la cella di uscita in cui inserire i caratteri selezionati.

Le persone razionali non si sorprenderanno constatando che anche per questi nomi si danno routine d’evento, tra cui, per quel che c’interessa, una Private Sub Spazio_Selected(...).

Ed ecco il codice che realizza l’obiettivo predetto:

Public Class Foglio1

    Private Sub Foglio1_Startup(ByVal sender As Object, ByVal e As

      System.EventArgs) Handles Me.Startup

 

    End Sub

 

    Private Sub Foglio1_Shutdown(ByVal sender As Object, ByVal e As

      System.EventArgs) Handles Me.Shutdown

  

    End Sub

 

    Private Sub AddDigit(ByVal n As String)

       Range("CellaOut").Value &= n

       Application.ActiveCell.Offset(0, 1).Select()

    End Sub

 

    Private Sub NamedRange1_Selected(ByVal Target As

     Microsoft.Office.Interop.Excel.Range) Handles NamedRange1.Selected

       AddDigit("1")

    End Sub

 

   Private Sub NamedRange2_Selected(ByVal Target As

    Microsoft.Office.Interop.Excel.Range) Handles NamedRange2.Selected

      AddDigit("2")

    End Sub

   

  '. . . O M I S S I S . . . (le Sub idem-cum-patatibus per le cifre 3-8)

 

    Private Sub NamedRange9_Selected(ByVal Target As

     Microsoft.Office.Interop.Excel.Range) Handles NamedRange9.Selected

       AddDigit("9")

    End Sub

 

    Private Sub NamedRange10_Selected(ByVal Target As

      Microsoft.Office.Interop.Excel.Range) Handles NamedRange10.Selected

        AddDigit("0")

    End Sub

 

    Private Sub Spazio_Selected(ByVal Target As

     Microsoft.Office.Interop.Excel.Range) Handles Spazio.Selected

        AddDigit(" ")

        'MsgBox("Spazio!") 'Servita per il debug

    End Sub

End Class

Commenti essenziali

Noti anzitutto, chi è alle prime armi coi VSTO, come il tutto sia incastonato tra Public Class Foglio1 ed End Class, ad esprimere che Foglio1 è per l’appunto una classe, contenenti vari oggetti (incorporati).

È evidente il mestiere della Sub AddDigit, richiamata da ciascuna routine di evento Select dei vari nomi di range, per cui non resta altro da far notare tranne la sintassi &= che nella Sub AddDigit permette di abbreviare l’istruzione che, in VB 6 si sarebbe dovuta scrivere così:

Range("CellaOut").Value = Range("CellaOut").Value & n

Nota – Già che ci siamo, ricordo che, analogamente, istruzioni come Cont = Cont + 1 o Tot = Tot + Dato si possono ridurre a Cont += 1 e Tot +=Dato.

 

Evidenziamo inoltre due rozzezze di questa sciocchezzuola:

  • per aggiungere una stessa cifra o uno spazio (più di uno) occorre ogni volta selezionare una diversa cella (altrimenti non succede nulla); vi è stata messa una pezza con la sistematica selezione della cella accanto, con
    Application.ActiveCell.Offset(0, 1).Select()
    che ovviamente deve essere vuota;
  • inserendo cifre si ottiene un numero, ben presto esorbitante il limite di Excel… Bella scoperta, si dirà. Sì, ma questo sistema non è troppo adatto a implementare una tastiera “virtuale” alfanumerica. Ma chi ci tiene – e ha tempo - può sempre farlo, no?

Ma è solo un esempio didattico, perbacco, che ha il solo scopo di illustrare un tipo di evento assente in VBA. Nel cui pur vetusto ambiente si può svolgere un compito analogo a quello del presente esempietto sfruttando l'evento SelectionChange dell'oggetto Worksheet, offerto perlatro anche dai VSTO. Confrontare, al riguardo l'articolo "Minitastiera virtuale, al seguente link:

http://blog.shareoffice.it/giannigiaccaglini/articles/8845.aspx .

Cenno agli eventi Startup e ShutDown

Nel precedente listato sono state anche inserite le due routine, vuote, di tali eventi . Relativi a oggetti quali Foglio1, Foglio2 ecc. – o un qualche Miodocum in casa World -  non vanno confusi con eventi come Activate o Deactivate, né tantomeno con l’evento di apertura o chiusura dell’intero cartella Excel o documento Word, tutte vecchie conoscenze VBA, supportate pure in VSTO..

Questi inediti eventi si scatenano, rispettivamente, al lancio o alla chiusura del modello ma agiscono nel foglio di appartenenza. Al lettore curioso proponiamo due banali esempietti:

Private Sub Foglio1_Startup(ByVal sender As Object, ByVal e As

  System.EventArgs) Handles Me.Startup

  Dim i As Integer

  For i = 1 To 9

    Range("NamedRange" & i).Value = i

  Next

    Range("NamedRange10").Value = 0

End Sub

 

Private Sub Foglio1_Shutdown(ByVal sender As Object, ByVal e As

  System.EventArgs) Handles Me.Shutdown

  Message.Show ("Lascio il Foglio 1, addio!")

End Sub

 

Il secondo è decisamente cretino (e fa appello alla creatività di chi è dotato di fantasia per ché ottengano cose più utili…), mentre il primo dovrebbe inserire le cifre da 1 a 9 più la cifra zero nelle celle da NamedRange1 a NamedRange10. Si dirà che questo è già stato fatto a project time... Sicuro, ma la cosa è meno folle di quel che si pensa, in quanto allude a possibili creazioni dinamiche di dati e, magari, formule a partire da una cartella semivuota.

Nota – Questi procedimenti dinamici sembrano strampalati ma hanno un vantaggio di security: solo chi riceve la DLL contenente questo codice VSTO può fruire appieno del modello.

Funzione inserita al volo

Già che siamo in tema di nomi di range, esaminiamo la chicca seguente, routine anch’essa inserita tra Public Class Foglio1 ed End Class:

Private Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click

    Range("F_x").Formula = "=" & Range("Funzione").Value

End Sub

(v. figura 3)

Come illustra la figura, sulla destra del solito Foglio1 si trova un intervanno contenente una serie di dati (da 0 a 10, con passo 0,5 nella fattispecie) con accanto l’intervallo nelle cui celle è inserita la funzione x^2/(1+x^2). Il tutto è raffigurato nel grafico xy incorporato, visibile in figura.

Preliminarmente, sono stati assegnati i nomi seguenti:

-          VarX, nome relativo!, alle celle della variabile indipendente;

-          F_X, all’intervallo G6:G26, della variabile dipendente;

-          Funzione, alla cella F28, contenente la stringa “VarX^2/(1+VarX^2)”

I più smaliziati già comprendono, e gli altri perlomeno intuiscono, che cosa accade sul Click del Button1: la formula scritta nella cella di nome Funzione viene inserita nelle celle della zona F_X.

Per chiudere il cerchio occorre ricordare agli smemorati – come ai molti che non l’hanno mai saputo! (nessuno si offenda) – come funzionano i nomi relativi in Excel. Vale la seguente

Regola. I nomi relativi sono caratterizzati dall’assenza di uno o entrambi i segni $ nei riferimenti della cella o intervallo. Un nome del genere, di conseguenza, si applica al variare del (o dei) riferimento (i) lasciato (i) “libero”.

In concreto, vediamo come si opera nel caso in questione, più che tipico diremmo.

  1. Selezionare la cella F6, poi scegliere Inserisci > Nome > Definisci.
  2. Nella casella in alto della susseguente dialog box scrivere VarX
  3. Nella casella in basso (“Riferito a”) modificare i riferimenti suggeriti $F$7 in $F7 e chiudere con OK.

Nota – A onor del vero, anche coi vituperati (da chi scrive) controlli NamedRange si possono definire nomi relativi. Facile da verificare, ma constatando di nuovo la difficoltà di assegnare nomi a piacere.

A questo punto, volendo agire manualmente, si può proseguire selezionando l’intervallo F_X (G6:G26) digitando poi “VarX^2/(1+VarX^2)” nella cella attiva e concludendo infine con Ctrl+Invio. Ciò consolida una identica formula in tutte le celle G6:G26, ciascun delle quali di fatto fa riferimento (relativo!) alla cella alla sua sinistra.

Questo stesso compito viene eseguito, come anticipato, cliccando sul nostro Button1 e tutti comprendono che ciò apre la strada all’inserimento dinamico di una qualsiasi formula-stringa digitata nella casella Funzione (F28).

I più abili & interessati possono ampliare il metodo con una casella a discesa che attinge a una serie di formule in forma di stringhe... Buon lavoro.

?>

?>

?>

?>

posted on mercoledì 21 febbraio 2007 14.36