Как можно использовать библиотеку xlwt в Python, чтобы объединить ячейки с одинаковыми значениями в столбце?

Как можно улучшить функцию формирования excel файла?
Изображение к вопросу
Изображение к вопросу
  • 7 февраля 2024 г. 8:19
Ответы на вопрос 2
Библиотека `xlwt` используется в Python для записи файлов в формате Excel (.xls). Чтобы объединить ячейки с одинаковыми значениями в столбце, следует выполнить следующие шаги:

1. Итерировать по столбцу, запоминая индекс ряда, где начинается новая группа одинаковых ячеек.
2. Когда вы находите ячейку со значением, отличным от предыдущих, использовать метод `Worksheet.write_merge`, чтобы объединить ряды от начального индекса до текущего индекса минус один.

Важно отметить, что `xlwt` может справляться только с файлами в формате `.xls`, которые имеют ограничения, такие как максимальное количество рядов в листе - 65536 и столбцов - 256. Для работы с более новым форматом `.xlsx`, используйте библиотеку `openpyxl` или `xlsxwriter`.

Ниже пример функции, которая использует `xlwt` для создания файла Excel и объединения ячеек с одинаковыми значениями в одноименном столбце:

```python
import xlwt

def merge_cells_in_column(sheet, column_index):
    current_value = None
    start_row_index = 0

    for row_index in range(sheet.nrows):
        cell_value = sheet.cell_value(row_index, column_index)
        if cell_value != current_value:
            if row_index > start_row_index:
                sheet.write_merge(start_row_index, row_index - 1, column_index, column_index, current_value)
            start_row_index = row_index
            current_value = cell_value
    
    # Объединение последней группы ячеек, если она существует
    if sheet.nrows > start_row_index:
        sheet.write_merge(start_row_index, sheet.nrows - 1, column_index, column_index, current_value)

# Создание нового Excel файла и листа
workbook = xlwt.Workbook()
worksheet = workbook.add_sheet('Sheet 1')

# Добавление данных в лист (например, значения в первом столбце повторяются)
values = ['A', 'A', 'B', 'B', 'B', 'C', 'C']
for i, value in enumerate(values):
    worksheet.write(i, 0, value)

# Объединение ячеек
merge_cells_in_column(worksheet, 0)

# Сохранение файла
workbook.save('output.xls')
```
Обратите внимание, что функция `merge_cells_in_column` предполагает, что данные уже записаны в лист, и она будет объединять ячейки на основе этих данных.

Для улучшения функции формирования Excel-файла, рассмотрите следующие аспекты:

1. Убедитесь, что ваша программа обрабатывает различные типы данных корректно (даты, числа, строки).
2. Добавьте стилизацию, чтобы улучшить визуальный аспект таблицы (например, шрифты, выравнивание, границы).
3. Используйте исключения, чтобы обработать возможные ошибки при записи данных.
4. Рассмотрите возможность добавления возможности работы с `.xlsx` файлами, используя библиотеку `openpyxl` или `xlsxwriter`.
5. Подумайте о параметризации вашей функции, чтобы сделать её более гибкой и универсальной (например, пусть функция принимает имя файла в качестве аргумента).
Так ничего и не вышло у меня с библиотекой xlwt. 
Пришлось использовать библиотеку openpyxl.
Код рабочий, только не стал объединять ячейки из последнего столбца.
Может кому-нибудь пригодится.
def export_excel(request):

    response = HttpResponse(content_type='application/vnd.ms-excel')
    response['Content-Disposition'] = ("attachment; filename=Numbers_" + str(datetime.datetime.now().strftime("%d/%m/%y")) + '.xlsx')
    workbook = openpyxl.Workbook()
    sheet = workbook.active
    headers = ('Подразделение',
               'Номер',
               'Сумма',
               'Итог (Сумма+ндс+абон.плата)',
               'Итог по подразделению')

    rows_parser = ReportFilter(request.GET, queryset=Parser.objects.all().values_list(
        'attachment__attachment', 'number', 'pay', 'result'
    )).qs
    rows_numbers = ReportFilterNumbers(request.GET, queryset=Numbers.objects.filter(is_enabled=True).values_list(
        'attachment__attachment', 'number'
    )).qs

    res = 0
    temp = []
    subFee = float(str(SubscriptionFee.objects.get(pk=1)))

    for item1 in rows_parser:
        temp.append(item1)
        res += item1[3]

    for item2 in rows_numbers:
        if Parser.objects.filter(number=item2[1]):
            None
        else:
            if Numbers.objects.filter(number=item2[1], cf=True):
                item2 = list(item2)
                item2.extend([0, 0])
                res += item2[3]
                item2 = tuple(item2)
                temp.append(item2)
            else:
                item2 = list(item2)
                item2.extend([subFee, subFee])
                res += item2[3]
                item2 = tuple(item2)
                temp.append(item2)

    temp.sort()

    itog = 0
    for row in range(len(temp)):
        itog += temp[row][3]

    temp.insert(0, headers)
    temp = tuple(temp)

    current_value = temp[1][0]
    start_row_index = 1
    now3 = 0
    sheet.append(headers)

    for row_index in range(1, len(temp)):
        cell_value = temp[row_index][0]
        if cell_value != current_value:
            sheet.append(temp[row_index])
            sheet.cell(row=row_index, column=5).value = now3
            now3 = temp[row_index][3]
            start_row_index = row_index
            current_value = cell_value

        elif cell_value == current_value:
            now3 += temp[row_index][3]
            sheet.append(temp[row_index])
            sheet.merge_cells(start_row=start_row_index + 1, start_column=1, end_row=row_index + 1, end_column=1)
            start_row_index = row_index
            current_value = cell_value

    sheet.cell(row=row_index + 1, column=5).value = now3
    sheet.cell(row=row_index + 2, column=3).value = 'ОБЩИЙ ИТОГ:'
    sheet.cell(row=row_index + 2, column=4).value = itog
    workbook.save(response)
    
    return response
Похожие вопросы