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

Python xlwt - доступ к существующему содержимому ячейки, автоматическая настройка ширины столбца

Я пытаюсь создать книгу Excel, где я могу автоматически установить или автоматическую настройку ширины столбцов перед сохранением книги.

Я читал учебник Python-Excel в надежде найти некоторые функции в xlwt, которые эмулируют xlrd (например, sheet_names(), cellname(row, col), cell_type, cell_value и т.д.)) Например, предположим, что у меня есть следующее:

from xlwt import Workbook    
wb = Workbook()
sh1 = wb.add_sheet('sheet1' , cell_overwrite_ok = True)    
sh2 = wb.get_sheet(0)

wb.get_sheet(0) похож на функцию rb.sheet_by_index(0), предлагаемую в xlrd, за исключением того, что первая позволяет вам изменять содержимое (при условии, что пользователь установил cell_overwrite_ok = True)

Предполагая, что xlwt DOES предлагают функции, которые я ищу, я планировал продолжить каждый лист, но на этот раз отслеживая содержимое, которое занимает больше всего места для определенного столбца, и установите ширину столбца на основе этого, Конечно, я также могу отслеживать максимальную ширину для определенного столбца, когда я пишу на листе, но я чувствую, что было бы проще устанавливать ширину после того, как все данные уже были записаны.

Кто-нибудь знает, смогу ли я это сделать? Если нет, что вы рекомендуете делать, чтобы настроить ширину столбцов?

4b9b3361

Ответ 1

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

import arial10

class FitSheetWrapper(object):
    """Try to fit columns to max size of any entry.
    To use, wrap this around a worksheet returned from the 
    workbook add_sheet method, like follows:

        sheet = FitSheetWrapper(book.add_sheet(sheet_name))

    The worksheet interface remains the same: this is a drop-in wrapper
    for auto-sizing columns.
    """
    def __init__(self, sheet):
        self.sheet = sheet
        self.widths = dict()

    def write(self, r, c, label='', *args, **kwargs):
        self.sheet.write(r, c, label, *args, **kwargs)
        width = arial10.fitwidth(label)
        if width > self.widths.get(c, 0):
            self.widths[c] = width
            self.sheet.col(c).width = width

    def __getattr__(self, attr):
        return getattr(self.sheet, attr)

Вся магия находится в модуле John Yeung arial10. Это имеет хорошую ширину для Arial 10, которая является шрифтом Excel по умолчанию. Если вы хотите писать рабочие листы с использованием других шрифтов, вам нужно будет изменить функцию fitwidth, в идеале с учетом аргумента style, переданного в FitSheetWrapper.write.

Ответ 2

В xlwt нет автоматического средства для этого. Вы должны следовать общему шаблону, который вы описываете, отслеживать максимальную ширину при написании и устанавливать ширину столбца в конце, когда-нибудь после того, как вы просмотрите все данные, но до того, как сохраните книгу.

Обратите внимание, что это самый чистый и эффективный подход, доступный при работе с файлами Excel. Если ваше понятие "после того, как данные уже были написаны" означает, что после того, как вы уже зафиксировали значения ячейки ( "запись" ), но до фактического сохранения рабочей книги, метод, описанный выше, выполняет именно это. Если вы имеете в виду, что после того, как вы уже сохранили книгу, вы хотите прочитать ее снова, чтобы получить максимальную ширину, а затем снова сохранить ее с новыми ширинами столбцов, это будет намного медленнее и будет включать использование как xlwt, так и xlrd (и, возможно, xlutils). Также обратите внимание, что, когда вы используете подлинный Microsoft Excel, нет понятия "обновления" файла. Это может показаться с точки зрения пользователя, но то, что происходит за кулисами, заключается в том, что каждый раз, когда вы делаете сохранение, Excel сбрасывает существующий файл и пишет совершенно новый с нуля.

Ответ 3

Если вы не заинтересованы в использовании другого класса (FitSheetWrapper), это можно реализовать с помощью столбца WorkSheet Method.

work = xlwt.WorkBook()
sheet = work.add_sheet('Sheet1')
for row_index in range(0,max_row):
   for column_index in range(0,max_col) :
      cwidth = sheet.col(column_index).width
      if (len(column_data)*367) > cwidth:  
          sheet.col(column_index).width = (len(column_data)*367) #(Modify column width to match biggest data in that column)

      sheet.write(row_index,column_index,column_data,style)

Значение по умолчанию для ширины составляет 2962 единицы, а excel - 8,11 единиц. Поэтому я умножаю 367 на длину данных.

Это адаптировано для Kevins FitSheetWrapper.

Ответ 4

FitSheetWrapper должен немного изменить с помощью xlwt3 в 3.3.4

строка 19:

изменение:

width = arial10.fitwidth(label)

в

width = int(arial10.fitwidth(label))  

Причина: \ Python\3.3.3\Lib\сайт-пакеты\xlwt3\biffrecords.py

1624 def __init__(self, first_col, last_col, width, xf_index, options):
1625        self._rec_data = pack('<6H', first_col, last_col, width, xf_index, options, 0)

width должно быть целым.

Ответ 5

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

from xlrd import *
from xlwt import *

def autoAdjustColumns(workbook, path, writerSheet, writerSheet_index, extraCushion):
    readerSheet = open_workbook(path).sheet_by_index(writerSheet_index)
    for row in range(readerSheet.nrows):
            for column in range(readerSheet.ncols):
                    thisCell = readerSheet.cell(row, column)
                    neededWidth = int((1 + len(str(thisCell.value))) * 256) 
                    if writerSheet.col(column).width < neededWidth:
                            writerSheet.col(column).width = neededWidth + extraCushion
    workbook.save(path)

Ответ 6

Я использую этот метод:

wb = Workbook()
ws = wb.add_sheet('Sheet1')
columnwidth = {}
row = 0
for rowdata in data:
    column = 0
    for colomndata in rowdata:
        if column in columnwidth:
            if len(colomndata) > columnwidth[column]:
                columnwidth[column] = len(colomndata)
        else:
            columnwidth[column] = len(colomndata)
        ws.write(row, column, colomndata, style0)
        column = column + 1
    row = row + 1
for column, widthvalue in columnwidth.items():
    ws.col(column).width = (widthvalue + 4) * 367