Python-openpyxl高级操作

54 阅读9分钟

获取单元格属性

单元格基本信息

除了 value(值),单元格还有以下常用属性:

属性说明示例
cell.row行号(从1开始)2
cell.column列号(从1开始)2
cell.coordinate坐标'B2'
cell.value单元格值'李白'

代码示例:

from openpyxl import load_workbook

filePath = r'D:\王者小学.xlsx'
workbook = load_workbook(filePath)
sheet = workbook["花名册"]

# 获取单元格
cell = sheet["B2"]  # 李白
cell2 = sheet["C4"]  # 96

# 打印单元格属性
print(f"单元格 {cell.coordinate}:")
print(f"   行号: {cell.row}")
print(f"   列号: {cell.column}")
print(f"   值: {cell.value}")

print(f"\n单元格 {cell2.coordinate}:")
print(f"   行号: {cell2.row}")
print(f"   列号: {cell2.column}")
print(f"   值: {cell2.value}")

运行结果:

单元格 B2:
   行号: 2
   列号: 2
   值: 李白

单元格 C4:
   行号: 4
   列号: 3
   值: 96

应用场景:

  • 遍历单元格时需要知道当前位置
  • 根据行列号进行条件判断
  • 动态生成坐标

获取区域数据进阶

按列获取数据:sheet.iter_cols()

上一篇我们学了 iter_rows() 按行获取数据,现在学习 iter_cols() 按列获取:

from openpyxl import load_workbook

filePath = r'D:\王者小学.xlsx'
workbook = load_workbook(filePath)
sheet = workbook["花名册"]

# 按列获取数据(第1-2列,第1-4行)
print("按列获取数据:\n")
for col in sheet.iter_cols(min_row=1, max_row=4, min_col=1, max_col=2):
    print(f"列数据: {[cell.value for cell in col]}")

运行结果:

按列获取数据:

列数据: ['学号', '1', '2', '3']
列数据: ['姓名', '李白', '甄姬', '后羿']

对比记忆:

  • iter_rows() → 横向遍历,一行一行读取
  • iter_cols() → 纵向遍历,一列一列读取

快速获取所有行列:sheet.rows / sheet.columns

from openpyxl import load_workbook

filePath = r'D:\王者小学.xlsx'
workbook = load_workbook(filePath)
sheet = workbook["花名册"]

# 获取所有行
print("所有行数据:")
for row in sheet.rows:
    print([cell.value for cell in row])

# 获取所有列
print("\n所有列数据:")
for col in sheet.columns:
    print([cell.value for cell in col])

效果等同于:

  • sheet.rows = sheet.iter_rows()
  • sheet.columns = sheet.iter_cols()

注意:这两个属性会加载所有数据,大数据量时建议使用 iter_rows() / iter_cols()


行列操作

插入空行/空列

方法语法说明
插入行sheet.insert_rows(idx, amount)在 idx 行前插入 amount 行
插入列sheet.insert_cols(idx, amount)在 idx 列前插入 amount 列

代码示例:

from openpyxl import load_workbook

filePath = r'D:\王者小学.xlsx'
workbook = load_workbook(filePath)
sheet = workbook['花名册']

# 在第3行前插入2行空行
sheet.insert_rows(idx=3, amount=2)

# 在第2列前插入1列空列
sheet.insert_cols(idx=2, amount=1)

workbook.save(r'D:\王者小学_插入行列.xlsx')
print("插入完成!")

参数说明:

  • idx:插入位置(行号/列号)
  • amount:插入数量(默认1)

删除行/列

方法语法说明
删除行sheet.delete_rows(idx, amount)从 idx 行开始删除 amount 行
删除列sheet.delete_cols(idx, amount)从 idx 列开始删除 amount 列

代码示例:

from openpyxl import load_workbook

filePath = r'D:\王者小学_插入行列.xlsx'
workbook = load_workbook(filePath)
sheet = workbook['花名册']

# 删除第3-4行(2行)
sheet.delete_rows(idx=3, amount=2)

# 删除第2列(1列)
sheet.delete_cols(idx=2, amount=1)

