解决xlsxwriter的format覆盖问题
2018-08-10 11:26:50来源:博客园 阅读 ()
最近在用Python写一个生成Excel日历的脚本, 功能上实现没多大问题, 倒是在xlsxwriter的格式写入上遇到了一个大坑.
举个例子:
import xlsxwriter
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 = {}
def write_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
# 批量套用样式
def write_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)
def write_value(row, col, value):
cell = xlsxwriter.worksheet.xl_rowcol_to_cell_fast(row, col)
cells_value[cell] = value
def write_finish(wb: xlsxwriter.Workbook,
ws: xlsxwriter.Workbook.worksheet_class):
values, formats = set(cells_value.keys()), set(cells_format.keys())
for c in values.difference(formats):
ws.write(c, cells_value[c])
for c in values.intersection(formats):
ws.write(c, cells_value[c], wb.add_format(cells_format[c]))
for c in formats.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()
效果如下:
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- linux安装 uwsgi 测试 test.py 不显示hello world 的解决办 2019-08-13
- 解决python中的Non-UTF-8 code starting with ‘\xbs4’ in 2019-07-24
- Python 用(无脑 and 有脑)方式解决小练习 2019-07-24
- django修改表数据结构后报错的解决办法 2019-07-24
- python 之网络编程(基于TCP协议Socket通信的粘包问题及解决 2019-07-24
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash