python

关注公众号 jb51net

关闭
首页 > 脚本专栏 > python > Python openpyxl自动生成表

Python+openpyxl自动生成工资表与员工考勤统计

作者:yuanpan

本文面向 Python 办公自动化初学者,演示如何使用 openpyxl 创建 Excel 工资考勤统计表,包括表头样式、员工数据写入、迟到统计、工资扣款、单元格高亮、标题合并和报表导出,需要的朋友可以参考下

在企业日常办公中,工资表、考勤表、迟到统计、扣款统计经常需要重复整理。如果数据量不大,人工处理看起来也能完成;但只要员工数量增加、统计周期变长,手动复制、筛选、套公式、改样式就会变得非常耗时,而且容易出错。

Python 的 openpyxl 库非常适合处理这类 Excel 自动化任务。它可以帮助我们创建 Excel 工作簿、写入员工数据、设置表头样式、合并标题单元格、根据考勤记录自动计算迟到次数和工资扣款,并最终导出一份格式清晰的工资统计表。

本文面向 Python 办公自动化初学者,会通过一个完整案例带你实现“自动生成工资表与员工考勤统计”。

一、openpyxl 库简介

openpyxl 是 Python 中常用的 Excel 读写库,主要用于操作 .xlsx 格式文件。它不依赖本机安装 Excel,因此非常适合在 Windows、Linux、服务器、自动化脚本或定时任务中使用。

使用 openpyxl 可以完成这些常见工作:

安装命令如下:

pip install openpyxl

导入方式:

from openpyxl import Workbook

本文重点使用 Workbook 创建工作簿,并使用 FontPatternFillAlignmentBorder 等样式对象美化工资表。

二、案例需求分析

我们要生成一份员工工资与考勤统计表,表格内容包括:

其中:

假设公司规定上班时间为 09:00,超过 09:00 打卡就记为迟到。

三、准备员工考勤数据

真实业务中,员工考勤数据可能来自:

为了让初学者更容易理解,本文先使用 Python 字典和列表模拟数据。

示例数据如下:

employees = [
    {
        "id": "E001",
        "name": "张三",
        "department": "技术部",
        "base_salary": 12000,
        "attendance": ["08:56", "09:03", "08:59", "09:12", "08:50"]
    },
    {
        "id": "E002",
        "name": "李四",
        "department": "产品部",
        "base_salary": 10000,
        "attendance": ["08:45", "08:58", "09:01", "08:55", "08:57"]
    },
    {
        "id": "E003",
        "name": "王五",
        "department": "运营部",
        "base_salary": 8500,
        "attendance": ["09:10", "09:08", "08:52", "08:49", "09:20"]
    }
]

这里的 attendance 表示员工连续几个工作日的上班打卡时间。后面程序会自动判断哪些时间晚于 09:00

四、创建 Excel 工作簿

使用 openpyxl 创建工作簿非常简单:

from openpyxl import Workbook

wb = Workbook()
ws = wb.active
ws.title = "工资考勤统计"

说明:

最终导出文件时使用:

wb.save("salary_attendance_report.xlsx")

五、自动合并标题单元格

工资统计表通常需要一个醒目的大标题。我们可以将第一行多个单元格合并成一个标题区域。

ws.merge_cells("A1:J1")
ws["A1"] = "员工工资与考勤统计表"

merge_cells("A1:J1") 表示把 A1 到 J1 合并成一个单元格。之后只需要给左上角单元格 A1 写入标题即可。

标题还可以设置字体、颜色和居中效果:

ws["A1"].font = Font(bold=True, size=16, color="FFFFFF")
ws["A1"].fill = PatternFill("solid", fgColor="305496")
ws["A1"].alignment = Alignment(horizontal="center", vertical="center")

六、设置表头样式

表头是 Excel 报表中非常重要的一部分,清晰的表头能让报表更专业。

我们需要的表头字段如下:

headers = [
    "员工编号", "姓名", "部门", "基本工资",
    "出勤天数", "迟到次数", "每次迟到扣款",
    "总扣款", "实发工资", "备注"
]

写入表头:

for col_index, header in enumerate(headers, start=1):
    cell = ws.cell(row=2, column=col_index, value=header)

设置表头样式:

cell.font = Font(bold=True, color="FFFFFF")
cell.fill = PatternFill("solid", fgColor="4472C4")
cell.alignment = Alignment(horizontal="center", vertical="center")

