因为工作需要对excel做了系列的处理,对于其中的几个功能实现颇费了一些精力,自己手动写了一些function。
合并单元格的split
首先获得这张sheet中所有的合并单元格,再依次循环每一个,因为合并单元格都是返回其第一个行列的值,所以只需要返回该值即可。
def unmergedValue(rowx, colx, thesheet):
'''
Split merged cells.
'''
for crange in thesheet.merged_cells:
rlo, rhi, clo, chi = crange
if rowx in range(rlo, rhi):
if colx in range(clo, chi):
return thesheet.cell_value(rlo, clo)
#if you reached this point, it's not in any merged cells
return thesheet.cell_value(rowx, colx)
表头拆分
这里用到了字典占位的思想,以及利用了yield阅后即焚的效果
首先要有所有的表头list,在这个list中的元素,即被分类
def split_tab_title(header, utitle):
'''
Split the separate tables' header from the title row of an excel sheet.
'''
tmp_dict = {i: None for i in header}
tmp_tab = {}
ntitle = [i.lower().replace(' ', '') for i in utitle]
unamelist = [i.lower().replace(' ', '') for i in header]
for idx, name in enumerate(ntitle):
if name in unamelist:
pos = unamelist.index(name)
element = header[pos]
#try:
if not tmp_dict[element]:
tmp_dict[element] = element
tmp_tab[element] = idx
else:
yield tmp_tab
tmp_dict = {i: None for i in header}
tmp_tab = {}
tmp_dict[element] = element
tmp_tab[element] = idx
#except KeyError:
#print(element + ' is not header type')
yield tmp_tab
确定好了表头的index之后,再逐一读行,获得其对应的元素
def get_tab_value(values, record):
'''
Get each line info for each table value.
'''
record_dict = {}
for tab in record:
for name, idx in tab.items():
record_dict[name] = values[idx]
yield record_dict
此处代码内部的dict只要更新了,key不变,但value会改变,只做循环的时候看不出来,但是,如果转成list,就会发现只能迭代最后一次的value。故代码需要修改,如下才是正确的代码。
def get_tab_value(values, record):
'''
Get each line info for each table value.
'''
record_dict = {}
for tab in record:
if not record_dict:
for name, idx in tab.items():
record_dict[name] = values[idx]
else:
yield record_dict
record_dict = {}
for name, idx in tab.items():
record_dict[name] = values[idx]
yield record_dict
此处有个大坑,就是yield是只能迭代一次的,下次再使用它已经空了,所以要么用list把record存好,要么每次迭代这个record。
records = list(split_tab_title(header, utitle)) ####can be iterable more than once
for row_index in range(title_row_index + 1, sheet.nrows):
tab_record = get_tab_value(values, records)
或者,每次循环都生成generator,其实也不占内存
for row_index in range(title_row_index + 1, sheet.nrows):
records = split_tab(header,mytitle) ###generator only use once
tab_record = get_tab_value(values, records)