Dash DataTable bug with merge_duplicate_headers

Hello there.

There is an issue with the use of merge_duplicate_headers in the dash datatable.
I use plotly 4.14.3, dash-table 4.11.3, dash-renderer 1.9.1, dash-html-components 1.1.3, but at this stage I’m quite sure that the problem relates to merge_duplicate_headers .

To better describe the problem, let’s start with the example available here:
Styling | Dash for Python Documentation | Plotly section “Multi Headers”.

I modified the code, as below:

import dash
import dash_html_components as html
import dash_table

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

app.layout = html.Div([
    html.H6("Test merge headers"),
    dash_table.DataTable(
        id="table1",
        columns=[
            {"name": ["", "Year"], "id": "year"},
            {"name": ["City", "Montreal"], "id": "montreal"},
            {"name": ["City", "Toronto"], "id": "toronto"},
            {"name": ["City", "Ottawa"], "id": "ottawa"},
            {"name": ["City", "Vancouver"], "id": "vancouver"},
            {"name": ["ClimateA", "Temperature"], "id": "tempA"},
            {"name": ["ClimateA", "Humidity"], "id": "humidityA"},
            {"name": ["Spacer1", "Spacer1"], "id": "spacer1"},
            {"name": ["ClimateB", "Temperature"], "id": "tempB"},
            {"name": ["ClimateB", "Humidity"], "id": "humidityB"},
            {"name": ["Spacer2", "Spacer2"], "id": "spacer2"},
            {"name": ["ClimateC", "Temperature"], "id": "tempC"},
            {"name": ["ClimateC", "Humidity"], "id": "humidityC"},
            {"name": ["Spacer3", "Spacer3"], "id": "spacer3"},
            {"name": ["ClimateD", "Temperature"], "id": "tempD"},
            {"name": ["ClimateD", "Humidity"], "id": "humidityD"},

        ],
        data=[
            {
                "year": i,
                "montreal": i * 10,
                "toronto": i * 100,
                "ottawa": i * -1,
                "vancouver": i * -10,
                "tempA": i * -100,
                "humidityA": i * 5,
                "spacer1": i*"",
                "tempB": i * -100,
                "humidityB": i * 5,
                "spacer2": i*"",
                "tempC": i * -100,
                "humidityC": i * 5,
                "spacer3": i*"",
                "tempD": i * -100,
                "humidityD": i * 5,
            }
            for i in range(10)
        ],

        merge_duplicate_headers=False,

        style_cell_conditional=[
            {
                'if': {'column_id': 'toronto'},
                'backgroundColor': 'tomato',
            },

            {
                'if': {'column_id': 'tempA'},
                'backgroundColor': 'rgb(30, 30, 30)',
                'color':'white'
            },
        ],

        style_header={
            'backgroundColor':'rgb(205,205,205)',
            'fontSize':'12pt',
            'fontWeight':'bold',
        },
        style_header_conditional=[
            {
                'if':{'column_id':'spacer1'},
                'backgroundColor':'hotpink',
            },

            {
                'if': {'column_id': 'spacer2'},
                'backgroundColor': 'hotpink',
            },
        ]
    ),
])

if __name__ == '__main__':
    app.run_server(debug=True, port=8090)

At this stage, we get this:

Note that the columns “Spacer” are there to add some empty columns in my table, instead of displaying 5 distinct tables side by side.

Now, if we change merge_duplicate_headers=False, to set it to True, we get that:

The style is not anymore applied on the correct header cells. It behaves like the id of the original cell is applied to another cell.

Is it a known issue?

Is there another way to apply a colspan? Manually maybe?

Hi @David22

Yes, this is a known issue. You can track any progress here

Ok! Thanks @AnnMarieW

Looks like a looping issue; would be glad to get my hands dirty, and try to fix it…I was looking on the git, but I don’t even know where to start looking :smiley:
Not sure I even have the skillset, but it’s worth a try