为了让表格边界更清楚,还可以统一设置边框:

thin_border = Border(
    left=Side(style="thin", color="BFBFBF"),
    right=Side(style="thin", color="BFBFBF"),
    top=Side(style="thin", color="BFBFBF"),
    bottom=Side(style="thin", color="BFBFBF")
)

七、自动计算迟到次数与工资扣款

判断迟到的核心逻辑是:如果打卡时间晚于 09:00,则迟到一次。

可以用字符串比较,也可以用 datetime 转换。为了更稳妥,建议使用 datetime.strptime()

from datetime import datetime

WORK_START_TIME = "09:00"

def count_late_times(attendance_times):
    start_time = datetime.strptime(WORK_START_TIME, "%H:%M").time()
    late_count = 0

    for time_text in attendance_times:
        check_time = datetime.strptime(time_text, "%H:%M").time()
        if check_time > start_time:
            late_count += 1

    return late_count

计算扣款:

late_count = count_late_times(employee["attendance"])
deduction = late_count * LATE_DEDUCTION_PER_TIME
actual_salary = employee["base_salary"] - deduction

在这个案例中:

LATE_DEDUCTION_PER_TIME = 50

如果某员工迟到 3 次,则扣款:

3 × 50 = 150 元

八、写入员工数据

员工数据从第 3 行开始写入,因为:

示例:

start_row = 3

for row_index, employee in enumerate(employees, start=start_row):
    late_count = count_late_times(employee["attendance"])
    attendance_days = len(employee["attendance"])
    deduction = late_count * LATE_DEDUCTION_PER_TIME
    actual_salary = employee["base_salary"] - deduction

    row_data = [
        employee["id"],
        employee["name"],
        employee["department"],
        employee["base_salary"],
        attendance_days,
        late_count,
        LATE_DEDUCTION_PER_TIME,
        deduction,
        actual_salary,
        "正常" if late_count == 0 else "存在迟到"
    ]

    for col_index, value in enumerate(row_data, start=1):
        ws.cell(row=row_index, column=col_index, value=value)

这样就完成了员工信息、考勤统计和工资结果的写入。

九、单元格颜色高亮

为了让 HR 或行政人员快速发现异常,可以对迟到员工所在行进行高亮。

例如:迟到次数大于 0 的员工使用浅红色背景。

late_fill = PatternFill("solid", fgColor="FCE4D6")

if late_count > 0:
    for col_index in range(1, len(headers) + 1):
        ws.cell(row=row_index, column=col_index).fill = late_fill

也可以只高亮“迟到次数”“总扣款”“备注”等关键单元格:

ws.cell(row=row_index, column=6).fill = late_fill
ws.cell(row=row_index, column=8).fill = late_fill
ws.cell(row=row_index, column=10).fill = late_fill

本文完整代码中会采用整行浅红色高亮,这样更直观。

十、设置列宽与数字格式

为了让 Excel 报表打开后更易读,可以设置列宽:

column_widths = {
    "A": 12,
    "B": 10,
    "C": 12,
    "D": 12,
    "E": 12,
    "F": 12,
    "G": 16,
    "H": 12,
    "I": 12,
    "J": 14
}

for column, width in column_widths.items():
    ws.column_dimensions[column].width = width

工资金额可以设置为数字格式:

for row in range(3, ws.max_row + 1):
    ws.cell(row=row, column=4).number_format = '#,##0'
    ws.cell(row=row, column=7).number_format = '#,##0'
    ws.cell(row=row, column=8).number_format = '#,##0'
    ws.cell(row=row, column=9).number_format = '#,##0'

这样 12000 在 Excel 中会显示为更易读的 12,000

十一、完整案例代码

下面是一份可以直接运行的完整代码。运行后会在当前目录生成 salary_attendance_report.xlsx 文件。

from datetime import datetime

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


WORK_START_TIME = "09:00"
LATE_DEDUCTION_PER_TIME = 50
OUTPUT_FILE = "salary_attendance_report.xlsx"


