Python openpyxl 空白单元格条件格式
Python openpyxl blank cells conditional formating
我在格式化空白单元格时遇到问题。
我的密码是
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,因此它们总是小于第 I 列,并对其进行格式化。我想跳过空白单元格,或将它们格式化为看起来像常规单元格。
我已经尝试了几乎所有来自论坛的建议,但似乎无法修复它。
请给我一些建议。
@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
,因为它低于 I3
。
productC
的所有单元格必须采用默认格式,因为 I 中的单元格为空。
我认为,如果我将我的格式化代码用于 lessThen,而另一个用于空白单元格的公式就可以完成这项工作。但是我无法让它工作。
我设法用 try/error 方法解决了我的问题。
我将 post 我的解决方案放在这里,希望有人会觉得它有用。
最终结果由:
- 将行中的所有单元格放入列表
- 将列表中的所有值与所需值进行比较
- 如果单元格较低 -> 应用格式
最终代码为:
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)
最终结果示例:
我在格式化空白单元格时遇到问题。 我的密码是
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,因此它们总是小于第 I 列,并对其进行格式化。我想跳过空白单元格,或将它们格式化为看起来像常规单元格。
我已经尝试了几乎所有来自论坛的建议,但似乎无法修复它。
请给我一些建议。
@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
,因为它低于 I3
。
productC
的所有单元格必须采用默认格式,因为 I 中的单元格为空。
我认为,如果我将我的格式化代码用于 lessThen,而另一个用于空白单元格的公式就可以完成这项工作。但是我无法让它工作。
我设法用 try/error 方法解决了我的问题。 我将 post 我的解决方案放在这里,希望有人会觉得它有用。 最终结果由:
- 将行中的所有单元格放入列表
- 将列表中的所有值与所需值进行比较
- 如果单元格较低 -> 应用格式
最终代码为:
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)
最终结果示例: