first commint

This commit is contained in:
suqin
2025-12-06 17:48:48 +08:00
commit 37f211ffc6
14 changed files with 5122 additions and 0 deletions

100
detect_filled_cells.py Normal file
View File

@@ -0,0 +1,100 @@
import csv
from openpyxl import load_workbook
from openpyxl.styles import PatternFill
def resolve_color_hex_from_colorobj(color):
"""Try to resolve an openpyxl Color object to ARGB hex string.
Returns None if cannot resolve.
"""
if color is None:
return None
# direct rgb (may be 'FF00B050' or '00B050')
rgb = getattr(color, "rgb", None)
if rgb:
s = str(rgb)
if len(s) == 6:
s = "FF" + s
return s.upper()
# try indexed (some workbooks may use indexed colors)
idx = getattr(color, "indexed", None) or getattr(color, "index", None)
if idx is not None:
try:
# openpyxl does not always expose a global list here; fallback to None
return f"INDEXED{int(idx)}"
except Exception:
pass
theme = getattr(color, "theme", None)
if theme is not None:
try:
return f"THEME{int(theme)}"
except Exception:
return str(theme)
return None
def detect_colored_cells(xlsx_path, sheet_name=None, write_csv=None):
"""Detect cells with fills (pattern fills) and return list of dicts:
[{'coordinate':'A1','row':1,'col':1,'value':..., 'color': 'FF00B050', 'fill_type': 'solid'}]
If write_csv is provided (path), write the results to that CSV.
"""
wb = load_workbook(xlsx_path, data_only=False)
ws = wb[sheet_name] if sheet_name else wb.active
results = []
min_row = ws.min_row or 1
max_row = ws.max_row or 1
min_col = ws.min_column or 1
max_col = ws.max_column or 1
for row in ws.iter_rows(min_row=min_row, max_row=max_row, min_col=min_col, max_col=max_col):
for cell in row:
fill = cell.fill
if fill is None:
continue
# patternType for PatternFill is fill.fill_type or fill.patternType depending on openpyxl version
pattern = getattr(fill, "patternType", None) or getattr(fill, "fill_type", None)
if pattern in (None, 'none'):
continue
fg = getattr(fill, 'fgColor', None) or getattr(fill, 'start_color', None) or getattr(fill, 'bgColor', None)
color = resolve_color_hex_from_colorobj(fg)
if color is None or color.startswith("FF") is False:
continue
results.append({
'coordinate': cell.coordinate,
'row': cell.row,
'col': cell.column,
'value': cell.value,
'color': color,
'fill_type': pattern,
})
if write_csv:
keys = ['coordinate', 'row', 'col', 'value', 'color', 'fill_type']
with open(write_csv, 'w', newline='', encoding='utf-8') as f:
writer = csv.DictWriter(f, fieldnames=keys)
writer.writeheader()
for r in results:
writer.writerow(r)
return results
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--xlsx', '-x', required=True, help='Path to xlsx file')
parser.add_argument('--sheet', '-s', default=None, help='Sheet name (optional)')
parser.add_argument('--csv', '-c', default=None, help='Write results to CSV')
args = parser.parse_args()
res = detect_colored_cells(args.xlsx, sheet_name=args.sheet, write_csv=args.csv)
for r in res:
print(r)