Подтвердить что ты не робот

Openpyxl - регулировка ширины столбца

У меня есть следующий script, который преобразует CSV файл в файл XLSX, но размер столбца очень узкий. Каждый раз, когда мне приходится перетаскивать их мышью, чтобы читать данные. Кто-нибудь знает, как установить ширину столбца в openpyxl?

Вот код, который я использую.

#!/usr/bin/python2.6
import csv
from openpyxl import Workbook
from openpyxl.cell import get_column_letter

f = open('users_info_cvs.txt', "rU")

csv.register_dialect('colons', delimiter=':')

reader = csv.reader(f, dialect='colons')

wb = Workbook()
dest_filename = r"account_info.xlsx"

ws = wb.worksheets[0]
ws.title = "Users Account Information"

for row_index, row in enumerate(reader):
    for column_index, cell in enumerate(row):
        column_letter = get_column_letter((column_index + 1))
        ws.cell('%s%s'%(column_letter, (row_index + 1))).value = cell

wb.save(filename = dest_filename)
4b9b3361

Ответ 1

Вы можете оценить (или использовать моноширинный шрифт) для достижения этой цели. Предположим, что данные - это вложенный массив, например [['a1', 'a2'], ['b1', 'b2']]

Мы можем получить максимальное количество символов в каждом столбце. Затем установите ширину для этого. Ширина точно соответствует ширине моноширинного шрифта (если не меняет другие стили, по крайней мере). Даже если вы используете шрифт переменной ширины, это достойная оценка. Это не будет работать с формулами.

column_widths = []
for row in data:
    for i, cell in enumerate(row):
        if len(column_widths) > i:
            if len(cell) > column_widths[i]:
                column_widths[i] = len(cell)
        else:
            column_widths += [len(cell)]

for i, column_width in enumerate(column_widths):
    worksheet.column_dimensions[get_column_letter(i+1)].width = column_width

Немного взломать, но ваши отчеты будут более читабельными.

Ответ 2

Мой вариант ответа Буфке. Избегает небольшого ветвления с массивом и игнорирует пустые ячейки/столбцы.

Теперь исправлено для нестроковых значений ячеек.

ws = your current worksheet
dims = {}
for row in ws.rows:
    for cell in row:
        if cell.value:
            dims[cell.column] = max((dims.get(cell.column, 0), len(str(cell.value))))    
for col, value in dims.items():
    ws.column_dimensions[col].width = value

Ответ 3

Еще более питоновский способ установить ширину всех столбцов, которые работают хотя бы в openpyxl версии 2.4.0:

for column_cells in worksheet.columns:
    length = max(len(as_text(cell.value)) for cell in column_cells)
    worksheet.column_dimensions[column_cells[0].column].width = length

Функция as_text должна быть чем-то, что преобразует значение в строку правильной длины, например, для Python 3:

def as_text(value):
    if value is None:
        return ""
    return str(value)

Ответ 4

У меня проблема с merged_cells, и autosize не работает правильно, если у вас есть та же проблема, вы можете решить следующий код:

for col in worksheet.columns:
    max_length = 0
    column = col[0].column # Get the column name
    for cell in col:
        if cell.coordinate in worksheet.merged_cells: # not check merge_cells
            continue
        try: # Necessary to avoid error on empty cells
            if len(str(cell.value)) > max_length:
                max_length = len(cell.value)
        except:
            pass
    adjusted_width = (max_length + 2) * 1.2
    worksheet.column_dimensions[column].width = adjusted_width

Ответ 5

Небольшое улучшение принятого выше ответа, которое, я думаю, более pythonic (просить прощения лучше, чем просить разрешения)

column_widths = []
for row in workSheet.iter_rows():
    for i, cell in enumerate(row):
        try:
            column_widths[i] = max(column_widths[i], len(cell.value))
        except IndexError:
            column_widths.append(len(cell.value))

for i, column_width in enumerate(column_widths):
    workSheet.column_dimensions[get_column_letter(i + 1)].width = column_width

Ответ 6

Это моя версия со ссылкой на фрагмент кода @Virako

def adjust_column_width_from_col(ws, min_row, min_col, max_col):

        column_widths = []

        for i, col in \
                enumerate(
                    ws.iter_cols(min_col=min_col, max_col=max_col, min_row=min_row)
                ):

            for cell in col:
                value = cell.value
                if value is not None:

                    if isinstance(value, str) is False:
                        value = str(value)

                    try:
                        column_widths[i] = max(column_widths[i], len(value))
                    except IndexError:
                        column_widths.append(len(value))

        for i, width in enumerate(column_widths):

            col_name = get_column_letter(min_col + i)
            value = column_widths[i] + 2
            ws.column_dimensions[col_name].width = value

И как использовать это следующим образом,

adjust_column_width_from_col(ws, 1,1, ws.max_column)

Ответ 7

Все вышеприведенные ответы порождают проблему, заключающуюся в том, что col [0].column возвращает число, в то время как worksheet.column_dimensions [column] принимает только такие символы, как "A", "B", "C" вместо столбца. Я изменил код @Virako, и теперь он работает нормально.

import re
import openpyxl
..
for col in _ws.columns:
    max_lenght = 0
    print(col[0])
    col_name = re.findall('\w\d', str(col[0]))
    col_name = col_name[0]
    col_name = re.findall('\w', str(col_name))[0]
    print(col_name)
    for cell in col:
        try:
            if len(str(cell.value)) > max_lenght:
                max_lenght = len(cell.value)
        except:
            pass
    adjusted_width = (max_lenght+2)
    _ws.column_dimensions[col_name].width = adjusted_width

Ответ 8

Мы можем преобразовать числа в их значения ASCII и передать их параметру column_dimension

import openpyxl as xl

work_book = xl.load_workbook('file_location')
sheet = work_book['Sheet1']
column_number = 2
column = str(chr(64 + column_number))
sheet.column_dimensions[column].width = 20
work_book.save('file_location')

Ответ 9

Я должен был изменить @User3759685 выше ответ на этот вопрос при обновлении openpxyl. Я получил ошибку. Ну, @phihag сообщил об этом и в комментариях

for column_cells in ws.columns:
    new_column_length = max(len(as_text(cell.value)) for cell in column_cells)
    new_column_letter = (openpyxl.utils.get_column_letter(column_cells[0].column))
    if new_column_length > 0:
        ws.column_dimensions[new_column_letter].width = new_column_length + 1