Python 實現excel 分類彙總、批量數據替換

最近在公司又收到了一個操作excel的項目(我們稱爲改善項目)特此記錄下來,希望對你也有用

需求分析

1.將之前的部分產品型號名稱替換爲新的指定產品型號名稱,並將替換過後的文字標紅,背景色改爲青色
2.將替換後的所有產品的數據按照產品型號進行分類,並將發貨數量進行彙總
3.類似第二步驟,將替換後的產品數據按照編碼進行分類,發貨數量彙總

批量數據替換

這裏是部分要替換的數據,其中E列是老的產品型號數據,C列是要替換成的型號數據(這個爲一個參照)
在這裏插入圖片描述
然後將所有準備好的數據添加到xlsx表中,這裏放入到sheet1中,將參照表當到sheet2中,替換的代碼如下:

import openpyxl
from openpyxl.styles import Font, Border, Side, PatternFill, colors, Alignment

font_false = Font(size=9, bold=True, color="FF0000")
red_fill = PatternFill("solid", fgColor="C1CDCD")

# read shipp.xlsx file
wb = openpyxl.load_workbook("wolaia.xlsx")
# get workbook every son
sheet_names = wb.sheetnames

sheet1 = wb[sheet_names[0]]
sheet2 = wb[sheet_names[1]]
# 1.先將存貨名稱進行替換
for i in range(2, sheet2.max_row-1):
    guige = sheet2['E' + str(i)].value
    for j in range(2, sheet1.max_row-1):
        if guige == sheet1['D' + str(j)].value:
            sheet1['D' + str(j)].value = sheet2['C' + str(i)].value
            sheet1['D' + str(j)].fill = red_fill
            sheet1['D' + str(j)].font = font_false
else:
    print("加載完成")
wb.save('wodiudiu.xlsx')

思路:
先通過openpyxl 讀取我們要進行操作的xlsx表格,然後讀取表格中所有的子表單sheet 拿到前兩個sheet表格,裏面就有我們所有的數據表和參照表,然後通過for循環先拿到所有數據表中的數據,獲取到我們所有列表中指定列的所有值,然後在循環遍歷參照表中的所有數據,然後進行條件判斷,如果所有數據表中的指定列的數據和我們參照表中的老產品型號數據相同,說明當前單元格我們需要進行產品型號提替換,這時我們將要替換的新的產品型號的值設置爲當前所有數據表中的當前單元格,就可以進行數據替換

根據產品型號進行分類彙總

思路:根據我們要操作的所有數據(sheet1)然後生成一個新的表單,並將sheet1中的所有數據賦值一份到新生成的表單中,在新生成的表單中進行分類彙總,這裏剛開始的時候我也想的挺簡單的,不就是類似excel的分類功能麼,但是當我實際去進行編碼時,卻出現了很多我意想不到的Bug,(這裏我的方法不一定是最好的),這裏也是本篇文章的重點
錯誤的思路:
運用雙重for循環去循環一個數據源,然後進行數據是否相等判斷,如果相等,將發貨數據列的數據進行彙總,並刪除當前相等的這一行,想象很豐滿,現實很骨感,當我信心滿滿的以爲這就可以完美收官的時候,當我查看分類過後的數據時,卻發現最後的發貨數據類的數據總和比之前的數據的要多,這不是逗我呢麼,有問題
然後一點點排查發現有兩處Bug,當我在進行第二重for循環時,我的數據起始值也是從第一條開始的,就導致當我開始第一次執行數據時就出現了問題,以及當我進行刪除指定行的操作時,當前所有數據的條數是在一個一個的減少的,就導致我會跳過很多未執行過的數據,導致數據的準確性是錯誤的
正確的思路:
同樣運用雙重for循環一個數據源,在第二重for循環時,起始值爲一重for循環的索引值+1,這樣會使我們跳過重複判斷第一條數據,然後當我找到相同的產品型號時,我將相等的產品型號名稱更改成了一個唯一值,並將當前相同產品型號的這一列的發貨數據數進行彙總(相加),將當前相同的列數添加到一個數組中,這樣在for循環中,所有數據的最大個數就時確定的,不會因爲刪除當前行而減少導致數據不正確,當我們循環完所有數據時,讀取我們有相同行的數組,然後拿到數組中的每一個數據然後在進行刪除操作,這裏還是有問題,因爲我們刪除當前行時,總數會隨之減少,導致後面數組中的數據的行數就不正確了,因爲是一條一條數據進行刪除的,所以我們可以根據這個特性對下一個行數進行減一操作,這樣就可以保證數據的準確性,看了這麼多,是不是有點迷,可能是我語言表達能力有點不精確
這裏我們來看最後的代碼:

# 2.將規格型號進行分類合併
sheet3 = wb.copy_worksheet(sheet1)
max = sheet3.max_row
util = []
for x in range(2, max):
    num = sheet3['F'+str(x)].value
    product = sheet3['D'+str(x)].value
    for z in range(x+1, max):
        if product == sheet3['D'+str(z)].value:

            if sheet3['F'+str(z)].value is not None:
                num += sheet3['F'+str(z)].value

            sheet3['F' + str(x)].value = num
            sheet3['D' + str(z)].value = "我是第"+str(z)
            util.append(z)
vount = 0
for i in sorted(util):
    sheet3.delete_rows(i-vount)
    vount += 1

到這裏,當我們運行代碼時,去看所有發貨數據之和時會發現是對應的,perfect!
在這裏插入圖片描述

根據編碼進行分類彙總

上面做好,這裏的編碼分類就簡單了很多,思路同上,這裏來看代碼:

cdutil = []
# 3.根據分類編碼進行分類
sheet4 = wb.copy_worksheet(sheet1)
for i in range(2, sheet4.max_row):
    code = sheet4['B'+str(i)].value
    num = sheet4['F'+str(i)].value
    for j in range(i+1, sheet4.max_row):
        if code == sheet4['B'+str(j)].value:
            if sheet4['F' + str(j)].value is not None:
                num += sheet4['F' + str(j)].value
            sheet4['F' + str(i)].value = num
            sheet4['B' + str(j)].value = "我是第" + str(j)
            cdutil.append(j)
count = 0
for i in sorted(cdutil):
    sheet4.delete_rows(i-count)
    count += 1

完整的代碼如下:

import openpyxl
from openpyxl.styles import Font, Border, Side, PatternFill, colors, Alignment

font_false = Font(size=9, bold=True, color="FF0000")
red_fill = PatternFill("solid", fgColor="C1CDCD")

# read shipp.xlsx file
wb = openpyxl.load_workbook("wolaia.xlsx")
# get workbook every son
sheet_names = wb.sheetnames

sheet1 = wb[sheet_names[0]]
sheet2 = wb[sheet_names[1]]
# 1.先將存貨名稱進行替換
for i in range(2, sheet2.max_row-1):
    guige = sheet2['E' + str(i)].value
    for j in range(2, sheet1.max_row-1):
        if guige == sheet1['D' + str(j)].value:
            sheet1['D' + str(j)].value = sheet2['C' + str(i)].value
            sheet1['D' + str(j)].fill = red_fill
            sheet1['D' + str(j)].font = font_false
else:
    print("加載完成")
# 2.將規格型號進行分類合併
sheet3 = wb.copy_worksheet(sheet1)
max = sheet3.max_row
util = []
for x in range(2, max):
    num = sheet3['F'+str(x)].value
    product = sheet3['D'+str(x)].value
    for z in range(x+1, max):
        if product == sheet3['D'+str(z)].value:

            if sheet3['F'+str(z)].value is not None:
                num += sheet3['F'+str(z)].value

            sheet3['F' + str(x)].value = num
            sheet3['D' + str(z)].value = "我是第"+str(z)
            util.append(z)
vount = 0
for i in sorted(util):
    sheet3.delete_rows(i-vount)
    vount += 1
cdutil = []
# 3.根據分類編碼進行分類
sheet4 = wb.copy_worksheet(sheet1)
for i in range(2, sheet4.max_row):
    code = sheet4['B'+str(i)].value
    num = sheet4['F'+str(i)].value
    for j in range(i+1, sheet4.max_row):
        if code == sheet4['B'+str(j)].value:
            if sheet4['F' + str(j)].value is not None:
                num += sheet4['F' + str(j)].value
            sheet4['F' + str(i)].value = num
            sheet4['B' + str(j)].value = "我是第" + str(j)
            cdutil.append(j)
count = 0
for i in sorted(cdutil):
    sheet4.delete_rows(i-count)
    count += 1

wb.save('wodiudiu.xlsx')

python確實很簡介,就62行代碼 ,希望本篇文章對你有用喲!!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章