Python openpyxl 空白单元格条件格式

标签 python excel openpyxl conditional-formatting

我在格式化空白单元格时遇到问题。 我的代码是

import setting_prices
import pandas as pd
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Color, PatternFill, Font, Border
from openpyxl.styles.differential import DifferentialStyle
from openpyxl.formatting.rule import ColorScaleRule, CellIsRule, FormulaRule
import os
from datetime import datetime


def load_file_apply_format():

    wb = load_workbook(filename)
    writer = pd.ExcelWriter(filename, engine='openpyxl')
    writer.book = wb
    prices.to_excel(writer, sheet_name=today_as_str)
    ws = wb[today_as_str]

    redFill = PatternFill(start_color='EE1111',
                              end_color='EE1111',
                              fill_type='solid')
    # whiteFill = PatternFill(start_color='FFFFFF',
    #                           end_color='FFFFFF',
    #                           fill_type='solid')


    ws.conditional_formatting.add('B2:H99',
                                      CellIsRule(operator='lessThan',
                                                 formula=['$I2'],
                                                 stopIfTrue=False, fill=redFill))
    

    writer.save()


prices = setting_prices.df

today_as_str = datetime.strftime(datetime.now(), ' %d_%m_%y')
desktop_path = os.path.expanduser("~/Desktop")

filename = 'price_check.xlsx'


if os.path.exists(filename):
    load_file_apply_format()
else:
    prices.to_excel(filename, sheet_name=today_as_str)
    load_file_apply_format()

我的公式工作得很好,但 Excel 将空白单元格视为 0,因此它们始终小于第一列,并设置它们的格式。我想跳过空白单元格,或将它们格式化为看起来像常规单元格。

我已经尝试了论坛上的几乎所有建议,但似乎无法修复它。

请给我一些建议。

@Greg 使用的答案:

   ws.conditional_formatting.add('B2:H99',
                                  CellIsRule(operator='between',
                                             formula=['1', '$I2'],
                                             stopIfTrue=False, fill=redFill))

导致格式化单元格==我想避免的“I”列。另外,如果“I”列中的单元格为空,则“Between”将设置所有空白单元格的格式。

Example picture

例如: ProductA 的所有单元格都必须采用默认格式,因为它们等于“I”列中的单元格。 对于productB,唯一格式化的单元格必须是G3,因为它低于I3productC 的所有单元格都必须采用默认格式,因为 I 中的单元格为空。

我认为,如果我使用 lessThen 的格式化代码,并且空白单元格的另一个公式就可以完成这项工作。但我没能让它发挥作用。

最佳答案

我设法使用尝试/错误方法解决我的问题。 我将在这里发布我的解决方案,希望有人会发现它有用。 最终结果由:

  1. 将行中的所有单元格放入列表
  2. 将列表中的所有值与所需值进行比较
  3. 如果单元格较低 -> 应用格式

最终代码为:

import ...



def apply_format_to_cell(cell):

    """
    Set background and font color For the current cell
    """

    ft = Font(color="FF0000")
    fill_black = PatternFill(bgColor="FFC7CE", fill_type="solid")

    cell.font = ft
    cell.fill = fill_black

    return cell


def open_existing_file(file_name):
    """
    open an existing file to format cell
    which is meeting a condition
    """

    wb = load_workbook(file_name)
    writer = pd.ExcelWriter(file_name, engine='openpyxl')
    writer.book = wb
    prices.to_excel(writer, sheet_name=today_as_str)
    ws = wb[today_as_str]

    for row in ws.iter_rows(2, ws.max_row, 2):
        """
        1st parameter says to start from 2 row 
        2nd parameter stands for -> till the last row with data. 
        3th parameter says start from 2 COLUMN. 
            In this case this is B2
        """
        cells_in_row = []  # making a list of cells which we will compare
        for cells in row:
            cells_in_row.append(cells)
        for cell in cells_in_row:
            if cell.value is not None and type(cell.value) is not str \
                    and cells_in_row[-1].value is not None and type(cells_in_row[-1].value) is not str:
                """
                Checks if the cell value is not Empty or str ( '' ).
                """

                if cell.value < cells_in_row[-1].value:
                    apply_format_to_cell(cell)
    if wb[f'{today_as_str + "1"}']:
        """
        For the first run only!
        Because: prices.to_excel(writer, sheet_name=today_as_str) will make again sheet
        with the same name -> Excel will put '1' at the end of name 'Sheet_name' > 'Sheet_name1'
        This if will delete this unwanted sheet!
        """
        del wb[f'{today_as_str + "1"}']

    writer.save()


prices = setting_prices.df  # import df with prices

today_as_str = datetime.strftime(datetime.now(), ' %d_%m_%y')
desktop_path = os.path.expanduser("~/Desktop")

filename = 'price_check.xlsx'


if os.path.exists(filename):
    open_existing_file(filename)
else:
    prices.to_excel(filename, sheet_name=today_as_str)
    open_existing_file(filename)

最终结果示例: Final result example

关于Python openpyxl 空白单元格条件格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64943191/

相关文章:

Python 对多个级别的列表列表进行排序并具有自定义顺序

vba - 如何在vba中刷新/加载Excel中的RTD Bloomberg函数(BDH)

java - 将 excel 字段与 java 对象映射的最佳方法

r - 使用命令行时无法通过 openxlsx 包将绘图插入 XLSX

python - openpyxl - x 和 y 轴刻度的增量

python - 转换 pandas 系列和日期时间对象

python - scala:具有可变长度参数的函数对象的特征?

python - 如何验证 pydantic 中的复杂列表类型?

python-3.x - 有没有更有效的方法将列表传递给 excel 文件(使用 Openpyxl)?

python - 从 .xlsx 获取单元格颜色