workbook.save(r'D:\王者小学_恢复.xlsx')
print("删除完成!")

注意:删除操作不可逆,建议先备份文件!


工作表管理

新建工作表

from openpyxl import load_workbook

filePath = r'D:\王者小学.xlsx'
workbook = load_workbook(filePath)

# 创建新工作表
workbook.create_sheet("身高")
print(f"所有工作表: {workbook.sheetnames}")

# 获取新工作表并写入数据
sheet = workbook["身高"]
data = [
    ['学号', '身高'],
    ['1', '168'],
    ['2', '181'],
    ['3', '160'],
]

for row in data:
    sheet.append(row)

workbook.save(filePath)
print("新工作表创建完成!")


删除工作表

两种方式:

from openpyxl import load_workbook

filePath = r'D:\王者小学.xlsx'
workbook = load_workbook(filePath)

print(f"删除前: {workbook.sheetnames}")

# 方式1:使用 del
del workbook['身高']

# 方式2:使用 remove()
# sheet = workbook['身高']
# workbook.remove(sheet)

print(f"删除后: {workbook.sheetnames}")
workbook.save(filePath)

Image 4

注意:

  • 工作表名区分大小写
  • 表名不存在会报错

新建 Excel 文件并修改表名

from openpyxl import Workbook

# 创建新工作簿
workbook = Workbook()

# 获取默认工作表并修改名称
sheet = workbook.active
sheet.title = "学生信息"

# 写入数据
sheet.append(['姓名', '年龄', '成绩'])
sheet.append(['张三', 18, 95])

# 保存
workbook.save(r"D:\新建Excel.xlsx")
print("新文件创建完成!")

对比:

  • load_workbook() → 打开已有文件
  • Workbook() → 创建新文件

设置表格样式

样式属性一览

样式类作用
字体Font设置字体、大小、颜色、加粗等
填充PatternFill设置背景颜色
对齐Alignment设置水平/垂直对齐
边框Border + Side设置单元格边框

完整样式设置示例

from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side, colors

# 打开文件
filePath = r"D:\2021年销售分析\全年数据.xlsx"
wb = load_workbook(filePath)
ws = wb.active

# 1. 调整列宽
ws.column_dimensions["A"].width = 25
ws.column_dimensions["B"].width = 10
ws.column_dimensions["C"].width = 10

# 2. 定义样式

# 字体样式
font = Font(
    name="微软雅黑",      # 字体名称
    size=12,             # 字体大小
    color=colors.BLACK,  # 字体颜色
    bold=False           # 是否加粗
)

# 背景填充(浅灰色)
fill = PatternFill(
    fill_type="solid",
    start_color="CDCDCD",
    end_color="CDCDCD"
)

# 对齐方式(居中)
alignment = Alignment(
    horizontal="center",  # 水平居中
    vertical="center"     # 垂直居中
)

# 边框样式(细黑线)
side = Side(
    border_style="thin",
    color=colors.BLACK
)
border = Border(
    left=side, right=side,
    top=side, bottom=side
)

# 3. 应用样式到所有单元格
for row in ws.rows:
    for cell in row:
        cell.font = font
        cell.fill = fill
        cell.alignment = alignment
        cell.border = border

# 4. 表头特殊样式(蓝色加粗)
header_font = Font(
    name="宋体",
    size=12,
    color=colors.BLUE,
    bold=True
)

for cell in ws[1]:  # 第一行(表头)
    cell.font = header_font

# 保存
wb.save(r"D:\2021年销售分析\全年数据-格式调整.xlsx")
print("样式设置完成!")


样式参数速查表

Font(字体)

Font(
    name='微软雅黑',      # 字体名称
    size=12,              # 字体大小
    bold=True/False,      # 是否加粗
    italic=True/False,    # 是否斜体
    color=colors.RED      # 字体颜色
)

PatternFill(填充)

PatternFill(
    fill_type='solid',    # 填充类型
    start_color='FF0000', # 开始颜色(十六进制)
    end_color='FF0000'    # 结束颜色
)

Alignment(对齐)

