2025-09-22
场景: 一个表格, 比如有 序号, 姓名, 班级, 考分 几列, 要求:
1. 要按照班级合并, 相同的班级的行合并在一起
2. 序号这一列也同时合并
3. 合并后, 计算每个班级的总考分
原始表:
处理后的表:
软件交互:
1: 选择原始文件, sheet, 以及需要合并的列名
2. 选择其他要一起合并的列名, (可选项, 可以多选)
3. 选择需要求和的列名 (可选项, 可多选)
4. 小工具只在本地运行, 不会上传数据, 有需要可加QQ群: 748194967 群名称: Excel便捷小工具. 也可以在评论区留言, 说出你想要的小工具需求.
5. 源代码

1 # 合并某一列的某几行 2 # 支持同时合并其他列的对应行 3 import os 4 import sys 5 import shutil 6 import tkinter as tk 7 from tkinter import filedialog, messagebox, scrolledtext 8 9 import openpyxl 10 from openpyxl import load_workbook 11 12 from utils import select_file, read_excel, tool, log, alert,style,org,ward_map 13 14 excel = False 15 selected = False 16 merge_index = False 17 18 #选择文件路径的公共方法 19 def open_file_dialog(): 20 # 打开文件选择对话框 21 file_path = select_file.excel_one("选择系数分报表文件", False) 22 if file_path: 23 append_text(f"选择文件:{file_path}") 24 merge_file_path = file_path + '-合并结果.xlsx' 25 if os.path.exists(merge_file_path): 26 os.remove(merge_file_path) 27 shutil.copy(file_path, merge_file_path) # 复制一份 28 read_file_data(merge_file_path) 29 else: 30 return 31 32 def read_file_data(file_path): 33 append_text(f"读取数据") 34 global excel 35 global selected 36 global merge_index 37 38 excel = read_excel.ExcelTool(file_path).excel 39 excel.all_data() 40 append_text(f"选择sheet: {excel.sheet_name}") 41 42 selected = select_file.radio(excel.title, "1.选择要合并的列, 单选") 43 label11.config(text=selected) 44 idx = excel.title_flip[selected] 45 col = tool.num_to_excel_col(idx+1) 46 merge_index = tool.same_content_index(excel.file_data, idx) 47 append_text(f"合并的行: {str(merge_index)}") 48 for v in merge_index: 49 start = v[0] 50 end = v[1] 51 if start < end: 52 excel.sheet.merge_cells(f"{col}{start}:{col}{end}") 53 54 def select_merge_cols(): 55 global excel 56 global selected 57 global merge_index 58 59 other_cols = select_file.checkbox(excel.title, "2.请选择其他需要一起合并的列, 多选") 60 if other_cols and len(other_cols) > 0: 61 str_cols = ', '.join(other_cols) 62 label32.config(text=str_cols) 63 64 for col in other_cols: 65 if col == selected: 66 continue 67 idx = excel.title_flip[col] + 1 68 col_num = tool.num_to_excel_col(idx) 69 #print([col, idx, col_num]) 70 for v in merge_index: 71 start = v[0] 72 end = v[1] 73 if start < end: 74 excel.sheet.merge_cells(f"{col_num}{start}:{col_num}{end}") 75 76 77 def select_sum_cols(): 78 global excel 79 global merge_index 80 global selected 81 82 sum_cols = select_file.checkbox(excel.title, "3.请选择需要求和的列, 多选") 83 if sum_cols and len(sum_cols) > 0: 84 str_sum_cols = ', '.join(sum_cols) 85 label42.config(text=str_sum_cols) 86 87 max_col = excel.sheet.max_column 88 for col in sum_cols: 89 if col == selected: 90 continue 91 #新加一列用于存放加和后的值 92 max_col += 1 93 max_col_num = tool.num_to_excel_col(max_col) 94 excel.sheet.insert_cols(idx=max_col) 95 #sheet.cell(row=1, column=max_col, value=f"{col}(合计)") 96 97 #读取待加和的列值 98 idx = excel.title_flip[col] + 1 99 col_num = tool.num_to_excel_col(idx) 100 col_data = excel.sheet[col_num] 101 for v in merge_index: 102 start = v[0] 103 end = v[1] 104 if start == end: #单行,不需要合并,直接讲数值写到新列 105 excel.sheet.cell(row=start,column=max_col, value=col_data[start-1].value) 106 else: 107 sum_value = 0 108 for i in range(start, end+1): 109 sum_value += col_data[i-1].value 110 excel.sheet.cell(row=start,column=max_col, value=sum_value) 111 excel.sheet.merge_cells(f"{max_col_num}{start}:{max_col_num}{end}") 112 113 114 def button_ok(): 115 global excel 116 excel.wb.save(excel.file_path) 117 tool.open_excel(excel.file_path) 118 119 def button_cancel(): 120 sys.exit() 121 122 def append_text(str): 123 str += "\n\n" 124 text_area.insert(tk.END, str) 125 126 #######################################主窗口 127 # 创建主窗口 128 root = tk.Tk() 129 root.title("合并行") 130 root.geometry("650x400") # 设置窗口大小 131 132 ########################################选择文件 133 frame1 = tk.Frame(root) 134 frame1.pack(anchor=tk.W) 135 136 # 创建一个标签 137 label1 = tk.Label(frame1, text="基础信息表:") 138 label1.pack(side=tk.LEFT, padx=10, pady=10) 139 140 # 创建一个按钮 141 button1 = tk.Button(frame1, text="选择文件", command=open_file_dialog) 142 button1.pack(side=tk.LEFT, pady=10) 143 144 label11 = tk.Label(frame1, text="单选") 145 label11.pack(side=tk.LEFT, pady=10) 146 147 ########################################选择按钮 148 frame3 = tk.Frame(root) 149 frame3.pack(anchor=tk.W) 150 151 # 创建一个按钮 152 button31 = tk.Button(frame3, text="选择要同时合并的列", command=select_merge_cols) 153 button31.pack(side=tk.LEFT, padx=10, pady=10) 154 155 label32 = tk.Label(frame3, text="非必须, 多选") 156 label32.pack(side=tk.LEFT, pady=10) 157 158 ########################################选择按钮 159 frame4 = tk.Frame(root) 160 frame4.pack(anchor=tk.W) 161 162 163 # 创建一个按钮 164 button41 = tk.Button(frame4, text="选择要同时合并求和的列", command=select_sum_cols) 165 button41.pack(side=tk.LEFT, padx=10, pady=10) 166 167 label42 = tk.Label(frame4, text="非必须, 多选") 168 label42.pack(side=tk.LEFT, pady=10) 169 170 171 ########################################选择文件 172 frame2 = tk.Frame(root) 173 frame2.pack(expand=True, fill=tk.X) 174 175 # 创建一个按钮 176 button21 = tk.Button(frame2, text="确认", command=lambda:button_ok()) 177 button21.pack(side=tk.LEFT, expand=True) 178 179 # 创建一个按钮 180 button22 = tk.Button(frame2, text="退出", command=lambda:button_cancel()) 181 button22.pack(side=tk.LEFT, expand=True) 182 183 184 ########################################检查过程 185 # 创建一个可滚动的 Text 小部件 186 text_area = scrolledtext.ScrolledText(root, wrap=tk.WORD, width=40, height=60) 187 text_area.pack(padx=10, pady=10, fill=tk.BOTH, expand=True) 188 text_area.insert(tk.END, "提醒: \n\n") 189 190 # 运行应用程序 191 root.mainloop()