employees = [
    {
        "id": "E001",
        "name": "张三",
        "department": "技术部",
        "base_salary": 12000,
        "attendance": ["08:56", "09:03", "08:59", "09:12", "08:50"],
    },
    {
        "id": "E002",
        "name": "李四",
        "department": "产品部",
        "base_salary": 10000,
        "attendance": ["08:45", "08:58", "09:01", "08:55", "08:57"],
    },
    {
        "id": "E003",
        "name": "王五",
        "department": "运营部",
        "base_salary": 8500,
        "attendance": ["09:10", "09:08", "08:52", "08:49", "09:20"],
    },
    {
        "id": "E004",
        "name": "赵六",
        "department": "财务部",
        "base_salary": 9500,
        "attendance": ["08:51", "08:53", "08:58", "08:56", "08:59"],
    },
    {
        "id": "E005",
        "name": "孙七",
        "department": "销售部",
        "base_salary": 11000,
        "attendance": ["09:15", "09:06", "09:02", "08:57", "08:54"],
    },
]


def count_late_times(attendance_times):
    """统计迟到次数。"""
    start_time = datetime.strptime(WORK_START_TIME, "%H:%M").time()
    late_count = 0

    for time_text in attendance_times:
        check_time = datetime.strptime(time_text, "%H:%M").time()
        if check_time > start_time:
            late_count += 1

    return late_count


def create_salary_report():
    wb = Workbook()
    ws = wb.active
    ws.title = "工资考勤统计"

    headers = [
        "员工编号",
        "姓名",
        "部门",
        "基本工资",
        "出勤天数",
        "迟到次数",
        "每次迟到扣款",
        "总扣款",
        "实发工资",
        "备注",
    ]

    title_fill = PatternFill("solid", fgColor="305496")
    header_fill = PatternFill("solid", fgColor="4472C4")
    late_fill = PatternFill("solid", fgColor="FCE4D6")
    normal_fill = PatternFill("solid", fgColor="E2F0D9")

    title_font = Font(bold=True, size=16, color="FFFFFF")
    header_font = Font(bold=True, color="FFFFFF")
    normal_font = Font(color="000000")

    center_alignment = Alignment(horizontal="center", vertical="center")

    thin_border = Border(
        left=Side(style="thin", color="BFBFBF"),
        right=Side(style="thin", color="BFBFBF"),
        top=Side(style="thin", color="BFBFBF"),
        bottom=Side(style="thin", color="BFBFBF"),
    )

    # 1. 合并标题单元格
    ws.merge_cells("A1:J1")
    title_cell = ws["A1"]
    title_cell.value = "员工工资与考勤统计表"
    title_cell.font = title_font
    title_cell.fill = title_fill
    title_cell.alignment = center_alignment
    ws.row_dimensions[1].height = 30

    # 2. 写入并设置表头样式
    for col_index, header in enumerate(headers, start=1):
        cell = ws.cell(row=2, column=col_index, value=header)
        cell.font = header_font
        cell.fill = header_fill
        cell.alignment = center_alignment
        cell.border = thin_border

    # 3. 写入员工数据并计算考勤、扣款、实发工资
    start_row = 3
    for row_index, employee in enumerate(employees, start=start_row):
        late_count = count_late_times(employee["attendance"])
        attendance_days = len(employee["attendance"])
        deduction = late_count * LATE_DEDUCTION_PER_TIME
        actual_salary = employee["base_salary"] - deduction
        remark = "正常" if late_count == 0 else "存在迟到"

        row_data = [
            employee["id"],
            employee["name"],
            employee["department"],
            employee["base_salary"],
            attendance_days,
            late_count,
            LATE_DEDUCTION_PER_TIME,
            deduction,
            actual_salary,
            remark,
        ]

        for col_index, value in enumerate(row_data, start=1):
            cell = ws.cell(row=row_index, column=col_index, value=value)
            cell.font = normal_font
            cell.alignment = center_alignment
            cell.border = thin_border

            if late_count > 0:
                cell.fill = late_fill
            else:
                cell.fill = normal_fill

    # 4. 设置列宽
    column_widths = {
        "A": 12,
        "B": 10,
        "C": 12,
        "D": 12,
        "E": 12,
        "F": 12,
        "G": 16,
        "H": 12,
        "I": 12,
        "J": 14,
    }

    for column, width in column_widths.items():
        ws.column_dimensions[column].width = width

    # 5. 设置工资相关列的数字格式
    for row in range(3, ws.max_row + 1):
        ws.cell(row=row, column=4).number_format = '#,##0'
        ws.cell(row=row, column=7).number_format = '#,##0'
        ws.cell(row=row, column=8).number_format = '#,##0'
        ws.cell(row=row, column=9).number_format = '#,##0'

    # 6. 冻结表头,方便查看大量数据
    ws.freeze_panes = "A3"

    # 7. 导出工资统计表
    wb.save(OUTPUT_FILE)
    print(f"工资考勤统计表已生成:{OUTPUT_FILE}")


