You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python与OpenPyXL处理Excel重复行的数值合并及去重需求

后续开发指导与代码优化建议

一、后续代码编写方向

当前代码完成了数据分类和重复行标记,但核心的重复行数据合并+重复行删除逻辑还未实现,可按以下步骤推进:

1. 重构数据存储逻辑,关联姓名与对应行数据

放弃当前单纯用数组分类的方式,改用字典存储每个姓名对应的所有行信息:

  • 定义字典(如name_rows_map),key为姓名,value为该姓名的所有行对象列表(包含首次行和所有重复行)
  • 遍历工作表时,直接将每行数据按姓名分组存入字典,同时记录首次出现的行作为主行

2. 实现手机号与邮箱的合并规则

遍历name_rows_map中的每个姓名组:

  • 取出该组的首行作为主行,其余为重复行
  • 处理手机号:
    • 先判断主行手机号是否为空,或主行手机号属于免费号码(用你已有的区号判断逻辑)
    • 若满足条件,遍历重复行,找到第一个非免费的手机号,替换主行的手机号单元格
  • 处理邮箱:
    • 判断主行邮箱是否为空,或主行邮箱属于非个人邮箱(不在你的emailDomains列表中)
    • 若满足条件,遍历重复行,找到第一个个人邮箱,替换主行的邮箱单元格
  • 注:如果有多个重复行符合条件,可选择保留最优的那个(比如第一个符合的,或所有符合的用逗号拼接,根据需求调整)

3. 统一删除重复行

收集所有重复行的行号,从大到小排序后逐个删除(因为openpyxl删除行后,后续行的行号会前移,从下往上删可避免行号混乱)

  • 示例:unwanted_rows.sort(reverse=True),然后遍历行号执行worksheet.delete_rows(row_num)

4. 保存处理后的工作簿

最后调用workBook.save("处理后的文件名.xlsx"),建议保存为新文件,避免覆盖原数据。

二、代码优化建议

针对你已完成的代码,可从以下方面优化:

1. 变量与命名规范

  • 常量用大写命名:比如FREE_AREA_CODES = [888, 877, 866, 855, 844, 833, 800],PERSONAL_EMAIL_DOMAINS = ["@gmail", "@yahoo", "@ymail", "@outlook", "@hotmail", "@aol", "@msn", "@me."]
  • 变量名用小驼峰或下划线:比如work_sheet替代workSheet,file_name替代filename,提升可读性
  • 避免错误的空列表初始化:unwantedRows, rows, nonPrefNum, prefNum, nonPrefEmail, prefEmail = []会报错,应逐个初始化:unwanted_rows = []、seen_names = set()等

2. 函数单一职责优化

把当前的批量分类函数改成单个数据的判断函数,复用性更强:

import re

def is_free_phone_number(phone_str):
    if not phone_str:
        return False
    # 去除所有非数字字符
    clean_num = re.sub(r'\D', '', str(phone_str))
    # 判断区号是否在免费列表中
    if len(clean_num) >= 3:
        area_code = clean_num[:3]
        return area_code in [str(code) for code in FREE_AREA_CODES]
    return False

def is_personal_email(email_str):
    if not email_str:
        return False
    email_lower = str(email_str).lower()
    return any(domain in email_lower for domain in PERSONAL_EMAIL_DOMAINS)

3. 提升遍历效率

  • 当前三个函数分别遍历工作表,数千行数据会重复遍历3次,改成一次遍历完成所有数据收集与标记,减少IO开销
  • indexDuplicates中用列表判断subList not in rows的时间复杂度是O(n),改用集合seen_names = set(),判断姓名是否已存在的时间复杂度为O(1)

4. 空值与异常处理

  • 处理单元格空值:比如row[10].value可能为None,直接转字符串会得到"None",需先判断:phone = row[10].value if row[10].value else ""
  • 增加文件加载异常捕获:比如工作表名称错误、文件不存在的情况:
try:
    work_book = load_workbook(filename=file_name)
    work_sheet = work_book["Worksheet Name"]
except FileNotFoundError:
    print(f"[-] 文件 {file_name} 不存在")
    sys.exit(1)
except KeyError:
    print("[-] 工作表 'Worksheet Name' 不存在")
    sys.exit(1)

5. 手机号处理简化

用正则表达式替换所有非数字字符,替代逐个字符替换:

clean_num = re.sub(r'\D', '', str(phone_str))  # 去除所有非数字字符

调整后的核心代码示例(部分)

def process_duplicates():
    name_rows_map = {}
    # 一次遍历完成行分组
    for row in work_sheet.iter_rows(min_row=2):  # 假设第一行是表头
        name = row[0].value
        if not name:
            continue
        if name not in name_rows_map:
            name_rows_map[name] = []
        name_rows_map[name].append(row)
    
    unwanted_rows = []
    # 处理每个姓名的行组
    for name, rows in name_rows_map.items():
        if len(rows) <= 1:
            continue
        main_row = rows[0]
        # 处理手机号
        main_phone = main_row[10].value
        if not main_phone or is_free_phone_number(main_phone):
            for duplicate_row in rows[1:]:
                dup_phone = duplicate_row[10].value
                if dup_phone and not is_free_phone_number(dup_phone):
                    main_row[10].value = dup_phone
                    break  # 找到第一个符合的就停止,可根据需求调整
        # 处理邮箱
        main_email = main_row[9].value
        if not main_email or not is_personal_email(main_email):
            for duplicate_row in rows[1:]:
                dup_email = duplicate_row[9].value
                if dup_email and is_personal_email(dup_email):
                    main_row[9].value = dup_email
                    break
        # 收集重复行的行号(注意行号是row[0].row)
        unwanted_rows.extend([row[0].row for row in rows[1:]])
    
    # 从下往上删除重复行
    unwanted_rows = sorted(list(set(unwanted_rows)), reverse=True)
    for row_num in unwanted_rows:
        work_sheet.delete_rows(row_num)
    
    # 保存文件
    work_book.save(f"processed_{file_name}")

内容的提问来源于stack exchange,提问作者Throwaway account

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 17:14:53