I have an Excel chart like this:
And the following VBA macro which is toggling the HasLegend property and checking the Left position of the first DataLabel several times. When the legend is removed the chart stretches to fill the space and all the data labels move to the right a bit.
Sub Button1_Click()
Debug.Print CStr(ActiveSheet.ChartObjects("Chart 1").Chart.SeriesCollection(1).DataLabels(1).Left)
ActiveSheet.ChartObjects("Chart 1").Chart.HasLegend = False
Debug.Print CStr(ActiveSheet.ChartObjects("Chart 1").Chart.SeriesCollection(1).DataLabels(1).Left)
DoEvents
Debug.Print CStr(ActiveSheet.ChartObjects("Chart 1").Chart.SeriesCollection(1).DataLabels(1).Left)
DoEvents
Debug.Print CStr(ActiveSheet.ChartObjects("Chart 1").Chart.SeriesCollection(1).DataLabels(1).Left)
DoEvents
Debug.Print CStr(ActiveSheet.ChartObjects("Chart 1").Chart.SeriesCollection(1).DataLabels(1).Left)
DoEvents
Debug.Print CStr(ActiveSheet.ChartObjects("Chart 1").Chart.SeriesCollection(1).DataLabels(1).Left)
DoEvents
Debug.Print CStr(ActiveSheet.ChartObjects("Chart 1").Chart.SeriesCollection(1).DataLabels(1).Left)
DoEvents
Debug.Print CStr(ActiveSheet.ChartObjects("Chart 1").Chart.SeriesCollection(1).DataLabels(1).Left)
DoEvents
ActiveSheet.ChartObjects("Chart 1").Chart.HasLegend = True
End Sub
As you can see in the Immediate window below, after removing the legend there is a delay before the DataLabel Left value is updated.
After the Legend is removed, the original position value is printed another 4 times before the new value is read from the Left property. How can I program this in a reliable way so that the code blocks until the value is updated without adding some random number of DoEvents, or adding a timer loop for some random timespan, and hoping for the best?
Example workbook: https://www.dropbox.com/scl/fi/3b96fim1lkxz1mh5i4pq4/test.xlsm?rlkey=ivdghw3xr87b99ss1avkqgi79&dl=1
Nothing can be done instantly...
In order to wait until left position is updated, please try the next adapted code:
Sub Button1_Click()
Dim prevPos As Double, actChart As ChartObject
Set actChart = ActiveSheet.ChartObjects("Chart 1") ' just to make following code lines shorter...
prevPos = actChart.Chart.SeriesCollection(1).DataLabels(1).Left
Debug.Print prevPos
actChart.Chart.HasLegend = False
Do While actChart.Chart.SeriesCollection(1).DataLabels(1).Left = prevPos
DoEvents
Loop
'do whatever you need here...
Debug.Print actChart.Chart.SeriesCollection(1).DataLabels(1).Left
actChart.Chart.HasLegend = True
End Sub
The above solution should be also adapted for the case you try it again **without setting .HasLegend = True
... One way would be to also use a Global boolean variable (boolHasLeg as Boolean
) which to be changed each time according to HasLegend
status. And, of course, conditioning the loop using this variable, too.
Otherwise, the code will be stuck in the loop...