Option Explicit
Sub Test_MoveDataLabelsOnActiveChart()
MoveDataLabelsOnSpecifiedSeriesInActiveChart 1, 0, -10, "CustomColumn", True, "OVERwRITe"
End Sub
Sub MoveDataLabelsOnSpecifiedSeriesInActiveChart(lSeries As Long, sngX As Single, sngY As Single, _
Optional sTypeErrorBar As String, Optional bReset As Boolean, Optional sEditDataLabel As String)
'For the series lSeries on the active chart, if data labels are present, move them as specified
'The data for the column chart must be arranged as follows:
'1st Column: Data Point Name
'2nd Column: Data Point Value
'3rd Column: Data Point Error Bar Value (will provide odd results if negative)
'4th Column: Data Label Modifier Value
'Positive sngX value moves label to right
'Positive sngY value moves label down
'sTypeErrorBar (only the following are implemented)
' "FixedValueColumn" uses sngX & sngY for offset 'Can be used for column or bar charts.
' "CustomColumn" uses column to right of values for vertical offset. Designed for Column Charts Only
'If bReset is true the labels will be set to their original position before applying the specified correction.
'sEditDataLabel if one of the following options is specified the data label will be modified as follows:
' "AppendWithSpace" - Space & Data Label Modifier Value will be added after the current Data Label Value
' "AppendWithCR" - Data Label Modifier Value will be added under the current Data Label Value
' "Overwrite" - Data Label Value will be replaced with the Data Label Modifier Value
Dim lChartSeriesCount As Long
Dim pt As Point
Dim sngOffset As Single
Dim sngMultiplier As Single
Dim sValuesRange As String
Dim aryErrors As Variant
Dim aryValues As Variant
Dim aryDataLabels As Variant
Dim lPointIndex As Long
Dim lPointCount As Long
Dim sngScalingFactor As Single
Dim sngMaxValue As Single
Dim sngValue As Single
Dim lMaxPoint As Long
Dim sngColumnHeight As Single
If ActiveChart Is Nothing Then _
MsgBox "Select a chart and try again.", , "Select Chart": GoTo End_Sub
On Error Resume Next
lChartSeriesCount = ActiveChart.SeriesCollection.Count
If Err.Number <> 0 Then _
MsgBox "No series in selected chart.", , "Add Series to Chart": GoTo End_Sub
On Error GoTo 0
If ActiveChart.SeriesCollection.Count < lSeries Then _
MsgBox "Chart has " & lChartSeriesCount & " series.", , "Specified Series Does Not Exist": GoTo End_Sub
If Not ActiveChart.SeriesCollection(lSeries).HasDataLabels Then
MsgBox "The specified series does not have data labels.", , "Specified Series Does Not Have Labels": GoTo End_Sub
End If
If bReset Then
'Reset the data labels to their original position before applying correction
ActiveChart.SeriesCollection(lSeries).HasDataLabels = False
ActiveChart.SeriesCollection(lSeries).HasDataLabels = True
End If
lPointCount = ActiveChart.SeriesCollection(lSeries).Points.Count
Select Case sTypeErrorBar
Case "CustomColumn"
sValuesRange = Split(ActiveChart.SeriesCollection(lSeries).Formula, ",")(2)
aryErrors = Range(Split(sValuesRange, "!")(1)).Offset(0, 1)
aryValues = Range(Split(sValuesRange, "!")(1))
aryDataLabels = Range(Split(sValuesRange, "!")(1)).Offset(0, 2)
'Calculate Offset Scaling Factor based on tallest column
sngMaxValue = 0
For lPointIndex = 1 To lPointCount
sngValue = aryValues(lPointIndex, 1)
If sngValue > sngMaxValue Then
sngMaxValue = sngValue
lMaxPoint = lPointIndex
End If
Next
sngColumnHeight = ActiveChart.SeriesCollection(lSeries).Points(lMaxPoint).Height
sngScalingFactor = sngColumnHeight / sngMaxValue
'Move Labels
For lPointIndex = 1 To lPointCount
With ActiveChart.SeriesCollection(lSeries).Points(lPointIndex).DataLabel
.Top = .Top - (aryErrors(lPointIndex, 1) * sngScalingFactor)
End With
Next
Case "FixedValueColumn"
For Each pt In ActiveChart.SeriesCollection(lSeries).Points
With pt.DataLabel
.Left = pt.DataLabel.Left + sngX
.Top = pt.DataLabel.Top + sngY
End With
Next
Case Else
MsgBox "Not yet implemented"
End Select
'Edit Data Labels
Select Case UCase(sEditDataLabel)
Case ""
'Do nothing
Case "APPENDWITHSPACE"
For lPointIndex = 1 To lPointCount
With ActiveChart.SeriesCollection(lSeries).Points(lPointIndex).DataLabel
.Text = .Text & " " & aryDataLabels(lPointIndex, 1)
End With
Next
Case "APPENDWITHCR"
For lPointIndex = 1 To lPointCount
With ActiveChart.SeriesCollection(lSeries).Points(lPointIndex).DataLabel
.Text = .Text & vbLf & aryDataLabels(lPointIndex, 1)
End With
Next
Case "OVERWRITE"
For lPointIndex = 1 To lPointCount
With ActiveChart.SeriesCollection(lSeries).Points(lPointIndex).DataLabel
.Text = aryDataLabels(lPointIndex, 1)
End With
Next
Case Else
MsgBox sEditDataLabel & " is not a valid option for sEditDataLabel. Use one of the following:" & vbLf & _
" AppendWithSpace" & vbLf & _
" AppendWithCR" & vbLf & _
" Overwrite" & vbLf, , "Invalid Edit Data Label Option"
End Select
'Color Data Labels
If False Then 'Change 2nd word in this line to True to color data labels to specified colors.
For lPointIndex = 1 To lPointCount
ActiveChart.SeriesCollection(lSeries).Points(lPointIndex).DataLabel.Select
With Selection.Format.Fill
.Visible = msoTrue
.ForeColor.RGB = RGB(255, 255, 0)
.Transparency = 0
.Solid
End With
With Selection.Format.Line
.Visible = msoTrue
.ForeColor.RGB = rgbRed
.Transparency = 0
End With
Next
End If
End_Sub:
End Sub