Fare un Grafico col vba - parte seconda - dal 04/09/04 pagina vista: volte

Come anticipato nella prima parte, ora ci occupiamo dell'oggetto ChartObjects e del metodo ChartWizard. Ne vedremo le caratteristiche e di come usarli. Non vi spaventate se leggerete descrizioni ampie perchè l'esempio che poi faremo rispecchierà il tema di questi due articoli : semplificare al massimo le istruzioni, riducendole al minimo.

Nota: l'intervallo dati in questo esempio l'ho iniziato dalla riga 3, ma senza intestazioni di colonna come invece apparivano nella tabella dell'esercizio precedente.

ChartObjects (con la "s" del plurale) rappresenta "l'insieme" di tutti i ChartObject (oggetto "grafico") presenti su una cartella di lavoro (siano essi su  fogli grafici oppure su  fogli di lavoro specificati).

Per identificare ed agire su un grafico (ChartObject) dobbiamo usare la sintassi ChartObjects(indice) che ne individua uno ben preciso; indice può essere il suo numero indice (o d'ordine, assegnato da Excel), oppure il suo nome, posto tra doppie virgolette. Il suo numero indice sarà influenzato dal progressivo di tutti i grafici presenti nella stessa cartella di lavoro.

ChartObject in realtà non è il grafico vero e proprio, ma il contenitore del grafico: è la cornice esterna a linea continua che contiene il grafico il quale si identifica con Chart (Chart è appunto una proprietà dell'oggetto ChartObject, ma può essere anche "l'oggetto" Chart dell'insieme Charts). Purtroppo in Excel questa storia di un "qualcosa" che può essere, a seconda del contesto di costruzione istruzioni, sia oggetto, sia proprietà, sia metodo, sicuramente crea molta confusione, quindi limitando le descrizioni di cosa sono, e semplificando, possiamo dire:

  • ChartObject è il contenitore "vuoto" del grafico, un pò come se avessimo usato una "casella di testo" presa da strumenti di disegno, e l'avessimo lasciata senza scrivere del testo, tantè che ChartObject è un membro degli oggetti Shapes, e possiede gran parte delle proprietà di questi, proprietà usate per esempio nel dimensionamento del grafico come visto nella parte prima.

  • Chart è il "contenuto" (il grafico vero e proprio) presente nel contenitore, e con ChartArea definiamo l'intera area del grafico.

  • ChartWizard (applicato all'oggetto Chart) invece è un metodo che ci consente di manipolare, formattare, un grafico senza dover impostare tutte le singole proprietà, quindi di definire alcune caratteristiche di base del grafico stesso. Attenzione, il metodo ChartWizard non è interattivo, e può modificare solo le proprietà ( vedi ) specificate come argomenti, che sono tanti. Comunque, per approfondimenti, leggetevi la guida in linea che è ben fatta.

Useremo quindi il metodo ChartWizard, ma usando solo in parte i suoi argomenti, e adattando altre istruzioni secondo nostre esigenze; in pratica "mescoliamo" (semplificando e migliorando) un pò di istruzioni per creare un grafico a Linee simile a quello dell'articolo precedente.

Uno dei vantaggi che otterremo usando ChartWizard è quello di ottenere in fase di creazione, già un ChartObject con le dimensioni da noi volute, senza ricorrere ai metodi legati agli Shapes. Useremo comunque il metodo Add applicato all'insieme ChartObjects, dandogli subito le impostazioni per le dimensioni. Vediamo il primo lotto di istruzioni (poi vedremo la macro completa) che provvedono alla creazione del grafico :

  • Sub MioGrafico()
    Dim ch As ChartObject
    Set ch = ActiveSheet.ChartObjects.Add(150, 20, 400, 250)
      -   dichiariamo una variabile "ch" e la dimensioniamo di tipo ChartObject, poi impostiamo con l'istruzione Set la variabile "ch" che sarà uguale al grafico che creiamo con ChartObjects.Add sul foglio attivo (ActiveSheet) . I numeri che seguono tra parentesi, sono i valori in punti che determinano dove (sul foglio attivo) e di che dimensione (lunghezza e altezza del grafico) creare il grafico. I valori, posti in questa sequenza e separati da virgole, identificano:

  • il primo valore (150) indica la distanza dal bordo sinistro della finestra foglio (quella che si identifica con Window) rispetto al bordo sinistro del grafico

  • Il secondo (20) indica la distanza dal bordo superiore della finestra foglio, rispetto al bordo superiore del grafico

  • il terzo (400) indica la lunghezza del "Contenitore" ChartObject

  • Il quarto (250) indica l'altezza del "Contenitore" ChartObject

Come si nota, istruzioni decisamente molto contenute (per ora) per la creazione del grafico, ma ne mancano ancora necessarie alla fase "creazione", che vediamo ora usando il metodo ChartWizard : di questo metodo useremo solo gli argomenti Source, Gallery e Title. Per tutte le altre informazioni necessarie alla realizzazione del grafico, useremo istruzioni ad hoc. Vediamo intanto il secondo blocco istruzioni :

  • ch.Chart.ChartWizard Source:=ActiveSheet.Range("B3:C53"), gallery:=xlLine, Title:="Visite Siti"

Usiamo ancora la variabile "ch" (non scordiamoci che ora è un oggetto ChartObject) e di questo oggetto usiamo la sua  proprietà Chart e di questa richiamiamo il metodo ChartWizard di cui usiamo l'argomento Source assegnandoli l'area di provenienza dati:

attenzione : come intervallo dati dobbiamo ora fornire solo l'area che contiene i valori e senza comprendervi le intestazioni di colonna (che metteremo noi via codice), quindi l'intervallo delle colonne B e C relative al numero di visite settimanali, non anche la colonna A dove sono le date che formeranno l'asse delle categorie; queste le assegneremo seguendo un'altra strada che vedremo sotto. Usiamo poi l'argomento Gallery assegnandoli la costante xlLine per avere un grafico a linee, e infine l'argomento Title con il quale impostiamo il testo che vedremo come titolo del grafico. Riuniamo ora il blocco delle istruzioni di creazione, come riepilogo:

  • Sub MioGrafico()
    Dim ch As ChartObject
    Set ch = ActiveSheet.ChartObjects.Add(150, 20, 400, 250)
    ch.Chart.ChartWizard Source:=ActiveSheet.Range("B3:C53"), gallery:=xlLine, Title:="Visite Siti"

Con queste poche istruzioni otterremo un risultato quasi perfetto, a cui mancano però alcune cose, e comunque questo:

come si nota, avendo dato noi un'altezza adeguata (250 punti), Excel ha provveduto a impostare una adeguata "unità" di scala valori, infatti va di 200 in 200; solo che manca sull'asse categorie l'impostazione a Days (7, una settimana) e relativa data, ed al loro posto troviamo comunque dei numeri che rappresentano il numero di "punti di intersezione" corrispondenti comunque a 51 settimane, cioè l'arco di tempo su cui si valutano i valori. Inoltre sono presenti lungo le linee gli "indicatori di punto" (MarkerStyle) che invece non vorremo vedere.

Poichè con le istruzioni viste sopra, creiamo il grafico ma ne perdiamo il focus, abbiamo bisogno di "riattivare" (Activate) il grafico per potergli assegnare le istruzioni per le nostre modifiche.

A questo punto, approfittiamo per creare una variante : useremo delle lettere come variabili alle quali assegnare gli indirizzi delle celle (Address) adattabile alla reale lunghezza delle varie colonne che interessano l'area dati. Prenderemo sia le celle iniziali, e sfruttando End(xlDown), anche gli indirizzi delle celle finali. Rendiamo quindi la sorgente dati adattabile al reale numero di righe usate, senza dovere impostare nel codice un'intervallo predeterminato.

Dobbiamo fare questo perchè useremo il metodo SeriesColletion(indice) applicato all'oggetto Chart, che ci restituisce un oggetto che rappresenta una singola serie di valori identificata da un numero indice. Alla SeriesColletion(indice) va specificato l'intervallo dell'area dati contenente i valori, per cui avremo la SeriesCollection(1) a cui affideremo l'intervallo dati colonna B (interfree) che vanno dalla cella B3 fino alla cella contenente l'ultimo dato, altrettanto avremo per la SeriesCollection(2) che riceverà l'intervallo dell'area altervista dalla C3 e fino all'ultima cella occupata. Da notare che non comprenderemo negli intervalli le intestazioni di colonna, che con le istruzioni finora usate, non sarebbero lette e assegnate come nome della serie, ma le forniremo via codice. Vediamo ora queste istruzioni: le lettere dalla "a" alla "f" sono i nomi delle variabili

  • a = ActiveSheet.[A3].Address  'cella iniziale date (sono nella colonna A)
    b = ActiveSheet.[A3].End(xlDown).Address 
    'cella finale date

    c = ActiveSheet.[B3].Address 
    'cella iniziale prima serie di valori relativi a "interfree" (sono nella colonna B)
    d = ActiveSheet.[B3].End(xlDown).Address
    'cella finale prima serie di valori relativi a "interfree"

    e = ActiveSheet.[C3].Address 
    'cella iniziale seconda serie di valori relativi a "altervista" (sono nella colonna C)
    f = ActiveSheet.[C3].End(xlDown).Address 
    'cella finale serie di valori relativi a "altervista"

ora iniziano le istruzioni anticipate sopra; dobbiamo Attivare il grafico usando ChartObjects seguito dal nome del grafico, che essendo il primo grafico sul foglio, si chiamerà "Grafico 1"; attenzione al numero indice: se eliminiamo il grafico e lo ricreaiamo, questo sarà il numero indice 2, o il 3 o il 4, dipende da quanti grafici avremo prima eliminato.

Una volta Attivato il grafico, ne dobbiamo selezionare l'area grafico (ChartArea) vera e propria, perchè è su essa che agiremo. Useremo infatti il metodo SeriesCollection. Per prima cosa assegneremo un'intervallo alla proprietà XValues; questa proprietà importante restituisce o imposta una matrice dei valori x di una serie (o più serie) del grafico; in pratica serve a definire l'inizio e la fine dell'intervallo corrispondente a quante righe sono occupate dai valori che formeranno le linee del grafico; noi forniamo l'intervallo rappresentato dalle date, e non è un controsenso riferirci alle date in quanto ogni data corrisponde a dei valori: tante sono le righe delle date, tante saranno le righe dei valori (cioè i numeri che rappresentano la quantità di visite). Questa è la proprietà che serve ad impostare la scala dell'asse valori. Useremo infine la proprietà Values alla quale assegneremo gli intervalli dei dati numerici, quindi per la serie 1 sarà la colonna B (interfree) e per la serie 2 la colonna C (altervista): per definire gli intervalli sul foglio attivo useremo le variabili viste sopra :

  • ActiveSheet.ChartObjects("Grafico 1").Activate  'si attiva il grafico
    ActiveChart.ChartArea.Select 
    'si seleziona l'area grafico
    ActiveChart.SeriesCollection(1).XValues = ActiveSheet.Range(a, b)  
    'intervallo nella colonna A delle date
    ActiveChart.SeriesCollection(1).Values = ActiveSheet.Range(c, d)  
    'intervallo nella colonna B per interfree
    ActiveChart.SeriesCollection(1).MarkerStyle = xlNone 
    'togliamo gli indicatori di punto alla serie 1
    ActiveChart.SeriesCollection(1).Name = "interfree"  
    'assegniamo il nome alla serie 1
    ActiveChart.SeriesCollection(2).Values = ActiveSheet.Range(e, f) 
    'intervallo nella colonna C per altervista
    ActiveChart.SeriesCollection(2).MarkerStyle = xlNone 
    'togliamo gli indicatori di punto alla serie 2
    ActiveChart.SeriesCollection(2).Name = "altervista" 
    'assegniamo il nome alla serie 2

  • ora interveniamo sull'asse delle categorie, selezionandolo, ed usando l'istruzione With...End With per impostarne proprietà senza citare tutte le volte ActiveChart.Axes(xlCategory)

    ActiveChart.Axes(xlCategory).Select  'selezioniamo l'asse delle categorie dell'area grafico
    With ActiveChart.Axes(xlCategory)
    ' e con l'asse selezionato...
    .TickLabels.Orientation = xlUpward 
    'impostiamo in verticale l'orientamento del testo nelle etichette
    .TickLabels.Font.Size = 6 
     'impostiamo la dimensione del carattere nelle etichette a 6
    .MinimumScale = ActiveSheet.Range(a)
     'si indica il valore iniziale di scala dell'asse (cella iniziale delle date)
    .MaximumScale = ActiveSheet.Range(b)
    'si indica il valore finale di scala dell'asse (cella finale delle date)
    .MajorUnit = 7
     'impostiamo la scala di unità da tenere come intervallo di scala ( a 7 giorni )
    .MajorUnitScale = xlDays 
     'impostiamo il tipo di unità, cioè "giorni"
    .MinorUnitIsAuto = True
     'se le unità secondarie per l'asse vengono calcolate automaticamente (non previste qui)
    .Crosses = xlAutomatic
    .AxisBetweenCategories = True
    .ReversePlotOrder = False
    End With
    ActiveChart.Deselect 
    'deselezioniamo il grafico

Ed ora vediamo la macro completa, alla quale aggiungiamo l'istruzione di non mostrarci gli aggiornamenti a schermo durante la creazione del grafico, ma solo alla fine, con Application.ScreenUpdating = False ad inizio macro e Application.ScreenUpdating = True a fine macro:

  • Sub MioGrafico()
    Application.ScreenUpdating = False
    Dim ch As ChartObject
    Set ch = ActiveSheet.ChartObjects.Add(150, 20, 400, 250)
    ch.Chart.ChartWizard Source:=ActiveSheet.Range("b2:C52"), _
    gallery:=xlLine, Title:="Visite Siti"

    a = ActiveSheet.[a3].Address
    b = ActiveSheet.[a3].End(xlDown).Address
    c = ActiveSheet.[b3].Address
    d = ActiveSheet.[b3].End(xlDown).Address
    e = ActiveSheet.[c3].Address
    f = ActiveSheet.[c3].End(xlDown).Address

    ActiveSheet.ChartObjects("Grafico 41").Activate
    ActiveChart.ChartArea.Select
    ActiveChart.SeriesCollection(1).XValues = ActiveSheet.Range(a, b)
    ActiveChart.SeriesCollection(1).Values = ActiveSheet.Range(c, d)
    ActiveChart.SeriesCollection(1).MarkerStyle = xlNone
    ActiveChart.SeriesCollection(1).Name = "interfree"
    ActiveChart.SeriesCollection(2).Values = ActiveSheet.Range(e, f)
    ActiveChart.SeriesCollection(2).MarkerStyle = xlNone
    ActiveChart.SeriesCollection(2).Name = "altervista"

    ActiveChart.Axes(xlCategory).Select
    With ActiveChart.Axes(xlCategory)
    .TickLabels.Orientation = xlUpward
    .TickLabels.Font.Size = 6
    .MinimumScale = ActiveSheet.Range(a)
    .MaximumScale = ActiveSheet.Range(b)
    .MajorUnit = 7
    .MajorUnitScale = xlDays
    .MinorUnitIsAuto = True
    .Crosses = xlAutomatic
    .AxisBetweenCategories = True
    .ReversePlotOrder = False
    End With
    ActiveChart.Deselect

    Application.ScreenUpdating = True
    End Sub

e questo sarà il risultato:

Non abbiamo toccato il valore di "unità" dell'asse valori lasciandolo di 200 in 200 perchè il grafico risulta comunque ben leggibile, altrimenti per modificare il valore di unità basta leggere e applicare le modifiche spiegate nell'articolo parte prima.

Anche per gli aggiornamenti vale la macro AggiornaGrafico() presente nel precedente articolo.

In conclusione so di non aver esaurito l'argomento "Grafici", peraltro troppo ampio, ma spero di avere fornito indicazioni utili ad orientarsi e comunque  ricordo di consultare la guida in linea, ed usare il registratore di macro.

 

Buon lavoro.

prelevato sul sito www.ennius.altervista.org