python xlsxwriter格式覆盖问题_解决xlsxwriter的format覆盖问题

最近在用Python写一个生成Excel日历的脚本, 功能上实现没多大问题, 倒是在xlsxwriter的格式写入上遇到了一个大坑.

举个例子:

importxlsxwriter

wb= xlsxwriter.Workbook("test.xlsx")

ws=wb.add_worksheet()#加粗和字体样式

bold = wb.add_format({"bold":True})

fontsize= wb.add_format({"font_size":15})

ws.write("A1", "test", bold)

ws.write("A2", "test", fontsize)

可以预见A1格是粗体, A2格字体则大了几号. 但我们无法同时给一个单元格套用两种样式, 或者说, 单元格只接受最后套用的样式:

ws.write("A1", "test", bold)

ws.write("A1", "test", fontsize)

这一格的文字只会变大而不会变粗 .

另一个问题是, 无法分别给一个单元格写入值和样式. 对于单个单元格, 必须在写入值的同时为单元格写入样式. 关于这个, 可以用 set_column 和 set_row 解决, 它们的实质是设置该列/行的默认样式:

ws.set_column("A:A", None, bold)

ws.set_row(2, None, fontsize) #第三行

ws.write("A1", "test1")

ws.write("A2", "test2", fontsize)

ws.write("A3", "test3")

运行代码可以发现A1继承了A列的默认样式(加粗), 而A2只有字体变大了, 样式覆盖问题依然存在; 另外, A3只继承了行默认样式: 不管 set_column 和 set_row 的先后顺序如何, 行默认样式会覆盖列默认样式.

对于规模极小的表格, 可以分别为单元格设置单独而完全的格式, 但我们依旧希望能够分别/分次为单元格追加新样式, 例如先对一些单元格设置字体, 然后再对一些单元格设置背景色, 最后再给整体添加框线等.

Xlsxwriter被设计为只能写入xlsx文件而不能读取或修改, 但问题在于, 我们xlsxwriter写入的数据会暂存在内存中, 直到最后close()时才会写入到文件中, 那么理应能够从缓存中修改, 最起码读出某单元格的值和样式. 而官方目前没有这样的设计, 所以我们可以先将设置的样式缓存下来, 如果某单元格已经有了样式那就合并, 最后再调用xlsxwriter的方法写入到表格中.

由于样式和值需要同时写入到单元格中, 所以值的写入也需要缓存. 我为我的Excel日历生成脚本写的缓存机制代码如下:

cells_format ={}

cells_value={}defwrite_format(row, col, append_format: dict):

cell=xlsxwriter.worksheet.xl_rowcol_to_cell_fast(row, col) # 将行列号转换成A1这样的格式

fmt= cells_format[cell].copy() if cell in cells_format else{}

fmt.update(append_format)

cells_format[cell]=fmt

# 批量套用样式defwrite_formats(s_row, s_col, e_row, e_col, append_format: dict):for row in range(s_row, e_row + 1):for col in range(s_col, e_col + 1):

write_format(row, col, append_format)defwrite_value(row, col, value):

cell=xlsxwriter.worksheet.xl_rowcol_to_cell_fast(row, col)

cells_value[cell]=valuedefwrite_finish(wb: xlsxwriter.Workbook,

ws: xlsxwriter.Workbook.worksheet_class):

values, formats=set(cells_value.keys()), set(cells_format.keys())for c invalues.difference(formats):

ws.write(c, cells_value[c])for c invalues.intersection(formats):

ws.write(c, cells_value[c], wb.add_format(cells_format[c]))for c informats.difference(values):

ws.write_blank(c, None, wb.add_format(cells_format[c]))

首先通过write_value和write_format(s)将值和样式写入缓存字典中, 如果已存在样式, 就拷贝并追加新样式, 在最后调用write_finish完成写入. 有兴趣的读者可以将它模块化, 再整合进一些其他功能, 方便xlsxwriter的写入.

然后就可以欢快地写样式了, 最后是一个简单的小日历:

# 每周前5天颜色较深

write_formats(0, 0, 4, 4, {"bg_color":"#C8C8C8"})

write_formats(0,5, 4, 6, {"bg_color":"#D9D9D9"})

# 外框线

write_formats(0, 0,4, 0, {"left":1})

write_formats(0,6, 4, 6, {"right":1})

write_formats(0, 0, 0,6, {"top":1})

write_formats(4, 0, 4, 6, {"bottom":1})for i in range(1, 32):

write_value(i//7, i%7, i)

wb= xlsxwriter.Workbook("test.xlsx")

ws=wb.add_worksheet()

write_finish(wb, ws)

wb.close()

效果如下:

2c88d905eda15033282c157971e81f13.png

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值