Formattazione Condizionale Grafico Excel

Anonimo
2015-10-28T17:38:18+00:00

Buonasera, 

Ho provato a trovare qualche soluzione su internet, ma non riesco a venirne a capo. Mi affido a voi. 

Supponiamo di voler valutare i progressi di un giocatore di calcio "Carlo", rappresentandoli su un grafico a bolle. 

Sull'ascissa avremo il punteggio ottenuto per la caratteristica e sull'ordinata la distanza in termini sempre di punteggio dal primo in classifica. 

Partendo da questo database vorrei che sul grafico venisse rappresentato così:

La mia esigenza sarebbe quindi quella di evidenziare in rosso quelle statistiche per cui Carlo ha perso posizioni in classifica ed in verde quelle in cui invece ne ha guadagnate.

Qualcuno di voi saprebbe aiutarmi? 

Vi ringrazio tantissimo in anticipo :)

Microsoft 365 e Office | Excel | Per la casa | Windows

Domanda bloccata. Questa domanda è stata eseguita dalla community del supporto tecnico Microsoft. È possibile votare se è utile, ma non è possibile aggiungere commenti o risposte o seguire la domanda.

0 commenti Nessun commento

Risposta accettata dall'autore della domanda

Anonimo
2015-10-29T00:11:11+00:00

Ho provato a trovare qualche soluzione su internet, ma non riesco a venirne a capo. Mi affido a voi. 

Supponiamo di voler valutare i progressi di un giocatore di calcio "Carlo", rappresentandoli su un grafico a bolle. 

Sull'ascissa avremo il punteggio ottenuto per la caratteristica e sull'ordinata la distanza in termini sempre di punteggio dal primo in classifica. 

Partendo da questo database vorrei che sul grafico venisse rappresentato così:

La mia esigenza sarebbe quindi quella di evidenziare in rosso quelle statistiche per cui Carlo ha perso posizioni in classifica ed in verde quelle in cui invece ne ha guadagnate. 

Ciao Paolo,

Prova qualcosa del genere:

  • Alt+F11 per aprire l'editor di VBA
  • Alt+IMper inserire un nuovo modulo di codice
  • Nel nuovo modulo vuoto, incolla il seguente codice:

 '=========>>

Option Explicit

'--------->>

Public Sub Tester()

    Dim WB As Workbook

    Dim SH As Worksheet

    Dim Rng As Range

    Dim arrInterYear

    Dim chObj As ChartObject

    Dim rPatterns As Range

    Dim i As Long

    Dim vValues As Variant

    Set WB = ThisWorkbook

    Set SH = WB.Sheets("Foglio1")

    Set Rng = SH.Range("D2:E6")

    arrInterYear = Rng.Value

    Set chObj = SH.ChartObjects(1)

    With chObj.Chart.SeriesCollection(1)

        vValues = .Values

        For i = 1 To UBound(vValues)

            If arrInterYear(i, 1) < arrInterYear(i, 2) Then

                .Points(i).Format.Fill.ForeColor.RGB = vbGreen

            Else

                .Points(i).Format.Fill.ForeColor.RGB = vbRed

            End If

        Next i

    End With

End Sub

'<<========= 

  • Alt+Q per chiudere l'editor di VBA e tornare a Excel.
  • Salva il file con un estensione di xlsm
  • Alt+F8 per aprire  la finestra di gestione delle macro
  • Seleziona Tester | Esegui

Se non hai familiarità con le macro, ti consiglio il seguente articolo eccellente di Mauro:

http://answers.microsoft.com/it-it/office/wiki/office\_2013\_release-excel/excel-dove-e-come-inserire-il-codice-visual-basic/ed29ee63-a537-4e5d-8631-76766cf40503

Potresti scaricare il mio file di prova Paolo20151028,xlsm a:

                        **http://1drv.ms/1NBWc00**

===

Regards,

Norman

La risposta è stata utile?

0 commenti Nessun commento

12 risposte aggiuntive

