在openpyxl中,有没有一种方法可以看到应用于一个单元格的条件格式化规则?

1 人关注

我正在使用openpyxl 2.5.6和py 3.7.0。我的目标是读取一个Excel工作簿,并将每个单元格的内容和格式都打印到CSV中。例如,如果一个单元格是蓝色的,有文本 "Data",那么我将在单元格的值上加上"[blu]"的标签,打印到CSV中为"[blu]Data",对于加粗的单元格和其他填充颜色等也是如此。

对于有静态格式的单元格,我可以很好地做到这一点,但对于有条件的格式化就不行。我的问题是,我不知道如何判断一个条件格式化规则是否被应用。我找到了 conditional_formatting._cf_rules 的口令,但我只看到像公式、优先级、dxfId和dxf规则本身的属性。我想相信一个cf规则是否被应用的数据可能存储在某个地方,但我找不到它可能在哪里。

到目前为止,我的代码看起来是这样的。

from openpyxl import load_workbook
wb = load_workbook('Workbook_Name.xlsx', data_only = True)
ws = wb['Worksheet1']
# Code that shows me each cf rule's formula, fill type, priority, etc
cellrangeslist = list(ws.conditional_formatting._cf_rules)
for cellrange in cellrangeslist:
    print('{:30s}{:^10s}{:30s}'.format('----------------------------',str(cellrange.sqref),'----------------------------'))
    for i in cellrange.cfRule:
        print('{:10s}{:8s}{:40s}{:10s}{:10s}'.format(str(i.dxf.fill.bgColor.index), str(i.dxf.fill.bgColor.type), str(i.formula), str(i.stopIfTrue), str(i.priority)))
# This is where I want to be able to identify which cf rule is applied to a given cell
# Code that interprets cell styling into appropriate tags, e.g.
for r in ws.iter_rows(min_row = ws.min_row, max_row = ws.max_row, min_col = ws.min_column, max_col = ws.max_column):
     for cell in r:
          if cell.font.b == True:
                 cell.value = "[bold]"+cell.value
# Code to write each cell as a string literal to a CSV file

My Excel file looks like this,

  • A1 == 1234
  • B1 == 1235
  • C1 == '=A1-B1'
  • 而我的Cf规则是这样的this,

  • Formula: =$A1 - $B1 < 0, Format: [red fill], Applies to: =$C$1
  • Formula: =$A1 - $B1 > 0, Format: [green fill], Applies to: =$C$1
  • 我从上述代码中收到的控制台输出是

    ----------------------------      C1    ----------------------------
    FF92D050  rgb     ['$A1-$B1>0']                           None      2
    FFFF0000  rgb     ['$A1-$B1<0']                           None      1
    

    输出显示规则正确存在,但我想知道是否有办法告诉这些规则中的哪些规则(如果有的话)实际应用到了单元格。

    我越来越怀疑这是在Excel运行时计算出来的东西,所以我的替代方案是写一个Excel公式解释器,但我真的希望通过任何手段避免这样做,因为我不确定我是否有这样的技能。

    2 个评论
    我不认为你可以用Excel中的VBA来做,所以这可能是不可能的。然而,在VBA中,你可以得到C1单元格的颜色,要么是红色,要么是绿色,并以此来确定实际应用的条件。所以这意味着你可以用XLwings来做同样的事情。但不确定openpyxl是否能做到这一点。
    Openpyxl只是让你管理条件格式。你必须编写自己的逻辑来查看它们何时被应用。
    python
    python-3.x
    excel
    openpyxl
    plegerbil9
    plegerbil9
    发布于 2022-05-07
    1 个回答
    moken
    moken
    发布于 2022-05-09
    已采纳
    0 人赞同

    如果你没有找到更好的选择,继我的评论之后,这是一个你可以用Xlwings做的例子。

    对于所示的输出示例,A1比B1的数字高,所以C1单元格是绿色的。
    A1 = 1236
    B1 = 1235
    如果A1被改回1234,C1的颜色恢复为红色,如果在保存工作簿后运行同样的代码,"应用于条件格式单元格的颜色:"将是 "条件格式1",即红色。

    import xlwings as xw
    from xlwings.constants import RgbColor
    def colour_lookup(cfc):
        cell_colour = (key for key, value in colour_dict.items() if value == cfc)
        for key in cell_colour:
            return key
    colour_dict = { key: getattr(RgbColor, key) for key in dir(RgbColor) if not key.startswith('_') }
    wb = xw.Book('test.xlsx)
    ws = wb.sheets('Sheet1')
    cf = ws['C1'].api.FormatConditions
    print("Number of conditional formatting rules: " + str(cf._inner.Count))
    print("Colour applied to conditional format cell:\n\tEnumerated: " +
          str(cf._inner.Parent.DisplayFormat.Interior.Color))
    print("\tRGBColor: " + colour_lookup(cf._inner.Parent.DisplayFormat.Interior.Color))
    print("------------------------------------------------")
    for idx, cf_detail in enumerate(cf, start=1):
        print("Conditional Format " + str(idx))
        print(cf_detail._inner.Formula1)
        print(cf_detail._inner.Interior.Color)
        print("\tRGBColor: " + colour_lookup(cf_detail._inner.Interior.Color))
        print("")
    

    Output

    Number of conditional formatting rules: 2
    Colour applied to conditional format cell:
        Enumerated: 32768.0
        RGBColor: rgbGreen
    ------------------------------------------------
    Conditional Format 1
    =$A1-$B1<0
    255.0
        RGBColor: rgbRed
    Conditional Format 2