需求说明
有多张Excel表,各表的格式是一样的,但是数值不同,现在需要将所有表中的数值加和。
例如,有1、2、3……月的各部门的收入表,现在需要将所有月份的各部门的收入加和。
成品设想
最终的工具是一个单一的exe文件,将它和所有待求和的原始表放在同一目录下。
运行后,该工具获取所在目录下的所有表格,对各表中的对应数值进行求和,生成一张最终表。
实现思路
求和前,判断条件是否满足
2个条件
- 目录下的表格文件数量多于1个
- 目录下的表格文件格式一致:当前判断只要行列数一样,就认为是格式相同
求和
如何判断哪些值是要求和的?
遍历各表的所有格子,只要该格子是数值或None,就认为是要求和的 -> 将所有表中该格中的数值加和,存入最终表
加和时,若是None则视为0。对加和的结果,若是0,则转为None。
具体代码
# 打包命令
# pyinstaller --hidden-import json -F -c D:\Fanjc\PythonProjects\多表求和\多表求和.py
import os
import sys
from openpyxl import load_workbook
from shutil import copyfile
class Table:
path = ''
name = ''
content = ''
rows = 0
cols = 0
def __init__(self, path):
self.path = path
self.name = os.path.basename(path)
self.content = load_workbook(path).active
self.rows = self.content.max_row
self.cols =self.content.max_column
def showInfo(self):
print(self.name,self.rows,self.cols)
def getCellFloatValue(self, row, col):
return ValueToFloat(self.content.cell(row = row, column = col).value)
def getValue(self, row, col):
return self.content.cell(row = row, column = col).value
def getPathList(path, suffix):
'''获取path下所有后缀为suffix的文件的路径'''
pathList = []
for mainDir, subDir, fileNameList in os.walk(path):
for fileName in fileNameList:
currentPath = os.path.join(mainDir, fileName)
if currentPath.endswith(suffix):
pathList.append(currentPath)
return pathList
def isFloat(data):
'''若是float则返回true'''
try:
temp = float(data)
return True
except:
return False
def IsNone(data):
return data == None
def IsNoneOrFloat(data):
return isFloat(data) or IsNone(data)
def ValueToFloat(data):
ret = 0
if isFloat(data):
ret = float(data)
return ret
def FloatToValue(data):
ret = None
if data != 0:
ret = data
return ret
if __name__ == "__main__":
'''多表求和'''
# 获取本目录下的所有.xlsx
curDir = os.path.realpath(os.path.dirname(sys.argv[0]))
suffix = '.xlsx'
tablesPath = getPathList(curDir,suffix)
if len(tablesPath) <= 1:
print('错误:当前目录下的表格文件不足2个,无法求和!')
input()
exit()
# 获取所有表格内容
tables = []
for path in tablesPath:
tables.append(Table(path))
# 判断前述所有xlsx行列数是否都一致
allRows = []
allCols = []
for t in tables:
allRows.append(t.rows)
allCols.append(t.cols)
# all:所有元素计算结果都是true才返回true
isSameSize = all(r == allRows[0] for r in allRows) and all(c == allCols[0] for c in allCols)
if not isSameSize:
print('错误:当前目录下的表格文件的行列数不相等,无法求和,请确认!')
for t in tables:
t.showInfo()
input()
exit()
# 复制表格
outputTableName = str(len(tables))+'表求和'+suffix
outputPath = os.path.join(curDir, outputTableName)
copyfile(tables[0].path, outputPath)
outputWorkbook = load_workbook(outputPath)
outputTable = outputWorkbook.active
# 遍历求和
firstTable = tables[0].content
for row in firstTable.iter_rows(values_only = False):
for cell in row:
curRow = cell.row
curCol = cell.column
canSum = False
for t in tables:
canSum = IsNoneOrFloat(t.getValue(curRow, curCol))
if canSum:
break
if canSum:
curValue = 0
for t in tables:
curValue += t.getCellFloatValue(curRow, curCol)
curValue = FloatToValue(curValue)
outputTable.cell(row = curRow, column = curCol, value = curValue)
# 保存
outputWorkbook.save(outputPath)
print("求和成功:",outputPath)
# 让打包后不自己退出
input()