2015-04-05 3 views
13

Я хотел бы моделировать функцию автозапуска Excel в xlsxwriter Python. В соответствии с этим URL, он непосредственно не поддерживается: http://xlsxwriter.readthedocs.io/worksheet.htmlИмитировать столбец автоопределения в xslxwriter

Тем не менее, она должна быть достаточно проста в цикле через каждую ячейку на листе и определить максимальный размер для столбца и просто использовать worksheet.set_column (строка, столбец , width), чтобы установить ширину.

Осложнения, что удерживает меня от просто написания этого:

  1. что URL не определяет, какие блоки для третьего аргумента set_column.
  2. Я не могу найти способ измерения ширины элемента, который я хочу вставить в ячейку.
  3. У xlsxwriter отсутствует способ чтения конкретной ячейки. Это означает, что мне нужно отслеживать каждую ширину ячейки, когда я пишу ячейку. Было бы лучше, если бы я мог просто пропустить все ячейки, таким образом можно было бы написать общую рутину.
+1

Попытки установить автоматическую ширину не так просто. Ширина глифа зависит от шрифта. А что, если вы пишете уравнения в ячейку? Тогда вы не можете определить ширину ячейки, основываясь на том, что вы пишете в ней. Единицы произвольны, это правда, но есть реальное определение! Один блок приближается к ширине одного символа в шрифте по умолчанию. См. Https://support.microsoft.com/en-us/kb/214123 –

+0

Связанный с этим вопрос относительно xlwt (общий подход будет таким же для XlsxWriter, хотя вы, вероятно, захотите использовать ширину для Calibri 11 вместо Arial 10) : http://stackoverflow.com/questions/6929115/python-xlwt-accessing-existing-cell-content-auto-adjust-column-width/23946840 –

ответ

2

Я недавно столкнулся с этим же вопросом, и это то, что я придумал:

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 = 0set_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 строку данных. Если у вас будет несколько строк, вам нужно будет определить, какая строка будет иметь самую длинную информацию и применять ее только к этой строке. Но если каждый столбец будет примерно того же размера, независимо от строки, тогда это должно сработать для вас.

Удачи, и я надеюсь, что это поможет!

10

Как правило, вы хотите, чтобы ширина столбцов была немного больше, чем размер самой длинной строки в столбце. С 1 единиц столбцов xlsxwriter примерно равна ширине одного символа. Таким образом, вы можете имитировать автозапуск, установив каждый столбец на максимальное количество символов в этом столбце.

В качестве примера я использую приведенный ниже код при работе с файловыми кадрами pandas и xlsxwriter.

Сначала он находит максимальную ширину индекса, который всегда является левым столбцом для pandas, чтобы превзойти визуализированный dataframe. Затем он возвращает максимум всех значений и имя столбца для каждого из оставшихся столбцов, перемещающихся влево-вправо.

Не нужно слишком сложно адаптировать этот код для любых данных, которые вы используете.

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) 
+0

Что такое метрика? –

+0

Извините, что метрика была именем фрейма данных. обновленный ответ, чтобы сказать ядро ​​данных для ясности. –

4

Я согласен с 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) 
1

Существует еще один обходной путь, чтобы имитировать кнопкуШирина, что я нашел Github site of 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 

Это не затрагивает жирный текст или другие элементы формата, которые могут повлиять на текст размер. Иначе это работает очень хорошо.

Чтобы найти ширину столбцов для AUTOFIT:

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