openpyxl如何设置自适应列宽

xlrd和openpyxl是pandas用于处理Excel文件的主要依赖库,前者用于读取.xls格式文件,后者用于读写.xlsx格式文件 。在使用openpyxl配合pandas生成特定格式表格文件时,经常遇到这个奇怪问题:虽然设置表格某列为X个字符宽度,但打开生成的文件查看该列宽度,往往少于X 。如下图所示,第一列实际列宽比脚本设置的列宽少了0.62个字符 。

openpyxl如何设置自适应列宽

文章插图
列宽缩水了!
【openpyxl如何设置自适应列宽】这是怎么回事呢?如何确保脚本设置的列宽和在Excel中查看的列宽相同?这需要我们首先了解Excel如何设置列宽 。
一、Excel列宽知识
Excel使用字符数(VBA中用ColumnWidth读写)设置列宽,这个字符是该字体中0-9里长得最胖的那个,一般是0 。如果某列宽度为10,则该列能够容纳默认字体字号的10个字符0 。列宽字符数也是我们查询列宽时看到的值 。
列宽像素是这样计算的:默认字体为宋体/Arial 10磅时,每个字符宽7像素,字符两侧有5像素的留白(padding),或者内边距 。下面的公式更加简单明了:
列宽像素=列宽字符数*7+5
举例:如果某列宽度为10字符,则该列宽为10*7+5=75像素 。
Excel还用磅(points)来表示列宽(VBA中用Width属性查看) 。计算公式如下:
列宽磅数=列宽像素*3/4
默认字体字号不同,字符0的像素宽度不同,留白像素也不同 。下表列出常见默认字体的情况:
默认字体
默认字号(磅)
字符宽度(像素)
留白(像素)
宋体
10
7
5
宋体
11
8
5
宋体
12
8
5
宋体
14
10
7
宋体
16
11
7
宋体
18
12
7
宋体
20
14
9
Arial
10
7
5
Arial
11
8
5
Arial
12
9
7
Arial
14
11
7
Arial
16
12
7
Arial
18
13
9
Arial
20
15
9
Calibri
10
7
5
Calibri
11
7
5
Calibri
12
8
5
Calibri
14
10
7
Calibri
16
11
7
Calibri
18
12
7
Calibri
20
14
9
微软雅黑
10
8
5
微软雅黑
11
9
7
二、openpyxl解决列宽“缩水”技巧
使用openpyxl生成.xlsx文件时,使用下列代码设置列宽:
sheet.column_dimensions['A'].width=X这里的X表示字符数 。但是在生成的.xlsx文件中,实际列宽总是“缩水” 。目前没有深入研究openpyxl源代码,没有证据表明这是代码本身的缺陷 。
另外,运行如下代码,可以知道openpyxl使用Calibri 11磅作为创建文件的默认字体和字号:
from openpyxl import Workbook, styleswb=Workbook()sheet=wb.activedefault_fOnt=styles.DEFAULT_FONTprint('default font:', default_font.name)print('default size:', default_font.size)sheet.save('test.xlsx')但在Win10+Excel 2016环境下,test.xlsx的默认字体是宋体,而不是Calibri,原因未知 。
如何解决这个小缺陷?可以考虑重新设置默认字体和字号,并在设置列宽时加上留白/字符宽度的比值 。相当于加上了留白需要的字符数 。示例代码如下:
from openpyxl import Workbook, styles#重设默认字体和字号styles.DEFAULT_FONT.name='宋体'styles.DEFAULT_FONT.size=10#新建工作簿wb=Workbook()sheet=wb.activesheet.title='test'#设置列宽为字符数+5/7(适用于默认字体为宋体/Arial 10磅)sheet.column_dimensions['A'].width=10+5/7wb.save('test.xlsx')

推荐阅读