pythonopenpyxl

How to create a multi-line chart title with different colors per line in openpyxl


I'm writing a program that takes in an excel file, distributes the data between multiple DataFrames and then creates a final excel with tables and bar charts. I have the entire thing working as expected except I cant figure out how to create a multiline chart title.

For example I have a title such as "Room: XXX, Sample Type: XXX, Grid: XXX" and beneath it I am trying to add "Acceptance Criteria: XXX". I can get the chart title in easily with chart.title but I can not figure out how to use CharacterProperties to change the appearance of each line.

Any help or direction would be greatly appreciated.

Thanks

I have no code working for this part other than chart.title = chart_title + "\n" + subtitle which does give me two lines for the title. I tried AI and have a function generated by Gemini I can share but everything its been generating has not worked at all.


Solution

  • It may be possible to do with the chart properties but need to be able to separate the two (or more) textblocks which could be something to work out.

    Therefore an alternative is you should be able to re-use xml with Openpyxl Advanced Chart Formatting

    You edit your test Chart'ss Title. Set it up how you want, then check the XML for that chart.
    Or can reuse what is shown here set the colours as you need and add any other Font property.

    from openpyxl.chart import BarChart, Reference
    from openpyxl.chart.text import RichText
    from openpyxl import Workbook
    from openpyxl.xml.functions import fromstring
    
    # Create a new Workbook.
    wb = Workbook()
    
    # Select the active Worksheet.
    ws = wb.active
    
    # Data
    rows = [
        ('val', 'Batch 1', 'Batch 2'),
        ('val_1', 10, 30),
        ('val_2', 40, 60),
        ('val_3', 50, 70),
        ('val_4', 20, 10),
        ('val_5', 10, 40),
        ('val_6', 50, 30),
    ]
    
    # Adding data to worksheet.
    for row in rows:
        ws.append(row)
    
    xml = """
    <txPr>
      <a:bodyPr wrap="square" lIns="38100" tIns="19050" rIns="38100" bIns="19050" anchor="ctr" xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
        <a:spAutoFit />
      </a:bodyPr>
      <a:lstStyle xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" />
      <a:p xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main">
          <a:pPr>
                <a:defRPr sz="1400"
                          b="0"
                          i="0"
                          u="none"
                          strike="noStrike"
                          kern="1200"
                          spc="0"
                          baseline="0">
                    <a:solidFill>
                        <a:schemeClr val="tx1">
                            <a:lumMod val="65000"/>
                            <a:lumOff val="35000"/>
                        </a:schemeClr>
                    </a:solidFill>
                    <a:latin typeface="+mn-lt"/>
                    <a:ea typeface="+mn-ea"/>
                    <a:cs typeface="+mn-cs"/>
                </a:defRPr>
          </a:pPr>
            <a:r>
                <a:rPr lang="en-AU"
                       b="1">
                    <a:solidFill>
                        <a:srgbClr val="FF0000"/>
                    </a:solidFill>
                </a:rPr>
                <a:t>Chart Title1</a:t>
            </a:r>
            <a:r>
                <a:rPr lang="en-AU"
                       b="1"
                       u="sng">
                    <a:solidFill>
                        <a:srgbClr val="00B0F0"/>
                    </a:solidFill>
                </a:rPr>
                <a:t>\nChart Title2</a:t>
            </a:r> 
      </a:p>
    </txPr>
    """
    
    # Create a new BarChart.
    bar = BarChart()
    
    # Add some properties.
    bar.type = "bar"
    bar.title = "Foo"  # Need to add the title to the Chart but it can be anything or blank string since the text is in the XML
    
    bar.title.text.rich = RichText.from_tree(fromstring(xml))
    
    # Add the data to the chart.
    data = Reference(ws, min_col=2, min_row=1, max_row=7, max_col=3)
    labels = Reference(ws, min_col=1, min_row=2, max_row=7)
    bar.add_data(data, titles_from_data=True)
    bar.set_categories(labels)
    
    bar.height = 15  
    bar.width = 25  
    
    # Add the chart to the worksheet.
    ws.add_chart(bar, 'A10')
    
    # Save the workbook.
    wb.save('chart_result.xlsx')
    
    

    Example Title on test Chart where first line is different bold/underline and colour
    Of course other Font characteristics can be changed too.
    The new line, '\n' can be at the start of text or end of the previous line as you need

    Example Chart