You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用openpyxl修改Excel工作表格式且保留原有样式?

解决openpyxl修改单元格格式时原有格式被重置的问题

你的问题出在每次给cell.font赋值全新的Font实例,这会完全覆盖单元格原有的字体属性——没在新Font里指定的属性会使用默认值(比如默认bold=False),所以之前设置的加粗效果会丢失。

核心解决方案

基于单元格已有字体属性,仅修改需要变更的部分,而不是直接替换整个Font对象。具体来说,先获取单元格当前的Font对象,复制其所有属性,再覆盖需要修改的参数,最后赋值回单元格。

修改后的完整代码

from openpyxl import load_workbook
from openpyxl.styles import Font, Color, PatternFill, Border, Side


def bold_italic(wb, ws, path, rows=None, cols=None, bold=None, italic=None):
    # 应用格式的内部函数
    def apply_format(cell_range):
        for row in cell_range:
            for cell in row:
                # 获取单元格现有字体属性
                existing_font = cell.font
                # 基于原有属性创建新字体,仅修改指定参数
                new_font = Font(
                    name=existing_font.name,
                    size=existing_font.size,
                    color=existing_font.color,
                    bold=bold if bold is not None else existing_font.bold,
                    italic=italic if italic is not None else existing_font.italic,
                    underline=existing_font.underline,
                    strike=existing_font.strike,
                    vertAlign=existing_font.vertAlign,
                    outline=existing_font.outline,
                    shadow=existing_font.shadow,
                    condense=existing_font.condense,
                    extend=existing_font.extend
                )
                cell.font = new_font
    
    # 处理行格式
    if rows:
        if isinstance(rows, int):
            apply_format(ws.iter_rows(min_row=rows, max_row=rows))
        elif isinstance(rows, list):
            for row in rows:
                apply_format(ws.iter_rows(min_row=row, max_row=row))
    # 处理列格式
    if cols:
        if isinstance(cols, int):
            apply_format(ws.iter_cols(min_col=cols, max_col=cols))
        elif isinstance(cols, list):
            for col in cols:
                apply_format(ws.iter_cols(min_col=col, max_col=col))

    wb.save(path)


def font_size_color(wb, ws, path, rows=None, cols=None, font_name=None, font_size=None, font_color=None):
    # 应用字体格式的内部函数
    def apply_font(cell_range):
        for row in cell_range:
            for cell in row:
                # 获取单元格现有字体属性
                existing_font = cell.font
                # 基于原有属性创建新字体,仅修改指定参数
                new_font = Font(
                    name=font_name if font_name is not None else existing_font.name,
                    size=font_size if font_size is not None else existing_font.size,
                    color=font_color if font_color is not None else existing_font.color,
                    bold=existing_font.bold,
                    italic=existing_font.italic,
                    underline=existing_font.underline,
                    strike=existing_font.strike,
                    vertAlign=existing_font.vertAlign,
                    outline=existing_font.outline,
                    shadow=existing_font.shadow,
                    condense=existing_font.condense,
                    extend=existing_font.extend
                )
                cell.font = new_font

    # 处理行格式
    if rows:
        if isinstance(rows, int):
            apply_font(ws.iter_rows(min_row=rows, max_row=rows))
        elif isinstance(rows, list):
            for row in rows:
                apply_font(ws.iter_rows(min_row=row, max_row=row))
    # 处理列格式
    if cols:
        if isinstance(cols, int):
            apply_font(ws.iter_cols(min_col=cols, max_col=cols))
        elif isinstance(cols, list):
            for col in cols:
                apply_font(ws.iter_cols(min_col=col, max_col=col))

    wb.save(path)


path = 'Book.xlsx'
workbook = load_workbook(path)
worksheet = workbook['SHEET_1']

bold_italic(workbook, worksheet, path, rows=2, cols=[2,3], bold=True)
font_size_color(workbook, worksheet, path, rows=1, cols=[2,3], font_name='Arial', font_size=12, font_color="FF0000")

关键优化点说明

  1. 参数默认值调整:把函数参数的默认值从False/具体值改成None,区分“用户明确要设置为False”和“用户不想修改该属性”两种场景。
  2. 继承原有属性:新Font对象完全复制原有字体的所有属性,仅替换用户指定的参数,确保原有格式不会丢失。
  3. 可进一步封装通用函数:为减少重复代码,可封装一个通用的字体更新函数:
def update_cell_font(cell, **kwargs):
    existing_font = cell.font
    # 收集原有属性,用传入的参数覆盖指定项
    font_attrs = {
        'name': existing_font.name,
        'size': existing_font.size,
        'color': existing_font.color,
        'bold': existing_font.bold,
        'italic': existing_font.italic,
        'underline': existing_font.underline,
        'strike': existing_font.strike,
        'vertAlign': existing_font.vertAlign,
        'outline': existing_font.outline,
        'shadow': existing_font.shadow,
        'condense': existing_font.condense,
        'extend': existing_font.extend
    }
    font_attrs.update(kwargs)
    cell.font = Font(**font_attrs)

之后在内部函数里只需调用update_cell_font(cell, bold=bold, italic=italic)或update_cell_font(cell, name=font_name, size=font_size, color=font_color)即可,代码更简洁。

内容的提问来源于stack exchange,提问作者dcoolwater0502

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 08:35:12