Alignment(
    horizontal='center',   # 水平对齐: left/center/right
    vertical='center',     # 垂直对齐: top/center/bottom
    wrap_text=True,        # 自动换行
    shrink_to_fit=True     # 自适应宽度
)

Border(边框)

side = Side(
    border_style='thin',   # 边框样式
    color=colors.BLACK     # 边框颜色
)
border = Border(
    left=side, right=side,
    top=side, bottom=side
)

边框样式可选值:

  • 'thin' - 细线
  • 'medium' - 中等
  • 'thick' - 粗线
  • 'dashed' - 虚线
  • 'dotted' - 点线
  • 'double' - 双线

实战项目一:数据汇总统计

项目背景

某公司用【明细.xlsx】登记了各部门办公设备使用情况,现在需要按部门统计各设备类型的数量。

原始数据:

目标结果:


实现思路

  1. 读取明细数据
  2. 用字典统计数据:{部门: [类型1数量, 类型2数量, ...]}
  3. 创建新工作簿,写入统计结果
  4. 添加边框、居中对齐

代码实现

import os
import openpyxl as xl
from openpyxl.styles import Alignment, Border, Side, colors

def 汇总数据(file_path, save_path):
    """汇总各部门设备数量"""
    
    # 检查文件是否存在
    if not os.path.exists(file_path):
        print("输入文件不存在")
        return
    
    # 1. 读取明细数据
    workbook = xl.load_workbook(file_path)
    sheet = workbook.worksheets[0]
    
    # 设备类型列表
    equipment_types = [
        '笔记本电脑', '台式电脑', '传真机', 
        '多功能复印机', '激光打印机', '针式打印机'
    ]
    
    # 统计数据:{部门: [类型1数量, 类型2数量, ..., 总计]}
    stats = {}
    
    # 遍历数据(从第3行开始,跳过表头)
    for row in sheet.iter_rows(min_row=3):
        department = row[0].value      # 部门
        equip_type = row[2].value      # 设备类型
        
        # 初始化部门数据
        if department not in stats:
            stats[department] = [0] * 7  # 6种类型 + 总计
        
        # 统计数量
        if equip_type in equipment_types:
            index = equipment_types.index(equip_type)
            stats[department][index] += 1
            stats[department][6] += 1  # 总计
    
    # 2. 创建汇总表
    workbook2 = xl.Workbook()
    sheet2 = workbook2.active
    sheet2.title = "设备汇总"
    
    # 写入表头
    headers = ['部门'] + equipment_types + ['总计']
    sheet2.append(headers)
    
    # 写入各部门数据
    total_row = ['总计'] + [0] * 7
    for dept, counts in stats.items():
        row_data = [dept] + counts
        sheet2.append(row_data)
        
        # 累加总计
        for i in range(7):
            total_row[i + 1] += counts[i]
    
    # 写入总计行
    sheet2.append(total_row)
    
    # 3. 设置样式
    设置样式(sheet2)
    
    # 4. 保存文件
    save_dir = os.path.dirname(save_path)
    if not os.path.exists(save_dir):
        os.makedirs(save_dir)
    
    workbook2.save(save_path)
    print(f"汇总完成!保存至: {save_path}")


def 设置样式(sheet):
    """设置表格样式"""
    # 边框样式
    side = Side(border_style="thin", color=colors.BLACK)
    border = Border(left=side, right=side, top=side, bottom=side)
    
    # 对齐方式(居中)
    alignment = Alignment(
        horizontal="center",
        vertical="center"
    )
    
    # 应用样式到所有单元格
    for row in sheet.rows:
        for cell in row:
            cell.alignment = alignment
            cell.border = border


# 运行
if __name__ == '__main__':
    汇总数据(
        r'D:\数据\第11讲\明细.xlsx',
        r'D:\数据\第11讲\汇总.xlsx'
    )

实战项目二:数据分类导出

项目背景

将【明细.xlsx】按部门分类,每个部门的数据保存到一个单独的工作表中。

目标结果:


代码实现

import openpyxl as xl
from openpyxl.styles import Alignment, Border, Side, colors

