脚本专家 发表于 2026-7-1 10:00:02

Python xlwings批量提取Excel工作簿所有工作表唯一值:set去重与纵向写入

在日常办公中,经常需要从多个Excel工作表中整理出一份去重后的清单。例如一个工作簿包含1月到12月的销售表,每张表都有“产品名称”列,我们希望得到所有出现过的产品名称,而不关心具体销量。手动操作需要逐个复制、粘贴、删除重复项,效率低且容易出错。本文介绍用Python和xlwings库批量提取一个工作簿中所有工作表的唯一值,并输出为纵向排列的新工作簿。

适用场景:多个工作表结构类似且包含同一目标列,比如产品名称、员工姓名、客户名称、设备型号等。如果表头名称不统一,需要预先做字段映射或修改代码处理。

核心原理是遍历所有工作表,将目标列的每个值收集到一个列表中,然后用set()去重,最后将结果纵向写入Excel。set天然不含重复元素,但会打乱原始顺序;如果需要保留首次出现顺序,可以用dict.fromkeys()替代。去重后可以借助sorted()排序。

下面给出完整的批量提取唯一值代码。先修改file_path、target_col和out_file三个参数,分别指定源文件路径、目标列名和输出文件路径。


import xlwings as xw

file_path = r"e:\file\销售数据.xlsx"
target_col = "产品名称"
out_file = r"e:\file\产品名称清单.xlsx"

app = xw.App(visible=False, add_book=False)
try:
    wb = app.books.open(file_path)
    all_values = []
    for sht in wb.sheets:
      table = sht.range("A1").current_region.value
      if not table or len(table) < 2:
            print(f"跳过:{sht.name},没有可处理的数据")
            continue
      header = table
      rows = table
      if target_col not in header:
            print(f"跳过:{sht.name},未找到列:{target_col}")
            continue
      col_idx = header.index(target_col)
      count = 0
      for row in rows:
            if col_idx >= len(row):
                continue
            value = row
            if value is None or str(value).strip() == "":
                continue
            all_values.append(str(value).strip())
            count += 1
      print(f"已读取:{sht.name},提取 {count} 个值")
    wb.close()

    unique_values = sorted(list(set(all_values)))
    unique_values.insert(0, target_col)

    out_wb = app.books.add()
    out_sht = out_wb.sheets
    out_sht.name = "唯一值清单"
    out_sht.range("A1").options(transpose=True).value = unique_values
    out_sht.autofit()
    out_wb.save(out_file)
    out_wb.close()
    print(f"清单生成完成:{out_file}")
    print(f"唯一值数量:{len(unique_values) - 1}")
finally:
    app.quit()


代码中关键处理:将每个值转为字符串并strip()去除前后空格,避免“背包”和“背包 ”被视为不同值。如果目标列包含数字编号(如001和1),直接转字符串可能产生歧义,需根据实际数据格式调整。out_sht.range("A1").options(transpose=True).value = unique_values实现纵向写入,符合清单阅读习惯。

运行后不要只看成功提示,建议从三个方面验证:检查控制台输出是否每张表都被读取;对比唯一值数量是否合理;打开输出文件确认第一行有表头且数据纵向排列。

举一反三:如果需要统计每个产品累计销量,可将set升级为dict。下面是按“产品名称”累计“销量”的示例:


import xlwings as xw

file_path = r"e:\file\销售数据.xlsx"
col_product = "产品名称"
col_qty = "销量"
out_file = r"e:\file\产品销量汇总.xlsx"

app = xw.App(visible=False, add_book=False)
try:
    wb = app.books.open(file_path)
    stat = {}
    for sht in wb.sheets:
      table = sht.range("A1").current_region.value
      if not table or len(table) < 2:
            continue
      header = table
      rows = table
      if col_product not in header or col_qty not in header:
            continue
      idx_p = header.index(col_product)
      idx_q = header.index(col_qty)
      for row in rows:
            if idx_p >= len(row) or idx_q >= len(row):
                continue
            product = row
            qty = row
            if product is None or str(product).strip() == "":
                continue
            product = str(product).strip()
            if qty is None or qty == "":
                qty = 0
            qty = float(qty)
            stat = stat.get(product, 0) + qty
    wb.close()

    out_wb = app.books.add()
    out_sht = out_wb.sheets
    out_sht.name = "产品销量汇总"
    out_sht.range("A1").value = [["产品名称", "累计销量"]]
    result = sorted(stat.items(), key=lambda x: x)
    out_sht.range("A2").value = result
    out_sht.autofit()
    out_wb.save(out_file)
    out_wb.close()
    print(f"统计完成:{out_file}")
    print(f"产品数量:{len(stat)}")
finally:
    app.quit()


stat.get(product,0)+qty是字典累加常用写法。注意销量字段必须能转成数字,否则float()会报错,可提前清洗或异常处理。

常见问题:表头不一致导致部分sheet被跳过;空格导致去重失败;set去重后顺序变化;隐藏工作表会被遍历。正式运行前建议备份文件,先打印工作表名称确认范围。

总结:唯一值提取的本质是“遍历收集→去重→输出”,可以沉淀为通用工具。将源路径、目标列、输出路径参数化后,即可复用于产品、客户、部门、城市等多种清单生成。记住三个要点:先明确目标列、先清洗再去重、输出后必须验证。自动化不是跑完就结束,而是交付可复查的结果。

热心网友1 发表于 2026-7-1 10:10:00

Re: Python xlwings批量提取Excel工作簿所有工作表唯一值:set去重与纵向写入

感谢分享,写得非常详细!特别是用 `set` 去重后加表头纵向写入,逻辑很清晰。有个小问题想请教:如果工作表中数据量很大(比如几十万行),用 `current_region` 一次性读取整个区域会不会撑爆内存?有没有分块读取的替代方案?另外,用 `dict.fromkeys()` 保留首次出现顺序时,是否还能保持原来每个表的内部顺序?希望能进一步指点,谢谢!

热心网友1 发表于 2026-7-1 10:10:00

Re: Python xlwings批量提取Excel工作簿所有工作表唯一值:set去重与纵向写入

楼主的分享非常实用!用 `set()` 去重加 `sorted()` 排序的思路简洁高效,而且特意处理了空值和前后空格细节,考虑得很周到。特别是那个 `dict.fromkeys()` 保留顺序的小贴士,对于需要保持原始出现顺序的场景很有帮助。我已经把代码存下来准备用在日常的报表整理上了。 想请教一下:如果工作表中目标列包含合并单元格,或者某个单元格内有多行文本(比如用换行符分隔的多个产品名称),当前的逻辑是直接取单元格整体值,有没有好的办法拆分成多个条目后再去重呢?期待楼主的进一步指点。

热心网友1 发表于 2026-7-1 10:10:00

Re: Python xlwings批量提取Excel工作簿所有工作表唯一值:set去重与纵向写入

亲测有效,代码逻辑清晰,特别是 set 去重和纵向写入的写法很实用。之前手动搞月度汇总表时总是漏掉某个产品,这下可以一键统一整理了。有个小建议:如果目标列数据量特别大,可以考虑用 pandas 的 unique 替代 set,处理速度会更快一些。另外对数字编号那部分的提醒也很到位,确实字符串转换要注意格式一致性。感谢分享!
页: [1]
查看完整版本: Python xlwings批量提取Excel工作簿所有工作表唯一值:set去重与纵向写入