Exce格式化批處理工具詳解:高效處理,讓數據更干凈!

Exce格式化批處理工具詳解:高效處理,讓數據更干凈!

1. 概述

在數據分析、報表整理、數據庫管理等工作中,數據清洗是不可或缺的一步。原始Excel數據常常存在格式不統一、空值、重復數據等問題,影響數據的準確性和可用性。本篇文章將詳細介紹一款高效的Excel數據清洗工具,幫助您輕松處理雜亂數據,提高數據質量。

2. 功能使用

在這里插入圖片描述

基本操作流程

使用本工具進行數據清洗的操作流程如下:

  1. 打開文件:點擊"瀏覽"按鈕,或使用菜單欄"文件 > 打開"選擇需要處理的Excel文件。
  2. 數據清洗:在左側工具面板選擇需要的清洗操作,例如刪除重復行、格式化日期等。
  3. 預覽結果:右側區域實時顯示數據變化,確保清洗效果符合預期。
  4. 保存文件:點擊"保存"按鈕,或使用菜單欄"文件 > 保存",將處理后的文件存儲。

3. 主要功能說明

1. 刪除重復行

作用:刪除數據表中完全相同的行,確保數據唯一性。

2. 刪除空行

作用:清除所有值均為空的行,避免無效數據干擾分析。

3. 去除空格

作用:移除文本字段中的首尾空格,防止隱藏字符影響計算。

4. 統一大小寫

作用:可選擇轉換為小寫、大寫或首字母大寫,以確保數據格式一致。

5. 數值格式化

作用:統一數值的小數位數(默認保留2位),保證數據規范。

6. 日期格式化

作用:提供多種日期格式選項,避免因格式混亂導致的數據處理錯誤。

7. 刪除特殊字符

作用:去除文本中的標點符號、特殊字符,適用于純文本數據處理。

8. 填充空值

作用:支持多種空值填充方式(平均值、中位數、眾數等),提高數據完整性。

4. 適用場景

4.1 典型使用場景

  1. 數據預處理:在進行數據分析前,先對原始數據進行標準化處理。
  2. 報表整理:整合不同來源的數據,保證格式統一。
  3. 數據庫導入準備:清理Excel數據,使其符合數據庫字段要求。
  4. 數據遷移:在不同系統之間轉移數據時,保證格式一致。
  5. 日常辦公:快速整理雜亂的Excel表格,提高工作效率。

4.2 適用人群

  • 數據分析師
  • 財務/行政人員
  • 市場研究人員
  • 數據庫管理員
  • 任何需要處理Excel數據的辦公人員

5. 注意事項

5. 1 使用前注意事項

  • 備份原始數據:建議在處理前保存一份原始文件,以免數據丟失。
  • 數據量限制:預覽功能僅顯示前100行,但清洗操作會應用于所有數據。
  • 文件格式:支持.xlsx和.xls格式,建議使用.xlsx以獲得更好的兼容性。

5.2 操作注意事項

  • 撤銷功能:當前版本不支持撤銷操作,請謹慎執行。
  • 特殊字符處理:刪除特殊字符可能影響某些編碼數據,請提前檢查。
  • 日期識別:自動識別日期列可能不夠準確,建議手動確認。
  • 數值處理:非數值字段嘗試數值格式化可能導致錯誤。

6.系統要求

本工具依賴Python環境,使用以下庫來處理數據:

  • Python 3.6+
  • pandas(數據處理核心庫)
  • numpy(數值運算支持)
  • openpyxl(用于Excel文件操作)
  • tkinter(用于GUI界面,Python自帶)
  • matplotlib(可視化功能支持)

7.高級技巧

  • 大型文件處理:對于超過10MB的文件,處理可能較慢,建議分批處理。
  • 數據可視化:工具提供基本的可視化功能,適用于數值型數據分析。
  • 快速數據分析:可查看基本統計信息,如均值、中位數、方差等,幫助快速了解數據分布。

8.總結

Excel格式化批處理工具是數據分析和日常辦公中不可或缺的步驟。本工具提供了一系列高效的功能,幫助用戶快速整理數據,提升數據質量。無論是數據分析師還是日常辦公人員,都可以借助該工具提高工作效率,減少數據整理的繁瑣工作。希望本篇指南能幫助大家更好地利用工具,提高數據處理能力!

9.相關源碼:

