使用xlsxwriter时短字符串与长字符串占用空间为何相近?
问题分析与解决方法
为什么短字符串和长字符串列占用空间接近?
这是因为Excel的OOXML文件格式中,单元格的存储开销主要来自XML结构的固定成本,而非字符串本身的长度:
- 每个单元格在XML中都会生成类似
<c r="A2" t="s"><v>0</v></c>的条目,这段结构的字节数是固定的(约30-40字节),和单元格内字符串的长短无关。 - 13万条记录的情况下,这部分固定的XML标签总字节数(130000 × 30字节 ≈ 3.9MB)远大于字符串长度差异带来的字节差(130000 × (10-4)字节 = 780KB),所以两列的总占用空间会显得几乎相同。
- 另外,XlsxWriter默认会将重复字符串存入共享字符串表(SST),只在单元格中存储引用ID。如果
business_unit的重复率很高(比如只有几个固定值),SST中该列的字符串总大小会很小,但单元格的引用条目数量和另一列一致,进一步拉平了两列的空间占比。
如何让短字符串列占用更少空间?
可以通过以下几种方式优化:
1. 启用constant_memory模式
创建Workbook时开启该模式,它会逐行写入数据,避免在内存中缓存所有内容,同时优化字符串存储和XML生成,显著减少文件大小:
wb = xlsxwriter.Workbook(output, {'constant_memory': True})
2. 批量写入整列数据
用write_column替代嵌套循环逐单元格写入,批量处理能减少XML结构的冗余开销:
# 写入表头 for col_idx, column in enumerate(columns): ws.write(0, col_idx, column) # 批量写入business_unit列 business_units = [row[0] for row in data] ws.write_column(1, 0, business_units) # 批量写入creator_login_sap列 logins = [row[1] for row in data] ws.write_column(1, 1, logins)
3. 最大化共享字符串复用
确保重复字符串被正确共享(XlsxWriter默认已开启,但可以确认没有禁用):
- 不要手动将字符串转为其他类型(比如数字),保持字符串类型才能被加入共享表。
- 如果
business_unit只有少量固定值,这种优化的效果会更明显,因为共享表中只需要存储少数几个4字符字符串,而非13万条重复内容。
4. 移除不必要的格式
如果代码中存在未使用的单元格格式,或者默认格式被重复设置,会增加文件大小。只保留实际需要的格式,避免冗余。
内容的提问来源于stack exchange,提问作者Альберт Александров
相关产品推荐
相关产品推荐

