该 URL 没有指定 set_column 的第三个参数的单位。
列宽是 Calibri 字体中“0”字符宽度的倍数,大小为 11(这是 Excel 标准)。
我找不到测量要插入单元格的项目宽度的方法。
为了掌握字符串的确切宽度,您可以使用tkinter 以像素为单位测量字符串长度的能力,具体取决于字体/大小/重量/等。如果您定义字体,例如
reference_font = tkinter.font.Font(family='Calibri', size=11)
之后您可以使用其measure 方法来确定以像素为单位的字符串宽度,例如
reference_font.measure('This is a string.')
为了对 Excel 表格中的单元格执行此操作,您需要考虑其格式(它包含有关所用字体的所有信息)。这意味着,如果您使用worksheet.write(row, col, cell_string, format) 在您的表格中写了一些东西,您可以像这样获得使用的字体:
used_font = tkinter.font.Font(family = format.font_name,
size = format.font_size,
weight = ('bold' if format.bold else 'normal'),
slant = ('italic' if format.italic else 'roman'),
underline = format.underline,
overstrike = format.font_strikeout)
然后确定单元格宽度为
cell_width = used_font.measure(cell_string+' ')/reference_font.measure('0')
空格被添加到字符串中以提供一些边距。这样结果实际上非常接近 Excel 的自动调整结果,所以我假设 Excel 就是这样做的。
要使tkinter 魔法起作用,tkinter.Tk() 实例(一个窗口)必须打开,因此返回所需单元格宽度的函数的完整代码如下所示:
import tkinter
import tkinter.font
def get_cell_width(cell_string, format = None):
root = tkinter.Tk()
reference_font = tkinter.font.Font(family='Calibri', size=11)
if format:
used_font = tkinter.font.Font(family = format.font_name,
size = format.font_size,
weight = ('bold' if format.bold else 'normal'),
slant = ('italic' if format.italic else 'roman'),
underline = format.underline,
overstrike = format.font_strikeout)
else:
used_font = reference_font
cell_width = used_font.measure(cell_string+' ')/reference_font.measure('0')
root.update_idletasks()
root.destroy()
return cell_width
当然,如果要频繁执行,您当然希望将root 处理和引用字体创建从函数中取出。此外,为您的工作簿使用查找表格式->字体可能会更快,这样您就不必每次都定义使用的字体。
最后,可以处理单元格字符串中的换行符:
pixelwidths = (used_font.measure(part) for part in cell_string.split('\n'))
cell_width = (max(pixelwidths) + used_font.measure(' '))/reference_font.measure('0')
另外,如果您使用 Excel 过滤器功能,下拉箭头符号需要另外 18 个像素(在 Excel 中 100% 放大)。并且可能有跨越多列的合并单元格......还有很大的改进空间!
xlsxwriter 似乎没有读回特定单元格的方法。这意味着我需要在编写单元格时跟踪每个单元格的宽度。如果我可以循环遍历所有单元格会更好,这样就可以编写通用例程。
如果您不喜欢在自己的数据结构中跟踪,至少有三种方法:
(A) 注册一个写处理程序来完成这项工作:
您可以为所有标准类型注册一个写处理程序。在处理函数中,您只需传递 write 命令,还可以进行簿记 wrt。列宽。这样,您只需要在最后(关闭workbook之前)读取并设置最佳列宽。
# add worksheet attribute to store column widths
worksheet.colWidths = [0]*number_of_used_columns
# register write handler
for stdtype in [str, int, float, bool, datetime, timedelta]:
worksheet.add_write_handler(stdtype, colWidthTracker)
def colWidthTracker(sheet, row, col, value, format):
# update column width
sheet.colWidths[col] = max(sheet.colWidths[col], get_cell_width(value, format))
# forward write command
if isinstance(value, str):
if value == '':
sheet.write_blank(row, col, value, format)
else:
sheet.write_string(row, col, value, format)
elif isinstance(value, int) or isinstance(value, float):
sheet.write_number(row, col, value, format)
elif isinstance(value, bool):
sheet.write_boolean(row, col, value, format)
elif isinstance(value, datetime) or isinstance(value, timedelta):
sheet.write_datetime(row, col, value, format)
else:
raise TypeError('colWidthTracker cannot handle this type.')
# and in the end...
for col in columns_to_be_autofitted:
worksheet.set_column(col, col, worksheet.colWidths[col])
(B) 使用karolyi's answer above 遍历XlsxWriter 内部变量中存储的数据。但是,这是 discouraged by the module's author,因为它可能会在未来的版本中中断。
(C) 遵循recommendation of jmcnamara:继承并覆盖默认工作表类并添加一些自动调整代码,例如:xlsxwriter.readthedocs.io/example_inheritance2.html