Option Explicit
Const Rad2Deg As Double = 57.2957795130823
Private p_Chart As Chart
Private p_ChartTitle As String
Private p_AxisTitle As String
Private p_Rays As Variant
Private p_Arc1 As Variant
Private p_Arc2 As Variant
Private p_StdMax As Double
Private p_StdRef As Double
Private p_Labels As Variant
Private p_StdDev As Variant
Private p_Correlation As Variant
Public Sub drwChart()
Dim newChart As Shape
Dim i As Long
Set newChart = ActiveWorkbook.ActiveSheet.Shapes.AddChart(xlXYScatterLinesNoMarkers, Left:=0, Top:=0, Width:=500, Height:=500)
Set Me.sh = newChart.Chart
With newChart.Chart
.HasTitle = True
.ChartTitle.Text = Me.ChartTitle
.HasLegend = False
With .PlotArea
.InsideWidth = .InsideHeight
.Width = 450
.Left = 20
.Height = 450
End With
With .Axes(xlValue)
.MaximumScale = Me.StdMax + (Me.StdMax / 15)
.MinimumScale = 0
.MajorGridlines.Delete
.HasTitle = True
With .AxisTitle
.Text = Me.AxisTitle
.Font.Size = 12
End With
End With
With .Axes(xlCategory)
.MaximumScale = Me.StdMax + (Me.StdMax / 15)
.MinimumScale = 0
.MajorGridlines.Delete
.HasTitle = True
With .AxisTitle
.Text = Me.AxisTitle
.Font.Size = 12
End With
End With
For i = .SeriesCollection.Count To 1 Step -1
.SeriesCollection(i).Delete
Next
End With
' Draw the Chart
For i = 2 To UBound(Me.Rays, 2)
Call addRays(CDbl(Me.Rays(1, i)))
Next
For i = 2 To UBound(Me.Arc1, 2)
Call drwArc(CDbl(Me.Arc1(1, i)), 0, 1, msoLineDash)
Next
Call drwArc(Me.StdRef, 0, 1, msoLineLongDashDot)
For i = 2 To UBound(Me.Arc2, 2)
Call drwArc(CDbl(Me.Arc2(1, i)), Me.StdRef, 1, msoLineRoundDot)
Next
For i = 2 To UBound(Me.stddev, 2)
Call addPoint(CDbl(Me.stddev(1, i)), CDbl(Me.correlation(1, i)), CStr(Me.Labels(1, i)))
Next
addScale
End Sub
Public Property Set sh(Value As Chart)
Set p_Chart = Value
End Property
Public Property Get sh() As Chart
Set sh = p_Chart
End Property
Public Property Let ChartTitle(Value As String)
p_ChartTitle = Value
End Property
Public Property Get ChartTitle() As String
ChartTitle = p_ChartTitle
End Property
Public Property Let AxisTitle(Value As String)
p_AxisTitle = Value
End Property
Public Property Get AxisTitle() As String
AxisTitle = p_AxisTitle
End Property
Public Property Let Rays(Value As Variant)
p_Rays = Value
End Property
Public Property Get Rays() As Variant
Rays = p_Rays
End Property
Public Property Let Arc1(Value As Variant)
p_Arc1 = Value
End Property
Public Property Get Arc1() As Variant
Arc1 = p_Arc1
End Property
Public Property Let Arc2(Value As Variant)
p_Arc2 = Value
End Property
Public Property Get Arc2() As Variant
Arc2 = p_Arc2
End Property
Public Property Let StdMax(Value As Variant)
p_StdMax = Value
End Property
Public Property Get StdMax() As Variant
StdMax = p_StdMax
End Property
Public Property Let StdRef(Value As Variant)
p_StdRef = Value
End Property
Public Property Get StdRef() As Variant
StdRef = p_StdRef
End Property
Public Property Let Labels(Value As Variant)
p_Labels = Value
End Property
Public Property Get Labels() As Variant
Labels = p_Labels
End Property
Public Property Let stddev(Value As Variant)
p_StdDev = Value
End Property
Public Property Get stddev() As Variant
stddev = p_StdDev
End Property
Public Property Let correlation(Value As Variant)
p_Correlation = Value
End Property
Public Property Get correlation() As Variant
correlation = p_Correlation
End Property
Public Sub drwArc(rad As Double, x0 As Double, weight As Single, dashstyle As Long)
Dim i As Long
Dim sr As Series
Dim xd As Double
Dim yd As Double
Dim x As Double
ReDim arrX(0 To 100)
ReDim arrY(0 To 100)
For i = 1 To UBound(arrX)
x = 2 * (i - (UBound(arrX) / 2))
xd = x0 + rad * Sin(x / Rad2Deg)
yd = rad * Cos(x / Rad2Deg)
If xd > -0.01 Then
If x0 > 0 And (xd ^ 2 + yd ^ 2) ^ 0.5 > (Me.StdMax * 1.001) Then Exit For
arrX(i) = xd
arrY(i) = yd
End If
Next
With Me.sh
Set sr = .SeriesCollection.NewSeries
With sr
.XValues = arrX
.Values = arrY
.MarkerStyle = xlMarkerStyleNone
With .Format.Line
.ForeColor.RGB = RGB(0, 0, 0)
.dashstyle = dashstyle
.weight = weight
End With
End With
End With
End Sub
Public Sub addRays(cor As Double)
Dim sr As Series
Dim r As Double
Dim x As Double
Dim arrX As Variant
Dim arrY As Variant
With Me.sh
' Draw radial lines
r = Me.StdMax
ReDim arrX(1 To 2)
ReDim arrY(1 To 2)
arrX(1) = (r * cor)
arrY(1) = r * Sin(WorksheetFunction.Acos(cor))
arrX(2) = 0
arrY(2) = 0
Set sr = .SeriesCollection.NewSeries
With sr
.HasDataLabels = False
.XValues = arrX
.Values = arrY
.MarkerStyle = xlMarkerStyleNone
With .Format.Line
.Visible = True
.ForeColor.RGB = RGB(200, 200, 200)
.dashstyle = msoLineSolid
.weight = 1
End With
End With
End With
End Sub
Sub addScale()
Dim i As Long
Dim sr As Series
Dim r As Double
Dim x As Double
Dim xd As Double
Dim yd As Double
Dim arrScale As Variant
Dim arrAngle As Variant
Dim arrTick As Variant
Dim arrX As Variant
Dim arrY As Variant
Dim dl As DataLabel
With Me.sh
arrScale = Array("0.0", "0.1", "0.2", "0.3", "0.4", "0.5", "0.6", "0.7", "0.8", "0.9", "0.95", "0.99", "1.0")
arrAngle = Array(0, 5.74, 11.54, 17.46, 23.58, 30, 36.87, 44.43, 53.3, 64.16, 71.81, 81.89, 90)
' Draw major tick marks
r = Me.StdMax
ReDim arrX(1 To 2)
ReDim arrY(1 To 2)
For i = LBound(arrAngle) To UBound(arrAngle)
x = arrAngle(i)
arrX(1) = (r * Sin(x / Rad2Deg))
arrY(1) = r * Cos(x / Rad2Deg)
arrX(2) = 0.97 * (r * Sin(x / Rad2Deg))
arrY(2) = 0.97 * (r * Cos(x / Rad2Deg))
Set sr = .SeriesCollection.NewSeries
With sr
.HasDataLabels = False
.XValues = arrX
.Values = arrY
.MarkerStyle = xlMarkerStyleNone
With .Format.Line
.Visible = True
.ForeColor.RGB = RGB(0, 0, 0)
.dashstyle = msoLineSolid
.weight = 2
End With
End With
Next
' Draw minor tick marks
arrTick = Array(2.87, 8.63, 14.48, 20.49, 26.74, 33.37, 40.54, 48.59, 58.21, 65.51, 66.93, 68.43, 70.05, 73.74, 75.93, 78.52)
r = Me.StdMax
ReDim arrX(1 To 2)
ReDim arrY(1 To 2)
For i = LBound(arrTick) To UBound(arrTick)
x = arrTick(i)
arrX(1) = (r * Sin(x / Rad2Deg))
arrY(1) = r * Cos(x / Rad2Deg)
arrX(2) = 0.98 * (r * Sin(x / Rad2Deg))
arrY(2) = 0.98 * (r * Cos(x / Rad2Deg))
Set sr = .SeriesCollection.NewSeries
With sr
.HasDataLabels = False
.XValues = arrX
.Values = arrY
.MarkerStyle = xlMarkerStyleNone
With .Format.Line
.Visible = True
.ForeColor.RGB = RGB(0, 0, 0)
.dashstyle = msoLineSolid
.weight = 1.5
End With
End With
Next
' Draw labels
r = 1.04 * Me.StdMax
ReDim arrX(LBound(arrAngle) To UBound(arrAngle))
ReDim arrY(LBound(arrAngle) To UBound(arrAngle))
For i = LBound(arrAngle) To UBound(arrAngle)
x = arrAngle(i)
arrX(i) = r * Sin(x / Rad2Deg)
arrY(i) = r * Cos(x / Rad2Deg)
Next
Set sr = .SeriesCollection.NewSeries
With sr
.HasDataLabels = True
.DataLabels.Font.Size = 12
.XValues = arrX
.Values = arrY
.Format.Line.Visible = False
.MarkerStyle = xlMarkerStyleNone
For i = LBound(arrAngle) To UBound(arrAngle)
With .Points(i + 1).DataLabel
.Text = arrScale(i)
.Orientation = 90 - arrAngle(i)
.Position = xlLabelPositionCenter
End With
Next
End With
' Draw "Correlation"
r = 1.1 * Me.StdMax
ReDim arrX(1 To 2)
ReDim arrY(1 To 2)
x = 45
arrX(1) = r * Sin(x / Rad2Deg)
arrY(1) = r * Cos(x / Rad2Deg)
arrX(2) = r * Sin(x / Rad2Deg)
arrY(2) = r * Cos(x / Rad2Deg)
Set sr = .SeriesCollection.NewSeries
With sr
.HasDataLabels = True
.DataLabels.Font.Size = 12
.XValues = arrX
.Values = arrY
.Format.Line.Visible = False
.MarkerStyle = xlMarkerStyleNone
For i = LBound(arrAngle) To UBound(arrAngle)
With .Points(1).DataLabel
.Text = "Correlation"
.Orientation = -45
.Position = xlLabelPositionCenter
.Font.Size = 14
End With
.Points(2).DataLabel.Text = ""
Next
End With
End With
Call drwArc(Me.StdMax, 0, 2, msoLineSolid)
End Sub
Public Sub addPoint(stddev As Double, correlation As Double, symbol As String)
Dim sr As Series
Dim r As Double
Dim arrX As Variant
Dim arrY As Variant
With Me.sh
Set sr = .SeriesCollection.NewSeries
With sr
.HasDataLabels = True
.MarkerStyle = xlMarkerStyleCircle
.XValues = stddev * correlation
.Values = stddev * Sin(WorksheetFunction.Acos(correlation))
.MarkerStyle = xlMarkerStyleCircle
With .Points(1).DataLabel
.Text = symbol
.Position = xlLabelPositionAbove
.Font.Size = 10
End With
End With
End With
End Sub