问题背景
作为数据分析员经常需要操作很多的EXCEL,俗话说“痛吾痛以及人之痛”,咱有这样的需求其他同事也会有这样的需求,所以利用最近在家的机会设计一个通用的EXCEL取数小工具,来帮助大家提升效率。
由于数据表有的人还在用xls的,所以本来想用openpyxl来读取的计划就搁置了,还是用pandas来处理数据。大概有两个问题:
①在Pandas中要如何使用EXCEL的横纵坐标。
②如何识别设置的公式。
解决方案
这里我们用到两个模块,一个是前面遗憾退场的openpyxl,另一个是re。
openpyxl里面有两个函数
get_column_letter
column_index_from_string
从名字就能看出一个是把列编号转成字母的,一个是把字母转成列编号的。
所以还需要配合我们的正则识别re使用。
代码如下:
re.findall(r'[A-Za-z]+\d+', tar)
为了更好的定位数据的位置,我把数据定义成这个样子:
使用者需要在格子前后插入$,来进行定位。支持一些简单的计算式,这些计算式指的是python的计算式而不是EXCEL里面的计算式,这点需要和脚本使用者强调一下,不过他们大部分都只使用简单的四则运算而已,应该还好。
$F4$
$C4$+$D4$+$E4$
max($C4$,$D4$,$E4$)
整个函数的代码如下:
def get_loc(tar):
# 识别所有需要的数据格
rets = re.findall(r'\$[A-Za-z]+\d+\$', tar)
print(rets)
# 识别去除数据格后剩余的公式
tar_str = re.sub(r'\$[A-Za-z]+\d+\$', '{}', tar)
print(tar_str)
if len(rets) > 0:
ret_list = []
for item in rets:
col, row = re.findall(r'[A-Za-z]+|\d+', item)
# 因为用到pandas,所以行号需要减2,减掉一个头和一个第0行
# 因为用到pandas,所以列号需要减1,减掉一个第0列
ret_list.append((int(row)-2, column_index_from_string(col)-1))
else:
return None
print(ret_list)
return tar_str, ret_list
以上面的max($C4$,$D4$,$E4$)为例,输出如下:
识别到的数据格子:['$C4$', '$D4$', '$E4$']
识别到的剩余公式:max({},{},{})
转换后的格子坐标:[(2, 2), (2, 3), (2, 4)]
到dataframe里面获取对应的数据:1552981.20626 205398.8105 270738.89093
输出最终计算结果:1552981.20626
后面就简单啦,根据格子从pandas里面取出数据,然后和剩余公式的字符串进行拼接,拼接的时候可以用*进行拆包。
value = eval(tar_str.format(*cell_value_list))
得到:
max(1552981.20626,205398.8105,270738.89093)
然后调用eval()函数进行运行,eval() 函数用来执行一个字符串表达式,并返回表达式的值。
挺简单的,具体效果可能还得在后期再验证一下,在这里稍微记录一下。我是llsxily,你可以叫我橘子。