论文阅读笔记excel的美化
我做了一个论文阅读的excel表格,写python代码帮我美化一下,例如增大每个单元格,调整间距 边框 颜色等,
“D:\aaa计算机论文\aaa论文名记录.xlsx”
# -*- coding: utf-8 -*-
"""
Excel Reading Log Beautifier —— 写死路径版
----------------------------------------
直接运行即可美化固定路径的 Excel:INPUT_PATH
- 自适应列宽(中英混排友好)、行高
- 表头配色、斑马纹、统一细边框
- 冻结首行首列、筛选
- 自动添加 Excel Table
- 可选条件格式:状态列(已读/未读)、评分/优先级数据条依赖:pip install openpyxl
"""import os
import re
import unicodedata
from typing import Optional, Listfrom openpyxl import load_workbook
from openpyxl.styles import Font, Alignment, PatternFill, Border, Side
from openpyxl.utils import get_column_letter
from openpyxl.worksheet.table import Table, TableStyleInfo
from openpyxl.formatting.rule import FormulaRule, DataBarRule# ========= 这里写死路径(按需修改) =========
INPUT_PATH = r"D:\aaa计算机论文\aaa论文名记录.xlsx"
# 输出文件:默认与输入同目录,文件名追加“_美化.xlsx”。如需自定义可填完整路径;设为 None 则用默认规则。
OUTPUT_PATH = None # 例如 r"D:\aaa计算机论文\aaa论文名记录_美化.xlsx"
# 指定仅美化的工作表名;设为 None 表示整本工作簿
SHEET_NAME = None# 外观参数(按需修改)
THEME = "ocean" # 可选:ocean / grape / gray
MIN_WIDTH = 12 # 列宽下限(字符数)
MAX_WIDTH = 40 # 列宽上限(字符数)
ADD_TABLE = True
ADD_FILTER = True
FREEZE = True
BANDED = True
ADD_CONDITIONAL = True
# ==========================================THEMES = {"ocean": {"header_fill": "D9E1F2", "odd_fill": "F7F7F7", "border": "BFBFBF", "table_style": "TableStyleMedium9", "font_color": "000000"},"grape": {"header_fill": "EAE2F8", "odd_fill": "F8F5FC", "border": "C7BFE6", "table_style": "TableStyleMedium7", "font_color": "000000"},"gray": {"header_fill": "EDEDED", "odd_fill": "F9F9F9", "border": "C9C9C9", "table_style": "TableStyleMedium2", "font_color": "000000"},
}def text_display_width(s) -> int:"""估算文本显示宽度:CJK 记为 2,其他 1。"""if s is None:return 0if not isinstance(s, str):s = str(s)w = 0for ch in s:ea = unicodedata.east_asian_width(ch)if ea in ("F", "W"):w += 2elif unicodedata.category(ch) == "Mn":continueelse:w += 1return wdef sanitize_tablename(name: str) -> str:base = re.sub(r"[^A-Za-z0-9_]", "_", name)if not base or not base[0].isalpha():base = "T_" + basereturn base[:200]def detect_column_index_by_header(ws, keywords: List[str]) -> Optional[int]:"""根据表头包含的关键词(任意一个)返回列索引(1-based)。"""headers = {}for c in range(1, ws.max_column + 1):val = ws.cell(1, c).valueif val is None:continueheaders[c] = str(val)for c, name in headers.items():if any(k in name for k in keywords):return creturn Nonedef beautify_sheet(ws, theme: str = "ocean", min_w: int = 12, max_w: int = 40,add_table: bool = True, add_filter: bool = True, freeze: bool = True,banded: bool = True, add_conditional: bool = True):t = THEMES[theme]max_row = ws.max_row or 1max_col = ws.max_column or 1ws.sheet_view.showGridLines = Falseif freeze:ws.freeze_panes = "B2"header_font = Font(name="Microsoft YaHei", bold=True, size=12, color=t["font_color"])body_font = Font(name="Microsoft YaHei", size=11, color=t["font_color"])header_fill = PatternFill("solid", fgColor=t["header_fill"])odd_fill = PatternFill("solid", fgColor=t["odd_fill"])thin_side = Side(style="thin", color=t["border"])thin_border = Border(left=thin_side, right=thin_side, top=thin_side, bottom=thin_side)for col in range(1, max_col + 1):cell = ws.cell(1, col)cell.font = header_fontcell.fill = header_fillcell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)cell.border = thin_borderfor row in range(2, max_row + 1):for col in range(1, max_col + 1):cell = ws.cell(row, col)cell.font = body_fontcell.alignment = Alignment(horizontal="left", vertical="center", wrap_text=True, indent=1)cell.border = thin_borderif banded and (row % 2 == 0):cell.fill = odd_fillws.row_dimensions[1].height = 28for r in range(2, max_row + 1):ws.row_dimensions[r].height = 24for col in range(1, max_col + 1):letter = get_column_letter(col)best = 0for row in range(1, max_row + 1):val = ws.cell(row, col).valuebest = max(best, text_display_width(val))best = min(max_w, max(min_w, best + 2))ws.column_dimensions[letter].width = bestif add_filter and max_row >= 1 and max_col >= 1:used = ws.calculate_dimension()ws.auto_filter.ref = usedif add_table and max_row >= 2 and len(ws.merged_cells.ranges) == 0:try:ref = ws.calculate_dimension()tname = sanitize_tablename(f"T_{ws.title}")table = Table(displayName=tname, ref=ref)style = TableStyleInfo(name=t["table_style"],showFirstColumn=False, showLastColumn=False,showRowStripes=True, showColumnStripes=False)table.tableStyleInfo = stylews.add_table(table)except Exception as e:print(f"[{ws.title}] 跳过添加 Table:{e}")if add_conditional and max_row >= 2 and max_col >= 1:status_col = detect_column_index_by_header(ws, ["状态", "已读", "阅读状态"])if status_col:col_letter = get_column_letter(status_col)rng = f"{col_letter}2:{col_letter}{max_row}"ws.conditional_formatting.add(rng,FormulaRule(formula=[f'ISNUMBER(SEARCH("已读",{col_letter}2)) + ISNUMBER(SEARCH("done",{col_letter}2)) + ISNUMBER(SEARCH("完成",{col_letter}2))'],stopIfTrue=True,fill=PatternFill("solid", fgColor="C6EFCE")))ws.conditional_formatting.add(rng,FormulaRule(formula=[f'ISNUMBER(SEARCH("未读",{col_letter}2)) + ISNUMBER(SEARCH("todo",{col_letter}2)) + ISNUMBER(SEARCH("未完成",{col_letter}2))'],stopIfTrue=True,fill=PatternFill("solid", fgColor="FFC7CE")))score_col = detect_column_index_by_header(ws, ["评分", "分数", "优先级", "priority", "score"])if score_col:col_letter = get_column_letter(score_col)rng = f"{col_letter}2:{col_letter}{max_row}"ws.conditional_formatting.add(rng, DataBarRule(start_type="min", end_type="max", showValue="None"))try:ws.page_setup.fitToWidth = 1ws.page_setup.fitToHeight = 0except Exception:passdef beautify_workbook(input_path: str, output_path: Optional[str] = None,sheet: Optional[str] = None, theme: str = "ocean",min_w: int = 12, max_w: int = 40,add_table: bool = True, add_filter: bool = True, freeze: bool = True,banded: bool = True, add_conditional: bool = True):assert os.path.exists(input_path), f"找不到文件:{input_path}"wb = load_workbook(input_path)sheets = [wb[sheet]] if sheet else wb.worksheetsfor ws in sheets:beautify_sheet(ws, theme, min_w, max_w, add_table, add_filter, freeze, banded, add_conditional)if not output_path:root, ext = os.path.splitext(input_path)output_path = root + "_美化.xlsx"wb.save(output_path)print(f"✅ 已完成美化:{output_path}")return output_pathif __name__ == "__main__":output = OUTPUT_PATH if OUTPUT_PATH else Nonebeautify_workbook(input_path=INPUT_PATH,output_path=output,sheet=SHEET_NAME,theme=THEME,min_w=MIN_WIDTH,max_w=MAX_WIDTH,add_table=ADD_TABLE,add_filter=ADD_FILTER,freeze=FREEZE,banded=BANDED,add_conditional=ADD_CONDITIONAL,)