朋友说:能不能用python,帮我写一个“制作工资条”的自动化程序?

举报
yd_226342373 发表于 2021/05/20 01:05:38 2021/05/20
【摘要】 本文说明 今天和一个朋友吃饭,她说我经常使用Excel制作工资条,但是每个月都要做一遍,你能不能用python写一个代码,能够自动化完成这个工作。这当然可以啦,就是这么牛逼! 我们先来看看原始数据是什么样子的。 那么最后做成的效果是什么样子的呢? 这就很方便了,不管你公司有多少人,只要你把原始数据丢给我,我都可以秒出一个工资条,省得每次都需要使用Excel操作一...

本文说明

今天和一个朋友吃饭,她说我经常使用Excel制作工资条,但是每个月都要做一遍,你能不能用python写一个代码,能够自动化完成这个工作。这当然可以啦,就是这么牛逼!
在这里插入图片描述
我们先来看看原始数据是什么样子的。
在这里插入图片描述
那么最后做成的效果是什么样子的呢?
在这里插入图片描述
这就很方便了,不管你公司有多少人,只要你把原始数据丢给我,我都可以秒出一个工资条,省得每次都需要使用Excel操作一遍,并且数据多了Excel还会卡顿。

代码逻辑剖析

那么这样一个程序,是怎么写的呢?

其实只要是逻辑想清楚了,剩下的就是写代码的事儿了。下面我就带着大家梳理一下,这段代码的逻辑。

首先,我们应该是读取Excel表格。然后需要拷贝其中一个sheet表到另外一张sheet表,并给sheet命名。这样做的目的:为了存放制作好工资条的那张sheet表。

import re
import openpyxl
from copy import copy

wb = openpyxl.load_workbook('工资条.xlsx')
# copy_worksheet():拷贝sheet表 
wb.copy_worksheet(wb['工资条'])
# worksheets:以列表的形式返回所有的Worksheet(表格)
ws = wb.worksheets[-1]
ws.title = 'final_工资条'

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

可能这样说的话,大家还是不知道上述代码每一行,到底是什么意思,我下面截一张图给大家,其实就可以很好的说明上述函数的含义了。
在这里插入图片描述
接着,就是给每一行数据前面添加一个表头。由于后面每一行表头的样式,都与第一行完全一模一样的,因此我们需要复制第一行表头中的样式。

def cell_style(cell): alignment = copy(cell.alignment) # 对齐样式 border = copy(cell.border) # 边框样式 fill = copy(cell.fill) # 填充样式 font = copy(cell.font) # 字体样式 return alignment, border, fill, font # 获取标题行中,每个单元格中的各种样式
alignment, border, fill, font = cell_style(cell=cells_rows[0][0])

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

从上面的代码中可以看到:我定义了一个函数,我们直接使用copy库中的copy()方法,直接拷贝单元格的4大样式。因为原表第一行中每个单元格的4大样式,都是完全一致的,因此我们直接获取第一个单元格的样式即可

最后这一part是整个代码中最精彩的部分,不太好叙述,大家仔细研究一下下方的注释。

for i, _ in enumerate(cells_rows[1:]): if i > 0: index = i*3 # 每循环一次,就在对应位置下方插入2行。1行是空行,1行是表头行。 ws.insert_rows(idx=index, amount=2) # 因为每次插入2行,所以需要在表头行那里,将表头及其样式写入。 for j, v in enumerate(header): r, c = index+1, j+1 cell = ws.cell(row=r, column=c) cell.value = v cell.alignment = alignment cell.font = font cell.border = border cell.fill = fill # 更新后面的公式 if cell.coordinate[:1] in ('H', 'J'): cell = ws.cell(row=r+1, column=c) cell.value = re.sub('\d+', str(r+1), cell.value)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

这里需要特别说明一点的就是更新公式。就拿第一次循环来说,我们在第3行的位置,插入了2个空白行。那么原本第3行的数据,此时就被挤到了第5行。

但是需要注意的是,它是被迫挤到第5行的,所以这一整行是原封不动搬到第5行的,包括它原来的公式。原来在第3行的时候,如果公式是SUM(E3:G3),被挤到到了第5行后,应该是SUM(E5:G5),但是它仍然是SUM(E3:G3),所以需要我们修改,上述代码中正是使用正则将这个数字3改为了5。

完整代码

import re
import openpyxl
from copy import copy

def cell_style(cell): alignment = copy(cell.alignment) # 对齐样式 border = copy(cell.border) # 边框样式 fill = copy(cell.fill) # 填充样式 font = copy(cell.font) # 字体样式 return alignment, border, fill, font

wb = openpyxl.load_workbook('工资条.xlsx') 
wb.copy_worksheet(wb['工资条'])
ws = wb.worksheets[-1]
ws.title = 'final_工资条'

# 获取每一列的值,拼接在一个列表中
cells_rows = [[cell for cell in row] for row in ws.rows]

# 获取标题
header = [cell.value for cell in cells_rows[0]]

# 获取标题行中,每个单元格中的各种样式
alignment, border, fill, font = cell_style(cell=cells_rows[0][0])

for i, _ in enumerate(cells_rows[1:]): if i > 0: index = i*3 # 每读取一行,就在下方插入两行 ws.insert_rows(idx=index, amount=2) # 写表头 for j, v in enumerate(header): r, c = index+1, j+1 cell = ws.cell(row=r, column=c) cell.value = v cell.alignment = alignment cell.font = font cell.border = border cell.fill = fill # 更新后面的公式 if cell.coordinate[:1] in ('H', 'J'): cell = ws.cell(row=r+1, column=c) cell.value = re.sub('\d+', str(r+1), cell.value)
# 整个代码写完后,一定要记得保存 
wb.save('工资条.xlsx') 
  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

文章来源: blog.csdn.net,作者:数据分析与统计学之美,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_41261833/article/details/107764280

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。