openpyxl python3——格式化整行会导致奇怪的行为

openpyxl python3——格式化整行会导致奇怪的行为,python,openpyxl,Python,Openpyxl,我正在使用pivot表格的XLSX文件,并编写一个脚本,将它们解析为每个选项卡的一个新文件 由于openpyxl默认不支持透视表,我需要做一些工作来重新插入在复制过程中丢失的透视“样式” 为此,我遍历每一行和每一列,查找第0列中的值Total。找到后,该行应更改为allbold=True 相反,我会收到不稳定的行为,有时会在第一个None之后加粗所有单元格。我的print('bolding totals')消息显示它正在正确计算每一行/单元格。我是不是有点头晕目眩,把我的环上的凹痕弄得乱七八糟

我正在使用pivot表格的XLSX文件,并编写一个脚本,将它们解析为每个选项卡的一个新文件

由于openpyxl默认不支持透视表,我需要做一些工作来重新插入在复制过程中丢失的透视“样式”

为此,我遍历每一行和每一列,查找第0列中的值
Total
。找到后,该行应更改为all
bold=True

相反,我会收到不稳定的行为,有时会在第一个
None
之后加粗所有单元格。我的
print('bolding totals')
消息显示它正在正确计算每一行/单元格。我是不是有点头晕目眩,把我的环上的凹痕弄得乱七八糟

from openpyxl import Workbook
from openpyxl import load_workbook
from copy import deepcopy

wb = load_workbook(filename=r'input.xlsx')

# Print 1
sheetlist = wb.get_sheet_names()
print(sheetlist)

for i in range(len(sheetlist)-1):
    dest_filename = r''+sheetlist[i]+'.xlsx'
    new_wb = Workbook()
    ws = wb.get_sheet_by_name(sheetlist[i])
    new_wb.add_sheet(ws, 0)

    for k in range(0, new_wb.worksheets[0].get_highest_row()):
        print(new_wb.worksheets[0].cell(row=k, column=0).value)
        # ignore empty cells
        if new_wb.worksheets[0].cell(row=k, column=0).value is not None:
            if 'Total' in new_wb.worksheets[0].cell(row=k, column=0).value:
                for j in range(0, new_wb.worksheets[0].get_highest_column()):
                    print('bolding totals, '+str(k), str(j))
                    new_wb.worksheets[0].cell(
                        row=k, column=j).style.font.bold = True
            elif 'Total' not in new_wb.worksheets[0].cell(row=k, column=0).value:
                for j in range(0, new_wb.worksheets[0].get_highest_column()):
                    print('not bolding anything')
                    new_wb.worksheets[0].cell(
                        row=k, column=j).style.font.bold = False

    # remove the blank sheet created in new_wb by openpyxl
    new_wb.remove_sheet(new_wb.get_sheet_by_name('Sheet'))
    print(new_wb.get_sheet_names())
    new_wb.save(dest_filename)
    break  # set to break after one sheet for testing

print('finished')

在这一点上,我怀疑这是openpyxl处理样式中的一个bug。我运行了另一个非常简单的编辑,得到了奇怪的行为

如果我们有一个粗体/非粗体单元格的简单布局。 然后我们运行这个简单的命令来更改一个单元格:

>>> new_wb.worksheets[0].cell(row=10,column=0).style.font.bold = False

整个列(而不仅仅是单元格)的输出更改。

在openpyxl 2.0之前,单元格样式在单元格之间共享:这是使用源XML中的指针实现的延迟:两个(或更多)单元格都将使用样式“1”。改变一个细胞的这种风格意味着改变所有细胞的这种风格,这听起来像是这里观察到的行为

从那时起,虽然在实现中进行了各种更改,但在更改一个单元格的样式时不再有任何副作用。一个重要的变化是,格式化对象(如
Font
)可以直接使用,而不必包装在样式中

还有一些其他更改:工作表无法在工作簿之间复制,因为它们依赖于父工作簿中存储的数据

如果没有原始文件,就很难确定,但是下面的代码应该适用于openpyxl>=2.2

from openpyxl import Workbook
from openpyxl import load_workbook

wb = load_workbook(filename='input.xlsx', read_only=True)

for sheet in wb.sheetnames:

    dest_filename = '{0}.xlsx'.format(sheet)
    new_wb = Workbook()
    del new_wb["Sheet"]

    ws1 = wb[sheet]
    ws2 = new_wb.create_sheet(sheet)

    for row in ws1:
        ws2.append([c.value for c in row])
        first = row[0]
        if first.data_type == "s" and "Total" in first.value:
            for idx in range(len(row)):
                cell = ws2.cell(row=ws2.max_row, column=idx+1)
                bolded = cell.font.copy(bold=True)
                cell.font = bolded

    new_wb.save(dest_filename)
    print("saving {0}".format(dest_filename))

print('finished')

您好,
openpyxl
中的bug对我来说并不太令人震惊。我以前对它有意见。对我来说,通过COM端口驱动Excel直接重写整个应用程序比修复
openpyxl
更容易。这是我的帖子,有一个答案;希望它能有所帮助:我投票决定结束这个问题,尽管它写得很好,也很有趣,因为:(a)它没有答案,不管是否被接受;(b) 与实际输出和期望输出的链接失效;(c) OP已近两年没有访问过;(d) 任何相关的openpyxl错误现在都可能已经修复;(e)这仍然是一个悬而未决的问题,尽管它现在实际上无法回答。@AleksanderLidtke我不记得有关于这个问题的错误报告。您的评论似乎暗示openpyxl非常有缺陷,我认为这是不公平的。当然,如果可以的话,直接使用Excel是很好的。您可能还想看看xlwings如何做到这一点。