import pandas as pd
import numpy as np
from tkinter import *
from tkinter import ttk, filedialog, messagebox
import os
from tkinter.scrolledtext import ScrolledText
import threading
from queue import Queue
import logging
from datetime import datetime# 配置日志
logging.basicConfig(filename='excel_cleaner.log',level=logging.INFO,format='%(asctime)s - %(levelname)s - %(message)s'
)# 模擬 DataHandler, ColumnSelector, ParameterDialog 類
class DataHandler:def __init__(self):self.df = Noneself.operation_history = []self.redo_history = []def load_excel(self, file_path):self.df = pd.read_excel(file_path)return self.dfdef save_excel(self, file_path):self.df.to_excel(file_path, index=False)def get_statistics(self):return {'row_count': len(self.df),'column_count': len(self.df.columns)}def get_column_types(self):return self.df.dtypesdef remove_spaces(self, columns):for col in columns:if self.df[col].dtype == object:self.df[col] = self.df[col].str.strip()return self.dfdef normalize_case(self, case_type, columns):for col in columns:if self.df[col].dtype == object:if case_type == 'lower':self.df[col] = self.df[col].str.lower()elif case_type == 'upper':self.df[col] = self.df[col].str.upper()elif case_type == 'title':self.df[col] = self.df[col].str.title()return self.dfdef format_numbers(self, decimal_places, columns):for col in columns:if pd.api.types.is_numeric_dtype(self.df[col]):self.df[col] = self.df[col].round(decimal_places)return self.dfdef format_dates(self, date_format, columns):for col in columns:if pd.api.types.is_datetime64_any_dtype(self.df[col]):self.df[col] = self.df[col].dt.strftime(date_format)return self.dfdef remove_special_chars(self, pattern, columns):for col in columns:if self.df[col].dtype == object:self.df[col] = self.df[col].str.replace(pattern, '', regex=True)return self.dfdef fill_empty_values(self, method, value=None, columns=None):if columns is None:columns = self.df.columnsfor col in columns:if method == 'value':self.df[col].fillna(value, inplace=True)elif method == 'mean':self.df[col].fillna(self.df[col].mean(), inplace=True)elif method == 'median':self.df[col].fillna(self.df[col].median(), inplace=True)elif method == 'mode':self.df[col].fillna(self.df[col].mode()[0], inplace=True)elif method == 'ffill':self.df[col].fillna(method='ffill', inplace=True)elif method == 'bfill':self.df[col].fillna(method='bfill', inplace=True)return self.dfclass ColumnSelector:def __init__(self, parent, columns, column_types, title, callback):self.callback = callbackself.selected_columns = []self.window = Toplevel(parent)self.window.title(title)ttk.Label(self.window, text="選擇列:").pack(pady=10)self.listbox = Listbox(self.window, selectmode=MULTIPLE)for col in columns:self.listbox.insert(END, col)self.listbox.pack(fill=BOTH, expand=True, padx=10, pady=10)button_frame = ttk.Frame(self.window)button_frame.pack(fill=X, padx=10, pady=10)ttk.Button(button_frame, text="確定", command=self.on_confirm).pack(side=LEFT, padx=10)ttk.Button(button_frame, text="取消", command=self.window.destroy).pack(side=LEFT)def on_confirm(self):self.selected_columns = [self.listbox.get(i) for i in self.listbox.curselection()]self.callback(self.selected_columns)self.window.destroy()class ParameterDialog:def __init__(self, parent, params, title, callback):self.callback = callbackself.params = paramsself.values = {}self.window = Toplevel(parent)self.window.title(title)for param_name, param_info in params.items():ttk.Label(self.window, text=param_info['label']).pack(pady=5)if param_info['type'] == 'choice':var = StringVar()var.set(param_info['default'])ttk.Combobox(self.window, textvariable=var, values=param_info['choices']).pack(fill=X, padx=10)self.values[param_name] = varelif param_info['type'] == 'int':var = IntVar()var.set(param_info['default'])ttk.Spinbox(self.window, from_=param_info['min'], to=param_info['max'], textvariable=var).pack(fill=X, padx=10)self.values[param_name] = varelif param_info['type'] == 'str':var = StringVar()var.set(param_info['default'])ttk.Entry(self.window, textvariable=var).pack(fill=X, padx=10)self.values[param_name] = varbutton_frame = ttk.Frame(self.window)button_frame.pack(fill=X, padx=10, pady=10)ttk.Button(button_frame, text="確定", command=self.on_confirm).pack(side=LEFT, padx=10)ttk.Button(button_frame, text="取消", command=self.window.destroy).pack(side=LEFT)def on_confirm(self):result = {param_name: var.get() for param_name, var in self.values.items()}self.callback(result)self.window.destroy()class ExcelCleaner:def __init__(self):self.window = Tk()self.window.title("Excel數據格式化批處理工具")self.window.geometry("1000x800")self.window.configure(bg='#f0f0f0')# 初始化數據處理器self.data_handler = DataHandler()self.processing_queue = Queue()# 設置樣式self.setup_styles()# 創建菜單欄self.create_menu()# 創建主框架main_frame = ttk.Frame(self.window)main_frame.pack(fill=BOTH, expand=True, padx=10, pady=5)# 左側工具面板left_panel = ttk.LabelFrame(main_frame, text="工具面板", padding=10)left_panel.pack(side=LEFT, fill=Y, padx=5, pady=5)# 文件操作區域self.create_file_frame(left_panel)# 清洗操作區域self.create_clean_frame(left_panel)# 右側主要內容區域right_panel = ttk.Frame(main_frame)right_panel.pack(side=LEFT, fill=BOTH, expand=True, padx=5)# 預覽區域self.create_preview_frame(right_panel)# 狀態欄self.create_status_bar()# 進度條self.create_progress_bar()# 綁定快捷鍵self.bind_shortcuts()def setup_styles(self):style = ttk.Style()style.theme_use('clam')# 配置按鈕樣式style.configure("Tool.TButton",padding=5,font=('微軟雅黑', 10),background='#e1e1e1',foreground='#333333')# 配置標簽樣式style.configure("Title.TLabel",font=('微軟雅黑', 12, 'bold'),background='#f0f0f0',foreground='#333333')# 配置框架樣式style.configure("Card.TLabelframe",background='#ffffff',padding=10)# 配置樹形視圖樣式style.configure("Preview.Treeview",font=('微軟雅黑', 10),rowheight=25)# 配置進度條樣式style.configure("Progress.Horizontal.TProgressbar",troughcolor='#f0f0f0',background='#4CAF50',thickness=10)def create_progress_bar(self):self.progress_var = DoubleVar()self.progress_bar = ttk.Progressbar(self.window,style="Progress.Horizontal.TProgressbar",variable=self.progress_var,maximum=100)self.progress_bar.pack(fill=X, padx=5, pady=2)def bind_shortcuts(self):self.window.bind('<Control-o>', lambda e: self.select_file())self.window.bind('<Control-s>', lambda e: self.save_file())self.window.bind('<Control-z>', lambda e: self.undo())self.window.bind('<Control-y>', lambda e: self.redo())self.window.bind('<F1>', lambda e: self.show_help())def process_in_background(self, func, *args, **kwargs):"""在后臺線程中處理耗時操作"""def wrapper():try:self.progress_var.set(0)self.status_var.set("正在處理...")self.window.update()# 執行操作result = func(*args, **kwargs)# 更新UIself.window.after(0, self.update_ui_after_processing, result)except Exception as e:logging.error(f"處理錯誤: {str(e)}")self.window.after(0, self.show_error, str(e))finally:self.window.after(0, self.progress_var.set, 100)self.window.after(0, self.status_var.set, "處理完成")# 啟動后臺線程thread = threading.Thread(target=wrapper)thread.daemon = Truethread.start()def update_ui_after_processing(self, result):"""處理完成后更新UI"""if isinstance(result, tuple):self.data_handler.df = result[0]if len(result) > 1:removed_rows = result[1]self.status_var.set(f"已刪除 {removed_rows} 行數據")elif isinstance(result, pd.DataFrame):self.data_handler.df = resultif result is not None:self.update_preview()def show_error(self, error_msg):"""顯示錯誤消息"""messagebox.showerror("錯誤", f"處理過程中出現錯誤:{error_msg}")self.status_var.set("處理失敗")def select_file(self):file_path = filedialog.askopenfilename(filetypes=[("Excel files", "*.xlsx *.xls")])if file_path:self.process_in_background(self.data_handler.load_excel, file_path)def save_file(self):if self.data_handler.df is not None:file_path = filedialog.asksaveasfilename(defaultextension=".xlsx",filetypes=[("Excel files", "*.xlsx")])if file_path:self.process_in_background(self.data_handler.save_excel, file_path)def undo(self):"""撤銷上一步操作"""if self.data_handler.operation_history:last_operation = self.data_handler.operation_history.pop()self.data_handler.df = last_operation['previous_state'].copy()self.update_preview()self.status_var.set("已撤銷上一步操作")def redo(self):"""重做上一步操作"""if hasattr(self.data_handler, 'redo_history') and self.data_handler.redo_history:last_operation = self.data_handler.redo_history.pop()self.data_handler.df = last_operation['next_state'].copy()self.data_handler.operation_history.append(last_operation)self.update_preview()self.status_var.set("已重做上一步操作")def add_operation_to_history(self, operation_name, previous_state, next_state):"""添加操作到歷史記錄"""self.data_handler.operation_history.append({'name': operation_name,'previous_state': previous_state.copy(),'next_state': next_state.copy()})# 清空重做歷史if hasattr(self.data_handler, 'redo_history'):self.data_handler.redo_history.clear()def remove_duplicates(self):if self.data_handler.df is not None:previous_state = self.data_handler.df.copy()self.data_handler.df = self.data_handler.df.drop_duplicates()removed_rows = len(previous_state) - len(self.data_handler.df)self.add_operation_to_history("刪除重復行", previous_state, self.data_handler.df.copy())self.update_preview()self.status_var.set(f"已刪除 {removed_rows} 行重復數據")def remove_empty_rows(self):if self.data_handler.df is not None:previous_state = self.data_handler.df.copy()self.data_handler.df = self.data_handler.df.dropna(how='all')removed_rows = len(previous_state) - len(self.data_handler.df)self.add_operation_to_history("刪除空行", previous_state, self.data_handler.df.copy())self.update_preview()self.status_var.set(f"已刪除 {removed_rows} 行空數據")def remove_spaces(self):if self.data_handler.df is not None:def on_columns_selected(columns):self.process_in_background(self.data_handler.remove_spaces,columns=columns)ColumnSelector(self.window,list(self.data_handler.df.columns),self.data_handler.get_column_types(),title="選擇要去除空格的列",callback=on_columns_selected)def normalize_case(self):if self.data_handler.df is not None:def on_params_set(params):def on_columns_selected(columns):self.process_in_background(self.data_handler.normalize_case,case_type=params["case_type"],columns=columns)ColumnSelector(self.window,list(self.data_handler.df.columns),self.data_handler.get_column_types(),title="選擇要統一大小寫的列",callback=on_columns_selected)params = {"case_type": {"type": "choice","label": "大小寫格式","default": "lower","choices": ["lower", "upper", "title"]}}ParameterDialog(self.window,params,title="選擇大小寫格式",callback=on_params_set)def format_numbers(self):if self.data_handler.df is not None:def on_params_set(params):def on_columns_selected(columns):self.process_in_background(self.data_handler.format_numbers,decimal_places=params["decimal_places"],columns=columns)ColumnSelector(self.window,list(self.data_handler.df.columns),self.data_handler.get_column_types(),title="選擇要格式化的數值列",callback=on_columns_selected)params = {"decimal_places": {"type": "int","label": "小數位數","default": 2,"min": 0,"max": 10}}ParameterDialog(self.window,params,title="設置數值格式",callback=on_params_set)def format_dates(self):if self.data_handler.df is not None:def on_params_set(params):def on_columns_selected(columns):self.process_in_background(self.data_handler.format_dates,date_format=params["date_format"],columns=columns)ColumnSelector(self.window,list(self.data_handler.df.columns),self.data_handler.get_column_types(),title="選擇要格式化的日期列",callback=on_columns_selected)params = {"date_format": {"type": "choice","label": "日期格式","default": "%Y-%m-%d","choices": ["%Y-%m-%d","%Y/%m/%d","%d-%m-%Y","%m/%d/%Y"]}}ParameterDialog(self.window,params,title="選擇日期格式",callback=on_params_set)def remove_special_chars(self):if self.data_handler.df is not None:def on_params_set(params):def on_columns_selected(columns):self.process_in_background(self.data_handler.remove_special_chars,pattern=params["pattern"],columns=columns)ColumnSelector(self.window,list(self.data_handler.df.columns),self.data_handler.get_column_types(),title="選擇要處理的列",callback=on_columns_selected)params = {"pattern": {"type": "str","label": "正則表達式","default": r'[^\w\s]'}}ParameterDialog(self.window,params,title="設置正則表達式",callback=on_params_set)def fill_empty_values(self):if self.data_handler.df is not None:def on_params_set(params):def on_columns_selected(columns):value = params.get("value")if params["method"] == "value" and value:try:# 嘗試轉換為數值value = float(value) if '.' in value else int(value)except ValueError:passself.process_in_background(self.data_handler.fill_empty_values,method=params["method"],value=value,columns=columns)ColumnSelector(self.window,list(self.data_handler.df.columns),self.data_handler.get_column_types(),title="選擇要填充的列",callback=on_columns_selected)params = {"method": {"type": "choice","label": "填充方式","default": "mean","choices": ["mean", "median", "mode", "ffill", "bfill", "value"]},"value": {"type": "str","label": "填充值","default": ""}}ParameterDialog(self.window,params,title="選擇填充方式",callback=on_params_set)def analyze_data(self):if self.data_handler.df is not None:analysis_window = Toplevel(self.window)analysis_window.title("數據分析")analysis_window.geometry("600x400")stats_text = ScrolledText(analysis_window, wrap=WORD, width=70, height=20)stats_text.pack(padx=10, pady=10, fill=BOTH, expand=True)stats = []stats.append("數據基本信息:")stats.append("-" * 50)stats.append(f"總行數:{len(self.data_handler.df)}")stats.append(f"總列數:{len(self.data_handler.df.columns)}")stats.append("\n數值列統計:")stats.append("-" * 50)numeric_stats = self.data_handler.df.describe()stats.append(str(numeric_stats))stats.append("\n空值統計:")stats.append("-" * 50)null_counts = self.data_handler.df.isnull().sum()stats.append(str(null_counts))stats_text.insert(END, "\n".join(stats))stats_text.configure(state='disabled')def visualize_data(self):if self.data_handler.df is not None:try:import matplotlib.pyplot as pltfrom matplotlib.backends.backend_tkagg import FigureCanvasTkAgg# 設置中文字體plt.rcParams['font.sans-serif'] = ['SimHei']  # 用來正常顯示中文標簽plt.rcParams['axes.unicode_minus'] = False  # 用來正常顯示負號viz_window = Toplevel(self.window)viz_window.title("數據可視化")viz_window.geometry("800x600")options_frame = ttk.Frame(viz_window)options_frame.pack(fill=X, padx=10, pady=5)ttk.Label(options_frame, text="圖表類型:").pack(side=LEFT)chart_type = StringVar(value="bar")ttk.Radiobutton(options_frame, text="柱狀圖", variable=chart_type, value="bar").pack(side=LEFT)ttk.Radiobutton(options_frame, text="折線圖", variable=chart_type, value="line").pack(side=LEFT)ttk.Radiobutton(options_frame, text="散點圖", variable=chart_type, value="scatter").pack(side=LEFT)# 添加列選擇ttk.Label(options_frame, text="  選擇列:").pack(side=LEFT)column_var = StringVar()numeric_columns = list(self.data_handler.df.select_dtypes(include=[np.number]).columns)if not numeric_columns:messagebox.showwarning("警告", "沒有可用的數值列進行可視化")returncolumn_combo = ttk.Combobox(options_frame, textvariable=column_var, values=numeric_columns)column_combo.pack(side=LEFT)column_combo.set(numeric_columns[0])fig, ax = plt.subplots(figsize=(10, 6))canvas = FigureCanvasTkAgg(fig, master=viz_window)canvas.get_tk_widget().pack(fill=BOTH, expand=True, padx=10, pady=5)def update_chart():try:ax.clear()chart_style = chart_type.get()selected_column = column_var.get()if not selected_column:messagebox.showwarning("警告", "請選擇要可視化的列")returnif chart_style == "bar":self.data_handler.df[selected_column].plot(kind='bar', ax=ax)ax.set_title(f"{selected_column} 柱狀圖")elif chart_style == "line":self.data_handler.df[selected_column].plot(kind='line', ax=ax)ax.set_title(f"{selected_column} 折線圖")else:  # scatterif len(numeric_columns) >= 2:x_col = selected_columny_col = next(col for col in numeric_columns if col != x_col)self.data_handler.df.plot(kind='scatter', x=x_col, y=y_col, ax=ax)ax.set_title(f"{x_col} vs {y_col} 散點圖")else:messagebox.showwarning("警告", "需要至少兩個數值列才能創建散點圖")returnplt.tight_layout()canvas.draw()except Exception as e:messagebox.showerror("錯誤", f"繪圖時發生錯誤:{str(e)}")ttk.Button(options_frame, text="更新圖表", command=update_chart).pack(side=LEFT, padx=10)update_chart()except ImportError:messagebox.showwarning("警告", "請安裝matplotlib庫以使用可視化功能")def run(self):self.window.mainloop()def create_menu(self):menubar = Menu(self.window)self.window.config(menu=menubar)# 文件菜單file_menu = Menu(menubar, tearoff=0)menubar.add_cascade(label="文件", menu=file_menu)file_menu.add_command(label="打開 (Ctrl+O)", command=self.select_file)file_menu.add_command(label="保存 (Ctrl+S)", command=self.save_file)file_menu.add_separator()file_menu.add_command(label="退出", command=self.window.quit)# 編輯菜單edit_menu = Menu(menubar, tearoff=0)menubar.add_cascade(label="編輯", menu=edit_menu)edit_menu.add_command(label="撤銷 (Ctrl+Z)", command=self.undo)edit_menu.add_command(label="重做 (Ctrl+Y)", command=self.redo)# 視圖菜單view_menu = Menu(menubar, tearoff=0)menubar.add_cascade(label="視圖", menu=view_menu)view_menu.add_checkbutton(label="顯示狀態欄", command=self.toggle_status_bar)# 幫助菜單help_menu = Menu(menubar, tearoff=0)menubar.add_cascade(label="幫助", menu=help_menu)help_menu.add_command(label="使用說明 (F1)", command=self.show_help)help_menu.add_command(label="關于", command=self.show_about)def create_file_frame(self, parent):file_frame = ttk.LabelFrame(parent, text="文件操作", padding=10, style="Card.TLabelframe")file_frame.pack(fill=X, pady=(0, 10))# 文件選擇self.file_path = StringVar()ttk.Label(file_frame, text="Excel文件:", style="Title.TLabel").pack(anchor=W)ttk.Entry(file_frame, textvariable=self.file_path, width=30).pack(fill=X, pady=5)button_frame = ttk.Frame(file_frame)button_frame.pack(fill=X)ttk.Button(button_frame, text="瀏覽", command=self.select_file, style="Tool.TButton").pack(side=LEFT, padx=2)ttk.Button(button_frame, text="保存", command=self.save_file, style="Tool.TButton").pack(side=LEFT, padx=2)def create_clean_frame(self, parent):clean_frame = ttk.LabelFrame(parent, text="數據清洗", padding=10, style="Card.TLabelframe")clean_frame.pack(fill=BOTH, expand=True)operations = [("刪除重復行", self.remove_duplicates),("刪除空行", self.remove_empty_rows),("去除空格", self.remove_spaces),("統一大小寫", self.normalize_case),("數值格式化", self.format_numbers),("日期格式化", self.format_dates),("刪除特殊字符", self.remove_special_chars),("填充空值", self.fill_empty_values),("數據分析", self.analyze_data),("數據可視化", self.visualize_data)]for text, command in operations:btn = ttk.Button(clean_frame, text=text, command=command, style="Tool.TButton")btn.pack(fill=X, pady=2)def create_preview_frame(self, parent):preview_frame = ttk.LabelFrame(parent, text="數據預覽", padding=10, style="Card.TLabelframe")preview_frame.pack(fill=BOTH, expand=True)# 創建帶滾動條的樹形視圖tree_frame = ttk.Frame(preview_frame)tree_frame.pack(fill=BOTH, expand=True)# 創建水平滾動條h_scrollbar = ttk.Scrollbar(tree_frame, orient=HORIZONTAL)h_scrollbar.pack(side=BOTTOM, fill=X)# 創建垂直滾動條v_scrollbar = ttk.Scrollbar(tree_frame)v_scrollbar.pack(side=RIGHT, fill=Y)# 創建樹形視圖self.tree = ttk.Treeview(tree_frame,style="Preview.Treeview",xscrollcommand=h_scrollbar.set,yscrollcommand=v_scrollbar.set)self.tree.pack(fill=BOTH, expand=True)# 配置滾動條h_scrollbar.config(command=self.tree.xview)v_scrollbar.config(command=self.tree.yview)# 創建統計信息面板stats_frame = ttk.Frame(preview_frame)stats_frame.pack(fill=X, pady=(10, 0))self.stats_label = ttk.Label(stats_frame, text="", style="Title.TLabel")self.stats_label.pack(side=LEFT)def create_status_bar(self):self.status_var = StringVar()self.status_bar = ttk.Label(self.window,textvariable=self.status_var,relief=SUNKEN,padding=(5, 2))self.status_bar.pack(fill=X, padx=5, pady=2)def toggle_status_bar(self):# 切換狀態欄顯示/隱藏if self.status_bar.winfo_viewable():self.status_bar.pack_forget()else:self.status_bar.pack(fill=X, padx=5, pady=2)def update_preview(self):# 清空現有數據for item in self.tree.get_children():self.tree.delete(item)if self.data_handler.df is not None:df = self.data_handler.df# 設置列self.tree["columns"] = list(df.columns)self.tree["show"] = "headings"for column in df.columns:self.tree.heading(column, text=column)self.tree.column(column, width=100, anchor='center')# 添加數據(僅顯示前100行)for i, row in df.head(100).iterrows():self.tree.insert("", END, values=list(row))# 更新統計標簽stats = self.data_handler.get_statistics()self.stats_label.config(text=f"行數: {stats['row_count']} | 列數: {stats['column_count']}")# 更新狀態欄self.status_var.set(f"當前加載文件: {os.path.basename(self.file_path.get())} | "f"行數: {stats['row_count']} | 列數: {stats['column_count']}")else:self.status_var.set("請先加載文件")def show_help(self):help_text = """
Excel數據格式化批處理工具使用說明:1. 文件操作:- 點擊"瀏覽"選擇Excel文件- 點擊"保存"保存處理后的文件2. 數據清洗功能:- 刪除重復行:刪除完全重復的數據行- 刪除空行:刪除全為空值的行- 去除空格:刪除文本中的首尾空格- 統一大小寫:統一文本的大小寫格式- 數值格式化:統一數值的小數位數- 日期格式化:統一日期的顯示格式- 刪除特殊字符:清除文本中的特殊字符- 填充空值:使用多種方式填充缺失值3. 數據分析:- 查看基本統計信息- 空值分析- 數據分布可視化4. 快捷鍵:- Ctrl+O:打開文件- Ctrl+S:保存文件- Ctrl+Z:撤銷- Ctrl+Y:重做- F1:顯示幫助"""help_window = Toplevel(self.window)help_window.title("使用說明")help_window.geometry("600x400")help_text_widget = ScrolledText(help_window, wrap=WORD, width=70, height=20)help_text_widget.pack(padx=10, pady=10, fill=BOTH, expand=True)help_text_widget.insert(END, help_text)help_text_widget.configure(state='disabled')def show_about(self):about_text = """
Excel數據格式化批處理工具功能特點:
- 支持多種數據清洗操作
- 實時預覽數據變化
- 數據分析和可視化
- 后臺處理,避免卡頓
- 撤銷/重做功能
- 友好的圖形界面"""messagebox.showinfo("關于", about_text)if __name__ == "__main__":try:app = ExcelCleaner()app.run()except Exception as e:logging.error(f"程序運行錯誤: {str(e)}")messagebox.showerror("錯誤", f"程序運行出錯:{str(e)}")# 優化的代碼,運行即出現GUI界面

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/77046.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/77046.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/77046.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

(三十七)Dart 中使用 Pub 包管理系統與 HTTP 請求教程

Dart 中使用 Pub 包管理系統與 HTTP 請求教程 Pub 包管理系統簡介 Pub 是 Dart 和 Flutter 的包管理系統&#xff0c;用于管理項目的依賴。通過 Pub&#xff0c;開發者可以輕松地添加、更新和管理第三方庫。 使用 Pub 包管理系統 1. 找到需要的庫 訪問以下網址&#xff0c…

代碼隨想錄算法訓練營第三十五天 | 416.分割等和子集

416. 分割等和子集 題目鏈接&#xff1a;416. 分割等和子集 - 力扣&#xff08;LeetCode&#xff09; 文章講解&#xff1a;代碼隨想錄 視頻講解&#xff1a;動態規劃之背包問題&#xff0c;這個包能裝滿嗎&#xff1f;| LeetCode&#xff1a;416.分割等和子集_嗶哩嗶哩_bilibi…

HTTP 教程 : 從 0 到 1 全面指南 教程【全文三萬字保姆級詳細講解】

目錄 HTTP 的請求-響應 HTTP 方法 HTTP 狀態碼 HTTP 版本 安全性 HTTP/HTTPS 簡介 HTTP HTTPS HTTP 工作原理 HTTPS 作用 HTTP 與 HTTPS 區別 HTTP 消息結構 客戶端請求消息 服務器響應消息 實例 HTTP 請求方法 各個版本定義的請求方法 HTTP/1.0 HTTP/1.1 …

spring功能匯總

1.創建一個dao接口&#xff0c;實現類&#xff1b;service接口&#xff0c;實現類并且service里用new創建對象方式調用dao的方法 2.使用spring分別獲取dao和service對象(IOC) 注意 2中的service里面獲取dao的對象方式不用new的(DI) 運行測試&#xff1a; 使用1的方式創建servic…

Vue.js 實現下載模板和導入模板、數據比對功能核心實現。

在前端開發中&#xff0c;數據比對是一個常見需求&#xff0c;尤其在資產管理等場景中。本文將基于 Vue.js 和 Element UI&#xff0c;通過一個簡化的代碼示例&#xff0c;展示如何實現“新建比對”和“開始比對”功能的核心部分。 一、功能簡介 我們將聚焦兩個核心功能&…

volatile關鍵字用途說明

volatile 關鍵字在 C# 中用于指示編譯器和運行時系統&#xff0c;某個字段可能會被多個線程同時訪問&#xff0c;并且該字段的讀寫操作不應被優化&#xff08;例如緩存到寄存器或重排序&#xff09;&#xff0c;以確保所有線程都能看到最新的值。這使得 volatile 成為一種輕量級…

【區塊鏈安全 | 第三十五篇】溢出漏洞

文章目錄 溢出上溢示例溢出漏洞溢出示例漏洞代碼代碼審計1. deposit 函數2. increaseLockTime 函數 攻擊代碼攻擊過程總結修復建議審計思路 溢出 算術溢出&#xff08;Arithmetic Overflow&#xff09;&#xff0c;簡稱溢出&#xff08;Overflow&#xff09;&#xff0c;通常分…

百度的deepseek與硅基模型的差距。

問題&#xff1a; 已經下載速度8兆每秒&#xff0c;請問下載30G的文件需要多長時間&#xff1f; 關于這個問題。百度的回答如下&#xff1a; ?30GB文件下載時間計算? ?理論計算?&#xff08;基于十進制單位&#xff09;&#xff1a; ?單位換算? 文件大小&#xff1a;3…

車載診斷架構 --- 特殊定義NRC處理原理

我是穿拖鞋的漢子,魔都中堅持長期主義的汽車電子工程師。 老規矩,分享一段喜歡的文字,避免自己成為高知識低文化的工程師: 周末洗了一個澡,換了一身衣服,出了門卻不知道去哪兒,不知道去找誰,漫無目的走著,大概這就是成年人最深的孤獨吧! 舊人不知我近況,新人不知我過…

面試題ing

1、js中set和map的作用和區別? 在 JavaScript 中&#xff0c;Set 和 Map 是兩種非常重要的集合類型 1、Set 是一種集合數據結構&#xff0c;用于存儲唯一值。它類似于數組&#xff0c;但成員的值都是唯一的&#xff0c;沒有重復的值。Set 中的值只能是唯一的&#xff0c;任何…

Python爬蟲第6節-requests庫的基本用法

目錄 前言 一、準備工作 二、實例引入 三、GET請求 3.1 基本示例 3.2 抓取網頁 3.3 抓取二進制數據 3.4 添加headers 四、POST請求 五、響應 前言 前面我們學習了urllib的基礎使用方法。不過&#xff0c;urllib在實際應用中存在一些不便之處。以網頁驗證和Cookies處理…

Go 學習筆記 · 進階篇 · 第一天:接口與多態

&#x1f436;Go接口與多態&#xff1a;繼承沒了&#xff0c;但自由炸裂&#xff01; 最近翻 Go 的代碼&#xff0c;突然看到這么一段&#xff1a; type Animal interface {Speak() string }我一愣&#xff0c;咦&#xff1f;這不就是 Java 里常見的“接口”嗎&#xff1f; …

信息學奧賽一本通 1929:【04NOIP普及組】火星人 | 洛谷 P1088 [NOIP 2004 普及組] 火星人

【題目鏈接】 ybt 1929&#xff1a;【04NOIP普及組】火星人 洛谷 P1088 [NOIP 2004 普及組] 火星人 【題目考點】 1. 深搜回溯 2. STL next_permutation函數 頭文件<algorithm> 函數定義&#xff1a;next_permutation(lb, ub, cmp) lb&#xff1a;區間下界&#xff…

借助 AI 工具使用 Python 實現北京市店鋪分布地理信息可視化教程

一、項目概述 本項目通過 Python 的pyecharts庫&#xff0c;結合 AI 工具輔助代碼編寫與邏輯梳理&#xff0c;實現北京市店鋪數量分布及區域連線的地理信息可視化&#xff0c;最終生成交互式地圖圖表。 二、準備工作 1. 環境與工具 Python 環境&#xff1a;確保已安裝 Pyth…

Python項目打包指南:PyInstaller與SeleniumWire的兼容性挑戰及解決方案

前言 前段時間做一個內網開發的需求&#xff0c;要求將selenium程序打包成.exe放在內網的win7上運行&#xff0c;在掘金搜了一圈也沒有發現相關文章&#xff0c;因此將過程中踩到的坑記錄分享一下。 本文涵蓋了具體打包操作、不同模塊和依賴項的兼容性解決方案&#xff0c;以…

(一)棧結構、隊列結構

01-線性結構-數組-棧結構 線性結構&#xff08;Linear List)是由n&#xff08;n>0)個數據元素&#xff08;結點&#xff09; a[0], a[1], a[2], a[3],...,a[n-1]組成的有限序列 數組 通常數組的內存是連續的&#xff0c;所以在知道數組下標的情況下&#xff0c;訪問效率是…

【學Rust寫CAD】35 alpha_mul_256(alpha256.rs補充方法)

源碼 // Calculates (value * alpha256) / 255 in range [0,256], // for [0,255] value and [0,256] alpha256. pub fn alpha_mul_256(self,value: u32) -> Alpha256 {let prod value * self.0;Alpha256((prod (prod >> 8)) >> 8) }代碼分析 這個函數 alph…

C# 與 相機連接

一、通過組件連接相機 需要提前在VisionPro里面保存一個CogAcqFifoTool相機工具為 .vpp 定義一個相機工具 CogAcqFifoTool mAcq null;將保存的相機工具放入mAcq中 string path “C:\Acq.vpp”; mAcq (CogAcqFifoTool)CogSerializer.LoadObjectFrommFile(path);給窗口相機…

Java并發編程高頻面試題

一、基礎概念 1. 并行與并發的區別&#xff1f; 并行&#xff1a;多個任務在多個CPU核心上同時執行&#xff08;物理上同時&#xff09;。并發&#xff1a;多個任務在單CPU核心上交替執行&#xff08;邏輯上同時&#xff09;。類比&#xff1a;并行是多個窗口同時服務&#x…

LiT and Lean: Distilling Listwise Rerankers intoEncoder-Decoder Models

文章&#xff1a;ECIR 2025會議 一、動機 背景&#xff1a;利用LLMs強大的能力&#xff0c;將一個查詢&#xff08;query&#xff09;和一組候選段落作為輸入&#xff0c;整體考慮這些段落的相關性&#xff0c;并對它們進行排序。 先前的研究基礎上進行擴展 [14,15]&#xff0c…