Python excel xlwings+QT 考勤表开发
1. 概述
这是一篇excel开发培训的示例教程。用考勤表作为示例进行演示:
-
如何创建QT界面, 如何衔接打开的Excell
-
如何读取数据
-
如何数据解析为一个树状结构
-
如何拆分成不同的excel文件。
-
如何合并不同的文件到一个汇总文件内
-
本文的代码仓地址: https://gitee.com/bigearrabbit/kevinpython/blob/master/KevinAttendance/
2. QT界面搭建
2.1搭建界面
用desiner所见即所得搭建界面,设置好自动缩放,设定好信号槽。
运行mainwindows.bat 生成mainwindows_ui.py文件:
或命令:pyuic5 -o mainwindows_ui.py mainwindows.ui
创建KevinAttendanceDlg.py。
运行效果:
3. 搭建软件架构
为了清晰结构,实现数据、算法、界面分开,采用下面的文件结构。
文件 | 用途 |
---|---|
mainwindows.ui | 自动创建的ui文件 |
mainwindows_ui.py | 自动创建的界面py文件 |
KevinAttendanceDlg.py | 自定义的界面文件,继承于mainwindows_ui.py |
KevinAttendanceParam.py | 自定义的参数类 |
KevinAttendanceCore.py | 核心算法类 |
3. 读取输入文件
请在下面文件内查看代码:
https://gitee.com/bigearrabbit/kevinpython/blob/master/kevinexcel/KevinAttendance/KevinAttendanceCore.py
3.1链接文件
请在KevinAttendanceCore.py文件内查看代码。
def LinkActiveSheet(self):
self.ErrMsg = ''
if xw.apps.active == None:
self.ErrMsg = "xw.apps.active == None"
return 1
param = self.param # 设定引用
# get pid
pid = xw.apps.active.pid
param.pid = pid
param.app = xw.apps[pid]
# 其中需要注意的是单元格的完全引用路径是:
# 第一个Excel程序的第一个工作薄的第一张sheet的第一个单元格
wb = param.wb = param.app.books.active
if wb == None:
self.ErrMsg = ("wb == None")
return 1
param.ExcelFileName = wb.name
# 引用工作簿中的sheet
# sht=xw.books['工作簿的名字‘].sheets['sheet的名字']
# or sht=wb.sheets[sheet的名字]
param.sht = wb.sheets[0] # get sheet
return 0
3.2读取表格
请在KevinAttendanceCore.py文件内查看代码。
def GetAttendTable(self):
param = self.param
wb = param.wb
sht = wb.sheets[0] # get sheet 0
param.inputTable = sht.used_range.value
if param.inputTable == None or len(param.inputTable) < 2:
self.ErrMsg = "Input Table data is not right. rows < 2"
return 2
return 0 # ok
3.3解析为树状结构
函数AnylisisAttend()
请在KevinAttendanceCore.py文件内查看代码。
解析的效果
ColumnNames :
['部门', '科室', '姓名', '工号', '级别', '正常出勤', '加班', '年假', '事假', '合计']
Dept Tree
开发部
┠ 软件科
┠ ┠ ['张1', 1001.0, 'E', 174.0, 8.0, 8.0, 0.0, 174.0]
┠ ┠ ['张2', 1002.0, 'F', 174.0, 0.0, 0.0, 0.0, 174.0]
┠ ┗ ['张3', 1003.0, 'G', 174.0, 0.0, 0.0, 8.0, 166.0]
┠ 硬件科
┠ ┠ ['张4', 1005.0, 'E', 174.0, 24.0, 0.0, 0.0, 198.0]
┠ ┠ ['张5', 1006.0, 'F', 174.0, 30.0, 8.0, 0.0, 196.0]
┠ ┠ ['张6', 1007.0, 'G', 174.0, 8.0, 0.0, 16.0, 166.0]
┠ ┗ ['张7', 1008.0, 'H', 174.0, 0.0, 0.0, 0.0, 174.0]
┠销售部
┠ 东北科
┠ ┠ ['张7', 1009.0, 'E', 174.0, 0.0, 0.0, 0.0, 174.0]
┠ ┠ ['张8', 1010.0, 'F', 174.0, 22.0, 0.0, 0.0, 196.0]
┠ ┗ ['张9', 1011.0, 'G', 174.0, 0.0, 16.0, 0.0, 158.0]
┗ 西南科
┠─['李1', 1012.0, 'E', 174.0, 34.0, 0.0, 4.0, 204.0]
┗─['李2', 1013.0, 'F', 174.0, 0.0, 0.0, 0.0, 174.0]
4.输出文件
拆分成不同的文件,然后分给不同的科室统计员进行填写、校核等工作
4.1 拆分文件
KevinAttendanceCore.SaveToFiles()函数
循环遍历部门的树,每个部门的科室保存到一个文件内
def SaveToFiles(self, iDeptTree):
ec = 0
app = self.param.app
datestr = "20210401"
for key, value in iDeptTree.items():
for key2, value2 in value.items():
filename = "{0}-{1}-{2}.xlsx".format(key, key2, datestr)
# filename = key + "-" + key2 + "-20210401" + ".xlsx"
print(filename)
wb = app.books.add() # wb就是新建的工作簿(workbook)
sht = wb.sheets['sheet1']
sht.range('A1').value = self.param.ColumnNames
i = 2
for key3, value3 in value2.items():
print(" ", value3)
sht.range(i,1).value = key
sht.range(i,2).value = key2
sht.range(i,3).value = value3
i+=1
outfile = 'out/' + filename
wb.save(outfile)
wb.close()
#return 0
输出信息,文件:
开发部-软件科-20210401.xlsx
开发部-硬件科-20210401.xlsx
销售部-东北科-20210401.xlsx
销售部-西南科-20210401.xlsx
5.合并文件
拆分成不同的文件,然后分给不同的科室统计员进行填写、校核等工作
(等待开发)