10

我正在使用透视表 XLSX 文件并编写脚本以将它们解析为每个选项卡的新文件。

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

为此,我将遍历每一行和每一列,查找第Total0 列中的值。一旦找到,该行应更改为 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 处理样式中的一个错误。我进行了另一个非常简单的编辑并得到了奇怪的行为。

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

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

整个列的输出会发生变化,而不仅仅是单元格。

4

1 回答 1

7

在 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')
于 2015-11-28T17:56:42.643 回答