Как добавить форматы к существующим объектам формата на лету с помощью xlsxwriter

Можно ли изменить или добавить существующий формат «на лету» в xlsxwriter? Мне бы хотелось, чтобы эта функциональность позволяла поддерживать несколько основных форматов и добавлять новые критерии в каждом конкретном случае.

Например, в приведенном ниже коде я хотел бы добавить формат подчеркивания к dark_blue_header_format только в ячейке A2. Однако это приводит к неожиданным результатам, которые показаны на рисунке ниже. Я ожидал, что A1 и A3 будут синими с белым текстом 24-го размера: и я ожидал, что A2 будет синим с белым текстом 24-го размера и подчеркнутым.

import xlsxwriter

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

dark_blue_header_format = workbook.add_format({
    'bg_color': '#5081BB',
    'font_color': '#FFFFFF',
    'font_size': 24
})

worksheet.set_column('A:A', 30)

worksheet.write('A1', 'Company Name', dark_blue_header_format)
worksheet.write('A2', 'Underlined Company Name', dark_blue_header_format.set_underline())
worksheet.write('A3', 'Company Name', dark_blue_header_format)

workbook.close()

введите здесь описание изображения

Я просмотрел документы по форматированию и не нашел ничего, что можно добавлять форматы на лету. Если функциональность set_whatever ведет себя так, как в этом примере, то я не понимаю, для чего она полезна.

Если невозможно добавить форматирование к существующим форматам «на лету», как лучше всего создавать множество уникальных форматов?

Спасибо!


person a15n    schedule 03.11.2014    source источник


Ответы (3)


Можно ли изменить или добавить существующий формат на лету в xlsxwriter?

В настоящее время нет.

Из документов:

Каждый уникальный формат ячейки в электронной таблице XlsxWriter должен иметь соответствующий объект Format. Невозможно использовать Format с методом write(), а затем переопределить его для использования на более позднем этапе. Это связано с тем, что формат применяется к ячейке не в ее текущем состоянии, а в ее конечном состоянии. Рассмотрим следующий пример:

format = workbook.add_format({'bold': True, 'font_color': 'red'})
worksheet.write('A1', 'Cell A1', format)

# Later...
format.set_font_color('green')
worksheet.write('B1', 'Cell B1', format)

Ячейке A1 назначается формат, в котором изначально установлен красный цвет шрифта. Однако впоследствии цвет устанавливается на зеленый. Когда Excel отображает ячейку A1, она отображает окончательное состояние формата, которое в данном случае будет зеленым.

Самый практичный обходной путь при создании множества уникальных форматов — хранить форматы в словаре, индексированном по их свойствам.

person jmcnamara    schedule 04.11.2014
comment
Отличная передовая идея. И спасибо, что указали мне на запросы функций. - person a15n; 05.11.2014
comment
Можете ли вы привести пример лучшей практики? - person liang; 10.07.2018
comment
Привет. Я застрял, используя старую версию pandas, которая не поддерживает форматирование чисел с ее стилем. Я собирался просто применить его после использования to_excel, но в вашей документации кажется, что это невозможно. Если я закрою файл Excel и снова открою его, а затем применю форматирование, перезапишут ли это текущие форматы? - person Melendowski; 06.04.2020

Вы можете сделать что-то вроде этого:

def copy_format(book, fmt):
    properties = [f[4:] for f in dir(fmt) if f[0:4] == 'set_']
    dft_fmt = book.add_format()
    return book.add_format({k : v for k, v in fmt.__dict__.items() if k in properties and dft_fmt.__dict__[k] != v})

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

initial_format = workbook.add_format({
    'font_size': 13,
    'bold': 1,
    'border': 1,
    'align': 'center',
})

new_format = copy_format(workbook, initial_format)
new_format.set_font_size(16)
new_format.set_font_color('white')
person Community    schedule 20.03.2019

Спасибо всем за решение этой проблемы. Это именно то, с чем я столкнулся. Случай использования: чтобы применить различное форматирование к разным типам содержимого, но, помимо этого, применить дополнительное форматирование ("выделение") к определенным ячейкам. Например, добавьте правую и/или нижнюю границу для разделения разных частей таблицы; выделить максимальные значения с дополнительным форматированием.

Если функция, которая возвращает формат рабочей книги, делает копию, я боюсь, что при заполнении большой таблицы будет сгенерировано слишком много экземпляров формата. Поэтому я реализовал решение, которое предварительно генерирует форматы со всеми комбинациями основных моментов. Формат, возвращаемый функцией, выбирает один из предварительно сгенерированных объектов. Я не уверен, стоит ли им делиться, так как я новичок в Python.

workbook = xlsxwriter.Workbook("test.xlsx")
### example cell formats and highlights
frm_types={
    "norm":   {},
    "it":     {"italic":True},
    "bold":   {"bold":True},
    "boldit": {"bold":True,"italic":True}
            }
frm_highlights={
     "max":           {"bold":True,"font_color":"#006699"},
     "border_right":  {"right":1},
     "border_bottom": {"bottom":1},
     "align_right":   {"align":"right"}
         }
### Creating a table of workbook formats with all highlights combinations 
##  Given:
#    wb - workbook, 
#    frm - format properties as dict, 
#    hlist - list of highlights as dicts.
##  Recursively adds levels to multidim. list - [with no highlight, with highlight],
#     finally returns the last level containing a pair of workbook formats
def frm_hl_level(wb,frm,hlist):
    # create two dicts. of properties: without and with first highlight from hlist
    frm_nohl=copy(frm)
    frm_withhl=copy(frm)
    frm_withhl.update(hlist[0])
    # recursion step
    if len(hlist)==1:
        return [
            wb.add_format(frm_nohl),
            wb.add_format(frm_withhl)    
                ]
    else:
        return[
            frm_hl_level(wb,frm_nohl,hlist[1:]),
            frm_hl_level(wb,frm_withhl,hlist[1:])
                ]
## The formats dictionary: 
#   keys = format names, 
#   items = multidim. tables of corresponding formats with 
#     all highlights combinations
frm_data_dict={
        fnm:
            frm_hl_level( workbook, frm_types[fnm],
                             list(frm_highlights.values()) )
            for fnm in frm_types
        }
## Function which returns workbook format object
## Given 
#   l - list of strings: [1st = format name, rest = highlights names],
#   frms, hls, tbl - format dicts., highlights dicts., dict. of formats tables;
## Returns the corresponding workbook format from the dict. of tables
def frm_select(l,frms=frm_types,hls=frm_highlights,fdt=frm_data_dict):
    # list of highlights keys for identifying table indices
    hl_names=list(hls.keys())
    # list of indices for identifying table element
    ind_l=[0 for _ in hls] # init. - format with no highlights
    # add highlights to index
    for nm in l[1:]:
        ind_l[hl_names.index(nm)]=1
    # access the element of the table
    arr=fdt[l[0]]
    for ind in ind_l:
        arr=arr[ind]
    return arr
person pdp    schedule 04.02.2020