Имитировать столбец автоопределения в 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