4

As I needed to add custom text to a chart data labels in python-pptx I used

for point in plot.series[1].points:
   frame = point.data_label.text_frame
   frame.text = "Test "
   for run in frame.paragraphs[0].runs:
      run.font.size = Pt(10)
      run.font.color.rgb = RGBColor(0x0A, 0x42, 0x80)

This allowed me to change the font to the labels but I would need to rotate them. I saw the solution from This other thread but it does not work. Any ideas?

CheshCat
  • 43
  • 6
  • Hi, welcome to Stack Overflow, thanks for taking your time in exploring solutions to your problem, which will surely make your problem more easy to tackle, making it more likely for you to recieve a good answer in little time. I don't know anything about python-pptx, but I think it would also be useful to include the error message you got when you tried the solution you linked. – OriolAbril May 06 '18 at 22:28
  • No error, really. Just nothing happens. The formatting (in this case the rotation) is not applied to the saved file. I suspect it is becaused I manually changed the text for the labels and it somehow overrides the data_labels settings. – CheshCat May 07 '18 at 07:57
  • Awesome thank you, you're question already answered mine! – Quastiat Nov 30 '21 at 16:14

2 Answers2

2

I believe you need to change the txPr (as in the thread you mention) but on the respective element child:

for all_series in range(0, len(plot.series)):
   for i in range(0, len(plot.series[all_series]._element)):
      if re.sub("{.*}", '', plot.series[all_series]._element[i].tag) == >"dLbls":
           txPr = plot.series[all_series]._element[i].get_or_add_txPr()
           txPr.bodyPr.set('rot', '-5400000')

So you need to access the "dLbls" child within the correct element index, the "[i]" is the difference to the mentioned thread. I use regular expressions to derive the name from the ".tag"-method. There is probably a better way to find the correct index, but this is at least one ;)

This solution iterates over all series, if you do not need this you can skip the first loop (assuming you want only the 1-series):

for i in range(0, len(plot.series[1]._element)):
    if re.sub("{.*}", '', plot.series[1]._element[i].tag) == "dLbls":
        txPr = plot.series[1]._element[i].get_or_add_txPr()
        txPr.bodyPr.set('rot', '-5400000')

Note, that this only applies to data labels which were set on the single point, so e.g. through

plot.series[1].points[0].data_label.text_frame.text = "Foo"

Hopefully this helps :)

Irgendniemand
  • 184
  • 1
  • 9
0

You can try this custom function, feed in your plot variable, and other style properties as you needed. If we go at point level for data label then this wont work as we think, and below can help to achieve.

def apply_data_labels(plot,font,fontsize,numformat,rotate = False):
plot.has_data_labels = True
data_labels = plot.data_labels
data_labels.font.size = Pt(fontsize)
data_labels.font.name = font
if rotate == True:
    data_labels._element.get_or_add_txPr().bodyPr.set('rot','-5400000')
data_labels.number_format = numformat

and call this function with your plot variable for example.

apply_data_labels(chart.plots[0],'Invention',10,'#,##0;[Red]#,##0',rotate = True)