1. 程式人生 > 其它 >openpyxl處理.xlsx合併單元格資料

openpyxl處理.xlsx合併單元格資料

技術標籤:處理excel資料python

openpyxl處理.xlsx合併單元格資料
一、之前學過xlrd處理.xls格式的excel資料,想著excel使用.xlsx格式比較多,所以用openpyxl做一個處理.xlsx格式的excel資料(僅供參考)
表單內容
二、思路:(我這裡只展示一個表單的情況)
1.讀取excel檔案
2.獲取表單裡面單元格資料(包含普通單元格、合併單元格)
3.將單元格資料用字典形式存在列表中

三、實踐
1.讀取excel檔案:
1.1、首先下載第三方庫openpyxl,進入doc使用命令pip install openpyxl
1.2、程式碼中引用openpyxl

import openpyxl

1.3、讀取excel檔案,定義檔案物件

data = openpyxl.load_workbook("壓測手機號.xlsx")

1.4、上面定義檔案物件後就相當於進入檔案了,進了檔案後我們要知道檔案裡的表單,所以定義檔案的表單物件

sheet = data['Sheet1']  # Sheet1為表單名

1.5、定義了表單物件後,就可以進行下一步獲取表單中單元格內容了

2.獲取表單裡面單元格資料
2.1、獲取指定單元格資料(row表示行,column表示列):

a = sheet.cell(row=3, column=1).value
print
(a)

2.2、單元格有合併單元格的情況,所以需要能夠獲取合併單元格的資料

# 獲取合併單元格需要用到下面幾個
print(sheet.max_row)  # TODO 獲取最大行數
print(sheet.min_row)  # TODO 獲取最小行數
print(sheet.max_column)  # TODO 獲取最大列數
print(sheet.min_column)  # TODO 獲取最小列數

openpyxl中使用merged_cells可以查詢出所有的合併單元格行和列,得到的是下面的A2:A3 A5:A6 B5:B6 C5:C6

merge_lists = sheet.
merged_cells
A2:A3 A5:A6 B5:B6 C5:C6

然後處理合並單元格,得到合併單元格的行列座標,我這裡做了個方法,整體程式碼如下

def merge():
    # TODO 查詢該sheet表單所有合併單元格
    merge_lists = sheet.merged_cells
    print(merge_lists)
    merge_all_list = []  # 接收最終內容並返回
    # TODO 遍歷合併單元格
    for merge_list in merge_lists:
        # TODO 獲取單個合併單元格的起始行(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  # 最終返回列表
    # TODO 得到的是個這樣的列表值:[[(2, 1), (3, 1)], [(5, 1), (6, 1)], [(5, 2), (6, 2)], [(5, 3), (6, 3)]],列表中每個列表表示合併單元格的跨度

使用上面方法得到合併單元格的行列後,就可以使用行列座標取出合併單元格資料了,這樣普通單元格、合併單元格資料都可以得到了,也做了個方法,程式碼如下

def merge_values(*rr):  # 這裡方法傳入一個元組入參,這個*叫啥入參來著,忘記了,可以去查查基礎知識
    mm_list = merge()  # 這裡呼叫上面的獲取合併單元格的方法
    # 迴圈取出合併單元格方法得到的值(這個值還是列表),檢查傳入的引數是不是在這些值裡面
    for ii in range(0, len(mm_list)):
        if rr in mm_list[ii]:  # 在,那就取值裡面的第一個值(即合併單元格左上角的第一個行列座標);
            value11 = sheet.cell(row=mm_list[ii][0][0], column=mm_list[ii][0][1]).value
            return value11
    else:  # 不在,說明不是合併單元格,使用普通單元格方法獲取即可
        value2 = sheet.cell(*rr).value
        #  這個判斷可要可不要,主要用來提示單元格為空,後期可以用log列印
        # if value2 is None:
        #     return "None:單元格無資料"
        # else:
        return value2

將取到的表單資料用列表包字典的形式展示,並且都用第一行的標題做為key,這樣後期可以方便取值

def list_excel_data():
    list_val = []
    for x in range(sheet.min_row, sheet.max_row+1):
        if x != 1:
            dict_val = {}
            for y in range(sheet.min_column, sheet.max_column+1):
                kk = (1, y)
                i = (x, y)
                dict_val[merge_values(*kk)] = merge_values(*i)
            list_val.append(dict_val)
    return list_val

最終展示效果:

[{'phone': '17601348350', 'name': '張三', 'sex': 22}, {'phone': '17601348350', 'name': '李四', 'sex': 33}, {'phone': '17601348352', 'name': '王五', 'sex': 40}, {'phone': '17601348358', 'name': '趙六', 'sex': '9'}, {'phone': '17601348358', 'name': '趙六', 'sex': '9'}, {'phone': '17601348360', 'name': '錢七', 'sex': 18}]

Process finished with exit code 0

全部程式碼如下:(沒有註釋了)

import openpyxl

data = openpyxl.load_workbook("壓測手機號.xlsx")
sheet = data['Sheet1']
# a = sheet.cell(row=3, column=1).value  # TODO 獲取指定行、列的值
# print(sheet.title)  # TODO 獲取sheet名稱
# print(sheet.max_row)  # TODO 獲取最大行數
# print(sheet.min_row)  # TODO 獲取最小行數
# print(sheet.max_column)  # TODO 獲取最大列數
# print(sheet.min_column)  # TODO 獲取最小列數


def merge():
    # TODO 查詢該sheet表單所有合併單元格
    merge_lists = sheet.merged_cells
    # print(merge_lists)
    merge_all_list = []
    # TODO 遍歷合併單元格
    for merge_list in merge_lists:
        # TODO 獲取單個合併單元格的起始行(row)和起始列(col)
        row_min, row_max, col_min, col_max = merge_list.min_row, merge_list.max_row, merge_list.min_col, merge_list.max_col
        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)
        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)
        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
    # TODO 得到的是個這樣的列表值:[[(2, 1), (3, 1)], [(10, 1), (10, 2), (10, 3), (11, 1), (11, 2), (11, 3)]]


def merge_values(*rr):
    mm_list = merge()
    for ii in range(0, len(mm_list)):
        if rr in mm_list[ii]:
            value11 = sheet.cell(row=mm_list[ii][0][0], column=mm_list[ii][0][1]).value
            return value11
    else:
        value2 = sheet.cell(*rr).value
        # if value2 is None:
        #     return "None:單元格無資料"
        # else:
        return value2


def list_excel_data():
    list_val = []
    for x in range(sheet.min_row, sheet.max_row+1):
        if x != 1:
            dict_val = {}
            for y in range(sheet.min_column, sheet.max_column+1):
                kk = (1, y)
                i = (x, y)
                dict_val[merge_values(*kk)] = merge_values(*i)
            list_val.append(dict_val)
    return list_val


bb = list_excel_data()
print(bb)
# print(bb[0].get('name'))
data.close()