1

I have this following code to export a set of dataframes and then convert them to tables in excel and applying a color format, then it creates Line Graphs for every table, everything works but I'm having trouble with the following:

  • Apply Style 12
  • Place Data Labels to "Above"
  • Remove Major Gridlines
  • Remove Bold Font from the title
  • Adjust the size of the chart
  • Change the color of the datalabels,
  • Remove the background of the plot area

This is what I'm getting

This is what I'm getting

This is what I need

This is what I need! Style 12 with no Major Gridlines and Data Labels Above

        # Load the existing workbook
        workbook = openpyxl.load_workbook(output_path + '\\' + output_file)

        # Get the 'USA (TM)' sheet or create it if it doesn't exist
        sheet_name = s
        if sheet_name not in workbook.sheetnames:
            workbook.create_sheet(sheet_name)
        sheet = workbook[sheet_name]

        # Assuming 'df' is your DataFrame

        # Write headers to the specified sheet starting from column F, row 1
        headers = merged_cc.columns.tolist()
        for idx, header in enumerate(headers, start=1):
            sheet.cell(row=1, column=idx + columns_position[e] - 1, value=header)

        # Write the DataFrame values to the specified sheet starting from column F, row 2
        for r_idx, row in enumerate(merged_cc.iterrows(), start=2):
            for c_idx, value in enumerate(row[1], start=1):
                sheet.cell(row=r_idx, column=c_idx + columns_position[e] -1 , value=value)
                if isinstance(value, (int, float)):
                    sheet.cell(row=r_idx, column=c_idx + columns_position[e] -1).number_format = '0%'

        # Adjust cell width of the table to specific width
        for idx, column_width in enumerate([10.71, 10.71,10.71, 10.71, 10.71], start=columns_position[e]):  # Example widths
            column_letter = openpyxl.utils.get_column_letter(idx)
            sheet.column_dimensions[column_letter].width = column_width


        # Replace 'A1:B10' with the range you want to convert
        table_range = w

        # Check if the table name already exists
        existing_tables = sheet.tables
        if table_name in existing_tables:
            del sheet._tables[table_name]
        
        # Format the range as a table
        table = openpyxl.worksheet.table.Table(displayName=table_name, ref=table_range)
        table.tableStyleInfo = TableStyleInfo(name="TableStyleMedium13", showFirstColumn=False,
               showLastColumn=False, showRowStripes=True, showColumnStripes=False)
        # Add the table to the worksheet
        sheet.add_table(table)

        # Create Graph *

        # Create a new LineChart object
        chart = LineChart()

        # Add data to the chart
        data = Reference(sheet, min_col=columns_position[e]+2, min_row=1, max_col=columns_position[e] + 4, max_row=sheet.max_row)
        chart.add_data(data, titles_from_data=True)

        # Set the categories (X-axis labels)
        categories = Reference(sheet, min_col=columns_position[e] + 1, min_row=2, max_row=len(merged_cc)+1)
        chart.set_categories(categories)

        # Set the title of the chart
        chart.title = companies[e]
        chart.style = 12
        '''
        # Create a DataLabelList object
        data_labels = DataLabelList()
        data_labels.showVal = True  # Show the values of the data points

        # Set the data labels for the chart
        chart.dLbls = data_labels

        # Iterate through each series in the chart
        for series in chart.series:
            # Set data labels for each data point in the series
            for point in series:
                data_label = DataLabel(idx=point.index, showVal=True, position='above')  # Position data label above the data point
                point.dataLabel = data_label

        # Add the chart to the worksheet
        '''
        sheet.add_chart(chart, graph_coordenades[e])  # Adjust the cell reference as needed
        # Save the workbook
        workbook.save(output_path + '\\' + output_file)

1 Answer 1

4

Not sure what you are looking for when you state style 12 but to duplicate what I assume is your required view in the second screen-shot you can specify most of the requirements.

Given your code is not runable I have included a standalone sample that sets the required Chart properties so you can add to your code as you need.

Updated code sample
Includes changing the Data Labels Font as well as colour and removing the plot area background.
Note; The Data Label section has been moved in to the series creation function and the Font changes are applied there as common to each series.
The Font change includes type and size, if you don't want to change these as well then just remove from the code.
The 'b=' sets bold to True or False.

from openpyxl import Workbook
from openpyxl.chart.label import DataLabelList
from openpyxl.chart.shapes import GraphicalProperties
from openpyxl.chart.text import RichText
from openpyxl.drawing.text import Paragraph, ParagraphProperties, CharacterProperties, Font
from openpyxl.chart import (
    LineChart,
    Reference,
    Series,
)

wb = Workbook()
ws = wb.active

### Some constants
min_col = 2
max_col = 5
marker_size = 8
marker_symb = "circle"

"""
This section just adds some data to the Sheet in the format of that used from the screen shot
"""
rows = [
    ('Quarter', 'FQ2 2022', 'FQ4 2022', 'FQ2 2023', 'FQ4 2023'),
    ('R1', 0.51, 0.53, 0.56, 0.58),
    ('R2', 0.26, 0.27, 0.28, 0.31),
    ('R3', 0.07, 0.08, 0.08, 0.1),
]
for r in rows:
    ws.append(r)

