本文目录导读:

我来介绍几种实现打卡数据统计脚本的方法,主要分为Excel VBA和Python两种方式。
Excel VBA 实现(适合日常统计)
VBA脚本示例
Sub 统计打卡数据()
Dim ws As Worksheet
Dim lastRow As Long
Dim i As Long
Dim dict As Object
Dim key As String
' 设置工作表
Set ws = ThisWorkbook.Sheets("打卡记录")
lastRow = ws.Cells(ws.Rows.Count, "A").End(xlUp).Row
' 创建字典用于统计
Set dict = CreateObject("Scripting.Dictionary")
' 遍历数据(假设A列是姓名,B列是日期,C列是打卡时间)
For i = 2 To lastRow
key = ws.Cells(i, 1).Value & "|" & ws.Cells(i, 2).Value
If Not dict.exists(key) Then
dict.Add key, 1
Else
dict(key) = dict(key) + 1
End If
Next i
' 输出统计结果
Dim outputRow As Long
outputRow = 2
' 创建统计表头
ws.Cells(1, 5).Value = "姓名"
ws.Cells(1, 6).Value = "日期"
ws.Cells(1, 7).Value = "打卡次数"
' 输出统计结果
Dim keys As Variant
keys = dict.keys
For i = 0 To UBound(keys)
Dim parts As Variant
parts = Split(keys(i), "|")
ws.Cells(outputRow, 5).Value = parts(0)
ws.Cells(outputRow, 6).Value = parts(1)
ws.Cells(outputRow, 7).Value = dict(keys(i))
outputRow = outputRow + 1
Next i
MsgBox "统计完成!"
End Sub
Python 实现(功能更强大)
基础统计脚本
import pandas as pd
from datetime import datetime
import os
class AttendanceStats:
def __init__(self, file_path):
self.file_path = file_path
self.df = None
def load_data(self):
"""加载打卡数据"""
if self.file_path.endswith('.xlsx'):
self.df = pd.read_excel(self.file_path)
elif self.file_path.endswith('.csv'):
self.df = pd.read_csv(self.file_path)
else:
raise ValueError("不支持的文件格式")
print(f"已加载 {len(self.df)} 条记录")
def daily_stats(self):
"""每日打卡统计"""
if self.df is None:
return None
# 假设数据包含:姓名、日期、打卡时间
daily_count = self.df.groupby(['姓名', '日期']).size().reset_index(name='打卡次数')
return daily_count
def monthly_stats(self):
"""月度统计"""
if self.df is None:
return None
# 提取月份
self.df['月份'] = pd.to_datetime(self.df['日期']).dt.month
monthly_count = self.df.groupby(['姓名', '月份']).size().reset_index(name='打卡次数')
return monthly_count
def abnormal_check(self, min_times=1, max_times=4):
"""异常打卡检测"""
if self.df is None:
return None
daily_count = self.daily_stats()
abnormal = daily_count[
(daily_count['打卡次数'] < min_times) |
(daily_count['打卡次数'] > max_times)
]
return abnormal
def export_stats(self, output_path):
"""导出统计结果"""
daily = self.daily_stats()
monthly = self.monthly_stats()
abnormal = self.abnormal_check()
with pd.ExcelWriter(output_path) as writer:
daily.to_excel(writer, sheet_name='每日统计', index=False)
monthly.to_excel(writer, sheet_name='月度统计', index=False)
abnormal.to_excel(writer, sheet_name='异常记录', index=False)
print(f"统计结果已导出到: {output_path}")
# 使用示例
def main():
# 初始化统计器
stats = AttendanceStats("打卡记录.xlsx")
# 加载数据
stats.load_data()
# 查看每日统计
daily = stats.daily_stats()
print("每日打卡统计:")
print(daily.head())
# 检查异常
abnormal = stats.abnormal_check()
if len(abnormal) > 0:
print(f"\n发现 {len(abnormal)} 条异常记录")
# 导出统计结果
stats.export_stats("打卡统计结果.xlsx")
if __name__ == "__main__":
main()
高级功能版本
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
class AdvancedAttendanceStats:
def __init__(self, data_file):
self.data_file = data_file
self.load_data()
def load_data(self):
"""加载数据并预处理"""
# 读取数据
if self.data_file.endswith('.csv'):
self.df = pd.read_csv(self.data_file)
else:
self.df = pd.read_excel(self.data_file)
# 确保时间列格式正确
self.df['打卡时间'] = pd.to_datetime(self.df['打卡时间'])
self.df['日期'] = self.df['打卡时间'].dt.date
self.df['时间'] = self.df['打卡时间'].dt.time
print(f"数据加载完成,共 {len(self.df)} 条记录")
def analyze_punch_pattern(self):
"""分析打卡模式"""
# 统计每人每天的打卡次数
daily_pattern = self.df.groupby(['姓名', '日期']).size().unstack(fill_value=0)
# 统计打卡时间分布
self.df['小时'] = self.df['打卡时间'].dt.hour
time_dist = self.df.groupby('小时').size()
return daily_pattern, time_dist
def calculate_working_hours(self):
"""计算工作时长(假设一天打卡两次)"""
# 获取每天的第一次和最后一次打卡
first_punch = self.df.groupby(['姓名', '日期'])['打卡时间'].min().reset_index()
last_punch = self.df.groupby(['姓名', '日期'])['打卡时间'].max().reset_index()
# 合并并计算时长
working_hours = pd.merge(first_punch, last_punch,
on=['姓名', '日期'],
suffixes=('_开始', '_结束'))
working_hours['工作时长(小时)'] = (
working_hours['打卡时间_结束'] - working_hours['打卡时间_开始']
).dt.total_seconds() / 3600
return working_hours
def detect_late_arrival(self, late_time='09:30'):
"""检测迟到"""
late_threshold = pd.to_datetime(late_time).time()
# 找出每天的第一次打卡
first_punch = self.df.groupby(['姓名', '日期'])['打卡时间'].min().reset_index()
first_punch['首次打卡时间'] = first_punch['打卡时间'].dt.time
# 标记迟到
first_punch['是否迟到'] = first_punch['首次打卡时间'] > late_threshold
late_records = first_punch[first_punch['是否迟到']]
return late_records
def generate_report(self):
"""生成统计报告"""
# 基础统计
daily_count = self.df.groupby(['姓名', '日期']).size().reset_index(name='打卡次数')
# 异常检测
abnormal = daily_count[daily_count['打卡次数'] != 2]
# 工作时长
working_hours = self.calculate_working_hours()
# 迟到统计
late_records = self.detect_late_arrival()
# 创建报告
report = {
'总记录数': len(self.df),
'统计人数': self.df['姓名'].nunique(),
'统计天数': self.df['日期'].nunique(),
'异常记录数': len(abnormal),
'迟到次数': len(late_records)
}
return report, {
'每日统计': daily_count,
'异常记录': abnormal,
'工作时长': working_hours,
'迟到记录': late_records
}
def visualize_stats(self):
"""可视化统计结果"""
fig, axes = plt.subplots(2, 2, figsize=(15, 10))
# 1. 每日打卡人数趋势
daily_people = self.df.groupby('日期')['姓名'].nunique()
daily_people.plot(ax=axes[0, 0], title='每日打卡人数趋势')
# 2. 打卡次数分布
daily_count = self.df.groupby(['姓名', '日期']).size()
daily_count.hist(ax=axes[0, 1], bins=10, title='每日打卡次数分布')
# 3. 打卡时间分布
hours = self.df['打卡时间'].dt.hour
hours.hist(ax=axes[1, 0], bins=24, title='打卡时间分布')
# 4. 个人打卡统计
personal_stats = self.df.groupby('姓名').size().sort_values()
personal_stats.plot(kind='barh', ax=axes[1, 1], title='个人总打卡次数')
plt.tight_layout()
plt.savefig('打卡统计图.png', dpi=300)
plt.show()
使用说明
Excel VBA使用步骤:
- 打开Excel文件,按
Alt + F11打开VBA编辑器 - 插入模块,粘贴代码
- 按
F5运行 - 确保数据格式与代码匹配
Python使用步骤:
# 1. 安装依赖 pip install pandas openpyxl matplotlib # 2. 运行脚本 python attendance_stats.py
数据格式要求:
| 姓名 | 日期 | 打卡时间 |
|------|------------|-------------------|
| 张三 | 2024-01-01 | 2024-01-01 09:00 |
| 李四 | 2024-01-01 | 2024-01-01 09:15 |
这些脚本可以根据实际需求进行调整,如果需要特定功能,可以提供更详细的需求说明。