找回密码
 立即注册
首页 业界区 安全 Python实现对比两个Excel表某个范围的内容并提取出差异 ...

Python实现对比两个Excel表某个范围的内容并提取出差异

郦惠 3 天前
  1. # pip install openpyxl
  2. from openpyxl import load_workbook, Workbook
  3. from openpyxl.utils.cell import coordinate_from_string, column_index_from_string, get_column_letter
  4. from openpyxl.styles import Font, PatternFill
  5. def _normalize_range(start_cell: str, end_cell: str) -> str:
  6.     """把两个单元格规范化成合法的范围字符串,例如 'A2', 'A10' -> 'A2:A10'"""
  7.     col1, row1 = coordinate_from_string(start_cell)
  8.     col2, row2 = coordinate_from_string(end_cell)
  9.     c1 = column_index_from_string(col1)
  10.     c2 = column_index_from_string(col2)
  11.     min_col = min(c1, c2)
  12.     max_col = max(c1, c2)
  13.     min_row = min(row1, row2)
  14.     max_row = max(row1, row2)
  15.     return f"{get_column_letter(min_col)}{min_row}:{get_column_letter(max_col)}{max_row}"
  16. def _read_range_values(ws, ranges):
  17.     """
  18.     从 worksheet 中的多个范围读取值。
  19.     返回 (原始值, 规范化值) 的列表。
  20.     - 规范化值:去掉前后空格,字符串转小写。
  21.     """
  22.     values = []
  23.     for start_cell, end_cell in ranges:
  24.         range_str = _normalize_range(start_cell, end_cell)
  25.         cells = ws[range_str]
  26.         for row in cells:
  27.             for cell in row:
  28.                 if cell.value is not None:
  29.                     raw = cell.value
  30.                     if isinstance(raw, str):
  31.                         norm = raw.strip().lower()  # 忽略大小写 + 去掉前后空格
  32.                     else:
  33.                         norm = raw
  34.                     values.append((raw, norm))
  35.     return values
  36. def _ordered_set_difference(list_a, list_b):
  37.     """
  38.     返回 list_a 独有的元素(基于规范化值比较)。
  39.     保持顺序 + 去重,输出原始值。
  40.     """
  41.     set_b_norm = {norm for _, norm in list_b}
  42.     seen_norm = set()
  43.     result = []
  44.     for raw, norm in list_a:
  45.         if norm in seen_norm:
  46.             continue
  47.         if norm not in set_b_norm:
  48.             result.append(raw)
  49.         seen_norm.add(norm)
  50.     return result
  51. def compare_excel_columns(
  52.     file1, ranges1, file2, ranges2,
  53.     output_file="result.xlsx",
  54.     sheet_name1=None, sheet_name2=None
  55. ):
  56.     """
  57.     比较两个 Excel 文件的指定范围,输出差异。
  58.     参数:
  59.       - file1, file2: 文件路径
  60.       - ranges1, ranges2: 列表,每个元素是 (start_cell, end_cell)
  61.       - sheet_name1, sheet_name2: 工作表名称(不传则用 active)
  62.       - output_file: 输出文件名
  63.     """
  64.     # 读取文件1
  65.     wb1 = load_workbook(file1, data_only=True)
  66.     ws1 = wb1[sheet_name1] if sheet_name1 else wb1.active
  67.     vals1 = _read_range_values(ws1, ranges1)
  68.     # 读取文件2
  69.     wb2 = load_workbook(file2, data_only=True)
  70.     ws2 = wb2[sheet_name2] if sheet_name2 else wb2.active
  71.     vals2 = _read_range_values(ws2, ranges2)
  72.     # 求差异
  73.     only_in_file1 = _ordered_set_difference(vals1, vals2)
  74.     only_in_file2 = _ordered_set_difference(vals2, vals1)
  75.     # 输出结果
  76.     wb_out = Workbook()
  77.     ws_out = wb_out.active
  78.     ws_out.title = "Comparison Result"
  79.     # 表头
  80.     ws_out["A1"] = "Only in file1"
  81.     ws_out["B1"] = "Only in file2"
  82.     ws_out["A1"].font = ws_out["B1"].font = Font(bold=True, color="FFFFFF")
  83.     ws_out["A1"].fill = ws_out["B1"].fill = PatternFill("solid", fgColor="4F81BD")
  84.     max_rows = max(len(only_in_file1), len(only_in_file2))
  85.     for i in range(max_rows):
  86.         if i < len(only_in_file1):
  87.             ws_out.cell(row=i+2, column=1, value=only_in_file1[i])
  88.         if i < len(only_in_file2):
  89.             ws_out.cell(row=i+2, column=2, value=only_in_file2[i])
  90.     # 在最后一行之后添加数量统计
  91.     stats_row = max_rows + 3
  92.     ws_out[f"A{stats_row}"] = f"Count: {len(only_in_file1)}"
  93.     ws_out[f"B{stats_row}"] = f"Count: {len(only_in_file2)}"
  94.     ws_out[f"A{stats_row}"].font = ws_out[f"B{stats_row}"].font = Font(bold=True, color="000000")
  95.     wb_out.save(output_file)
  96.     print(f"对比完成,结果已保存到: {output_file}")
  97.     return output_file
  98. # 示例调用
  99. if __name__ == "__main__":
  100.     compare_excel_columns(
  101.         "D:\code\python\pythonProject1\新建 XLSX 工作表.xlsx", [("A1", "A7")],   # 支持多个范围,比如 [("A1","A6"), ("B1","B3")]
  102.         "D:\code\python\pythonProject1\新建 XLSX 工作表 (2).xlsx", [("A1", "A4")],
  103.         output_file="result.xlsx",
  104.         sheet_name1="Sheet1",
  105.         sheet_name2="Sheet1"
  106.     )
复制代码
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册