for row in ws.iter_rows(min_row=2, min_col=min_col, max_row=4, max_col=max_col):
    for cell in row:
        cell.number_format = '0%'

# ----------------------------------------------------------------- #


def chart_series(s_clr, s_title, s_row):
    # Function to create the series for each plot line

    data = Reference(ws, min_col=min_col, min_row=s_row, max_col=max_col, max_row=s_row)
    series = Series(data, title=s_title)  # or have Title reference a cell
    series.graphicalProperties.line.solidFill = s_clr  # Colour of the plotted line
    # Set Marker for series
    series.marker.symbol = marker_symb
    series.marker.size = marker_size  # Size of the Marker symbol
    series.marker.graphicalProperties.solidFill = s_clr  # Marker filling
    series.marker.graphicalProperties.line.solidFill = s_clr  # Marker outline
    # Set Datalabels
    series.dLbls = DataLabelList()
    series.dLbls.showVal = True
    series.dLbls.position = 't'  # Put the datalabel above marker
    # Set Data Label font properties Note 'b=' is Bolding
    cp = CharacterProperties(latin=Font(typeface='Arial'), sz=1900, b=False, solidFill=s_clr)
    series.dLbls.txPr = RichText(p=[Paragraph(pPr=ParagraphProperties(defRPr=cp))])

    return series


### Create Line chart
l_chart1 = LineChart()

### Set data and line colour and markers for first row data
s1_line_colour = "0000FF"  # Colour of series plot line
s1_title = 'Unaided Awareness'  # or reference a cell
s1_row = 2  # Row data for this series exists on
### Add Series1 to the chart
l_chart1.append(chart_series(s1_line_colour, s1_title, s1_row))

### Set data and line colour and markers for second row data
s2_line_colour = "FF0000"
s2_title = 'Unaided Consideration'
s2_row = 3
### Add Series2 to the chart
l_chart1.append(chart_series(s2_line_colour, s2_title, s2_row))

### Set data and line colour and markers for third row data
s3_line_colour = "00FF00"
s3_title = 'Unaided Preference'
s3_row = 4
### Add Series3 to the chart
l_chart1.append(chart_series(s3_line_colour, s3_title, s3_row))

### Set Chart Style
# l_chart1.style = 12  # Can be set but will not affect chart

### Set x-axis names
## Get the names from the Excel Range off Sheet
x_values = Reference(ws, min_col=min_col, min_row=1, max_col=max_col, max_row=1)
l_chart1.set_categories(x_values)

### Set y-axis Gridlines and number format
l_chart1.y_axis.minorGridlines = None  # Disable minor gridlines
l_chart1.y_axis.majorGridlines = None  # Disable major gridlines
l_chart1.y_axis.number_format = '0%'  # Set the number format for the Y axis

### Set Chart title
l_chart1.title = 'Store 1'
## Remove Bolding from the Title Text
l_chart1.title.text.rich.paragraphs[0].pPr = ParagraphProperties(defRPr=CharacterProperties(b=False))

### Set position for the Legend
l_chart1.legend.position = 'b'  # Place legend at the bottom of the chart

### Further changes
l_chart1.graphical_properties = GraphicalProperties()

## Make the border area around the plot area transparent
l_chart1.graphical_properties.noFill = True

## Remove the border around the edge of the chart
l_chart1.graphical_properties.line.noFill = True

## Make the Plot Area transparent
l_chart1.plot_area.graphicalProperties = GraphicalProperties(noFill=True)

### Set the Chart size, height and width
l_chart1.height = 15  # default height is 7.5
l_chart1.width = 40  # default width is 15

### Add Chart to Excel Sheet
ws.add_chart(l_chart1, "F1")

### Save Sheet
wb.save("LineChart.xlsx")

Resultant Chart with additional changes;
Line Chart

6
  • One more question while we are here, How do I remove the Bold Font from the title, and is there a way to adjust the size of the chart?
    – Berny
    Commented Mar 24 at 18:15
  • 1
    I've updated the code to include removing bold font under ## Remove Bolding from the Title Text and changing the size of the chart under ### Set the Chart size, height and width
    – moken
    Commented Mar 25 at 7:37
  • I'm sorry, I just need this last one thing, I need to change the color of the datalabels, the % ones above the dots, and I need to remove the background of the plot area, you are just the best!!
    – Berny
    Commented Mar 28 at 0:34
  • 1
    Given these additional changes to the Chart properties it probably would have been better to do this with Xlwings or Win32com (it's usually easier to work out the required param(s) to change) but these modules have their limits too. Openpyxl has included limited properties for Chart attributes. Anything not deemed standard should be able to be changed by determining the required param hence the strange settings for some of these changes. Theoretically the datalabels colour can be changed but may take some checking to find the param(s) to do this.
    – moken
    Commented Mar 28 at 8:40
  • 1
    I have updated the code with section ### Further changes on how to remove the background of the plotarea and the border around that including the chart outer border, see updated chart image, which I think includes the "remove the background of the plot area" requirement. I'll have to look further into the datalabels colour change as mentioned tho of course somebody else may have done this already and answer the question.
    – moken
    Commented Mar 28 at 8:44

Not the answer you're looking for? Browse other questions tagged or ask your own question.