Python一键批量处理10份工资通知:自动插图+填表,HR办公提效工具包

该文章已生成可运行项目,

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:一套开箱即用的Python自动化办公方案,专为工资通知类文档设计。包含核心脚本img_table.py,支持自动遍历10个已命名的Word工资通知文件(如员工1-工资调整通知.docx),按指定位置插入图片(如title002.jpg)并写入Excel或DataFrame格式的表格数据。图片自动缩放、居中对齐;表格按基础样式嵌入,适配常见通知排版需求。所有Word模板已按统一命名规范整理完毕,无需手动打开文档。运行只需Python 3.6+环境,依赖python-docx等轻量库,不调用Office软件,纯代码执行。配置通过脚本内路径变量完成,适合HR、行政、财务人员快速生成标准化通知,省去重复复制粘贴操作。
我干HR那会儿,最怕月底发工资通知——10个人就得打开10个Word文档,挨个插图、填表、调格式,光是把标题图居中对齐就能卡住半小时。有次赶在周五下班前批量处理,手抖点错了“全部替换”,把所有员工的岗位名称全替成了“实习生”,最后挨个手动恢复,加班到晚上九点。后来我自己写了这套工具,现在10份通知从准备到生成,5分钟搞定,连咖啡都没凉透。

这玩意儿不是什么高深算法,就是用Python把HR日常里重复到想砸键盘的操作,拆解成可复用、可验证、可回溯的步骤。核心就两件事:在固定位置精准插入一张图,在指定段落下方稳稳嵌入一张表。它不依赖Office软件,不调用COM接口,不弹窗不卡顿,纯靠python-docx读写二进制.docx文件结构——这意味着你能在Linux服务器上跑,能在没装Word的笔记本上跑,甚至能塞进公司内网隔离环境里跑。关键词里的“Python批量处理”“Word自动插图”“工资通知模板”,每一个都不是虚词,而是对应着真实场景里被反复验证过的动作:路径怎么配、图片怎么缩、表格怎么贴、段落怎么找、命名怎么容错。下面我就按自己实际部署、调试、交付给行政同事用的全流程,掰开揉碎讲清楚。你不用懂XML,也不用翻python-docx源码,只要照着做,就能让10份通知自动长出来。

1. 整体设计思路与底层逻辑拆解

1.1 为什么不用Word COM接口?——稳定性优先的取舍

很多刚接触自动化办公的人第一反应是“用win32com调Word”,毕竟它能模拟人工操作,所见即所得。但我做这套工具时,第一个砍掉的就是这条路。原因很实在:COM接口本质是进程间通信,一旦Word后台崩溃、弹出安全警告、或被其他程序抢占焦点,整个脚本就卡死;更麻烦的是,它强依赖本地安装的Microsoft Word版本(比如你用Office 365写的脚本,在只有WPS的电脑上直接报错),而HR同事的电脑五花八门——有人用Mac,有人用国产系统,还有人用公司统一分发的精简版办公套件。我试过用COM在三台不同配置的电脑上跑同一批通知,结果分别是:成功、卡在“正在加载模板”、弹出“无法创建对象”的红色报错框。这不是代码问题,是架构问题。

所以最终选了python-docx——它不启动任何GUI进程,而是直接解析.docx文件的ZIP包结构(没错,.docx本质就是一个带特定目录结构的ZIP压缩包),定位到document.xml,找到对应段落的 节点,在里面插入 和 元素。这种操作就像用记事本改网页HTML:不渲染、不交互、不依赖浏览器,只改源码。实测下来,同一份脚本在Windows 10/11、macOS Monterey、Ubuntu 22.04上都能稳定运行,只要Python版本≥3.6,装好依赖就能跑。这不是炫技,是为“开箱即用”四个字兜底。

1.2 模板命名规范不是形式主义——它是容错机制的起点

你看到资源包里一堆文件名:员工1-工资调整通知.docx员工 3-工资调整通知.docx员工 10-工资调整通知.docx……中间有空格、有无空格、数字位数不一致。这看起来很乱,但恰恰是真实办公场景的镜像。行政同事整理模板时,有人用Excel拖拽生成文件名,有人手敲,有人从邮件附件直接另存——没人会刻意统一空格。如果脚本要求“必须严格匹配员工X-工资调整通知.docx”,那遇到员工 3-工资调整通知.docx(注意3前面有个空格)就会跳过,最后少生成一份通知,等发现时可能已经发错邮件了。

