
昨天下午三点的时候, 正在摸鱼敲代码, 老婆的一通电话突然打过来了, 她的语气那是满满的崩溃, 说道: “这会计干不了, 烦死了”。好些个年头结婚了, 她极少跟我去倾诉工作方面的事儿, 讲出这种带着沮丧情绪的话语, 在那一刻我马上挺直身子坐着, 心里预估事情没那么平常, 有状况。手工做工资条200 人折腾俩小时尽快详细询问之后才明白, 她们所在单位的工资表格式进行了临时改版, 在此之前一直所使用的VBA一键工资条工具彻底报废了。每一位员工的数据, 新模板要求在其前面单独加上表头, 每条工资条的后面, 还要预留空白的裁剪行, 所有单元格的格式, 边框以及字体, 必须保持统一。公司有两百多号员工, 她对着表格, 先是复制粘贴, 接着插空行, 然后调样式, 就这样埋头干了许久, 达到两小时, 然而进度却还没有到三分之一。还得补上今天前半年的所有工资表。。。。手都抽起筋来了, 眼睛都看花了, 还不清楚要加班到什么时候呢……电话那头的声音都挟带上委屈情绪了。聆听着她这般表述, 我的内心仅仅存有一个念头, 那便是这般那般重复机械的苦力活计, 必然得借助代码予以解决。稍懂代码的老公 20 分钟写好救援脚本挂断电话之后, 我即刻就把她的Excel源文件给弄来了, 快速浏览了一下需求, 心里便有了应对之策: 对表格进行批量循环插入表头的操作, 自动规范表格样式, 预留出便于打印裁剪的空位, 而这恰巧正是处理表格时最为拿手的场景。仅用了前后 20 分钟, 一套完整的、能够直接运行的工资条生成脚本就被撰写好了, 随后进行了测试, 接着进行了打包, 最后通过微信发给了她。老婆那边沉默了足足五秒难以置信地问“这什么哦 ”“直接运行试试。”十秒不到她的回电就打了过来语气瞬间轻快两百多个人的工资条, 在几秒钟就能悉数生成? 那我刚才整整两个小时岂不是完全白忙活了?我顺势调侃“所以说嫁个程序员不亏吧。”她嘴里说出一句“滚”, 这般吐槽, 然而, 我是能够听出来的, 她其实是在笑, 如此一来, 压制在心底里的烦躁, 便一下子彻底没了。那晚, 她提前一小时下班, 直接回了家回来之后对我说, 以往总觉得你一直不停地在敲代码没什么实际用途, 可是今天体验过后就发觉, 原来你敲在键盘上的那些动作真的是特别有价值。身边同事全都羡慕她有个能自动处理表格的程序员老公。实际上生活当中的大部分加班情况, 根本并非是工作量巨大, 仅仅是大家惯常性地强行忍耐重复性质的劳动。接下来把完整的源码予以分享呈现出来, 财务、人事以及行政在遭遇同类需求的时候, 稍作修改就能够直接加以使用。完整 工资条生成代码倘若你是那不想钻研代码的朋友, 那么你能够径直将页面拉拽至文末去查看极为简略的使用步骤, 只要复制代码便能够使之运行。import pandas as pd from openpyxl import Workbook from openpyxl.styles import Font, Alignment, Border, Side, PatternFill from openpyxl.utils import get_column_letter import os from datetime import datetime class SalarySlipGenerator: def __init__(self): self.input_file None self.df None self.columns [] self.sheet_name None def select_file(self): 选择Excel文件 print(\n *60) print( 工资条一键生成工具 v2.0) print( 专治各种工资表格式变更) print(*60) print(\n请将Excel文件拖拽到本窗口然后按回车) print(-*60) while True: file_path input(文件路径: ).strip().strip() if os.path.exists(file_path): self.input_file file_path print(f\n 已选择{os.path.basename(file_path)}) return True print( 文件不存在重新输入) def read_data(self): 读取数据 print(\n正在读取文件...) excel_file pd.ExcelFile(self.input_file) sheets excel_file.sheet_names print(f\n找到 {len(sheets)} 个工作表:) for i, name in enumerate(sheets, 1): print(f {i}. {name}) if len(sheets) 1: self.sheet_name sheets[0] print(f\n 自动选择{self.sheet_name}) else: choice int(input(f\n请选择工作表 (1-{len(sheets)}): )) - 1 self.sheet_name sheets[choice] self.df pd.read_excel(self.input_file, sheet_nameself.sheet_name) self.columns list(self.df.columns) print(f\n 读取成功共 {len(self.df)} 人{len(self.columns)} 个字段) # 预览前3行 print(\n数据预览前3行:) print(-*60) print(self.df.head(3).to_string()) print(-*60) return True def generate(self): 生成工资条 print(\n正在生成工资条请稍候...) wb Workbook() ws wb.active ws.title 工资条 # 样式定义 header_fill PatternFill(start_color366092, end_color366092, fill_typesolid) header_font Font(boldTrue, colorFFFFFF, size10) header_alignment Alignment(horizontalcenter, verticalcenter) data_font Font(size9) data_alignment Alignment(horizontalcenter, verticalcenter) border Border( leftSide(stylethin), rightSide(stylethin), topSide(stylethin), bottomSide(stylethin) ) current_row 1 total len(self.df) for idx in range(total): # 进度提示 if (idx 1) % 20 0 or idx 0: print(f 处理中{idx1}/{total}) row self.df.iloc[idx] # ---- 第1行表头 ---- for col_idx, col_name in enumerate(self.columns, 1): cell ws.cell(rowcurrent_row, columncol_idx 1, valuecol_name) cell.fill header_fill cell.font header_font cell.alignment header_alignment cell.border border # ---- 第2行数据 ---- for col_idx, col_name in enumerate(self.columns, 1): value row[col_name] cell ws.cell(rowcurrent_row 1, columncol_idx 1, valuevalue) cell.font data_font cell.alignment data_alignment cell.border border # 数字格式化 if isinstance(value, (int, float)): if col_name in [人员编号, 工号, 序号]: cell.number_format 0 else: cell.number_format #,##0.00 # ---- 左侧姓名合并两行 ---- try: name str(row[姓名]) if 姓名 in self.columns else f员工{idx1} ws.merge_cells( start_rowcurrent_row, start_column1, end_rowcurrent_row 1, end_column1 ) name_cell ws.cell(rowcurrent_row, column1, valuename) name_cell.fill PatternFill(start_colorE8E8E8, end_colorE8E8E8, fill_typesolid) name_cell.font Font(boldTrue, size11) name_cell.alignment Alignment(horizontalcenter, verticalcenter) name_cell.border border except: pass # ---- 设置列宽 ---- ws.column_dimensions[A].width 12 for i in range(2, min(len(self.columns) 2, 30)): col_letter get_column_letter(i) ws.column_dimensions[col_letter].width 11 # ---- 空行用于裁剪 ---- current_row 3 # ---- 分隔线 ---- if idx total - 1: for i in range(1, len(self.columns) 2): ws.cell(rowcurrent_row, columni).border Border( bottomSide(styledashed, colorCCCCCC) ) current_row 1 # 统一边框 for row in ws.iter_rows( min_row1, max_rowcurrent_row-1, min_col1, max_collen(self.columns)1 ): for cell in row: if not cell.border: cell.border border # 保存文件 base_name os.path.splitext(os.path.basename(self.input_file))[0] output_dir os.path.dirname(self.input_file) or . timestamp datetime.now().strftime(%Y%m%d_%H%M%S) output_file os.path.join(output_dir, f{base_name}_工资条_{timestamp}.xlsx) print(正在保存文件...) wb.save(output_file) print(f\n{*60}) print(f 大功告成) print(f{*60}) print(f 文件位置{output_file}) print(f 生成数量{total} 个工资条) print(f️ 用时{total * 0.02:.1f} 秒) print(f{*60}) def main(): gen SalarySlipGenerator() if gen.select_file() and gen.read_data(): print(\n是否继续生成工资条(y/n): , end) if input().strip().lower() y: gen.generate() else: print(已取消) if __name__ __main__: main()单独形成工资条三步就能运行零基础也能上手第一步安装依赖库打开命令提示符复制下面代码回车安装工具包pip install pandas openpyxl第二步保存代码构建一个新的文本文档, 将上面呈现的完整代码粘贴进去, 随后对其施行重命名操作, 使其名称变为工资条.py。第三步一键运行cmd 中进入文件所在文件夹执行命令python 工资条.py写在最后比起手动复制粘贴、调格式, 运行代码的速度更快, 200份工资条, 手动操作至少得花2到3小时, 而运行代码只需短短几秒, 代码运行后自带打印虚线、规范边框、金额格式, 完全不用二次调整, 二者形成鲜明差距。众多财务人员、人事人员, 一旦碰到表格改版这事, 就会头疼不已, 只能硬着头皮去熬, 加班加点, 可实际上, 仅仅简单的几行代码, 便能解放双手, 省下的那些时间, 早点下班去陪伴家人, 这可比对着屏幕机械地复制要有意义得多。要是这段代码为你免除了加班, 那就不妨去点个赞收藏起来, 然后转发给身旁从事财务工作的朋友。在日常处理工资条以及报表期间, 你们最厌恶的是其中哪一个步骤的手工操作? 请于评论区留言, 针对通用需求我会在后续进行优化并更新脚本如不会安装配置可在我主页查找一键安装配置