pythonexcelxlsxwriter

xlsxwriter - Creating Table Formulas using Structural References


I am trying to create a table in Excel using XLSX writer where a lot of the data is precomputed, but a few columns need running formulas.
I am trying to use structural references (headers as reference) to improve readability of the formulas in the table.
However, upon opening the generated file, I get a warning that the file has to be repaired and the formula is zero'd out.

Here's code that has the same idea as my actual code and recreates my problem:

import xlsxwriter

workbook = xlsxwriter.Workbook('example.xlsx')
worksheet = workbook.add_worksheet()

data = [
    ['SOH', 'SOO', 'Actual Order', 'Total'],  # Headers
    [10, 5, 3, None],
    [20, 10, 7, None],
    [15, 8, 6, None]
]

for row, row_data in enumerate(data):
    worksheet.write_row(row, 0, row_data)

worksheet.add_table('A1:D4', {
    'name': 'orderTable',
    'columns': [
        {'header': 'SOH'},
        {'header': 'SOO'},
        {'header': 'Actual Order'},
        {'header': 'Total'}
    ]
})

for row in range(1, 4):
    formula = '=orderTable[@[SOH]] + orderTable[@[SOO]] + orderTable[@[Actual Order]]'
    worksheet.write_formula(row, 3, formula)

workbook.close()

What I have tried so far:

Thanks in advance!


Solution

  • The structured formula that Excel displays in a Table isn't the formula that it stores. In addition to this Excel has changed the syntax of referring to table elements from [#This Row],[Column] to @[Column] over time but it still uses the former in the stored formula.

    XlsxWriter tries to account for this and in most cases it will modify and store the required formula correctly. For example the program would generate the required output if the formula was added to the table column parameters like this:

    import xlsxwriter
    
    workbook = xlsxwriter.Workbook('example.xlsx')
    worksheet = workbook.add_worksheet()
    
    data = [
        ['SOH', 'SOO', 'Actual Order', 'Total'],  # Headers
        [10, 5, 3, None],
        [20, 10, 7, None],
        [15, 8, 6, None]
    ]
    
    for row, row_data in enumerate(data):
        worksheet.write_row(row, 0, row_data)
    
    worksheet.add_table('A1:D4', {
        'name': 'orderTable',
        'columns': [
            {'header': 'SOH'},
            {'header': 'SOO'},
            {'header': 'Actual Order'},
            {'header': 'Total',
             'formula': 'orderTable[@[SOH]] + orderTable[@[SOO]] + orderTable[@[Actual Order]]'}
        ]
    })
    
    workbook.close()
    

    Output:

    enter image description here

    This is explained, to some extent, in the XlsxWriter docs on table columns.

    If you wish to explicitly set the formula, like in the for() loop of your example you will need to explicitly expand the formula yourself to the following:

    
    for row in range(1, 4):
        formula = 'orderTable[[#This Row],[SOH]] + orderTable[[#This Row],[SOO]] + orderTable[[#This Row],[Actual Order]]'
        worksheet.write_formula(row, 3, formula)