由于在日常运维中经常出现一些合并单元格的表格,如果要获取数据比较麻烦,现将将封装成类,并通过调用list_excel_data()获取列表形式的数据, dict_excel_data():获取字典格式的数据。
当以字典形式获取数据时要注意,默认以第一行作为字典的key。
代码如下:
from openpyxl import load_workbook
class Get_table_data():
"""
对带有合并单元格的表格数据进行处理
"""
def __init__(self,sh):
"""
定义初始传入的表
:param sh: 表
"""
self.sh = sh
def get_row_col(self):
"""
# 获取表格的行、列信息
:param sh: 表
:return:
"""
# title = sh.title # 获取sheet名称
max_row_num = self.sh.max_row # 获取最大行数
max_col_num = self.sh.max_column # 获取最大列数
# min_row_num=sh.min_row # 获取最小行数
# min_col_num = sh.min_column # 获取最小列数
return max_row_num,max_col_num
# 获取合并的单元格的坐标信息及合并的单元格行、列数
def get_merge_data(self):
"""
通过获取的合并单元格的转换成特定的格式
:return: 合并的单元格的索引信息
"""
# 查询该sheet表单所有合并单元格
merge_lists = self.sh.merged_cells
# print('merge_lists',merge_lists)
merge_all_list = [] # 接收最终内容并返回
# 遍历合并单元格
for merge_list in merge_lists:
# 获取单个合并单元格的起始行(row_min)终止行(row_max)和起始列(col_min)终止列(col_max)
row_min, row_max, col_min, col_max = merge_list.min_row, merge_list.max_row, merge_list.min_col, merge_list.max_col
# 这里判断如果合并单元格起始、终止的行和列都不相等,说明合并单元格既合并了行又合并了列,两个for循环依次取出行列位置分别存在x,y中
if row_min != row_max and col_min != col_max:
row_col = [(x, y) for x in range(row_min, row_max + 1) for y in range(col_min, col_max + 1)]
merge_all_list.append(row_col) # 取出的值存在列表中
# 这里判断如果合并单元格起始、终止行相等,起始、终止列不相等,说明合并单元格只合并了列,所以行不动,只循环取出列的值,存在y中,行可以随意取row_min/row_max
elif row_min == row_max and col_min != col_max:
row_col = [(row_min, y) for y in range(col_min, col_max + 1)]
merge_all_list.append(row_col) # 取出的值存在列表中
# 这里判断如果合并单元格起始、终止行不相等,起始、终止列相等,说明合并单元格只合并了行,所以列不动,只循环取出行的值,存在x中,列可以随意取col_min/col_max
elif row_min != row_max and col_min == col_max:
row_col = [(x, col_min) for x in range(row_min, row_max + 1)]
merge_all_list.append(row_col) # 取出的值存在列表中
return merge_all_list # 最终返回列表
# 得到的是个这样的列表值:[[(2, 1), (3, 1)], [(10, 1), (10, 2), (10, 3), (11, 1), (11, 2), (11, 3)]]
def merge_values(self,merge_cell): # 传入一个元组入参
"""
处理合并单元格,返回合并的单元格数值
:param merge_cell: 合并的单元格信息,以内嵌二元组的列表形式
:return: 返回单元格数值
"""
# 循环取出合并单元格方法得到的值(这个值还是列表),检查传入的参数是不是在这些值里面
for i in range(0, len(merge_cell)):
# 获取合并单元格的值:合并单元格左上角的第一个行列坐标的值
cell_value = self.sh.cell(row=merge_cell[i][0][0], column=merge_cell[i][0][1]).value
return cell_value
def list_excel_data(self):
"""
按列表格式获取表中所有行数据
:return: 按行以列表嵌套的格式
"""
merge_list = self.get_merge_data() # 获取表格合并的单元格的信息
merge_list_all = sum(merge_list,[]) # 将合并的单元格转换成一个大列表
table_value = []
for row in range(1,self.sh.max_row + 1):
row_value = [] # 定义一个空列表存放有数据的行数据
for col in range(1,self.sh.max_column + 1):
cell_data = (row, col)
if cell_data in merge_list_all:
row_value.append(self.merge_values(merge_list)) # 是合并单元格,则调用合并单元格数值获取函数
else: # 不在,说明不是合并单元格,使用普通单元格方法获取即可
row_value.append(self.sh.cell(*cell_data).value)
table_value.append(row_value)
return table_value
def dict_excel_data(self):
"""
按字典格式显示表中数据
:return: 按行以字典嵌套列表的格式
"""
merge_list = self.get_merge_data() # 获取表格合并的单元格的信息
merge_list_all = sum(merge_list, []) # 将合并的单元格转换成一个大列表
list_val = []
for row in range(1, self.sh.max_row + 1):
if row > 1: # 第二行开始
dict_val = {} # 定义一个空字典存放数据
for col in range(1, self.sh.max_column + 1):
title_row = (1, col) # 表格的第一行:标题栏
cell_data = (row, col)
if cell_data in merge_list_all:
# 是合并单元格,则调用合并单元格数值获取函数
dict_val[self.merge_values(merge_list)] = self.merge_values(merge_list)
else: # 不在,说明不是合并单元格,使用普通单元格方法获取即可
dict_val[self.sh.cell(*title_row).value] = self.sh.cell(*cell_data).value
list_val.append(dict_val)
return list_val
# 读取excel表
wb = load_workbook('shebei.xlsx')
# 获取指定的sheet
sheet_sb = wb['sheet']
c = Get_table_data(sheet_sb) # 创建获取表格数据对象
print(c.dict_excel_data()) # 字典格式
# print(c.list_excel_data()) # 列表格式