Python Excel设置列宽行高自适应:内容不再被截断
用openpyxl设置列宽、行高,按内容长度估算自适应列宽,避免文字显示成####或被截断,附完整代码。
场景痛点
导出的表在自己电脑上看好好的,发给同事打开发现金额列全是 ####,长文本列被截断成一串 #。原因是列宽没设。手动拖列又慢又不齐。用 openpyxl 遍历每一列,按该列最长内容算出合适宽度,一次性调好;行高也能统一设成舒服的尺寸。
用到的库
pip install openpyxl
完整代码
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter
def auto_fit(file_path: str) -> None:
wb = load_workbook(file_path)
ws = wb.active
# 1) 先按列估算内容宽度
col_widths = {}
for row in ws.iter_rows(values_only=False):
for cell in row:
if cell.value is None:
continue
text = str(cell.value)
# 中文字符按 2 个宽度算,英文按 1 个
length = sum(2 if ord(ch) > 127 else 1 for ch in text)
col_idx = cell.column
if length > col_widths.get(col_idx, 0):
col_widths[col_idx] = length
# 2) 应用到列宽,加 2 个字符的留白,最小 8、最大 40
for col_idx, width in col_widths.items():
letter = get_column_letter(col_idx)
ws.column_dimensions[letter].width = min(max(width + 2, 8), 40)
# 3) 行高:表头行设 22,数据行设 18
ws.row_dimensions[1].height = 22
for r in range(2, ws.max_row + 1):
ws.row_dimensions[r].height = 18
# 4) 也可以单独写死某一列宽度,比如备注列宽一点
if "备注" in [c.value for c in ws[1]]:
header = [c.value for c in ws[1]]
remark_col = header.index("备注") + 1
ws.column_dimensions[get_column_letter(remark_col)].width = 30
wb.save(file_path)
print("列宽行高已调整")
if __name__ == "__main__":
auto_fit(r"D:\reports\销售明细.xlsx")
代码讲解
ws.column_dimensions["A"].width = 20是设置列宽的标准写法,单位是「字符宽度」,不是像素。get_column_letter(col_idx)把数字列号(1=A、27=AA)转成字母,方便写进column_dimensions。- 自适应列宽的核心是先扫一遍表,记录每一列最长内容的字符长度;中文按 2、英文按 1 估算,因为 Excel 默认字体下中文确实占两个英文字符宽。
min(max(width + 2, 8), 40)做上下限:太短的列至少 8,太长的列封顶 40,避免某列一句话把整张表拉得特别宽。ws.row_dimensions[r].height = 18设置行高,单位是磅;表头单独设大一点突出。- 最后单独把「备注」列设成 30,演示按列名精调。
运行结果
打开文件,每一列宽度刚好能放下该列最长内容,表头行高 22、数据行高 18,「备注」列宽 30,长文本和金额都不再被截断或显示 ####。
注意事项
- openpyxl 没有 Excel 那种「双击列标自动适应」的内置方法,必须自己按内容估算,中文按 2、英文按 1 是常用近似。
- 数字宽度受单元格数字格式影响,纯按文本估算可能偏小,金额列建议手动再加 2~3。
- 行高设过小时,wrap_text 自动换行的内容会被裁切,需要换行的列别把行高压得太低。
column_dimensions用列字母索引,写错字母(比如"a"小写)不生效,统一用get_column_letter。- 大表扫一遍全列会慢一点,但一次性扫完再赋值,比重复读单元格快。

更新时间:2026-09-15 09:16:02