简体   繁体   中英

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

I want to Highlight specific rows in excel file like whenever a specific keyword occurred in any rows, it should highlight that row. For example: Open below image and see whenever the word "Weekly Avg" will come in any row, it should highlight that specific row.

Image:

单击此链接查看图像

Current coding:

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)

I tried below way and successfully ran but I'm unable to do highlight whole row在这里看图片 .

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)

You were almost there!

I tend not to have to rely on hard-coded values for rows and columns when dealing with openpyxl since data is dynamic and can easily change to offset your hard-coded values. While my solution is not perfect, I have tested it on Python 3.6 and openpyxl 3.0.6 and it produces the desired output. I believe the logic can be improved to avoid the resource-intensive for loops.

I choose to use Named Styles since we are applying formats to many cells and as per the openpyxl styles documentation,

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.

The rest of the Logic should be self-explanatory from the comments.

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM