摘要
本文分享兩個基于Python的Excel數據凈化腳本,通過多進程并行技術清除工作表內不可見字符、批注、單元格樣式等冗余內容,利用OpenPyXL實現底層操作,結合tqdm進度條和進程級任務分配,可快速處理百萬級單元格數據。適用于數據分析預處理、跨系統數據遷移等場景。
腳本一:并行處理統一(單)進度條版本
架構設計:
源碼:
import openpyxl
from openpyxl.styles import NamedStyle, Font, Border, PatternFill
from openpyxl.formatting import Rule
import re
from tqdm import tqdm
import multiprocessing
from functools import partialdef clean_invisible_chars(text):"""清除字符串中的不可見字符"""if not isinstance(text, str):return textreturn re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]', '', text)def process_cell(cell, no_style, no_fill, cleared_list):"""處理單個單元格的并行化函數"""# 清除單元格所有樣式cell.fill = no_fillcell.font = Font(name='Calibri', size=11, bold=False, italic=False)cell.border = Border()cell.number_format = 'General'# 清除不可見字符if cell.value and isinstance(cell.value, str):cell.value = clean_invisible_chars(cell.value)cleared_list.append('不可見字符')# 清除批注if cell.comment:cell.comment = Nonecleared_list.append('批注')# 清除樣式cell.style = no_stylecleared_list.append('單元格樣式')def process_sheet(args):"""處理整個工作表的并行化函數"""input_file, output_file, sheet_name = argscleared_items = set()# 每個進程獨立處理一個完整的工作表wb = openpyxl.load_workbook(input_file)ws = wb[sheet_name]no_style = NamedStyle(name="Normal")no_fill = PatternFill(fill_type=None)# 清除所有條件格式ws.conditional_formatting = []cleared_items.add('條件格式填充色')total_rows = ws.max_rowtotal_cols = ws.max_column# 使用tqdm顯示進度for row in tqdm(ws.iter_rows(), total=total_rows, desc=f"處理 {sheet_name}"):for cell in row:# 清除單元格所有樣式cell.fill = no_fillcleared_items.add('背景填充色')cell.font = Font(name='Calibri', size=11, bold=False, italic=False)cell.border = Border()cell.number_format = 'General'cell.style = no_stylecleared_items.add('單元格樣式')# 清除不可見字符if cell.value and isinstance(cell.value, str):cell.value = clean_invisible_chars(cell.value)cleared_items.add('不可見字符')# 清除批注if cell.comment:cell.comment = Nonecleared_items.add('批注')# 保存臨時文件temp_file = f"temp_{sheet_name}.xlsx"wb.save(temp_file)return (temp_file, sheet_name, list(cleared_items))def clear_all_and_save(input_file, output_file, sheet_name, num_processes=None):"""多進程并行清除工作表中的:1. 不可見字符2. 批注3. 單元格樣式"""if num_processes is None:num_processes = multiprocessing.cpu_count()print(f"使用 {num_processes} 個進程并行處理...")# 準備參數 (這里可以擴展為處理多個sheet)args = [(input_file, output_file, sheet_name)]# 創建進程池with multiprocessing.Pool(processes=num_processes) as pool:results = list(tqdm(pool.imap(process_sheet, args), total=len(args), desc="總進度"))# 合并處理結果cleared_items = set()for temp_file, sheet_name, items in results:cleared_items.update(items)# 這里可以添加合并多個臨時文件的邏輯# 保存最終工作簿 (簡化處理,直接使用第一個結果)import shutilshutil.move(results[0][0], output_file)cleared_text = "\n".join(f" ? 清除-{item}" for item in cleared_items)print("已完成:\n"+cleared_text+f"\n并保存到 {output_file}")if __name__ == '__main__':input_excel_file = '測試文件.xlsx' # 原始文件output_excel_file = '清除樣式_測試文件_并行版.xlsx' # 生成文件sheet_to_clean = 'sheet1' # sheet nameprint(f"輸入文件: {input_excel_file}")print(f"輸出文件: {output_excel_file}")print(f"目標工作表: {sheet_to_clean}")try:clear_all_and_save(input_excel_file, output_excel_file, sheet_to_clean)except Exception as e:print(f"處理過程中發生錯誤: {str(e)}")
腳本二:多核獨立進度條版本
架構設計:
源碼:
import openpyxl
from openpyxl.styles import NamedStyle, Font, Border, PatternFill
from openpyxl.formatting import Rule
import re
from tqdm import tqdm
import multiprocessing
from functools import partialdef clean_invisible_chars(text):"""清除字符串中的不可見字符"""if not isinstance(text, str):return textreturn re.sub(r'[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]', '', text)def process_sheet(args):"""處理整個工作表的并行化函數"""input_file, output_file, sheet_name, process_idx = argscleared_items = set()# 每個進程獨立處理一個完整的工作表wb = openpyxl.load_workbook(input_file)ws = wb[sheet_name]no_style = NamedStyle(name="Normal")no_fill = PatternFill(fill_type=None)# 清除所有條件格式ws.conditional_formatting = []cleared_items.add('條件格式填充色')total_rows = ws.max_rowtotal_cols = ws.max_column# 使用多行進度條(position參數控制行位置)process_idx = args[3] # 獲取進程索引for row in tqdm(ws.iter_rows(), total=total_rows, desc=f"進程{process_idx}", position=process_idx+1):for cell in row:# 清除單元格所有樣式cell.fill = no_fillcell.font = Font(name='Calibri', size=11, bold=False, italic=False)cell.border = Border()cell.number_format = 'General'cell.style = no_stylecleared_items.update(['背景填充色', '單元格樣式'])# 清除不可見字符if cell.value and isinstance(cell.value, str):cell.value = clean_invisible_chars(cell.value)cleared_items.add('不可見字符')# 清除批注if cell.comment:cell.comment = Nonecleared_items.add('批注')# 保存臨時文件temp_file = f"temp_{sheet_name}.xlsx"wb.save(temp_file)return (temp_file, sheet_name, list(cleared_items))def clear_all_and_save(input_file, output_file, sheet_name, num_processes=None):"""多進程并行清除工作表中的:1. 不可見字符2. 批注3. 單元格樣式"""if num_processes is None:num_processes = multiprocessing.cpu_count()print(f"使用 {num_processes} 個進程并行處理...")# 準備參數并添加進程索引args = [(input_file, output_file, sheet_name, i) for i in range(num_processes)]# 確保至少有一個參數組if not args:args = [(input_file, output_file, sheet_name, 0)]# 創建進程池并顯示總進度with multiprocessing.Pool(processes=num_processes) as pool:# 在主進度條下方顯示各進程進度with tqdm(total=len(args), desc="總進度", position=0) as pbar:results = []for result in pool.imap(process_sheet, args):results.append(result)pbar.update()# 合并處理結果cleared_items = set()for temp_file, sheet_name, items in results:cleared_items.update(items)# 這里可以添加合并多個臨時文件的邏輯# 保存最終工作簿 (簡化處理,直接使用第一個結果)import shutilshutil.move(results[0][0], output_file)cleared_text = "\n".join(f" ? 清除-{item}" for item in cleared_items)print("已完成:\n"+cleared_text+f"\n并保存到 {output_file}")if __name__ == '__main__':input_excel_file = '測試文件.xlsx' # 原始文件output_excel_file = '清除樣式_測試文件_并行版.xlsx' # 生成文件sheet_to_clean = 'sheet1' # sheet nameprint(f"輸入文件: {input_excel_file}")print(f"輸出文件: {output_excel_file}")print(f"目標工作表: {sheet_to_clean}")try:clear_all_and_save(input_excel_file, output_excel_file, sheet_to_clean)except Exception as e:print(f"處理過程中發生錯誤: {str(e)}")
核心清除能力
- 數據凈化:過濾ASCII 0-31不可見控制字符
- 元數據清理:徹底清除單元格批注內容
- 樣式重置:
- 移除條件格式規則
- 重置字體為Calibri 11pt
- 清除所有填充顏色
- 移除單元格邊框樣式
- 性能優化:
- 多進程負載均衡
- 基于CPU核心數自動擴展
- 無鎖內存獨立操作
適用場景
- 第三方系統導出的臟數據清洗
- 金融數據脫敏后標準化處理
- 跨平臺遷移Excel文件前的格式轉換
- 機器學習數據預處理階段
- 定期自動化報表生成前的重置