Ordina per: Più utili
  1. Anonimo
    2015-10-29T14:35:28+00:00

    Ciao Palo,

    Avrei dovuto anche spiegare, che per utilizzare il pulsante per aggiornare la formattazione dei grafici, essi e le loro tabelle di dati, possono essere disposti ovunque sul foglio. Però, per sfruttare le modificazione dinamiche, dato il modo in cui ho scritto il codice, è necessario che i dati per Posizione 2015 e Posizione 2014 per ciascun grafico siano disposti in colonne E: F.

    ===

    Regards,

    Norman

    La risposta è stata utile?

    0 commenti Nessun commento
  2. Anonimo
    2015-10-29T14:14:23+00:00

    Ciao Paolo,

    Per gestire tutti i grafici per tutti i giocatori, e per modificare la loro formatazione dinamicamente in risposta ad una modifica dei valori nelle colonne E:F , cioè, le colonnePosizione 2015Posizione 2014, prova  quanto segue:

    • Alt+F11 per aprire l'editor di VBA
    • Alt+IMper inserire un nuovo modulo di codice
    • Nel nuovo modulo vuoto, incolla il seguente codice:

    '=========>>

    Option Explicit

    '--------->>

    Public Function DataAddress(aChartObj As ChartObject)

        Dim MySeries As New ChartSeries

        With MySeries

            .Chart = aChartObj.Chart

            .ChartSeries = 1

                DataAddress = .XValues.Address

        End With

    End Function

    '--------->>

    Public Sub Tester()

        Dim WB As Workbook

        Dim SH As Worksheet

        Dim Rng As Range

        Dim arrInterYear

        Dim chObj As ChartObject

        Dim rPatterns As Range

        Dim i As Long

        Dim vValues As Variant

        Dim MySeries As New ChartSeries

        Set WB = ThisWorkbook

        Set SH = WB.Sheets("Foglio1")

        For Each chObj In SH.ChartObjects

            With chObj.Chart.SeriesCollection(1)

           Set Rng = SH.Range(DataAddress(chObj)).Offset(0, 2).Resize(, 2)

              arrInterYear = Rng.Value

                vValues = .Values

                For i = 1 To UBound(vValues)

                    If arrInterYear(i, 1) < arrInterYear(i, 2) Then

                        .Points(i).Format.Fill.ForeColor.RGB =vbGreen

                    Else

                        .Points(i).Format.Fill.ForeColor.RGB = vbRed

                    End If

                Next i

            End With

        Next chObj

    End Sub

    '<<========= 

    • Alt+IC per inserire un modulo Class
    • Nel nuovo modulo vuoto, incolla il seguente codice:

    '=========>>

    Option Explicit

    'This Class module provides an easy way to access the items in a

    'chart's SERIES formula. It can be exported and then imported into

    'any project

    'Developed by John Walkenbach, JWALK AND ASSOCIATES

    'Copyright 1999. All rights reserved.

    'May be used and distributed freely, but may not be sold.

    'http://www.j-walk.com/ss/

    '===================================

    ' PROPERTIES FOR CHARTSERIES OBJECT

    '===================================

    'Chart (read/write)

    'ChartSeries (read/write)

    'SeriesName (read/write)

    'XValues (read/write)

    'Values (read/write)

    'PlotOrder (read/write)

    'SeriesNameType (read-only)

    'XValuesType (read-only)

    'ValuesType (read-only)

    'PlotOrderType (read-only)

    Dim CurrChart As Chart    'accessible to all procedures

    Dim CurrSeries As Integer 'accessible to all procedures

    '--------->>

    Property Get Chart() As Chart

        Set Chart = CurrChart

    End Property

    '--------->>

    Property Let Chart(Cht)

        Set CurrChart = Cht

    End Property

    '--------->>

    Property Get ChartSeries()

        ChartSeries = CurrSeries

    End Property

    '--------->>

    Property Let ChartSeries(SeriesNum)

        CurrSeries = SeriesNum

    End Property

    '--------->>

    Property Get SeriesName() As Variant

        If SeriesNameType = "Range" Then

            Set SeriesName = Range(SERIESFormulaElement(CurrChart, CurrSeries, 1))

        Else

            SeriesName = SERIESFormulaElement(CurrChart, CurrSeries, 1)

        End If

    End Property

    '--------->>

    Property Let SeriesName(SName)

        CurrChart.SeriesCollection(CurrSeries).Name = SName

    End Property

    '--------->>

    Property Get SeriesNameType() As String

        SeriesNameType = SERIESFormulaElementType(CurrChart, CurrSeries, 1)

    End Property

    '--------->>

    Property Get XValues() As Variant

        If XValuesType = "Range" Then

            Set XValues = Range(SERIESFormulaElement(CurrChart, CurrSeries, 2))

        Else

            XValues = SERIESFormulaElement(CurrChart, CurrSeries, 2)

        End If

    End Property

    '--------->>

    Property Let XValues(XVals)

        CurrChart.SeriesCollection(CurrSeries).XValues = XVals

    End Property

    '--------->>

    Property Get XValuesType() As String

        XValuesType = SERIESFormulaElementType(CurrChart, CurrSeries, 2)

    End Property

    '--------->>

    Property Get Values() As Variant

        If ValuesType = "Range" Then

            Set Values = Range(SERIESFormulaElement(CurrChart, CurrSeries, 3))

        Else

            Values = SERIESFormulaElement(CurrChart, CurrSeries, 3)

        End If

    End Property

    '--------->>

    Property Let Values(Vals)

        CurrChart.SeriesCollection(CurrSeries).Values = Vals

    End Property

    '--------->>

    Property Get ValuesType() As String

        ValuesType = SERIESFormulaElementType(CurrChart, CurrSeries, 3)

    End Property

    '--------->>

    Property Get PlotOrder()

            PlotOrder = SERIESFormulaElement(CurrChart, CurrSeries, 4)

    End Property

    '--------->>

    Property Let PlotOrder(PltOrder)

        CurrChart.SeriesCollection(CurrSeries).PlotOrder = PltOrder

    End Property

    '--------->>

    Property Get PlotOrderType() As String

        PlotOrderType = SERIESFormulaElementType(CurrChart, CurrSeries, 4)

    End Property

    '--------->>

    Private Function SERIESFormulaElementType(ChartObj, SeriesNum, Element) As String

    '   Returns a string that describes the element of a chart's SERIES formula

    '   This function essentially parses and analyzes a SERIES formula

    '   Element 1: Series Name. Returns "Range" , "Empty", or "String"

    '   Element 2: XValues. Returns "Range", "Empty", or "Array"

    '   Element 3: Values. Returns "Range" or "Array"

    '   Element 4: PlotOrder. Always returns "Integer"

        Dim SeriesFormula As String

        Dim FirstComma As Integer, SecondComma As Integer, LastComma As Integer

        Dim FirstParen As Integer, SecondParen As Integer

        Dim FirstBracket As Integer, SecondBracket As Integer

        Dim StartY As Integer

        Dim SeriesName, XValues, Values, PlotOrder As Integer

    '   Exit if Surface chart (surface chrarts do not have SERIES formulas)

        If ChartObj.ChartType >= 83 And ChartObj.ChartType <= 86 Then

            SERIESFormulaElementType = "ERROR - SURFACE CHART"

            Exit Function

        End If

    '   Exit if nonexistent series is specified

        If SeriesNum > ChartObj.SeriesCollection.Count Or SeriesNum < 1 Then

            SERIESFormulaElementType = "ERROR - BAD SERIES NUMBER"

            Exit Function

        End If

    '   Exit if element is > 4

        If Element > 4 Or Element < 1 Then

            SERIESFormulaElementType = "ERROR - BAD ELEMENT NUMBER"

            Exit Function

        End If

    '   Get the SERIES formula

        SeriesFormula = ChartObj.SeriesCollection(SeriesNum).Formula

    '   Get the First Element (Series Name)

        FirstParen = InStr(1, SeriesFormula, "(")

        FirstComma = InStr(1, SeriesFormula, ",")

        SeriesName = Mid(SeriesFormula, FirstParen + 1, FirstComma - FirstParen - 1)

        If Element = 1 Then

            If IsRange(SeriesName) Then

                SERIESFormulaElementType = "Range"

            Else

                If SeriesName = "" Then

                    SERIESFormulaElementType = "Empty"

                Else

                    If TypeName(SeriesName) = "String" Then

                        SERIESFormulaElementType = "String"

                    End If

                End If

            End If

            Exit Function

        End If

    '   Get the Second Element (X Range)

        If Mid(SeriesFormula, FirstComma + 1, 1) = "(" Then

    '       Multiple ranges

            FirstParen = FirstComma + 2

            SecondParen = InStr(FirstParen, SeriesFormula, ")")

            XValues = Mid(SeriesFormula, FirstParen, SecondParen - FirstParen)

            StartY = SecondParen + 1

        Else

            If Mid(SeriesFormula, FirstComma + 1, 1) = "{" Then

    '           Literal Array

                FirstBracket = FirstComma + 1

                SecondBracket = InStr(FirstBracket, SeriesFormula, "}")

                XValues = Mid(SeriesFormula, FirstBracket, SecondBracket - FirstBracket + 1)

                StartY = SecondBracket + 1

            Else

    '          A single range

                SecondComma = InStr(FirstComma + 1, SeriesFormula, ",")

                XValues = Mid(SeriesFormula, FirstComma + 1, SecondComma - FirstComma - 1)

                StartY = SecondComma

            End If

        End If

        If Element = 2 Then

            If IsRange(XValues) Then

                SERIESFormulaElementType = "Range"

            Else

                If XValues = "" Then

                    SERIESFormulaElementType = "Empty"

                Else

                    SERIESFormulaElementType = "Array"

                End If

            End If

            Exit Function

        End If

    '   Get the Third Element (Y Range)

        If Mid(SeriesFormula, StartY + 1, 1) = "(" Then

    '       Multiple ranges

            FirstParen = StartY + 1

            SecondParen = InStr(FirstParen, SeriesFormula, ")")

            Values = Mid(SeriesFormula, FirstParen + 1, SecondParen - FirstParen - 1)

            LastComma = SecondParen + 1

        Else

            If Mid(SeriesFormula, StartY + 1, 1) = "{" Then

    '           Literal Array

                FirstBracket = StartY + 1

                SecondBracket = InStr(FirstBracket, SeriesFormula, "}")

                Values = Mid(SeriesFormula, FirstBracket, SecondBracket - FirstBracket + 1)

                LastComma = SecondBracket + 1

            Else

    '          A single range

                FirstComma = StartY

                SecondComma = InStr(FirstComma + 1, SeriesFormula, ",")

                Values = Mid(SeriesFormula, FirstComma + 1, SecondComma - FirstComma - 1)

                LastComma = SecondComma

            End If

        End If

        If Element = 3 Then

            If IsRange(Values) Then

                SERIESFormulaElementType = "Range"

            Else

                SERIESFormulaElementType = "Array"

            End If

            Exit Function

        End If

    '   Get the Fourth Element (Plot Order)

        PlotOrder = Mid(SeriesFormula, LastComma + 1, Len(SeriesFormula) - LastComma - 1)

        If Element = 4 Then

            SERIESFormulaElementType = "Integer"

            Exit Function

        End If

    End Function

    '--------->>

    Private Function SERIESFormulaElement(ChartObj, SeriesNum, Element) As String

    '   Returns one of four elements in a chart's SERIES formula (as a string)

    '   This function essentially parses and analyzes a SERIES formula

    '   Element 1: Series Name. Can be a range reference, a literal value, or nothing

    '   Element 2: XValues. Can be a range reference (including a non-contiguous range), a literal array, or nothing

    '   Element 3: Values. Can be a range reference (including a non-contiguous range), or a literal array

    '   Element 4: PlotOrder. Must be an integer

        Dim SeriesFormula As String

        Dim FirstComma As Integer, SecondComma As Integer, LastComma As Integer

        Dim FirstParen As Integer, SecondParen As Integer

        Dim FirstBracket As Integer, SecondBracket As Integer

        Dim StartY As Integer

        Dim SeriesName, XValues, Values, PlotOrder As Integer

    '   Exit if Surface chart (surface chrarts do not have SERIES formulas)

        If ChartObj.ChartType >= 83 And ChartObj.ChartType <= 86 Then

            SERIESFormulaElement = "ERROR - SURFACE CHART"

            Exit Function

        End If

    '   Exit if nonexistent series is specified

        If SeriesNum > ChartObj.SeriesCollection.Count Or SeriesNum < 1 Then

            SERIESFormulaElement = "ERROR - BAD SERIES NUMBER"

            Exit Function

        End If

    '   Exit if element is > 4

        If Element > 4 Then

            SERIESFormulaElement = "ERROR - BAD ELEMENT NUMBER"

            Exit Function

        End If

    '   Get the SERIES formula

        SeriesFormula = ChartObj.SeriesCollection(SeriesNum).Formula

    '   Get the First Element (Series Name)

        FirstParen = InStr(1, SeriesFormula, "(")

        FirstComma = InStr(1, SeriesFormula, ",")

        SeriesName = Mid(SeriesFormula, FirstParen + 1, FirstComma - FirstParen - 1)

        If Element = 1 Then

            SERIESFormulaElement = SeriesName

            Exit Function

        End If

    '   Get the Second Element (X Range)

        If Mid(SeriesFormula, FirstComma + 1, 1) = "(" Then

    '       Multiple ranges

            FirstParen = FirstComma + 2

            SecondParen = InStr(FirstParen, SeriesFormula, ")")

            XValues = Mid(SeriesFormula, FirstParen, SecondParen - FirstParen)

            StartY = SecondParen + 1

        Else

            If Mid(SeriesFormula, FirstComma + 1, 1) = "{" Then

    '           Literal Array

                FirstBracket = FirstComma + 1

                SecondBracket = InStr(FirstBracket, SeriesFormula, "}")

                XValues = Mid(SeriesFormula, FirstBracket, SecondBracket - FirstBracket + 1)

                StartY = SecondBracket + 1

            Else

    '          A single range

                SecondComma = InStr(FirstComma + 1, SeriesFormula, ",")

                XValues = Mid(SeriesFormula, FirstComma + 1, SecondComma - FirstComma - 1)

                StartY = SecondComma

            End If

        End If

        If Element = 2 Then

            SERIESFormulaElement = XValues

            Exit Function

        End If

    '   Get the Third Element (Y Range)

        If Mid(SeriesFormula, StartY + 1, 1) = "(" Then

    '       Multiple ranges

            FirstParen = StartY + 1

            SecondParen = InStr(FirstParen, SeriesFormula, ")")

            Values = Mid(SeriesFormula, FirstParen + 1, SecondParen - FirstParen - 1)

            LastComma = SecondParen + 1

        Else

            If Mid(SeriesFormula, StartY + 1, 1) = "{" Then

    '           Literal Array

                FirstBracket = StartY + 1

                SecondBracket = InStr(FirstBracket, SeriesFormula, "}")

                Values = Mid(SeriesFormula, FirstBracket, SecondBracket - FirstBracket + 1)

                LastComma = SecondBracket + 1

            Else

    '          A single range

                FirstComma = StartY

                SecondComma = InStr(FirstComma + 1, SeriesFormula, ",")

                Values = Mid(SeriesFormula, FirstComma + 1, SecondComma - FirstComma - 1)

                LastComma = SecondComma

            End If

        End If

        If Element = 3 Then

            SERIESFormulaElement = Values

            Exit Function

        End If

    '   Get the Fourth Element (Plot Order)

        PlotOrder = Mid(SeriesFormula, LastComma + 1, Len(SeriesFormula) - LastComma - 1)

        If Element = 4 Then

            SERIESFormulaElement = PlotOrder

            Exit Function

        End If

    End Function

    '--------->>

    Private Function IsRange(ref) As Boolean

    '   Returns True if ref is a Range

        Dim x As Range

        On Error Resume Next

        Set x = Range(ref)

        If Err = 0 Then IsRange = True Else IsRange = False

    End Function

    '<<=========

    • Fai clic dx sulla linguetta del foglio
    • Seleziona l'opzione Visualizza Codicedal menu contestuale risultante
    • Incolla il seguente codice:

    '=========>>

    Option Explicit

    '--------->>

    Private Sub Worksheet_Change(ByVal Target As Range)

        If Not Intersect(Target, Me.Columns("D:E")) Is Nothing Then

            Call Tester

        End If

    End Sub

    '<<=========

    • Alt+Q per chiudere l'editor di VBA e tornare a Excel.
    • Salva il file con un'estensione xlsm

     Potresti scaricare il mio file di prova Paolo20151029.xlsm a:

                                 **http://1drv.ms/1O9QTYU**

    Supponiamo, come nel file di prova che ci siano due giocatori, i suoi dati e grafici potrebbero essere:

    Modificando i dati Posizione 2015/2014, o premendo il pulsante, si otterrebbe qualcosa del genere:

    ===

    Regards,

    Norman

    La risposta è stata utile?

    0 commenti Nessun commento
  3. Anonimo
    2015-10-29T10:26:41+00:00

    Mille grazie, il codice funziona alla grande per la domanda che ti ho posto. 

    Quando ho la mia sfera di cristallo, posso anche rispondere a domande che non sono state poste, ma ieri l`ho lasciato a casa :-))

    Ora però mi sono reso conto delle limitazioni del caso.

    1. Per poter aggiungere il nome della caratteristica sul grafico, dovrei creare n serie per n statistiche. In questo modo il codice non funziona dato che lavora soltanto sulla prima riga.
    2. Se la tabella fosse dinamica, cioè se potessi, attraverso un convalida dati, selezionare il nome del giocatore, aggiornando di conseguenza i valori; la tabella non modifica la formattazione ma mantiene quella ottenuta al momento del lancio della macro (e questo penso sia un limite inizialmente non percepito dalla mia non eccelsa conoscenza delle macro).

    Io non vedo nulla di insuperabile: a patto che ci sia una disposizione logica-simmetrica dei tuoi dati, credo che si possa facilmente formattare i grafici per più gioccatori. Se vorresti caricare un esempio dei dati  e i grafici per, diciamo, tre giocatori, cercherò di adattare il codice.

    ===

    Regards,

    Norman

    La risposta è stata utile?

    0 commenti Nessun commento
  4. Anonimo
    2015-10-29T10:00:32+00:00

    Ciao Norman,

    Mille grazie, il codice funziona alla grande per la domanda che ti ho posto.

    Ora però mi sono reso conto delle limitazioni del caso.

    1. Per poter aggiungere il nome della caratteristica sul grafico, dovrei creare n serie per n statistiche. In questo modo il codice non funziona dato che lavora soltanto sulla prima riga.
    2. Se la tabella fosse dinamica, cioè se potessi, attraverso un convalida dati, selezionare il nome del giocatore, aggiornando di conseguenza i valori; la tabella non modifica la formattazione ma mantiene quella ottenuta al momento del lancio della macro (e questo penso sia un limite inizialmente non percepito dalla mia non eccelsa conoscenza delle macro).

    Qualche suggerimento per rendere un po'più fluido il report?

    Grazie ancora a prescindere, che comunque la prima indicazione mi tornerà utile.

    La risposta è stata utile?

    0 commenti Nessun commento