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行代码 ,希望本篇文章对你有用哟!!!

扫描二维码关注公众号,回复: 11398448 查看本文章

猜你喜欢

转载自blog.csdn.net/yuhang01/article/details/107087786