问题描述
最近在做一个小工具,要求用户上传一个3列N行的excel文件,后台接收后调用程序计算一些值,然后将新值附加到dataframe中,然后输出到新的excel文件中。
解决方案
思路比较简单,这里只给出关键代码。
def probatch_process_excel(in_file_path:str) -> List[str]:
'''
Read and write excel for protein analysis batch.
:param in_file_path: input excel file path
:return: output file path and error messages
path: output excel file path
error codes: "ok" for success, others for reasons
'''
code = "ok"
# read
# 读取excel文件的所有sheet, 没有表头
sheets = pd.read_excel(in_file_path, sheet_name=None, header=None)
results = {}
# 获取所有sheet的名称
sheet_names = list(sheets.keys())
# 新的headers,内容略
headers = ['ID', 'x', 'xx', 'xxx', 'x', 'xx', 'xxx']
# 遍历每个sheet
for sheet in sheet_names:
df = sheets[sheet]
# 如果是空表或者列数小于3,跳过
# 因为要修改表头,空表可能会导致后面的1号报错
if df.shape[0] == 0 or df.shape[1] < 3: continue
# 先添加几列,初始值全部为NaN
df[3] = None
df[4] = None
df[5] = None
df[6] = None
# 获取行数
nrow = df.shape[0]
# 遍历每一行
for ridx in range(nrow):
# 读取cell
in_id = df.iloc[ridx, 0]
# 调用函数计算一些数据
res_sp = probatch_signalp(in_id)
# 修改cell的值,其他列略
df.at[ridx, 3] = res_sp[0]
# 如果想要修改整列的数据
# 需要注意df.shape[1]与右值的长度需要一致,不然报错
# df.iloc[:, 4] = res_sp[0]
# 处理完这个sheet,修改列名
df.columns = headers
results[sheet] = df
# write
# get name
xlsx_name = 'out.' + in_file_path.split('/')[-1]
# 注意,这里使用w,因为要新建一个excel表
with pd.ExcelWriter(xlsx_name, mode='w', engine="openpyxl") as writer:
for key, val in results.items():
val.to_excel(writer, sheet_name=key, index=False)
return [xlsx_name, code]
报错处理
- ValueError: Length mismatch: Expected axis has 4 elements, new values have 7 elements
这个是我为新表增加表头时报的错误。原因是:由于我遍历了所有表,对于有内容的表,原本有3列,增加4列新值后刚好可以匹配新的、长度为7的headers;但是对于没有内容的空表,由于我没有跳过,实际只有4列新值,那是无法匹配新headers的。 - 写出到excel时报错:没有xlsx_name
这是模式写错了,不能用追加的a
,而要用w
。也可以做检查:try: with pd.ExcelWriter(xlsx_name, mode='a', engine="openpyxl") as writer: df.to_excel(writer, sheet_name="Sheet1", index=False) except FileNotFoundError: # 文件不存在,使用写入模式创建文件 with pd.ExcelWriter(xlsx_name, mode='w', engine="openpyxl") as writer: df.to_excel(writer, sheet_name="Sheet1", index=False)