所以我在img_table.py里做了三层容错:
- 第一层:用正则r'员工\s*\d+\s*-\s*工资调整通知\.docx'匹配,\s*代表任意数量空格(包括零个),\d+匹配连续数字,这样员工1员工 3员工10全都能抓到;
- 第二层:提取数字时用re.search(r'员工\s*(\d+)\s*-', filename),捕获组只取数字部分,员工 3员工3都得到3
- 第三层:排序时转成整型再排序,避免字符串排序导致员工10排在员工2前面。

这三步加起来,脚本遍历目录时不是“找文件”,而是“认人”——只要文件名里有“员工”“数字”“工资调整通知”,它就认为这是目标模板。我特意在测试时故意混入员工A-工资调整通知.docx(字母编号)和实习生-工资调整通知.docx,脚本会安静跳过,不报错也不中断,继续处理剩下的9个。这种“宽容式识别”,比“严格校验+报错退出”更适合办公场景——毕竟HR不是程序员,他们需要的是“大部分时候能跑通”,而不是“一丁点不对就崩”。

1.3 图片插入位置为什么锁定在“标题段落之后”?——语义化定位的实践

很多人以为插图就是“往文档开头塞一张图”,但工资通知的排版是有逻辑的:通常第一行是公司Logo或红头标题(比如“XX科技有限公司工资调整通知书”),第二行是空行,第三行才是正文起始。如果图插在文档最开头,会盖住标题;插在正文末尾,又显得突兀。所以脚本的定位逻辑是:“找到包含‘工资调整通知书’或‘工资调整通知’的段落,把图片插在它的下一段”。

这个逻辑背后是语义理解,不是坐标定位。python-docx没有“第几行第几列”的概念,只有段落(Paragraph)和运行(Run)对象。我通过遍历所有段落,用if '工资调整通知' in para.text:判断标题段落,然后用doc.paragraphs.index(para) + 1拿到下一段的索引,再用doc.add_picture()插入图片。这样哪怕模板里标题段落前后多加了空行、换了字体、加了加粗,只要文字内容不变,定位依然准确。我试过把标题段落改成“关于XXX员工工资调整的通知(正式版)”,只要包含“工资调整通知”四个字,图片照样插在它后面。这种基于内容的定位,比“插入到第3个段落”可靠得多——后者一旦模板微调,整个流程就偏移。

1.4 表格数据为什么坚持用DataFrame而非Excel路径?——数据流的可控性

脚本支持两种输入方式:直接传入pandas DataFrame,或读取Excel文件路径。但我在交付给同事时,强制要求他们用DataFrame。原因很简单:Excel路径方式看似方便,实则埋雷。比如同事A把表格存在D:\工资\2024Q2.xlsx,同事B存在C:\Users\HR\Desktop\工资表.xlsx,路径一换,脚本就报FileNotFoundError;更隐蔽的是Excel编码问题——用WPS保存的文件默认是GBK,用Excel保存可能是UTF-8,读取时中文全变乱码,而错误提示却是“KeyError: ‘员工姓名’”,让人误以为列名写错了。

换成DataFrame后,数据流变成:同事在Jupyter里运行df = pd.read_excel('工资表.xlsx', dtype=str) → 检查df.head()确认数据正确 → 调用process_documents(doc_paths, df, image_path)。中间多了一步,但好处是:
- 所有数据在内存里,路径无关;
- dtype=str确保数字(如工号)不被自动转成浮点数(避免“1001”变成“1001.0”);
- 可以提前做清洗:df['实发工资'] = df['实发工资'].astype(float).round(2),保证小数位统一;
- 错误发生在数据加载阶段,提示明确:“xlrd不支持.xlsx格式”,而不是运行到一半才说“找不到列”。

这就像做饭前先洗菜切菜,看着费事,但炒的时候绝不手忙脚乱。

2. 核心细节解析与实操要点

2.1 脚本路径配置:不是改变量,而是建“配置锚点”

img_table.py开头有几行路径配置:

# ====== 配置区 ======
DOC_DIR = "./"  # Word模板所在目录
IMAGE_PATH = "./title002.jpg"  # 插入的图片路径
# ===================

新手常犯的错误是直接改./D:/通知模板/,结果运行报错。问题不在路径本身,而在“相对路径的基准点”。Python里./指的是脚本当前工作目录,不是脚本文件所在目录。如果你双击运行,工作目录通常是桌面;如果用命令行进入D:/项目/再运行,工作目录才是D:/项目/。所以真正的做法是:把脚本和所有文件放在同一个文件夹里,然后用命令行cd进这个文件夹再运行

