Python 3.0:使用 openpyxl 根据其他 2 个单元格的计算值对单元格应用条件格式

问题描述 投票:0回答:1

我正在尝试使用以下命令自动处理表单;
(1) F 列和 G 列中的两个计算字段,并且
(2) H 列中的一个手动输入字段。

  1. 如果一行中的这两个值计算得出> = 30,我想突出显示A列中的相应单元格。

  2. 或者,如果 H 列中的值为“保修 PM”,我想以黄色突出显示 A 列中的相应单元格。

此时,我还没有开始执行函数(2),因为我希望它在函数(1)之后运行,这样它就是优先函数。如果我弄乱了 Excel 的命名约定,我深表歉意!

如果有帮助,以下是我的数据示例:

案例号 状态 当前日期 创建日期 修改日期 创建以来的天数 修改后天数 类型
3051 [今天] 2024 年 11 月 1 日 2024 年 11 月 1 日 =DATEDIF(D2,C2,"d") =DATEDIF(E2,C2,"d") 保修PM
3048 服务已安排 [今天] 2024 年 10 月 31 日 2024 年 11 月 1 日 =DATEDIF(D3,C3,"d") =DATEDIF(E3,C3,"d") 硬件
...
2832 服务已安排 [今天] 2024 年 8 月 20 日 2024 年 8 月 27 日 =DATEDIF(D16,C16,"d") =DATEDIF(E16,C16,"d") 客户要求(搬家)

在我当前的代码中,我能够根据计算值正确突出显示 F 和 G 列。
如果细胞超过 30,这些应该呈浅红色。
这是使用条件格式完成的:

from openpyxl import load_workbook
from openpyxl.styles import PatternFill, NamedStyle
from openpyxl.formatting.rule import CellIsRule

def format_xlsx(xlsx_file):
    #Load the file and workbook
    file_path = xlsx_file
    workbook = load_workbook(file_path)
    sheet = workbook.active

    #Define the fills
    light_red_fill = PatternFill(start_color="FFC7CE", end_color="FFC7CE", fill_type="solid")
    dark_red_fill = PatternFill(start_color="8B0000", end_color="8B0000", fill_type="solid")
    yellow_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")

    #Create conditional format rules for F and G:
    sheet.conditional_formatting.add(
        "F2:F1048576",  # Apply to column F from row 2 onwards
        CellIsRule(operator="greaterThanOrEqual", formula=["30"], fill=light_red_fill))

    sheet.conditional_formatting.add(
        "G2:G1048576",  # Apply to column G from row 2 onwards
        CellIsRule(operator="greaterThanOrEqual", formula=["30"], fill=light_red_fill))
    
    workbook.save(file_path)
    return xlsx_file

但是,如果我尝试包含一个突出显示 A 列中的单元格的函数:

from openpyxl import load_workbook 
from openpyxl.styles import PatternFill, NamedStyle
from openpyxl.formatting.rule import CellIsRule
    
def format_xlsx(xlsx_file): #Load the file and workbook file_path = xlsx_file workbook = load_workbook(file_path) sheet = workbook.active
    #Define the fills
    light_red_fill = PatternFill(start_color="FFC7CE", end_color="FFC7CE", fill_type="solid")
    dark_red_fill = PatternFill(start_color="8B0000", end_color="8B0000", fill_type="solid")
    yellow_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")

    #Create conditional format rules for F and G:
    sheet.conditional_formatting.add(
        "F2:F1048576",  # Apply to column F from row 2 onwards
        CellIsRule(operator="greaterThanOrEqual", formula=["30"], fill=light_red_fill))

    sheet.conditional_formatting.add(
        "G2:G1048576",  # Apply to column G from row 2 onwards
        CellIsRule(operator="greaterThanOrEqual", formula=["30"], fill=light_red_fill))

    #Loop through each cell in columns F and G, ignoring the first row for headers.
    red = "AND($F2>=30, $G2>=30)"
    sheet.conditional_formatting.add(
        "A2:A1048576",  # Apply to column F from row 2 onwards
        CellIsRule(formula=[red], fill=dark_red_fill))

    workbook.save(file_path)
    return xlsx_file

在 Excel 中打开工作簿时出现以下错误:

"We found a problem with some content in 'testfile_04-Nov-2024.xlsx'.
Do you want us to try to recover as much as we can? If you trust the source of this workbook, click Yes."

然后我会看到查看选项

Excel was able to open the file by repairing or removing the unreadable content.

以及 Word 文档中的此错误消息:

Repair Result to testfile_04-Nov-2024.xlsx Errors were detected in file '/Users/llindgren/Downloads/testfile_04-Nov-2024.xlsx'
Removed Records: Conditional formatting from /xl/worksheets/sheet1.xml part

