Install
openclaw skills install @pkx07/wmu-volunteer-hours-collector温州医科大学各二级学院学生会实践部内部工具,用于统计收集上来的志愿时长数据。自动从多个表格文件中提取志愿者信息,按规范格式填入模板,生成月度志愿时长汇总表。触发场景:用户提到志愿时长统计、志愿服务汇总、实践部数据整理、志愿者信息录入、或需要处理多个报名表格生成汇总表。
openclaw skills install @pkx07/wmu-volunteer-hours-collector温州医科大学各二级学院内部工具,用于将收集上来的志愿者报名表格汇总为规范格式的志愿时长统计表。读取到的源数据往往不符合规范,需要发挥判断力自行推理和修正,只有确实无法确定的才向用户提问。
确保已安装依赖:
pip install openpyxl pandas
assets/志愿服务.xlsx — 输出模板文件,Sheet1(模板)是输出格式,Sheet2(学院专业简称表)是学院专业简称对照表scripts/helpers.py — 辅助 Python 脚本,提供常用函数references/mapping.md — 学院专业简称对照表(完整版,含模糊匹配规则)整个流程分为五个步骤,必须按顺序执行,每一步遇到需要用户确认的情况必须暂停等待回复后再继续。
首先确认用户的工作目录(用户指定的目录或当前系统工作目录)。
将 assets/志愿服务.xlsx 复制到工作目录,使用以下方式:
from scripts.helpers import copy_template
dest = copy_template("<工作目录>")
print(f"模板已复制到: {dest}")
后续所有修改都针对这个复制后的文件进行,不修改原始模板和 assets/ 中的文件。
使用 glob 扫描工作目录下的所有表格文件:
import os, glob
files = glob.glob(os.path.join("<工作目录>", "*.xlsx")) + \
glob.glob(os.path.join("<工作目录>", "*.xls")) + \
glob.glob(os.path.join("<工作目录>", "*.csv"))
排除模板文件自身("志愿服务.xlsx")。
对每个文件,用 pandas 逐行读取并解析为结构化记录。重要规则:
有些表格文件可能不包含活动名称和活动时间信息。在读取完成后,检查是否所有记录都已获取到活动名称和时间:
对每个唯一的活动/文件,如果原始数据中没有活动名称,或者只有简短描述(如"非遗香囊"、"招生宣传"等),需要向用户确认活动名称。
由我自己根据文件名、表格内嵌的活动标题行、以及已有描述推测活动名称,规则:
阿尔伯塔|XX志愿服务),先问用户需要的格式例如(以阿尔伯塔学院为例):
如果源数据中没有活动时间(起止),向用户确认:
通常每个表格中的所有条目属于同一个活动,相同活动的条目活动名称和时间相同。
对合并后的每一条记录,逐一解析各字段并写入模板。
重要:所有写入操作使用 openpyxl 直接操作工作表,调用
scripts/helpers.py中的函数。不要手动用 pandas 重建。
先统计总共有多少条记录(设为 N 条),然后调整模板的数据区行数:
from scripts.helpers import load_template, adjust_rows, get_data_range, fill_data
wb, ws = load_template("<工作目录>/志愿服务.xlsx")
adjust_rows(ws, N) # 自动插入或删除行,使数据区恰好容纳 N 条记录
所有记录按以下优先级排序后逐条填入:
对每条记录的每个字段,按以下规则解析:
活动名称(A列)
活动时间起(B列)与活动时间止(C列)
YYYY年M月D日,如 2026年1月10日helpers.parse_date() 解析,再用 helpers.date_to_chinese() 格式化序号(D列)
报名来源(E列)
姓名(F列)
学院简称(G列)
helpers.resolve_college(raw) 解析references/mapping.md 中的模糊匹配规则年级(H列)
25webfetch 搜当前年份确认)helpers.extract_grade() 函数helpers.validate_grade_vs_student_id() 验证专业简称(I列)
helpers.resolve_major(raw, college_abbr) 解析certain=True: 直接使用 major 值possible 非空(如"护理"无法区分护本/护专):用平台内置交互工具请用户选择major 为 None(无法识别):用平台内置交互工具请用户手动告知is_graduate=True:保留原始数据,在流程结束后统一汇报references/mapping.md 中的完整对照表和模糊匹配规则学号(J列)
联系方式长号(K列)
联系方式短号(L列)
无服务时长(M列)
4.5、7备注(N列)
helpers.fill_row() 或 helpers.fill_data() 批量填写表头(1-4行)和表尾(最后10行)绝对不能修改,只填写中间的数据区。
from scripts.helpers import load_template, adjust_rows, fill_data, date_to_chinese
wb, ws = load_template("工作目录/志愿服务.xlsx")
records = [
{
"活动名称": "非遗香囊制作志愿服务",
"活动时间起": "2026年1月10日",
"活动时间止": "2026年1月10日",
"序号": 1,
"报名来源": "(用户指定来源)",
"姓名": "张三",
"学院": "临一",
"年级": "25",
"专业": "临床",
"学号": "2518260000",
"长号": "13812345678",
"短号": "无",
"服务时长": 4.5,
"备注": "",
},
# ... 更多记录
]
adjust_rows(ws, len(records))
fill_data(ws, records)
wb.save("工作目录/志愿服务.xlsx")
保存填写好的文件后,重命名为最终交付名称(先问用户学院名称/前缀,如阿尔伯塔学院用"阿尔伯塔"):
(学院名)X月份志愿收集.xlsx
例如 阿尔伯塔6月份志愿收集.xlsx。
确定月份:
阿尔伯塔1月份志愿收集.xlsx流程完成后,向用户汇报以下信息:
完整对照表见 references/mapping.md。以下为常用匹配规则:
| 输入可能包含 | → 学院简称 |
|---|---|
| 仁济 | 仁济 |
| 眼视光/眼生 | 眼生 |
| 临一/第一临床/一临/信息与工程 | 临一 |
| 临二/第二临床/二临 | 临二 |
| 药学院/药学 | 药学院 |
| 中医药/中医 | 中医药 |
| 精神/精神医学 | 精神 |
| 检生/检验 | 检生 |
| 公卫/公共卫生 | 公卫 |
| 口腔 | 口腔 |
| 康复 | 康复 |
| 护理 | 护理 |
| 外国语/外语 | 外国语 |
| 基础 | 基础 |
| 文管/人文/医学人文 | 文管 |
| 输入可能包含 | → 专业简称 | 所属学院 |
|---|---|---|
| 生物医药数据科学 | 生物医药数据科学 | 眼生 |
| 护理学 | 护本 | 护理 |
| 护理(无"学") | 需确认护本还是护专 | 护理 |
| 眼视光/眼本 | 眼本 | 眼生 |
| 眼专/眼视光技术 | 眼专 | 眼生 |
| 临床(非5+3) | 临床 | 临一或临二 |
| 临八/5+3一体化 | 临八 | 临一或临二 |
| 麻醉/麻八 | 麻醉/麻八 | 临二 |
| 中药 | 中药 | 中医药 |
| 中医 | 中医 | 中医药 |
| 口腔 | 口腔 | 口腔 |
| 康复 | 康复 | 康复 |
| 医检/检验 | 医检 | 检生 |
| 药学 | 药学 | 药学院 |
| 助产 | 助产 | 护理 |
| 心理 | 心理 | 精神 |
| 英语 | 英语 | 外国语 |
| 日语 | 日语 | 外国语 |
| 信管 | 信管 | 临一 |
| 影像/影技 | 影像/影技 | 临一 |
| 预防 | 预防 | 公卫 |
| 法医 | 法医 | 仁济 |
| 全科 | 全科 | 仁济 |
date.today() 获取当前日期进行计算。