如何使用 openpyxl 根据 python 中的特定条件格式化 excel 文件的行?

How to format row of excel file based on specific condition in python using openpyxl?

我想突出显示 excel 文件中的特定行,就像每当特定关键字出现在任何行中时,它应该突出显示该行。 例如:打开下面的图片,看看每当单词 "Weekly Avg" 出现在任何行时,它应该突出显示该特定行。

图片:

当前编码:

wb = openpyxl.load_workbook(filename = excel_filename)
sheet_obj = wb.active
sheet_obj.delete_cols(1)

sheet = wb.get_sheet_by_name('Sheet1')
red_font = openpyxl.styles.Font(bold=True)

for row in sheet.iter_rows(values_only=True):
    if 'Weekly Avg' in row:
        for cell in row:
             sheet[str(cell.coordinate)].font = red_font

wb.save(excel_filename)

我尝试了以下方法并成功 运行 但我无法突出显示整行

col = "ABCDEFG"              # to get column
wb = openpyxl.load_workbook(filename = excel_filename)
sheet_obj = wb.active
sheet_obj.delete_cols(1)

sheet = wb.get_sheet_by_name('Sheet1')
for cell in sheet["A"]:
    if "Weekly Avg" in cell.value:
        for i in range(0, len(col)):
            cell_coordinate = col[i]+str(cell.row)            # create cell ID
            sheet[cell_coordinate].font = openpyxl.styles.Font(color='000000FF', bold=True)
wb.save(excel_filename)

你快到了!

在处理 openpyxl 时,我倾向于不必依赖 rowscolumns 的 hard-coded 值,因为数据是动态的,可以很容易地更改以抵消您的hard-coded 值。虽然我的解决方案并不完美,但我已经在 Python 3.6openpyxl 3.0.6 上对其进行了测试,它产生了所需的输出。我相信可以改进逻辑以避免 resource-intensive for 循环。

我选择使用 Named Styles,因为我们要将格式应用到许多 cells 并且根据 openpyxl styles 文档,

In contrast to Cell Styles, Named Styles are mutable. They make sense when you want to apply formatting to lots of different cells at once.

逻辑的其余部分应该是 self-explanatory 来自评论。

import os
from pathlib import Path
from openpyxl import load_workbook
from openpyxl.utils import get_column_letter
from openpyxl.styles import Font, PatternFill, Border, Side, Alignment, NamedStyle


# Define the colors to style the cells
BLACK = "000000"
YELLOW = "FFFF00"

# Define the cell fonts and fills
avg_cell_font = Font(name="Calibri", size=10, color=BLACK, bold=True)
avg_rows_fill = PatternFill(fill_type="solid", fgColor=YELLOW)

# Named style for the average totals rows
avg_totals_style = NamedStyle(
    name="avgTotals",
    font=avg_cell_font,
    fill=avg_rows_fill,
)

# load the workbook
excel_filename = Path(os.path.dirname(os.path.realpath(__file__))).joinpath(
    "averages_test_data.xlsx"
)
wb = load_workbook(filename=excel_filename)

# Register the named style cell formats to the workbook
if avg_totals_style.name not in wb.style_names:
    wb.add_named_style(avg_totals_style)

# get worksheet to apply formats to
ws = wb.active

# get minimum and maximum row numbers with data as strings
first_row_str = str(ws.min_row)
last_row_str = str(ws.max_row)

# get column letters of first and last columns with data
first_col_str = get_column_letter(ws.min_column)
last_col_str = get_column_letter(ws.max_column)

for row_index, row_data in enumerate(
    ws[f"{first_col_str}{first_row_str}:{last_col_str}{last_row_str}"]
):
    avg_total_str = "Weekly Avg"
    avg_totals_check = False
    avg_total_rows = []

    for cell in row_data:
        # check if the cell contains a value
        if cell.value:
            # if any cell contains the "Weekly Avg" string value
            # update the avg_totals_check flag and append that
            # row number to the avg_total_rows list
            if avg_total_str in str(cell.value):
                avg_totals_check = True
                avg_total_rows.append(str(cell.row))

    # if the avg_totals_check flag is True, then
    # iterate each cell in the row number strings in the
    # avg_total_rows list and apply a style to the cells
    if avg_totals_check:
        for row_str in avg_total_rows:
            for cell in ws[f"{row_str}:{row_str}"]:
                cell.style = avg_totals_style.name

# save the workbook
wb.save(filename=excel_filename)