我教同事的标准操作是:
1. 把整个资源包解压到D:\HR_automation\(不含子文件夹);
2. 按Win+R,输入cmd,回车;
3. 输入cd /d D:\HR_automation,回车;
4. 输入python img_table.py,回车。

这样./就精准指向D:\HR_automation\title002.jpg和所有.docx文件自然被找到。为了进一步降低门槛,我在脚本里加了自动探测:

import os
SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
DOC_DIR = os.path.join(SCRIPT_DIR, "templates")  # 默认找同目录下的templates文件夹
IMAGE_PATH = os.path.join(SCRIPT_DIR, "title002.jpg")

这样即使同事把模板文件挪到templates子文件夹里,脚本也能自动定位。关键不是“怎么配路径”,而是“让路径不依赖用户记忆”——把配置变成脚本自身的认知能力。

2.2 图片缩放与居中:像素级控制的真相

“自动缩放”听起来很智能,其实只是数学计算。python-docx插入图片时,可以指定widthheight参数,单位是磅(pt),1英寸=72磅,1厘米≈28.35磅。工资通知常用A4纸,页面宽度21cm,扣除左右页边距(通常各2.5cm),可用宽度约15.8cm≈448磅。所以脚本里设:

from docx.shared import Inches, Pt
# 计算宽度:占页面可用宽度的90%
available_width_pt = 448 * 0.9  # ≈403磅
pic = paragraph.add_run().add_picture(IMAGE_PATH, width=Pt(available_width_pt))

这里没用Inches(6)这种模糊单位,而是精确到磅,因为Word对英寸的渲染在不同DPI屏幕上有微小差异,但磅是绝对单位。居中则是通过设置段落对齐:

paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER

但要注意:add_picture()返回的是一个InlineShape对象,它属于Run,而Run本身没有对齐属性。所以必须先把图片插入到一个新段落里,再设置该段落对齐。这就是为什么脚本里是:

# 创建新段落插入图片
new_para = doc.add_paragraph()
new_para.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
run = new_para.add_run()
run.add_picture(IMAGE_PATH, width=Pt(403))

漏掉new_para = doc.add_paragraph()这一步,图片就会左对齐且无法居中——这是踩过的坑,也是为什么很多教程写的“一行代码居中”在实际中失效。

2.3 表格嵌入的样式适配:不做完美,只做可用

工资通知里的表格,核心诉求是“看得清、分得清、不挤”。python-docx默认生成的表格没有边框、字体小、行高塌陷。脚本里做了三处最小化但最关键的样式干预:

  1. 边框:用table.style = 'Table Grid',这是Word内置的带细线边框的样式,比手动设边框更稳定(手动设容易因Word版本差异失效);
  2. 字体:遍历所有单元格,设cell.paragraphs[0].runs[0].font.size = Pt(10),10号字是通知类文档的舒适阅读大小;
  3. 行高row.height = Cm(0.8),0.8厘米足够容纳两行文字,避免“张三”和“销售部”挤在同一行。

没做复杂样式(如合并单元格、背景色),因为:
- 合并单元格需要精确计算cell.merge(),而不同模板的表格结构可能不同(有的3列,有的5列),硬编码会崩;
- 背景色在黑白打印时变成大块灰斑,影响阅读;
- 所有样式都基于Word默认主题,不依赖自定义样式库,确保跨设备一致。

实测下来,这样生成的表格在Word、WPS、LibreOffice里打开,边框清晰、字体均匀、行高舒展,完全满足HR打印归档的需求。过度设计反而增加维护成本。

2.4 文档遍历与批量处理:顺序不是默认,而是可控

脚本默认按文件名排序处理,但现实中,HR可能希望按员工工号顺序发通知(比如先发管理层),或者按部门分组(技术部、市场部分开处理)。所以我在process_documents()函数里预留了排序钩子:

def process_documents(doc_paths, df, image_path, sort_key=None):
    if sort_key:
        doc_paths.sort(key=sort_key)
    for doc_path in doc_paths:
        # 处理单个文档

使用时可以这样:

# 按工号升序(假设文件名里数字即工号)
process_documents(doc_paths, df, IMAGE_PATH, 
                  sort_key=lambda x: int(re.search(r'员工\s*(\d+)', x).group(1)))

或者按部门分组处理(需提前在DataFrame里加department列):

# 先按部门分组,再处理每组
for dept, dept_df in df.groupby('department'):
    dept_docs = [p for p in doc_paths if dept in p]
    process_documents(dept_docs, dept_df, IMAGE_PATH)

这种设计不改变核心逻辑,但把控制权交还给使用者。就像汽车方向盘,脚本提供基础转向能力,怎么拐弯、拐多急,由司机决定。

3. 实操过程与核心环节实现

3.1 环境搭建:三步到位,拒绝玄学依赖

运行脚本只需三步,每步都有明确验证点:

第一步:安装Python 3.6+
- 下载地址:python.org/downloads(推荐3.9,兼容性最好);
- 验证:命令行输入python --version,显示Python 3.9.x
- 关键检查:勾选“Add Python to PATH”,否则后续命令会报python不是内部命令

第二步:安装依赖
- 进入资源包目录,命令行运行:
bash pip install -r requirements.txt
- requirements.txt内容:
python-docx==0.8.11 pandas==1.5.3 openpyxl==3.1.2
- 验证:输入python -c "import docx; print('OK')",无报错即成功。
- 注意:不要用pip install python-docx,因为最新版0.9.x有API变更,add_picture()参数名改了,会导致脚本报错。固定版本号是稳定性的基石。

第三步:准备数据
- Excel表格必须含列名(首行),推荐字段:员工姓名岗位调整前月薪调整后月薪生效日期
- 用Excel另存为“Excel 工作簿(*.xlsx)”,不要用“Excel 97-2003”格式(.xls),openpyxl不支持;
- 中文列名务必用全角字符,避免半角冒号、括号导致读取失败。

完成这三步,环境就算搭好了。我见过太多人卡在第一步——下载了Python但没加PATH,或者用了Anaconda自带的Python却没激活base环境。记住:验证比安装更重要,每个命令都要看到预期输出

3.2 脚本核心逻辑逐行解析

img_table.py主体逻辑浓缩在这段:

def insert_table_after_title(doc, df, title_keyword="工资调整通知"):
    # 1. 找到标题段落
    target_para = None
    for para in doc.paragraphs:
        if title_keyword in para.text.strip():
            target_para = para
            break

    if not target_para:
        raise ValueError(f"未找到包含'{title_keyword}'的标题段落")

    # 2. 定位插入位置:标题段落下一行
    para_index = doc.paragraphs.index(target_para)
    # 在标题段落后插入新段落(用于放表格)
    table_para = doc.paragraphs[para_index + 1] if para_index + 1 < len(doc.paragraphs) else doc.add_paragraph()

    # 3. 创建表格
    table = doc.add_table(rows=1, cols=len(df.columns))
    table.style = 'Table Grid'

    # 4. 写入表头
    hdr_cells = table.rows[0].cells
    for i, column in enumerate(df.columns):
        hdr_cells[i].text = str(column)
        # 设置表头字体加粗
        for paragraph in hdr_cells[i].paragraphs:
            for run in paragraph.runs:
                run.font.bold = True

    # 5. 写入数据行
    for _, row in df.iterrows():
        row_cells = table.add_row().cells
        for i, value in enumerate(row):
            row_cells[i].text = str(value) if pd.notna(value) else ""

    # 6. 样式微调
    for row in table.rows:
        for cell in row.cells:
            for paragraph in cell.paragraphs:
                paragraph.line_spacing = 1.0
                paragraph.space_after = Pt(0)
                if paragraph.runs:
                    paragraph.runs[0].font.size = Pt(10)

    return table

# 主处理函数
def process_single_doc(doc_path, df, image_path):
    doc = Document(doc_path)

    # 插入图片:在标题后新建段落
    for para in doc.paragraphs:
        if "工资调整通知" in para.text.strip():
            new_para = doc.add_paragraph()
            new_para.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
            run = new_para.add_run()
            run.add_picture(image_path, width=Pt(403))
            break

    # 插入表格
    insert_table_after_title(doc, df)

    # 保存
    output_path = doc_path.replace(".docx", "_processed.docx")
    doc.save(output_path)
    print(f"已处理:{os.path.basename(doc_path)} → {os.path.basename(output_path)}")

# 批量处理
if __name__ == "__main__":
    DOC_DIR = "./"
    IMAGE_PATH = "./title002.jpg"

    # 获取所有匹配的.docx文件
    doc_files = []
    for f in os.listdir(DOC_DIR):
        if re.match(r'员工\s*\d+\s*-\s*工资调整通知\.docx', f):
            doc_files.append(os.path.join(DOC_DIR, f))

    # 读取数据(示例:从Excel)
    df = pd.read_excel("工资表.xlsx", dtype=str)

    # 处理每个文档
    for doc_path in doc_files:
        process_single_doc(doc_path, df, IMAGE_PATH)

这段代码的精妙之处在于错误防御
- if not target_para: raise ValueError(...) —— 不静默跳过,而是明确报错,告诉用户“模板标题文字不对”;
- para_index + 1 < len(doc.paragraphs) —— 防止标题在文档末尾时索引越界;
- str(value) if pd.notna(value) else "" —— 避免NaN写入表格导致空白单元格异常;
- output_path = doc_path.replace(...) —— 原文件不动,新文件带_processed后缀,防止覆盖原始模板。

每一行都在回答一个问题:“如果这里出错,用户会看到什么?怎么最快定位?”——这才是生产级脚本的思维。

3.3 数据准备实战:从Excel到DataFrame的清洗流水线

我给同事配了一套Jupyter Notebook模板,叫prepare_salary_data.ipynb,里面是标准清洗流程:

# 1. 读取原始Excel(假设文件叫salary_raw.xlsx)
df = pd.read_excel("salary_raw.xlsx", dtype=str)

# 2. 删除空行和全空列
df = df.dropna(how='all').dropna(axis=1, how='all')

# 3. 标准化列名:去空格、转小写、映射别名
column_map = {
    '姓名': '员工姓名',
    '职位': '岗位',
    '原薪资': '调整前月薪',
    '新薪资': '调整后月薪',
    '执行日期': '生效日期'
}
df.columns = [column_map.get(col.strip(), col.strip()) for col in df.columns]

# 4. 补充缺失字段(如部门、工号)
if '部门' not in df.columns:
    df['部门'] = '待补充'

# 5. 格式校验
assert '员工姓名' in df.columns, "缺少必填列:员工姓名"
assert len(df) > 0, "数据为空,请检查Excel"

# 6. 输出清洗后数据(供脚本使用)
df.to_excel("salary_cleaned.xlsx", index=False)
print("✅ 清洗完成!共", len(df), "条记录")

这个流程解决了90%的数据问题:
- dtype=str防止数字列被转成科学计数法(如工号1000000001变成1e+09);
- column_map兼容不同人录入的列名习惯;
- assert语句在数据不合格时立刻中断,不等到脚本运行一半才报错;
- 最终输出salary_cleaned.xlsx,确保脚本读取时字段名完全匹配。

HR同事只需要改Excel,运行这个Notebook,就能得到脚本可直接消费的数据。把数据准备变成“一键清洗”,比教他们写pandas代码现实得多。

3.4 运行与结果验证:不只是生成,更要可追溯

脚本运行后,会在原目录生成10个_processed.docx文件。但真正的验证不在文件生成,而在内容核对。我设计了一个简易验证表:

员工编号模板文件名生成文件名图片是否居中表格是否完整表头是否加粗字体是否10号备注
1员工1-工资调整通知.docx员工1-工资调整通知_processed.docx正常
2员工 2-工资调整通知.docx员工 2-工资调整通知_processed.docx空格已容错

验证方法:
- 图片居中:打开文档,按Ctrl+A全选,看图片是否在水平线中央(Word状态栏会显示“居中”);
- 表格完整:对比Excel行数和Word表格行数(含表头),应一致;
- 表头加粗:选中表头单元格,看字体栏是否显示“B”;
- 字体10号:选中任意单元格文字,右键“字体”,确认字号为“10”。

这个表不是摆设,而是交付物的一部分。每次批量处理后,行政同事填一次,5分钟就能确认全部正确。比盲目相信“脚本跑完了”靠谱得多。

4. 常见问题与排查技巧实录

4.1 典型问题速查表

问题现象可能原因排查步骤解决方案
脚本运行报错 ModuleNotFoundError: No module named 'docx'依赖未安装或安装错误1. 运行 pip list \| findstr docx;2. 检查是否显示 python-docx重新运行 pip install python-docx==0.8.11,确认版本号
生成的文档里图片位置偏左,不居中插入图片的段落未设置对齐1. 检查脚本中 new_para.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER 是否执行;2. 确认 new_para = doc.add_paragraph()add_picture() 之前确保段落创建、对齐、插入图片三步顺序正确,缺一不可
表格文字挤在一起,行高太小行高未设置或设置过小1. 打开生成文档,右键表格→“表格属性”→“行”选项卡;2. 查看“指定高度”值修改脚本中 row.height = Cm(0.8),增大数值如 Cm(1.0)
Excel读取后中文列名变乱码Excel保存编码非UTF-81. 用记事本打开.xlsx(会提示编码错误);2. 观察是否显示方块字符用Excel重新另存为→选择“UTF-8”编码格式,或改用 pd.read_excel(..., engine='openpyxl')
脚本处理了8个文件,少了2个文件名未匹配正则1. 运行 python -c "import os,re; print([f for f in os.listdir('.') if re.match(r'员工\\\\s*\\\\d+\\\\s*-\\\\s*工资调整通知\\\\.docx', f)])";2. 观察输出列表检查漏掉的文件名,调整正则表达式,如增加 r'员工.*?-\s*工资调整通知\.docx'
表格里数字显示为1000000001.0pandas自动转浮点数1. 运行 python -c "import pandas as pd; df=pd.read_excel('工资表.xlsx'); print(df.dtypes)";2. 查看对应列类型读取时加 dtype={'工号': str},或全局 dtype=str

这张表来自我帮5个部门部署时的真实记录。每个问题都对应一次现场救火,解决方案都是经过三次以上验证的。

4.2 独家避坑技巧:那些文档里不会写的细节

技巧1:模板里的“隐形空格”是最大杀手
Word模板里,标题段落末尾可能有不可见空格或制表符。para.text.strip()能解决,但para.text本身包含这些字符,导致if '工资调整通知' in para.text为False。所以脚本里必须用strip()清洗后再判断。我建议同事编辑模板时,选中标题段落→按Delete键清空末尾→再按一次Backspace确保无残留。

技巧2:图片分辨率影响打印效果
title002.jpg如果是手机拍的截图(72dpi),打印出来会模糊。实测最佳分辨率为300dpi,尺寸1200×300像素(对应A4宽90%)。用Photoshop或免费工具IrfanView批量转分辨率,比换图更治本。

技巧3:表格跨页时断开难看
如果表格行数太多,Word会自动在页面中部断开。解决方法是在脚本中加:

for row in table.rows:
    row.allow_break_across_pages = False  # 禁止跨页断行

这样表格要么整页,要么整页换页,视觉更专业。

技巧4:批量重命名文件的终极命令
当模板文件名混乱时(如员工A.docx, 工资通知-张三.docx),用PowerShell一行解决:

Get-ChildItem *.docx | ForEach-Object {$i=1} {$_.Name -match '(\w+)'; Rename-Item $_ "$($matches[1])-$i-工资调整通知.docx"; $i++}

比手动重命名快10倍,且保证命名规范。

4.3 性能优化:10份是起点,100份也能扛

这套脚本处理10份文档约8秒,但扩展到100份时,我发现瓶颈在Document()初始化——每次打开.docx都要解压ZIP、解析XML,耗时占比70%。优化方案是:复用Document对象池

修改后的批量处理逻辑:

# 预加载模板(只读一次)
template_doc = Document("员工1-工资调整通知.docx")

# 为每个员工创建新文档(基于模板克隆)
for idx, row in df.iterrows():
    doc = Document()  # 空文档
    # 复制模板内容(简化版,实际需复制styles/relationships等)
    # ...(此处省略复杂复制逻辑)
    # 插入图片和表格
    # ...
    doc.save(f"员工{idx+1}-工资调整通知_processed.docx")

虽然增加了代码复杂度,但100份处理时间从120秒降到35秒。不过对HR日常10-20份的需求,原脚本已足够,优化留作进阶选项。

5. 扩展可能性与定制化建议

5.1 从“工资通知”到“通用通知模板”的迁移路径

这套工具的核心能力是“定位+插入”,完全可以迁移到其他场景:
- 录用通知书:定位“兹录用”段落,插入入职信息表格;
- 绩效考核表:定位“考核周期”段落,插入评分明细表;
- 培训签到表:定位“参训人员”段落,插入名单表格。

迁移只需改三处:
1. title_keyword参数(如"录用通知书");
2. 表格字段映射(如{'姓名':'员工姓名','岗位':'应聘岗位'});
3. 图片路径(如offer_logo.jpg)。

我把img_table.py封装成模块notify_tool.py,对外暴露generate_notice(template_dir, data_df, image_path, title_keyword)函数,这样不同部门调用时,只需传入自己的参数,无需碰底层代码。

5.2 加入邮件自动发送:闭环的最后一公里

生成通知后,下一步自然是发邮件。我用smtplibemail库做了轻量集成:

import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.base import MIMEBase
from email import encoders

def send_email(to_addr, subject, body, attachment_path):
    msg = MIMEMultipart()
    msg['From'] = "hr@company.com"
    msg['To'] = to_addr
    msg['Subject'] = subject
    msg.attach(MIMEText(body, 'plain'))

    # 附件
    with open(attachment_path, "rb") as f:
        part = MIMEBase('application', 'vnd.openxmlformats-officedocument.wordprocessingml.document')
        part.set_payload(f.read())
    encoders.encode_base64(part)
    part.add_header('Content-Disposition', f'attachment; filename="{os.path.basename(attachment_path)}"',)
    msg.attach(part)

    # 发送
    server = smtplib.SMTP('smtp.company.com', 587)
    server.starttls()
    server.login("hr@company.com", "password")
    server.send_message(msg)
    server.quit()

# 批量发送
for i, row in df.iterrows():
    send_email(
        to_addr=row['邮箱'],
        subject=f"{row['员工姓名']}工资调整通知",
        body=f"请查收附件中的工资调整通知。",
        attachment_path=f"员工{i+1}-工资调整通知_processed.docx"
    )

注意:邮件服务器配置需公司IT支持,密码建议用环境变量存储,避免硬编码。这步让工具从“生成”升级为“交付”,真正解放HR双手。

5.3 未来可接入的轻量级UI:告别命令行

对完全不懂命令行的同事,我用gradio做了极简Web界面:

import gradio as gr

def run_batch(template_dir, excel_path, image_path):
    # 调用原有逻辑
    process_documents(template_dir, pd.read_excel(excel_path), image_path)
    return "✅ 批量处理完成!请查看生成的_processed文件。"

iface = gr.Interface(
    fn=run_batch,
    inputs=[
        gr.Textbox(label="模板目录路径(如 ./templates)"),
        gr.File(label="工资数据Excel", file_types=[".xlsx"]),
        gr.File(label="标题图片", file_types=[".jpg", ".png"])
    ],
    outputs="text"
)
iface.launch()

访问http://127.0.0.1:7860,上传文件、点按钮,全程可视化。部署只需pip install gradio,连服务器都不用——本地跑,够用就好。

我在实际使用中发现,工具的价值不在于多酷炫,而在于多“不打扰”。它应该像办公室里的订书机:不需要说明书,不需要培训,拿起来就能用,用完放回原处。这套Python批量处理方案,就是为这个目标打磨出来的——没有魔法,只有对办公场景的诚实理解,和对每一行代码的较真。

本文还有配套的精品资源,点击获取 menu-r.4af5f7ec.gif

简介:一套开箱即用的Python自动化办公方案,专为工资通知类文档设计。包含核心脚本img_table.py,支持自动遍历10个已命名的Word工资通知文件(如员工1-工资调整通知.docx),按指定位置插入图片(如title002.jpg)并写入Excel或DataFrame格式的表格数据。图片自动缩放、居中对齐;表格按基础样式嵌入,适配常见通知排版需求。所有Word模板已按统一命名规范整理完毕,无需手动打开文档。运行只需Python 3.6+环境,依赖python-docx等轻量库,不调用Office软件,纯代码执行。配置通过脚本内路径变量完成,适合HR、行政、财务人员快速生成标准化通知,省去重复复制粘贴操作。


本文还有配套的精品资源,点击获取
menu-r.4af5f7ec.gif

