Задать вопрос

По какой причине excel ругается на файл с объединенными ячейками, сформированный с Python OpenPyXL?

Очень прошу помочь. Перечитал кучу решений в интернете, пока ничто не оказалось полезным. Не могу понять как поправить эту проблему.
Причем, если открывать тот-же файл Libre Office-ом, то все выглядит как должно...
Для примера, прикладываю скриншоты:
так должно 65dda26180f5e520768947.jpeg.
Так выходит с excel: 65dda3dd49c6d915242670.jpeg.
Вот какие ошибки вылетают в процессе открытия файла:
1) 65dda40ad5591467760084.jpeg
2) 65dda42099ed7583993774.jpeg

На всякий случай приложу функцию формирования отчета:
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
  • Вопрос задан
  • 131 просмотр
Подписаться 3 Простой 2 комментария
Решения вопроса 1
@o5a
Проблема в этом:
sheet.merge_cells(start_row=start_row_index + 1, start_column=1, end_row=row_index + 1, end_column=1)

При каждом повторении текста в 1-й колонке (Подразделение) будет повторяться объединение ячеек от начальной (где начался повторяющийся текст) до каждой новой строки, т.е. куча наслаивающихся объединений A2:A3, A2:A4 и т.д.
Это Excel и не нравится. Объединение ячеек должно быть одно на всю группу ячеек, т.е. скажем тут только A2:A14.

Так что измените код, чтобы объединяло не по каждому совпадению, а по окончанию повторяющегося блока, одно объединение на каждый повторяющийся блок.

Можете или свой вариант проверки повторения видоизменить (только чтобы объединяло не более 1 раза на каждый блок повторений), или же просто в самом конце уже после построения всех ячеек согласно повторяющимся данным применить объединения на каждую из групп, например так:
from itertools import groupby

    # из текущего кода убираем все merge_cells, а затем уже после цикла for row_index in ...
    # проходимся по всем повторениям (используем группировку groupby)
    idx = 2
    for k, g in groupby(temp[1:], key = lambda x: x[0]):
        # количество повторяющихся значений
        cnt = len(list(g))
        if cnt > 1:
            sheet.merge_cells(start_row=idx, start_column=1, end_row=idx+cnt-1, end_column=1)
        idx += cnt
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы