需求说明
已知要提取的目标值:例如所在表的名称是“A.xlsx”,该数据在该表中所属行是“合计”,所属列是“销售额”。
“所属行”、“所属列”的意思是:行标签和列标签的名称,通常在最左一列和最上一行。
实际实现时:会找到某单元格的内容等于该标签名称,该单元格的行序和列序就是要找是目标行和目标列。
如果Cfg.txt某些数据(如 其他值)无法提取,而是通过其他方式获得,可直接写成下面的形式。
在最终生成的提取结果.txt中会保留原始描述。
在配置文件Cfg.txt中这样填写
{
"目标值":["A","合计","销售额"],
"其他值":"描述数据来源"
}
在最终生成的提取结果.txt中,可看到提取到的值(例如是500)
{
"目标值":"500",
"其他值":"描述数据来源"
}
如果提取失败,则显示为null
{
"目标值": null,
"其他值":"描述数据来源"
}
成品设想
将工具和所有表(.xlsx)、Cfg.txt放在同一目录下。
运行后,在该目录下生成:提取结果.txt。形式和Cfg.txt一致,只是提取值替换了原本对提取值所属表、行、列的描述。
实现思路
生成数据字典
2个字典。
- 各表的名称及各单元格的值和其行序列序
- Key是各表(.xlsx)的名称,无后缀,即Cfg.txt对目标值的描述中的3个子项中的第1项
- Value是若干个子字典
Key:单元格中的值
Value:该单元格所属的行序、列序
- 各表的名称及各表
目标值位置描述 -> 目标值
根据目标值的位置描述,从数据字典1找到该值所属的表以及行序列序,从数据字典2找到目标值。
具体代码
# 打包命令
# pyinstaller --hidden-import json -F -c D:\Fanjc\PythonProjects\从多个excel表中提取目标数据\从多个excel表中提取目标数据.py D:\Fanjc\PythonProjects\ReadAndWriteTable.py
import os
import sys
from openpyxl import load_workbook
sys.path.append('D:\Fanjc\PythonProjects')
# .py文件(模块)名称是ReadAndWriteTable
from ReadAndWriteTable import readJson, writeJson
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 getValueByTableRowColName(nameList, dataDict, tableDict):
'''nameList长度应为3:表名、行名、列名;
dataDict的key是表名,值是行列名-[对应的行序号,列序号];
tableDict:表名-表'''
ret = None
if len(nameList) == 3:
tableName = curValue[0]
rowName = curValue[1]
colName = curValue[2]
if tableName in dataDict.keys() and rowName in dataDict[tableName].keys() and colName in dataDict[tableName].keys():
rowIndex = dataDict[tableName][rowName][0]
colIndex = dataDict[tableName][colName][1]
ret = tableDict[tableName].cell(row = rowIndex, column = colIndex).value
return ret
if __name__ == "__main__":
'''从多个excel表中提取目标数据'''
# 获取本目录下的所有.xlsx
curDir = os.path.realpath(os.path.dirname(sys.argv[0]))
suffix = '.xlsx'
tablesPath = getPathList(curDir,suffix)
# 获取所有表格内容
tableDict = {}
tableNameAndValueDict = {}
for path in tablesPath:
curName = os.path.basename(path)
# 剔除后缀
curName = os.path.splitext(curName)[0]
curTable = load_workbook(path).active
tableDict[curName] = curTable
curValueAndRowColDict = {}
for row in curTable.iter_rows(values_only = False):
for cell in row:
curValue = cell.value
# 剔除空格、换行
if type(curValue) == str:
curValue = curValue.replace(' ','')
curValue = curValue.replace('\n','')
curValueAndRowColDict[curValue] = [cell.row, cell.column]
tableNameAndValueDict[curName] = curValueAndRowColDict
# 输出的是字典
output = {}
# 读配置
cfgFileDir = os.path.dirname(sys.argv[0])
cfgPath =os.path.join(cfgFileDir,'Cfg.txt')
cfg = readJson(cfgPath)
for item in cfg.items():
curKey = item[0]
curValue = item[1]
outputValue = curValue
if type(curValue) == list:
# 尝试找到curValue对应的表中的值
outputValue = getValueByTableRowColName(curValue, tableNameAndValueDict, tableDict)
output[curKey] = outputValue
# 导出
outputPath = os.path.join(curDir,'提取结果.txt')
writeJson(outputPath,output)
print('成功提取!\n',outputPath)
# 让打包后不自己退出
input()