我还尝试对上述所有内容使用不同的函数,但这导致没有突出显示的值:

import openpyxl
from openpyxl.styles import PatternFill

# Load the Excel file
file_path = "your_file.xlsx"
workbook = openpyxl.load_workbook(file_path)
sheet = workbook.active

# Define the fill styles for highlighting
light_red_fill = PatternFill(start_color="FFC7CE", end_color="FFC7CE", fill_type="solid")  # Light red for columns F and G
dark_red_fill = PatternFill(start_color="8B0000", end_color="8B0000", fill_type="solid")   # Dark red for column A

# Loop through each row and check values in columns F and G
for row in range(2, sheet.max_row + 1):  # Starting from row 2 to skip headers if they exist
    cell_f = sheet[f"F{row}"]
    cell_g = sheet[f"G{row}"]
    
    # Check and highlight cells in F and G if their value >= 30
    if cell_f.value is not None and isinstance(cell_f.value, (int, float)):
        if cell_f.value >= 30:
            cell_f.fill = light_red_fill  # Highlight F
            print(f"Highlighted F{row} with light red.")  # Debug statement

    if cell_g.value is not None and isinstance(cell_g.value, (int, float)):
        if cell_g.value >= 30:
            cell_g.fill = light_red_fill  # Highlight G
            print(f"Highlighted G{row} with light red.")  # Debug statement

    # Check if both F and G are >= 30, then apply dark red fill to column A
    if (
        cell_f.value is not None and cell_g.value is not None and
        isinstance(cell_f.value, (int, float)) and isinstance(cell_g.value, (int, float)) and
        cell_f.value >= 30 and cell_g.value >= 30
    ):
        sheet[f"A{row}"].fill = dark_red_fill
        print(f"Highlighted A{row} with dark red.")  # Debug statement

# Save changes to the same file
workbook.save(file_path)
print("File saved successfully.")
python python-3.x excel
1个回答
0
投票

解决您的第一个问题;
如果一行中的这两个值计算得出> = 30,我想突出显示A列中相应的单元格。
您只需使用“FormulaRule”为 A 列添加另一个 CF 规则

使用包含示例数据的工作表,我将用它来填充 3 行,以便数据覆盖范围 A1:H4,添加另一个 CF 规则来检查同一行的 F 和 G 列的值(如果两者都大于或)等于 30 然后突出显示 A

我已经使用附加规则更新了您的第一个代码示例。
该规则使用这个公式

IF(AND($F2>=30,$G2>=30),TRUE,FALSE)

基本上查看 F 列和 G 列中的值,如果两者都大于或等于 30,则突出显示 A 列。
注意:公式规则的额外导入
您似乎不太可能拥有一个使用所有 1048576 行的工作表,但会坚持使用该示例的最大值

from openpyxl import load_workbook
from openpyxl.styles import PatternFill, NamedStyle
from openpyxl.formatting.rule import CellIsRule, FormulaRule  # <--- Add import


def format_xlsx(xlsx_file):
    # Load the file and workbook
    file_path = xlsx_file
    workbook = load_workbook(file_path)
    sheet = workbook.active

    # Define the fills
    light_red_fill = PatternFill(start_color="FFC7CE", end_color="FFC7CE", fill_type="solid")
    dark_red_fill = PatternFill(start_color="8B0000", end_color="8B0000", fill_type="solid")
    yellow_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")

    # Create conditional format rules for F and G:
    sheet.conditional_formatting.add(
        "F2:F1048576",  # Apply to column F from row 2 onwards
        CellIsRule(operator="greaterThanOrEqual", formula=["30"], fill=light_red_fill))

    sheet.conditional_formatting.add(
        "G2:G1048576",  # Apply to column G from row 2 onwards
        CellIsRule(operator="greaterThanOrEqual", formula=["30"], fill=light_red_fill))

    ### Additional Rule for Column A
    sheet.conditional_formatting.add(
        "A2:A1048576",  # Apply to column A from row 2 onwards
        FormulaRule(formula=["IF(AND($F2>=30,$G2>=30),TRUE,FALSE)"], fill=light_red_fill))

    workbook.save(f"new2_{file_path}")
    return xlsx_file


new_file = format_xlsx('cf1.xlsx')

样本表
我已手动将单元格 F3 中的值更改为 31 以进行显示
在下面的示例表中;
在第 2 行中,F 和 G 值低于 30,因此没有任何内容未突出显示
在第 3 行中,F 大于或等于 30,但 G 不大于或等于 30,因此 F 突出显示,而 A 和 G 不突出显示
在第 4 行中,F 和 G 大于或等于 30,因此 A 也突出显示。
F 和 G 列的规则是您原创的

Example Sheet

© www.soinside.com 2019 - 2024. All rights reserved.