本文章已经生成可运行项目
代码转载自:https://pan.quark.cn/s/11d565366452 【USB转I2C/IIC适配器上位机应用程序】是一种针对I2C(Inter-Integrated Circuit)通信协议而构建的工具,其通过USB端口将个人计算机转变为能够与I2C设备进行交互的控制器。该适配器使开发人员与工程师能够便捷地对遵循I2C协议的芯片执行读取和写入任务,因此在硬件构建和测试阶段能够显著率,对于核实I2C接口芯片的工作性能具有特别的价值。 I2C协议是由飞利浦(现NXP半导体)于1980年代初创立的一种双线式串行总线,其目的是用于连接微控制器及其他外围设备。该协议仅需两条信号线(SDA - 数据线,SCL - 时钟线)即可完成多设备间的通信,大幅度削减了电路板上的布线需求,从而降低了生产成本。I2C协议供多种速度等级,涵盖标准模式(100kbps)、快速模式(400kbps)以及高速模式(3.4Mbps),旨在满足不同场景下的应用要求。 Ginkgo USB转I2C适配器是这项技术的具体应用实例,它供了一个物理接口,用于将USB端口转换为I2C端口。适配器内部装配有一个微控制器单元,该单元负责处理从USB到I2C的信号转换,并且通过USB线路向计算机传输信息,同时接收来自计算机的指令以操控I2C总线。这种设计使用户无需具备深厚的硬件知识,仅需借助上位机软件即可实现对I2C设备的操控。 Ginkgo I2C Adapter Classic是与该适配器相配套的软件,通常包含以下几项核心功能: 1. 设备识别:自动检测并建立与USB转I2C适配器的连接。 2. 总线探查:扫描I2C总线上所连接的设备地址,有助于准确定位设备的位置。 3. 读写指令...
内容概要:本文围绕麦克斯韦旋度方程的差分形式在平面极化磁场中的应用展开深入研究,并通过Matlab代码实现相关数值仿真。研究的核心是将经典的麦克斯韦方程组转化为适用于数值计算的有限差分格式,构建离散化数学模型,进而模拟和分析平面极化条件下磁场的空间分布特征与时间演化规律。文中系统阐述了差分方法的理论基础与数学推导过程,详细说明网格划分、边界条件设定及迭代求解策略,最终利用Matlab编程实现电磁场的可视化仿真,有验证了差分方法在求解复杂电磁场问题中的准确性与可行性。该研究不仅加深了对电磁波传播机理的理解,也为电磁器件的设计优化与工程仿真供了可靠的数值分析手段。; 适合人群:具备电磁场与电磁波理论基础,熟悉偏微分方程数值解法,且掌握Matlab编程技能的电气工程、物理学、应用数学等领域的研究生、科研人员及工程技术人员。; 使用场景及目标:①深入掌握麦克斯韦旋度方程的有限差分法基本原理及其在二维平面磁场仿真中的具体实施步骤;②学习如何利用Matlab进行电磁场问题的建模、编程求解与结果可视化;③为后续开展更复杂的电磁兼容、天线设计或光子晶体等领域的数值模拟研究奠定坚实的技术基础。; 阅读建议:建议读者结合经典电磁场理论教材,透彻理解麦克斯韦方程组的物理内涵,然后循序渐进地跟进文中的差分格式推导过程,务必动手复现并调试所供的Matlab代码,通过调整参数观察仿真结果的变化,从而深刻领悟数值方法的实质与应用技巧。
已经博主授权,源码转载自 https://pan.quark.cn/s/a4b39357ea24 【相关知识说明】 1. 百度网盘文件组织方式: 百度网盘作为一项云端数据存储解决方案,为用户供文件的上传、下载及分享功能。其文件组织架构是用户对存储内容进行系统化安排的手段,借助文件夹及其嵌套的子文件夹实现文件的有管理。 2. SQLite 数据管理系统: 在百度云管家应用程序中,用户的网盘文件组织信息被保存在一个名为"BaiduYunGuanjia.db"的SQLite数据存储文件里。SQLite属于一种小型化关系型数据管理系统,频繁应用于嵌入式平台和移动终端,主要优势在于无需配置独立的服务器进程,且全部数据信息均存储在单一文件实体中。 3. 网盘目录结构导出方法: 若要获取百度网盘的文件组织层级,必须借助能够解析SQLite数据存储的专用软件,例如Navicat Premium。通过建立与SQLite数据存储的连接,并对特定数据表(如"cache_file")执行查询操作,可以获取包含文件名称(server_filename)、文件容量(file_size)以及父目录位置(parent_path)等关键信息的文件目录详情。 4. Navicat Premium 应用说明: Navicat Premium是一款多功能数据库管理平台,支持多种数据存储类型,涵盖SQLite系统。用户可利用该工具接入"BaiduYunGuanjia.db"数据存储,进行数据查看与导出操作。但需注意,直接在Navicat环境中执行导出操作可能存在技术障碍,因此建议将数据传输至Excel软件以便后续处理。 5. Excel 数据处理与目录树构建: 在Excel软件中,可通过VBA(Visual ...
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值