def 部门分类(file_path, save_path):
    """按部门分类数据"""
    
    # 1. 读取数据
    workbook = xl.load_workbook(file_path)
    sheet = workbook.worksheets[0]
    
    # 按部门分组数据
    dept_data = {}
    
    for row in sheet.iter_rows(min_row=3, values_only=True):
        department = row[0]
        
        if department not in dept_data:
            dept_data[department] = []
        
        dept_data[department].append(row[1:])  # 保存除部门外的数据
    
    # 2. 创建新工作簿
    header = ['房间', '类型', '使用人', '品牌', '规格', 'IP地址', '登记日期']
    workbook2 = xl.Workbook()
    
    # 删除默认工作表
    workbook2.remove(workbook2.active)
    
    # 3. 为每个部门创建工作表
    for dept, data in dept_data.items():
        # 创建工作表
        sheet2 = workbook2.create_sheet(title=dept)
        
        # 写入表头
        sheet2.append(header)
        
        # 写入数据
        for row_data in data:
            sheet2.append(row_data)
    
    # 4. 设置样式
    for sheet in workbook2.worksheets:
        设置样式(sheet)
    
    # 5. 保存
    workbook2.save(save_path)
    print(f"分类完成!共生成 {len(dept_data)} 个工作表")


def 设置样式(sheet):
    """设置表格样式"""
    side = Side(border_style="thin", color=colors.BLACK)
    border = Border(left=side, right=side, top=side, bottom=side)
    alignment = Alignment(horizontal="center", vertical="center")
    
    for row in sheet.rows:
        for cell in row:
            cell.alignment = alignment
            cell.border = border


# 运行
if __name__ == '__main__':
    try:
        部门分类(
            r'D:\数据\第11讲\明细.xlsx',
            r'D:\数据\第11讲\分类-部门.xlsx'
        )
    except Exception as e:
        print(f"出错了: {e}")
        raise

文档总结

一、核心知识点回顾

1. 单元格属性

属性说明示例值
cell.row行号2
cell.column列号2
cell.coordinate坐标'B2'
cell.value值'李白'

2. 数据获取方法对比

方法遍历方向适用场景
iter_rows()按行逐行处理数据
iter_cols()按列逐列处理数据
sheet.rows按行快速获取所有行
sheet.columns按列快速获取所有列

3. 行列操作

操作方法参数说明
插入行insert_rows(idx, amount)idx:位置, amount:数量
插入列insert_cols(idx, amount)idx:位置, amount:数量
删除行delete_rows(idx, amount)idx:位置, amount:数量
删除列delete_cols(idx, amount)idx:位置, amount:数量

4. 工作表管理

操作方法
新建工作表workbook.create_sheet("表名")
删除工作表del workbook["表名"] 或 workbook.remove(sheet)
修改表名sheet.title = "新名称"
新建文件Workbook()

5. 样式设置

from openpyxl.styles import Font, PatternFill, Alignment, Border, Side

# 字体
cell.font = Font(name='微软雅黑', size=12, bold=True, color=colors.RED)

# 填充
cell.fill = PatternFill(fill_type='solid', start_color='CDCDCD')

# 对齐
cell.alignment = Alignment(horizontal='center', vertical='center')

# 边框
side = Side(border_style='thin', color=colors.BLACK)
cell.border = Border(left=side, right=side, top=side, bottom=side)

# 列宽
sheet.column_dimensions['A'].width = 20

二、学习建议

  1. 先功能后样式:先确保数据处理正确,再美化样式
  2. 善用循环:批量设置样式时使用循环,避免重复代码
  3. 注意性能:大数据量时优先使用 iter_rows() / iter_cols()
  4. 及时保存:重要操作前备份,防止数据丢失
  5. 封装函数:将常用操作(如设置样式)封装成函数复用

三、常见应用场景

  1. 报表生成:从数据库导出数据,生成格式化的 Excel 报表
  2. 数据汇总:多个文件/工作表的数据汇总统计
  3. 数据分类:按条件将数据分类到不同工作表
  4. 批量处理:批量修改文件格式、添加边框等
  5. 自动化办公:定时生成日报、月报等