2
votes

I have a function to generate XY scatter plots based on any number of dictionaries (with each dictionary representing a line on the graph), each containing a date key and a number value. So far the values seem to work on the Y axis, but the date axis (X) seems to be broken. Every time I add the series to the graph from the dictionary, it forces it to a bar graph, when I specifically want a scatter plot. If I force it back to a scatter plot after assigning it, it completely refuses to display the date axis at all.

Here are some examples.

I want the graph to look like this enter image description here

If I tell it not to use a date, the graph looks like this

enter image description here

When I specifically set the data type of the series to xlDate, the graph changes to this. It has mysteriously changed to a bar graph

enter image description here

if I specifically change it back to a scatter plot after setting it to use an xlDate, it looks like this

enter image description here

Any help would be very much appreciated. Here is my VBA code

Sub GenerateProgressGraph()


Dim Dictionaries(1 To 2) As New Dictionary

    Dictionaries(1).Add DateValue("1/2/2012"), 1
    Dictionaries(1).Add DateValue("2/2/2012"), 2
    Dictionaries(1).Add DateValue("3/2/2012"), 3
    Dictionaries(1).Add DateValue("4/2/2012"), 4

    Dictionaries(2).Add DateValue("1/2/2012"), 1
    Dictionaries(2).Add DateValue("2/2/2012"), 1
    Dictionaries(2).Add DateValue("3/2/2012"), 3
    Dictionaries(2).Add DateValue("4/2/2012"), 4

    Call ProcessProgressGraph(Dictionaries)
End Sub

Sub ProcessProgressGraph(Dict() As Dictionary)

    Dim Graph As Shape
    Dim GraphRange As Range

    With ActiveSheet

        'set graph area
        Set GraphRange = Application.Range("E4:P21")

        'add a new chart
        Set Graph = Shapes.AddChart(xlXYScatterLinesNoMarkers, GraphRange.Left, _
                                    GraphRange.Top, GraphRange.Width, GraphRange.Height)

        With Graph.Chart

            With .Axes(xlCategory)
                .HasTitle = True
                .AxisTitle.Characters.Text = "Dates"
            End With

            .HasTitle = True
            .ChartTitle.Text = "Chart Title"
            .ChartType = xlXYScatterLinesNoMarkers

            'clear all chart data
            '(Excel has a tendency to give us silly resultsets by default)
            For Each srs In .SeriesCollection
                srs.Delete
            Next

            For Each Dictionary In Dict
                Dim ss As Series
                Set ss = .SeriesCollection.NewSeries
                ss.Name = "Values"
                ss.XValues = Dictionary.Keys
                ss.Type = xlDate
                .ChartType = xlXYScatterLinesNoMarkers 'this forces it back into a scatter plot since it auto makes a bar graph
                ss.Values = Dictionary.Items
            Next
        End With
    End With
End Sub
1
The problem is that your dates are coming in as labels rather than as Excel date values ("1/2/2012" rather than 40910, for example).chuff

1 Answers

2
votes

The problem lies in Excel's native handling of the X axis values. to be honest, i have no idea why this happens, but i know how to solve it:

  1. Get your X axis date values and cast them to type Long using something like this:

    ReDim longDates(Dictionary.Count) as Long
    For i = LBound(Dictionary.Keys) to UBound(Dictionary.Keys)
        longDates(i) = Dictionary.Keys(i)
    Next
    
  2. Assign the longDates to be the X axis values using ss.XValues = longDates

  3. Set the TickLabel number format to date at the end of the function using:

    .Axes(xlCategory).TickLabels.NumberFormat = "d/mm/yyyy"
    

That should work