Имитировать столбец автоопределения в xslxwriter
Я хотел бы симулировать функцию автозапуска Excel в Python xlsxwriter. Согласно этому URL-адресу он не поддерживается напрямую:
http://xlsxwriter.readthedocs.io/worksheet.html
Тем не менее, должно быть довольно просто прокрутить каждую ячейку на листе и определить максимальный размер для столбца и просто использовать таблицу workheet.set_column (row, col, width) для установки ширины.
Сложности, которые мешают мне просто написать это:
- В этом URL-адресе не указано, какие единицы относятся к третьему аргументу для set_column.
- Я не могу найти способ измерения ширины элемента, который я хочу вставить в ячейку.
- xlsxwriter, похоже, не имеет метода для чтения конкретной ячейки. Это означает, что мне нужно отслеживать каждую ширину ячейки, когда я пишу ячейку. Было бы лучше, если бы я мог просто пропустить все ячейки, таким образом можно было бы написать общую процедуру.
Ответы
Ответ 1
Как правило, вы хотите, чтобы ширина столбцов была немного больше, чем размер самой длинной строки в столбце. С 1 единиц столбцов xlsxwriter примерно равна ширине одного символа. Таким образом, вы можете имитировать автозапуск, установив каждый столбец на максимальное количество символов в этом столбце.
В качестве примера я обычно использую код ниже при работе с pandas файлами данных и xlsxwriter.
Сначала он находит максимальную ширину индекса, который всегда является левым столбцом для pandas, чтобы преуспеть визуализированный фрейм. Затем он возвращает максимум всех значений и имя столбца для каждого из оставшихся столбцов, перемещающихся влево-вправо.
Не нужно слишком сложно адаптировать этот код для любых данных, которые вы используете.
def get_col_widths(dataframe):
# First we find the maximum length of the index column
idx_max = max([len(str(s)) for s in dataframe.index.values] + [len(str(dataframe.index.name))])
# Then, we concatenate this to the max of the lengths of column name and its values for each column, left to right
return [idx_max] + [max([len(str(s)) for s in dataframe[col].values] + [len(col)]) for col in dataframe.columns]
for i, width in enumerate(get_col_widths(dataframe)):
worksheet.set_column(i, i, width)
Ответ 2
Я согласен с Cole Diamond. Мне нужно было сделать что-то очень похожее, это сработало хорошо для меня. где self.columns - мой список столбцов
def set_column_width(self):
length_list = [len(x) for x in self.columns]
for i, width in enumerate(length_list):
self.worksheet.set_column(i, i, width)
Ответ 3
Недавно я столкнулся с этой проблемой, и именно это я придумал:
r = 0
c = 0
for x in list:
worksheet.set_column('{0}:{0}'.format(chr(c + ord('A'))), len(str(x)) + 2)
worksheet.write(r, c, x)
c += 1
В моем примере r
будет номером строки, на который вы выводите, c
будет номером столбца, который вы выводите (индексируется как 0), а x
будет значением из list
, которое вы хотите быть в камере.
фрагмент '{0}:{0}'.format(chr(c + ord('A')))
содержит предоставленный номер столбца и преобразует его в письмо столбца, принятое xlsxwriter, поэтому, если c = 0
set_column
будет видеть 'A:A'
, если c = 1
, то он увидит 'B:B'
, и т.д.
фрагмент len(str(x)) + 2
определяет длину строки, которую вы пытаетесь вывести, затем добавляет 2 к ней, чтобы гарантировать, что ячейка excel достаточно широка, поскольку длина строки не точно коррелирует с шириной ячейки. Возможно, вы захотите сыграть, вместо того, чтобы добавить 2
или, возможно, больше в зависимости от ваших данных.
Единицы, которые принимает xlsxwriter, немного сложнее объяснить. Когда вы находитесь в режиме excel, и вы наведите указатель мыши туда, где вы можете изменить ширину столбца, вы увидите Width: 8.43 (64 pixels)
. В этом примере единица, которую он принимает, - это 8.43
, который, я думаю, равен сантиметрам? Но excel даже не предоставляет единицу, по крайней мере, неявно.
Примечание. Я только пробовал этот ответ на файлах excel, содержащих 1 строку данных. Если у вас будет несколько строк, вам нужно будет определить, какая строка будет иметь самую длинную информацию и применять ее только к этой строке. Но если каждый столбец будет примерно того же размера, независимо от строки, тогда это должно сработать для вас.
Удачи, и я надеюсь, что это поможет!
Ответ 4
Существует еще одно обходное решение для моделирования Autofit, которое я нашел сайт Github xlsxwriter. Я изменил его, чтобы вернуть приблизительный размер горизонтального текста (ширина столбца) или 90 ° повернутого текста (высота строки):
from PIL import ImageFont
def get_cell_size(value, font_name, font_size, dimension="width"):
""" value: cell content
font_name: The name of the font in the target cell
font_size: The size of the font in the target cell """
font = ImageFont.truetype(font_name, size=font_size)
(size, h) = font.getsize(str(value))
if dimension == "height":
return size * 0.92 # fit value experimentally determined
return size * 0.13 # fit value experimentally determined
Это не относится к жирным текстам или другим элементам формата, которые могут повлиять на размер текста. В противном случае он работает очень хорошо.
Чтобы найти ширину столбцов для автоподстройки:
def get_col_width(data, font_name, font_size, min_width=1):
""" Assume 'data' to be an iterable (rows) of iterables (columns / cells)
Also, every cell is assumed to have the same font and font size.
Returns a list with the autofit-width per column """
colwidth = [min_width for col in data[0]]
for x, row in enumerate(data):
for y, value in enumerate(row):
colwidth[y] = max(colwidth[y], get_cell_size(value, font_name, font_size))
return colwidth