优化之前写的文档更新工具,输出指定列的数据到公式表中,且确保数值单元格不会被识别为文本,导致Excel文档数值计算公式失效
ExcelTool.py
import os
import pandas as pd
from openpyxl import load_workbook
import json
### Excel表指定sheet更新
# 更新计算文档所需表的内容
class update_calculate_excel:
def __init__(self):
# 此处先初始化所需数据信息
# 读取json文件,获取数据表对应信息
data_json = json.loads(open('excel_data.json','r',encoding='UTF-8').read())
# 配置表位置
self.file_path = data_json['数据来源']
# 要导入到哪个计算公式表
self.excel_path = data_json['公式表']
# 要导入哪些表
self.sheet_name = data_json['excel_name']
# 更新工作表
def update_sheet(self):
# 读取需要导入更新的工作表
for excel_name in self.sheet_name:
# 拼接Excel文件路径:Excel\xxxxx.xlsx
read_excel_doc = self.file_path + "\\" + excel_name + ".xlsx"
# 判断文件是否存在
if not os.path.exists(read_excel_doc):
print("------------------------------------------------")
print(read_excel_doc, "文件不存在!!!!!", )
print("------------------------------------------------")
# 此处仅是中断不存在表的读取,如果还有其他表,会继续循环,尝试读取
continue
# 存在,则读取文件内容
data = self.read_sheet(read_excel_doc,excel_name)
if data:
# 将读取到的数据写入公式表中
if self.write_calculation_excel(excel_name, data):
print(excel_name, "复制完成")
else:
print("------------------------------------------------")
print(excel_name, "内容不存在!")
print("------------------------------------------------")
# 读取工作表内容并拷贝
def read_sheet(self,excel_path,name):
data = None
try:
# 读取Excel表内容
# 如果要从指定行开始读取,比如想从第3行开始读取数据,参数header设置为2即可
raw_data = pd.read_excel(excel_path, header=None, index_col=None )
data = raw_data.values.tolist()
except ValueError:
print("------------------------------------------------")
print(name , "不存在!")
print("------------------------------------------------")
finally:
return data
# 写入数据
def write_calculation_excel(self,name, data):
# 此时只是设置插入公式表中的sheet名
if len(name.split("-")) < 2:
print("------------------------------------------------")
print(name, "名字格式异常")
print("------------------------------------------------")
return False
sheet_name = name.split('-')[1]
# 加载公式表
calculate_excel_sheet = load_workbook(self.excel_path)
# 查找公式表中是否有同名工作表
if sheet_name in calculate_excel_sheet.sheetnames:
# 删除公式文档内原有的工作表
calculate_excel_sheet.remove(calculate_excel_sheet[sheet_name])
# 创建空白工作表sheet_name
calculate_excel_sheet.create_sheet(sheet_name)
# 格式化数据内容
self.data_format(calculate_excel_sheet[sheet_name],data,self.sheet_name[name])
# 保存文件
calculate_excel_sheet.save(self.excel_path)
# 关闭文件
calculate_excel_sheet.close()
return True
# 将字符串分割成list
def to_str_rt_list(self,str):
rt_list = []
if len(str.split(";")) > 1 and len(str.split(";")[1]) != 0:
for l in str.split(";"):
rt_list.append(l.split(","))
else:
rt_list=str.split(";")[0].split(",")
return rt_list
# 按需求格式返回所需数据
def data_format(self,sheet_name,data,data_row):
i = 0
type_row =[]
for row_data in data:
# 记录每列数据的类型
row_list = []
# 当前处理列
t_id = 0
for row_id in data_row:
if i < 2:
# 前两行为无用数据
break
elif i == 2:
# 第三行为类型,用于处理数据类型
type_row.append(row_data[row_id])
elif i == 3:
# 第四行为标题,
row_list.append(row_data[row_id])
# 如果该列类型为array,则数据做拆分处理,此处暂处理k,y形式的值
if type_row[t_id] == "array":
row_list.append(row_data[row_id] +"_值")
else:
# 其他行为具体数据,根据类型强转成指定类型,避免数据插入后变为文本类型,导致对数值操作的Excel公式失效
if type_row[t_id] == "int":
row_list.append(int(row_data[row_id]))
elif type_row[t_id] == "float":
row_list.append(float(row_data[row_id]))
elif type_row[t_id] == "array":
list = self.to_str_rt_list(str(row_data[row_id]))
# 拆分成单独列
if len(list) > 1:
row_list.append(float(list[0]))
row_list.append(float(list[1]))
elif len(list) == 1 and type_row[t_id] == type_row[t_id]:
row_list.append(float(list[0]))
row_list.append("")
else:
row_list.append("")
row_list.append("")
else:
row_list.append(str(row_data[row_id]))
t_id = t_id + 1
i = i + 1
if i <= 3:
# 前三行无需追加新表中
continue
sheet_name.append(row_list)
excel_data.json
{
"数据来源": "Excel",
"公式表": "Excel\\导入公式表.xlsx",
"excel_name": {
"out-导出数据-out": [0,1,2,3,4]
}
}
执行后,导入公式表.xlsx便会新增工作表【导入数据】,并且有我们所需的数据内容
也可导入多张表,以及选择指定列导入
{
"数据来源": "Excel",
"公式表": "Excel\\导入公式表.xlsx",
"excel_name": {
"out-导出数据-out": [0,1,2,3,4],
"out2-导出数据2-out2": [0,2,4]
}
}
导出数据表内容
执行后,公式表内容,其中工作表【导出数据2】并没有标题和float数据列