if __name__ == "__main__":
    create_salary_report()

运行命令:

python salary_attendance_report.py

运行成功后,会生成:

salary_attendance_report.xlsx

打开 Excel 后可以看到:

十二、把案例改造成真实企业数据流程

上面的代码使用了固定的员工列表。实际企业中,可以进一步扩展为更完整的自动化流程。

1. 从考勤 Excel 中读取数据

如果考勤系统导出的是 Excel,可以使用 openpyxl.load_workbook() 读取:

from openpyxl import load_workbook

wb = load_workbook("attendance.xlsx")
ws = wb.active

for row in ws.iter_rows(min_row=2, values_only=True):
    employee_id = row[0]
    employee_name = row[1]
    check_time = row[2]

这样可以把外部考勤数据接入到工资统计脚本中。

2. 从员工信息表中读取基本工资

企业通常会有一份员工基础信息表,例如:

员工编号 | 姓名 | 部门 | 基本工资

程序可以先读取员工信息表,再读取考勤表,最后通过员工编号进行匹配,自动生成工资报表。

3. 增加请假、早退、缺勤等规则

工资计算规则也可以继续扩展:

这些规则都可以封装成函数,让工资计算逻辑更清晰。

例如:

def calculate_actual_salary(base_salary, late_count, absence_days, bonus):
    late_deduction = late_count * 50
    absence_deduction = absence_days * 300
    return base_salary - late_deduction - absence_deduction + bonus

十三、企业办公自动化实际应用场景

这个案例虽然简单,但背后的思路非常实用。企业办公自动化中经常会遇到类似需求:

1. HR 工资核算

HR 每月需要统计考勤、迟到、请假、缺勤、绩效奖金等数据。使用 Python + openpyxl 可以把重复的 Excel 操作自动化,减少手动汇总时间。

2. 行政考勤统计

行政人员可以定期从打卡系统导出考勤数据,然后运行脚本自动生成部门考勤汇总表,把异常记录高亮显示。

3. 财务工资复核

财务部门可以拿到自动生成的工资表后,快速检查扣款、实发工资、异常员工,提高复核效率。

4. 部门月度报表

除了工资表,类似的方式还可以生成销售统计表、项目工时报表、库存明细表、费用报销表等。

5. 定时任务自动生成报表

如果脚本部署在服务器上,还可以结合 Windows 任务计划程序或 Linux crontab,每月自动生成工资统计表,并通过邮件发送给相关负责人。

十四、初学者容易踩的坑

1. 文件正在被 Excel 打开

如果 salary_attendance_report.xlsx 正在被 Excel 打开,Python 保存时可能会报错。解决方法是先关闭 Excel 文件,再运行脚本。

2. 时间格式不统一

考勤数据中可能出现 9:0009:0009:00:00 等不同格式。真实项目中需要先做数据清洗。

3. 中文字体显示问题

如果需要设置指定中文字体,可以使用:

Font(name="微软雅黑", bold=True)

不过不同电脑上字体环境可能不同,建议使用常见系统字体。

4. 公式和 Python 计算的选择

工资扣款既可以由 Python 直接计算后写入,也可以写成 Excel 公式。例如:

ws["H3"] = "=F3*G3"
ws["I3"] = "=D3-H3"

如果希望用户打开 Excel 后能看到公式,可以使用 Excel 公式;如果希望结果固定、方便系统导入,可以使用 Python 直接计算。本文采用 Python 直接计算,更适合自动导出报表。

十五、总结

本文使用 Python + openpyxl 实现了一个“自动生成工资表与员工考勤统计”的完整案例,覆盖了办公自动化中非常常见的 Excel 报表处理流程。

你已经学习了:

对于 Python 办公自动化初学者来说,掌握这个案例后,就可以继续扩展到更多 Excel 自动化任务,例如批量生成报表、合并多份表格、自动整理数据、自动发送邮件等。

只要你的工作中存在大量重复性的 Excel 操作,就可以考虑用 Python 把它自动化。

以上就是Python+openpyxl自动生成工资表与员工考勤统计的详细内容,更多关于Python openpyxl自动生成表的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文