python處理Excel單機小工具:匹數據,增強版VLookup
2025年9月22日
場景:
如果使用vlookup匹數據的話, 每次只能匹配一列, 并且關聯的列只能有一列, 比如有同名同姓的數據, 在匹配時就會出現錯誤
實現目標:
1. 可以同時使用多列數據進行關聯, 比如用 姓名和工號, 同時進行匹配
2. 可以同時匹配多列數據, 比如將匹配上的身份證號, 部門等多列數據一次性追加到前表后邊
數據截圖:
1. A表

2. B表

3. 追加信息后的表

交互截圖:
1. 打開文件

2. 選擇待追加信息的表(A表), 以及關聯用的字段, 多選

3. 選擇附加信息表(B表), 以及要追加的字段

工具下載
小工具只在本地運行, 不會上傳數據, 有需要可加QQ群: 748194967 群名稱: Excel便捷小工具. 也可以在評論區留言, 說出你想要的小工具需求.
源代碼
1 #給某個表格追加編號,身份證號等信息 2 import sys 3 import tkinter as tk 4 from tkinter import filedialog, messagebox, scrolledtext 5 6 import openpyxl 7 from openpyxl import load_workbook 8 9 from utils import select_file, read_excel, tool, log, alert, style 10 11 excel_a = False 12 excel_b = False 13 14 file_titles_a = {} 15 file_titles_b = {} 16 17 def read_file_a(): 18 global excel_a 19 file_path = select_file.excel_one('選擇A文件, 單選') 20 if file_path == False: 21 return 22 append_text(f"選擇文件:{file_path}") 23 24 excel_a = read_excel.ExcelTool(file_path).excel 25 excel_a.sheet_data() 26 titles = ','.join(excel_a.title) 27 append_text(f"A文件表頭:{titles}") 28 29 choice = tool.array_lpad_idx(excel_a.title) 30 selected = select_file.checkbox(choice, '選擇字段(可以選擇多個字段。B表也要存在同樣的字段。)') 31 if selected == False: 32 return False 33 else: 34 for v in selected: 35 idx,t = v.split('-') 36 file_titles_a[idx] = t 37 38 str = ','.join(list(file_titles_a.values())) 39 label11.config(text=str) 40 append_text(f"A表選擇了字段:{str}") 41 42 def read_file_b(): 43 global excel_b 44 file_path = select_file.excel_one('選擇B文件, 單選') 45 if file_path == False: 46 return 47 append_text(f"選擇文件:{file_path}") 48 49 excel_b = read_excel.ExcelTool(file_path).excel 50 excel_b.sheet_data() 51 titles = ','.join(excel_b.title) 52 append_text(f"B文件表頭:{titles}") 53 54 choice = tool.array_lpad_idx(excel_b.title) 55 selected = select_file.checkbox(choice, '選擇字段(這些數據將會補充到A表中)') 56 if selected == False: 57 return False 58 else: 59 for v in selected: 60 idx,t = v.split('-') 61 file_titles_b[idx] = t 62 63 str = ','.join(list(file_titles_b.values())) 64 label22.config(text=str) 65 append_text(f"B表, 選擇了字段:{str}") 66 67 def append_data(): 68 global excel_a 69 global excel_b 70 global file_titles_a 71 global file_titles_b 72 73 append_text(f"開始查找并追加數據") 74 75 #檢查依據字段是否存在 76 for k,v in file_titles_a.items(): 77 if v not in excel_b.title: 78 messagebox.showinfo("錯誤", f"此表中不存在字段: “{v}”, 請確認。") 79 return False 80 81 #新建標簽存儲數據 82 sheet_name = '補充數據' 83 new_sheet = read_excel.create_new_sheet(excel_a.wb, sheet_name, []) 84 85 need_append_match_titles = list(file_titles_a.values()) #參與匹配的字段 86 all_info_match_index = [] #完整數據表中對應字段的索引 87 for v in need_append_match_titles: #第一行是標題 88 i = excel_b.title_flip[v] 89 all_info_match_index.append(i) 90 91 all_info_map = {} 92 all_info_append_index = list(file_titles_b.keys()) #完整數據中補充字段的索引 93 for row in excel_b.file_data: 94 # 取出用來做鍵的字段 95 keys = tool.array_index_values(row, all_info_match_index) 96 str = ','.join(keys) 97 if str not in all_info_map: 98 all_info_map[str] = [] 99 100 # 取出用來做值的字段 101 values = tool.array_index_values(row, all_info_append_index) 102 103 all_info_map[str].append(values) 104 105 106 #開始映射 107 need_append_index = list(file_titles_a.keys()) 108 for row in excel_a.file_data: 109 keys = tool.array_index_values(row, need_append_index) 110 str = ','.join(keys) 111 112 if str in all_info_map: 113 for v in all_info_map[str]: 114 for vv in v: 115 keys.append(vv) 116 117 new_sheet.append(keys) 118 119 excel_a.save_file() 120 append_text(f"追加結束,寫入到表格:{excel_a.file_path} 標簽:{sheet_name}") 121 alert.success('結束') 122 tool.open_excel(excel_a.file_path) 123 #sys.exit() 124 125 126 def append_text(str): 127 str += "\n\n" 128 text_area.insert(tk.END, str) 129 130 def button_cancel(): 131 sys.exit() 132 133 #######################################主窗口 134 # 創建主窗口 135 root = tk.Tk() 136 root.title("Excel追加信息") 137 root.geometry("650x400") # 設置窗口大小 138 139 ########################################選擇被追加表 140 frame1 = tk.Frame(root) 141 frame1.pack(anchor=tk.W) 142 143 # 創建一個標簽 144 label1 = tk.Label(frame1, text="A表:") 145 label1.pack(side=tk.LEFT, pady=10, padx=5) 146 147 # 創建一個按鈕 148 button1 = tk.Button(frame1, text="選擇文件", command=read_file_a) 149 button1.pack(side=tk.LEFT, pady=10) 150 151 label11 = tk.Label(frame1, text="注意:第一行應是表頭") 152 label11.pack(side=tk.LEFT, pady=10, padx=5) 153 154 ##########################################選擇考核人員名單 155 frame2 = tk.Frame(root) 156 frame2.pack(anchor=tk.W) 157 158 # 創建一個標簽 159 label2 = tk.Label(frame2, text="B表:") 160 label2.pack(side=tk.LEFT, pady=10, padx=5) 161 162 # 創建一個按鈕 163 button2 = tk.Button(frame2, text="選擇文件", command=read_file_b) 164 button2.pack(side=tk.LEFT, pady=10) 165 166 # 創建一個標簽 167 label22 = tk.Label(frame2, text="注意:第一行應是表頭") 168 label22.pack(side=tk.LEFT, pady=10, padx=5) 169 170 #########################################計算按鈕 171 172 frame4 = tk.Frame(root) 173 frame4.pack(expand=True, fill=tk.X) 174 175 button41 = tk.Button(frame4, text=" 追加信息 ", command=append_data) 176 button41.pack(side=tk.LEFT, expand=True) 177 178 button42 = tk.Button(frame4, text=" 退出 ", command=button_cancel) 179 button42.pack(side=tk.LEFT, expand=True) 180 181 ########################################檢查過程 182 # 創建一個可滾動的 Text 小部件 183 text_area = scrolledtext.ScrolledText(root, wrap=tk.WORD, width=40, height=60) 184 text_area.pack(padx=10, pady=10, fill=tk.BOTH, expand=True) 185 readme = '''使用說明: 186 187 1. 本程序會將B表的信息追加到A表對應行的后邊. 188 比如兩個表中都有"姓名", 把B表中有相同姓名的"部門", "身份證號" 等信息追加到A表中 189 190 2. 第一步: 選擇A表中用于和B表關聯用的列, 比如"姓名", 這一步要求兩個表里都有"姓名"這一列 191 192 3. 第二步: 選擇B表中需要追加到A表的列, 比如"部門", "身份證號"等 193 194 4. 如果B表中有多個"姓名"相同的數據, 追加時會同時顯示在同一行 195 ''' 196 text_area.insert(tk.END, readme) 197 198 # 運行應用程序 199 root.mainloop()

浙公網安備 33010602011771號