最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Python實現(xiàn)excel拆分和合并工具并打包

 更新時間:2026年02月06日 08:52:27   作者:忘憂記  
這篇文章介紹了一個基于Python的Excel文件拆分與合并工具,采用模塊化設(shè)計實現(xiàn)高效處理,系統(tǒng)通過Pandas和openpyxl庫支持快速數(shù)據(jù)操作和格式保留兩種模式并提供GUI界面簡化操作流程,希望對大家有所幫助

拆分代碼

處理核心流程

  • 驗證輸入
  • 讀取數(shù)據(jù)
  • 拆分數(shù)據(jù)
  • 保存文件

拆分代碼的核心邏輯可以總結(jié)為:“讀取數(shù)據(jù)→計算拆分規(guī)則→按規(guī)則切割數(shù)據(jù)→保存小文件”,具體步驟如下,結(jié)合代碼細節(jié)一步步解釋:

前提:用戶輸入準備

在拆分前,程序需要兩個關(guān)鍵信息:

  • 要拆分的Excel文件路徑(用戶通過“瀏覽”按鈕選擇)
  • 每個小文件包含的行數(shù)(用戶在輸入框填寫,默認10000行)

這兩個信息會通過start_split函數(shù)做有效性檢查

  • 檢查文件是否存在(如果沒選文件或文件路徑無效,彈出警告)
  • 檢查行數(shù)是否為正數(shù)(如果填0或負數(shù)或文字,彈出警告)

核心拆分函數(shù)split_excel的邏輯(重點)

當輸入有效后,程序調(diào)用split_excel(file_path, rows_per_file)函數(shù),這個函數(shù)是拆分的核心,步驟如下:

步驟1:讀取Excel數(shù)據(jù)

pandas庫的pd.read_excel(file_path)讀取整個Excel文件,得到一個“數(shù)據(jù)框”df(可以理解為內(nèi)存中的表格,包含所有行和列)。
然后用len(df)獲取總數(shù)據(jù)行數(shù)(比如總共有25000行)。

步驟2:檢查數(shù)據(jù)是否為空

如果總行數(shù)為0(即Excel里沒數(shù)據(jù)),直接彈出“錯誤”提示,終止拆分。

步驟3:計算需要拆分成多少個文件

用“總行數(shù) ÷ 每個文件的行數(shù)”,并向上取整(避免最后一個文件行數(shù)不足時被漏掉)。

例如:總共有25000行,每個文件10000行 → 25000 ÷ 10000 = 2.5 → 向上取整后是3個文件。

代碼里用math.ceil(total_rows / rows_per_file)實現(xiàn)這個計算。

步驟4:確定拆分后文件的保存位置和名稱

  • 保存位置:和原文件在同一個文件夾(用os.path.dirname(file_path)獲取原文件目錄)。
  • 文件名稱:原文件名 + “_拆分_序號”(比如原文件叫data.xlsx,拆分后是data_拆分_1.xlsxdata_拆分_2.xlsx…)。

步驟5:循環(huán)拆分并保存每個小文件

for循環(huán)遍歷每個要生成的小文件(從0到“文件數(shù)量-1”),每次循環(huán)做3件事:

計算當前小文件的“起始行”和“結(jié)束行”:

  • 起始行 = 序號 × 每個文件的行數(shù)(比如第1個文件是0×10000=0,第2個是1×10000=10000)
  • 結(jié)束行 = (序號+1)× 每個文件的行數(shù),但如果超過總行數(shù),就取總行數(shù)(避免越界)。例如總25000行,第3個文件的結(jié)束行是min(3×10000, 25000) = 25000

提取當前小文件的數(shù)據(jù):用df.iloc[start_row:end_row]從總數(shù)據(jù)中“切出”當前范圍的行(比如第3個文件取20000到25000行),得到子數(shù)據(jù)框df_subset

保存子文件:用df_subset.to_excel(output_path, index=False)將子數(shù)據(jù)框保存為Excel文件(index=False表示不保存行號,避免多余數(shù)據(jù))。

步驟6:反饋結(jié)果

  • 如果所有文件都保存成功,彈出“成功”提示,顯示拆分的文件數(shù)量(比如“共拆分成3個文件”)。
  • 如果過程中出錯(比如文件損壞、沒有權(quán)限保存等),彈出“錯誤”提示,顯示具體錯誤原因。

完整代碼

“先讀全表,算好要拆成幾個文件,再按行數(shù)一段一段切下來,每段存成一個新Excel,最后告訴用戶結(jié)果”。

整個過程不需要手動計算,程序會自動處理邊界情況(比如最后一個文件行數(shù)不足),并通過圖形界面讓操作更簡單。

import pandas as pd
import os
import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk
import math


def split_excel(file_path, rows_per_file):
    """將Excel文件按指定行數(shù)拆分成多個文件"""
    try:
        # 讀取Excel文件
        df = pd.read_excel(file_path)
        total_rows = len(df)
        
        if total_rows == 0:
            messagebox.showerror("錯誤", "Excel文件中沒有數(shù)據(jù)!")
            return
        
        # 計算需要拆分的文件數(shù)量
        num_files = math.ceil(total_rows / rows_per_file)
        
        # 獲取文件目錄和文件名(不含擴展名)
        file_dir = os.path.dirname(file_path)
        file_name = os.path.splitext(os.path.basename(file_path))[0]
        
        # 拆分文件
        for i in range(num_files):
            start_row = i * rows_per_file
            end_row = min((i + 1) * rows_per_file, total_rows)
            
            # 提取數(shù)據(jù)子集
            df_subset = df.iloc[start_row:end_row]
            
            # 生成輸出文件名
            output_filename = f"{file_name}_拆分_{i+1}.xlsx"
            output_path = os.path.join(file_dir, output_filename)
            
            # 保存拆分后的文件
            df_subset.to_excel(output_path, index=False)
        
        messagebox.showinfo("成功", f"文件拆分完成!\n共拆分成 {num_files} 個文件\n每個文件約 {rows_per_file} 行")
        
    except Exception as e:
        messagebox.showerror("錯誤", f"拆分過程中出現(xiàn)錯誤:{str(e)}")


def select_file():
    """選擇Excel文件"""
    file_path = filedialog.askopenfilename(
        title="選擇要拆分的Excel文件",
        filetypes=[("Excel files", "*.xlsx *.xls"), ("All files", "*.*")]
    )
    if file_path:
        file_var.set(file_path)
        
        # 自動讀取文件信息
        try:
            df = pd.read_excel(file_path)
            total_rows = len(df)
            info_var.set(f"文件總行數(shù): {total_rows} 行")
        except Exception as e:
            info_var.set("無法讀取文件信息")


def start_split():
    """開始拆分"""
    file_path = file_var.get()
    
    if not file_path or not os.path.exists(file_path):
        messagebox.showwarning("警告", "請先選擇有效的Excel文件!")
        return
    
    try:
        rows_per_file = int(rows_var.get())
        if rows_per_file <= 0:
            messagebox.showwarning("警告", "請輸入有效的行數(shù)(大于0)!")
            return
    except ValueError:
        messagebox.showwarning("警告", "請輸入有效的數(shù)字!")
        return
    
    split_excel(file_path, rows_per_file)


# 創(chuàng)建主窗口
root = tk.Tk()
root.title("Excel文件拆分工具:數(shù)據(jù)分析")
root.geometry("550x200")

# 變量
file_var = tk.StringVar()
rows_var = tk.StringVar(value="10000")  # 默認10000行
info_var = tk.StringVar(value="請選擇Excel文件")

# 界面布局
frame = ttk.Frame(root, padding="15")
frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

# 文件選擇行
ttk.Label(frame, text="選擇Excel文件:").grid(row=0, column=0, sticky=tk.W, pady=5)
ttk.Entry(frame, textvariable=file_var, width=40).grid(row=0, column=1, padx=5, pady=5)
ttk.Button(frame, text="瀏覽", command=select_file).grid(row=0, column=2, padx=5, pady=5)

# 文件信息顯示
ttk.Label(frame, textvariable=info_var, foreground="blue").grid(row=1, column=1, sticky=tk.W, pady=2)

# 行數(shù)設(shè)置行
ttk.Label(frame, text="每份文件行數(shù):").grid(row=2, column=0, sticky=tk.W, pady=10)
ttk.Entry(frame, textvariable=rows_var, width=15).grid(row=2, column=1, sticky=tk.W, padx=5, pady=10)
ttk.Label(frame, text="行").grid(row=2, column=1, sticky=tk.W, padx=100, pady=10)

# 開始拆分按鈕
ttk.Button(frame, text="開始拆分", command=start_split).grid(row=3, column=1, pady=20)

# 配置網(wǎng)格權(quán)重
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)

root.mainloop()

合并代碼

合并代碼的核心邏輯可以總結(jié)為:“選一個基準文件→自動找相似文件→確認后合并→統(tǒng)一格式并保存”,整個過程不需要手動逐個選擇文件,重點在“智能識別相似文件”和“兼容不同格式的表格”。下面分步驟拆解邏輯:

前提:用戶輸入準備

程序需要用戶先做一件事:選擇一個“基準Excel文件”(通過“瀏覽”按鈕選擇)。這個文件的作用是“模板”——程序會以它的文件名為線索,去同目錄下找其他“長得像”的文件。

核心合并函數(shù)combine_similar_files的邏輯(重點)

當用戶點擊“開始智能合并”后,程序調(diào)用這個函數(shù),核心步驟如下:

步驟1:定位文件目錄并收集所有Excel文件

  • 先確定基準文件所在的文件夾(比如基準文件在D:\數(shù)據(jù),就只在這個文件夾里找其他文件)。
  • 遍歷這個文件夾,把所有以.xlsx.xls結(jié)尾的文件都挑出來(這些是潛在的合并對象)。
  • 如果文件夾里沒有Excel文件,直接彈“錯誤”提示(比如“目錄中沒有找到Excel文件”)。

步驟2:從基準文件名中提取“相似模式”(核心?。?/h4>

這是程序“智能”的關(guān)鍵——通過基準文件名,提煉出一個“共同特征”,用來判斷其他文件是否相似。比如:

  • 若基準文件是銷售數(shù)據(jù)_1.xlsx,會提煉出銷售數(shù)據(jù)(去掉數(shù)字和后綴);
  • 若基準文件是報表-202401.xlsx,會提煉出報表-2024(去掉末尾的日期序號);
  • 若基準文件是客戶列表 v2.xlsx,會提煉出客戶列表(去掉版本號)。

具體由extract_common_pattern函數(shù)實現(xiàn),邏輯是:

  • 先去掉文件后綴(如.xlsx),只看文件名主體;
  • 去掉文件名里的數(shù)字(比如文件123文件);
  • 按常見分隔符(_-、空格)拆分,取前面的部分(比如數(shù)據(jù)_拆分_3數(shù)據(jù)_拆分);
  • 如果以上都不適用,就用整個文件名主體作為模式。

步驟3:用“相似模式”篩選同目錄的文件

有了“相似模式”后,程序會在步驟1收集的所有Excel文件中,篩選出符合模式的文件。由find_similar_files函數(shù)實現(xiàn),比如:

  • 模式是銷售數(shù)據(jù),則銷售數(shù)據(jù)_2.xlsx、銷售數(shù)據(jù)_3.xlsx會被選中(包含銷售數(shù)據(jù));
  • 模式是報表-2024,則報表-202402.xlsx、報表-202403.xlsx會被選中(以模式開頭)。

篩選時會自動排除基準文件本身嗎?不,會包含基準文件(最終合并的文件列表里,基準文件是第一個)。

步驟4:讓用戶確認要合并的文件

如果篩選出的相似文件只有1個(也就是只有基準文件自己),會彈“提示”說“沒有找到其他相似文件”,終止流程。
如果有多個,會列出所有文件(比如“銷售數(shù)據(jù)_1.xlsx、銷售數(shù)據(jù)_2.xlsx、銷售數(shù)據(jù)_3.xlsx”),讓用戶選“是”或“否”——用戶確認后才繼續(xù)合并。

步驟5:合并文件數(shù)據(jù)(處理格式兼容)

這一步是實際合并數(shù)據(jù),核心是解決“不同文件列不一致”的問題(比如A文件有“姓名、金額”,B文件只有“姓名”)。步驟:

  • 逐個讀取相似文件的表格數(shù)據(jù)(用pd.read_excel),得到每個文件的“數(shù)據(jù)框”(內(nèi)存中的表格)。
  • 第一個文件的數(shù)據(jù)作為“基準結(jié)構(gòu)”,后續(xù)文件的數(shù)據(jù)會和它對齊:
    • 如果列名完全一致(比如都有“姓名、金額”),直接拼接(按行疊加);
    • 如果列名不一致(比如B文件缺“金額”),則給B文件自動補一個“金額”列,空值填充(保證合并后所有列名和第一個文件一致)。
  • pd.concat把所有數(shù)據(jù)框“拼”成一個大的數(shù)據(jù)框(df_combined)。

步驟6:保存合并結(jié)果(避免文件名沖突)

  • 生成結(jié)果文件名:用步驟2提煉的“相似模式”+“_合并結(jié)果.xlsx”(比如銷售數(shù)據(jù)_合并結(jié)果.xlsx)。
  • 檢查是否有重名:如果同名文件已存在,自動加序號(比如銷售數(shù)據(jù)_合并結(jié)果(1).xlsx、(2).xlsx)。
  • 保存到基準文件所在的文件夾(用to_excel函數(shù))。

步驟7:反饋合并結(jié)果

  • 成功:彈窗顯示“合并了3個文件,總行數(shù)1500,保存路徑XXX”;
  • 失敗:彈窗顯示具體錯誤(比如“某文件損壞無法讀取”“沒有權(quán)限保存”)。

完整代碼

“以一個文件為模板,自動找到同目錄下名字相似的其他Excel文件,對齊它們的表格列,拼在一起后存成一個新文件,過程中讓用戶確認并反饋結(jié)果”

這個邏輯的核心優(yōu)勢是“智能找文件”(不用手動選)和“自動兼容格式”(不怕列不一致),特別適合處理按序號拆分的文件(如數(shù)據(jù)1數(shù)據(jù)2)或按時間拆分的文件(如202401報表、202402報表)。

import pandas as pd
import os
import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk
from collections import defaultdict


def combine_similar_files(selected_file):
    """合并與選定文件類似的所有Excel文件"""
    try:
        file_dir = os.path.dirname(selected_file)
        file_name = os.path.basename(selected_file)
        
        # 獲取目錄下所有Excel文件
        listdir = os.listdir(file_dir)
        excel_files = [f for f in listdir if f.endswith(('.xlsx', '.xls'))]
        
        if not excel_files:
            messagebox.showerror("錯誤", "目錄中沒有找到 Excel 文件!")
            return
        
        # 分析選定文件的特征(文件名模式)
        base_name = file_name
        # 嘗試提取共同前綴(去除序號、版本號等)
        common_patterns = extract_common_pattern(base_name)
        
        # 根據(jù)特征篩選相似文件
        similar_files = find_similar_files(excel_files, common_patterns, base_name)
        
        if len(similar_files) <= 1:
            messagebox.showinfo("提示", f"沒有找到與 '{file_name}' 相似的其他文件")
            return
        
        # 顯示找到的相似文件列表
        file_list = "\n".join(similar_files)
        confirm = messagebox.askyesno(
            "確認合并", 
            f"找到以下相似文件,是否合并?\n\n{file_list}\n\n共 {len(similar_files)} 個文件"
        )
        
        if not confirm:
            return
        
        # 合并文件
        df_combined = None
        for filename in similar_files:
            file_path = os.path.join(file_dir, filename)
            df_temp = pd.read_excel(file_path)
            
            if df_combined is None:
                df_combined = df_temp
            else:
                # 檢查列結(jié)構(gòu)是否一致
                if set(df_combined.columns) != set(df_temp.columns):
                    # 如果不一致,嘗試對齊列
                    df_temp = df_temp.reindex(columns=df_combined.columns, fill_value=None)
                
                df_combined = pd.concat([df_combined, df_temp], ignore_index=True, sort=False)
        
        # 生成輸出文件名
        output_name = generate_output_name(common_patterns, base_name)
        output_path = os.path.join(file_dir, f"{output_name}_合并結(jié)果.xlsx")
        
        # 避免文件名沖突
        counter = 1
        while os.path.exists(output_path):
            output_path = os.path.join(file_dir, f"{output_name}_合并結(jié)果({counter}).xlsx")
            counter += 1
        
        # 保存合并后的文件
        df_combined.to_excel(output_path, index=False)
        
        messagebox.showinfo(
            "成功", 
            f"數(shù)據(jù)合并完成!\n"
            f"合并了 {len(similar_files)} 個文件\n"
            f"保存位置:{output_path}\n"
            f"總行數(shù):{len(df_combined)}"
        )
        
    except Exception as e:
        messagebox.showerror("錯誤", f"合并過程中出現(xiàn)錯誤:{str(e)}")


def extract_common_pattern(filename):
    """提取文件名的共同模式"""
    # 去除擴展名
    name_without_ext = os.path.splitext(filename)[0]
    
    patterns = []
    
    # 常見模式識別
    # 1. 按數(shù)字分割(如:文件1.xlsx, 文件2.xlsx)
    if any(char.isdigit() for char in name_without_ext):
        # 提取非數(shù)字部分作為模式
        non_digit_parts = []
        current_part = ""
        for char in name_without_ext:
            if char.isdigit():
                if current_part:
                    non_digit_parts.append(current_part)
                    current_part = ""
            else:
                current_part += char
        if current_part:
            non_digit_parts.append(current_part)
        
        if non_digit_parts:
            patterns.append(''.join(non_digit_parts).strip(' _-'))
    
    # 2. 按常見分隔符分割
    separators = ['_', '-', ' ']
    for sep in separators:
        if sep in name_without_ext:
            parts = name_without_ext.split(sep)
            # 取前面幾個部分作為模式
            if len(parts) > 1:
                patterns.append(sep.join(parts[:-1]))
    
    # 3. 如果以上都不適用,使用整個文件名(不含擴展名)
    if not patterns:
        patterns.append(name_without_ext)
    
    return patterns


def find_similar_files(all_files, patterns, base_file):
    """根據(jù)模式查找相似文件"""
    similar_files = [base_file]  # 包含選定的文件
    
    for pattern in patterns:
        if pattern:  # 確保模式不為空
            for filename in all_files:
                if filename == base_file:
                    continue  # 跳過選定的文件本身
                
                name_without_ext = os.path.splitext(filename)[0]
                
                # 多種匹配策略
                if (pattern in filename or 
                    pattern in name_without_ext or
                    filename.startswith(pattern) or
                    name_without_ext.startswith(pattern)):
                    similar_files.append(filename)
    
    # 去重并返回
    return list(dict.fromkeys(similar_files))


def generate_output_name(patterns, base_file):
    """生成輸出文件名"""
    if patterns:
        # 使用最長的模式作為基礎(chǔ)名稱
        longest_pattern = max(patterns, key=len)
        if len(longest_pattern) > 3:  # 確保模式有足夠長度
            return longest_pattern
    
    # 回退方案:使用基礎(chǔ)文件名(不含擴展名)
    return os.path.splitext(base_file)[0]


def select_file():
    """選擇Excel文件"""
    file_path = filedialog.askopenfilename(
        title="選擇要合并的Excel文件",
        filetypes=[("Excel files", "*.xlsx *.xls"), ("All files", "*.*")]
    )
    if file_path:
        file_var.set(file_path)
        # 顯示選中的文件名
        file_name = os.path.basename(file_path)
        info_var.set(f"已選擇: {file_name}")


def start_combine():
    """開始合并"""
    file_path = file_var.get()
    
    if not file_path or not os.path.exists(file_path):
        messagebox.showwarning("警告", "請先選擇有效的Excel文件!")
        return
    
    combine_similar_files(file_path)


# 創(chuàng)建主窗口
root = tk.Tk()
root.title("智能文件合并:數(shù)據(jù)分析")
root.geometry("600x180")

# 變量
file_var = tk.StringVar()
info_var = tk.StringVar(value="請選擇Excel文件")

# 界面布局
frame = ttk.Frame(root, padding="15")
frame.grid(row=0, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))

# 文件選擇行
ttk.Label(frame, text="選擇基準Excel文件:").grid(row=0, column=0, sticky=tk.W, pady=5)
ttk.Entry(frame, textvariable=file_var, width=50).grid(row=0, column=1, padx=5, pady=5)
ttk.Button(frame, text="瀏覽", command=select_file).grid(row=0, column=2, padx=5, pady=5)

# 文件信息顯示
ttk.Label(frame, textvariable=info_var, foreground="blue").grid(row=1, column=1, sticky=tk.W, pady=5)

# 說明文字
info_text = "系統(tǒng)會自動查找與選定文件相似的其他文件進行合并\n(基于文件名模式識別,如:文件1.xlsx, 文件2.xlsx)"
ttk.Label(frame, text=info_text, foreground="gray", font=("Arial", 9)).grid(row=2, column=1, sticky=tk.W, pady=5)

# 開始合并按鈕
ttk.Button(frame, text="開始智能合并", command=start_combine).grid(row=3, column=1, pady=15)

# 配置網(wǎng)格權(quán)重
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
frame.columnconfigure(1, weight=1)

root.mainloop()

整合代碼

import pandas as pd
import os
import tkinter as tk
from tkinter import filedialog, messagebox
from tkinter import ttk
import math
import logging
import sys

# --- 1. 日志配置 ---
# 配置日志輸出到控制臺 (CMD) 和文件,用于調(diào)試和運行狀態(tài)跟蹤
def setup_logging():
    # 使用 StreamHandler 將日志輸出到標準輸出,確保在 CMD 中可見
    logging.basicConfig(
        level=logging.INFO, # 默認級別為 INFO,會輸出 INFO, WARNING, ERROR, CRITICAL
        format='%(asctime)s - %(levelname)s - %(message)s',
        handlers=[
            logging.StreamHandler(sys.stdout)
        ]
    )
    logging.info("日志初始化完成。Excel 處理工具啟動。")

# --- 2. 文件合并邏輯 (Merge Functions) ---

def extract_common_pattern(filename):
    """提取文件名的共同模式(用于智能識別相似文件)"""
    name_without_ext = os.path.splitext(filename)[0]
    logging.debug(f"分析文件名模式: {name_without_ext}")
    
    patterns = []
    
    # 1. 按數(shù)字分割(提取非數(shù)字部分作為模式)
    non_digit_parts = []
    current_part = ""
    for char in name_without_ext:
        if char.isdigit():
            if current_part:
                non_digit_parts.append(current_part)
                current_part = ""
        else:
            current_part += char
    if current_part:
        non_digit_parts.append(current_part)
    
    pattern1 = ''.join(non_digit_parts).strip(' _-')
    if pattern1:
        patterns.append(pattern1)
        logging.debug(f"模式 1 (非數(shù)字部分): {pattern1}")

    # 2. 按常見分隔符分割(提取前綴)
    separators = ['_', '-']
    for sep in separators:
        if sep in name_without_ext:
            parts = name_without_ext.split(sep)
            if len(parts) > 1:
                pattern2 = sep.join(parts[:-1]).strip()
                if pattern2:
                    patterns.append(pattern2)
                    logging.debug(f"模式 2 (分隔符 '{sep}' 前綴): {pattern2}")
    
    # 3. 回退方案:使用整個文件名(不含擴展名)
    if not patterns:
        patterns.append(name_without_ext)
    
    return list(set(patterns))


def find_similar_files(all_files, patterns, base_file):
    """根據(jù)提取的模式查找相似文件"""
    similar_files = [base_file] 
    logging.info(f"基準文件: {base_file}")
    
    for pattern in patterns:
        logging.debug(f"檢查模式: '{pattern}'")
        if not pattern:
            continue
        
        for filename in all_files:
            if filename == base_file:
                continue 
            
            name_without_ext = os.path.splitext(filename)[0]
            
            # 匹配邏輯:文件名中包含模式,或文件名以模式開頭
            if (pattern in name_without_ext or
                name_without_ext.startswith(pattern)):
                
                if filename not in similar_files:
                    similar_files.append(filename)
                    logging.info(f"找到相似文件: {filename}")
    
    return list(dict.fromkeys(similar_files))


def generate_output_name(patterns, base_file):
    """生成輸出文件名"""
    # 優(yōu)先使用最長的、有意義的模式
    meaningful_patterns = [p for p in patterns if len(p) > 3]
    if meaningful_patterns:
        longest_pattern = max(meaningful_patterns, key=len)
        return longest_pattern
    
    # 回退到基準文件名(不含擴展名)
    return os.path.splitext(base_file)[0]


def combine_similar_files(selected_file):
    """執(zhí)行文件合并操作的核心邏輯"""
    logging.info("-" * 50)
    logging.info(f"開始合并操作,基準文件: {selected_file}")
    
    try:
        file_dir = os.path.dirname(selected_file)
        file_name = os.path.basename(selected_file)
        
        # 1. 查找所有 Excel 文件
        listdir = os.listdir(file_dir)
        excel_files = [f for f in listdir if f.lower().endswith(('.xlsx', '.xls', '.xlsm'))]
        
        if not excel_files:
            logging.error("目錄中未找到 Excel 文件。")
            messagebox.showerror("錯誤", "目錄中沒有找到 Excel 文件!")
            return
        
        # 2. 分析模式并查找相似文件
        common_patterns = extract_common_pattern(file_name)
        similar_files = find_similar_files(excel_files, common_patterns, file_name)
        
        if len(similar_files) <= 1:
            logging.warning("未找到相似的其他文件。")
            messagebox.showinfo("提示", f"沒有找到與 '{file_name}' 相似的其他文件")
            return
        
        # 3. 確認合并
        file_list = "\n".join(similar_files)
        logging.info(f"共找到 {len(similar_files)} 個文件準備合并。")
        
        confirm = messagebox.askyesno(
            "確認合并", 
            f"找到以下相似文件,是否合并?\n\n{file_list}\n\n共 {len(similar_files)} 個文件"
        )
        
        if not confirm:
            logging.info("用戶取消了合并操作。")
            return
        
        # 4. 執(zhí)行合并
        df_combined = pd.DataFrame() 
        
        for filename in similar_files:
            file_path = os.path.join(file_dir, filename)
            logging.info(f"正在讀取文件: {filename}")
            
            try:
                # 使用 openpyxl 引擎處理 .xlsx 文件
                df_temp = pd.read_excel(file_path, engine='openpyxl')
                df_combined = pd.concat([df_combined, df_temp], ignore_index=True, sort=False)
                logging.debug(f"文件 {filename} 讀取成功,已合并。")
                
            except Exception as read_e:
                logging.error(f"讀取文件 {filename} 時出錯: {str(read_e)}")
                messagebox.showwarning("文件讀取警告", f"無法讀取文件 '{filename}'。該文件將被跳過。")
                continue

        if df_combined.empty:
            messagebox.showerror("錯誤", "所有文件讀取失敗,無法合并。")
            logging.error("合并后的 DataFrame 為空。")
            return

        # 5. 保存結(jié)果
        output_name = generate_output_name(common_patterns, file_name)
        output_path = os.path.join(file_dir, f"{output_name}_合并結(jié)果.xlsx")
        
        # 避免文件名沖突
        counter = 1
        while os.path.exists(output_path):
            output_path = os.path.join(file_dir, f"{output_name}_合并結(jié)果({counter}).xlsx")
            counter += 1
            
        logging.info(f"保存合并結(jié)果到: {output_path}")
        
        df_combined.to_excel(output_path, index=False, engine='openpyxl')
        
        messagebox.showinfo(
            "成功", 
            f"數(shù)據(jù)合并完成!\n合并了 {len(similar_files)} 個文件\n保存位置:{output_path}\n總行數(shù):{len(df_combined)}"
        )
        logging.info(f"合并成功,總行數(shù): {len(df_combined)}")
        
    except Exception as e:
        logging.critical(f"合并過程中發(fā)生致命錯誤: {str(e)}")
        messagebox.showerror("錯誤", f"合并過程中出現(xiàn)錯誤:{str(e)}")


# --- 3. 文件拆分邏輯 (Split Functions) ---

def split_excel(file_path, rows_per_file):
    """執(zhí)行文件拆分操作的核心邏輯"""
    logging.info("-" * 50)
    logging.info(f"開始拆分操作,文件: {file_path}")
    logging.info(f"每份文件行數(shù): {rows_per_file}")

    try:
        df = pd.read_excel(file_path, engine='openpyxl')
        total_rows = len(df)
        
        if total_rows == 0:
            messagebox.showerror("錯誤", "Excel文件中沒有數(shù)據(jù)!")
            logging.error("待拆分文件為空。")
            return
        
        # 計算文件數(shù)量
        num_files = math.ceil(total_rows / rows_per_file)
        
        file_dir = os.path.dirname(file_path)
        file_name = os.path.splitext(os.path.basename(file_path))[0]
        
        logging.info(f"總行數(shù): {total_rows} 行,將拆分成 {num_files} 個文件。")
        
        # 拆分和保存
        for i in range(num_files):
            start_row = i * rows_per_file
            end_row = min((i + 1) * rows_per_file, total_rows)
            
            df_subset = df.iloc[start_row:end_row]
            
            output_filename = f"{file_name}_拆分_{i+1}.xlsx"
            output_path = os.path.join(file_dir, output_filename)
            
            logging.info(f"保存第 {i+1}/{num_files} 份文件 (行 {start_row+1} 到 {end_row}) 到: {output_path}")

            df_subset.to_excel(output_path, index=False, engine='openpyxl')
        
        logging.info(f"文件拆分操作成功完成。")
        messagebox.showinfo("成功", f"文件拆分完成!\n共拆分成 {num_files} 個文件\n每個文件約 {rows_per_file} 行")
        
    except Exception as e:
        logging.critical(f"拆分過程中發(fā)生致命錯誤: {str(e)}")
        messagebox.showerror("錯誤", f"拆分過程中出現(xiàn)錯誤:{str(e)}")


# --- 4. Tkinter GUI 界面 ---

class ExcelProcessorApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Excel文件智能處理工具 (合并與拆分)")
        # 優(yōu)化界面樣式
        try:
            style = ttk.Style()
            style.theme_use('vista') # 嘗試使用Windows風格主題
            style.configure('TButton', font=('Arial', 10, 'bold'), padding=6)
        except:
             pass # 如果主題不存在,保持默認
             
        self.root.geometry("650x300")
        self.root.resizable(False, False)

        # 變量初始化
        self.merge_file_var = tk.StringVar()
        self.merge_info_var = tk.StringVar(value="請選擇Excel文件作為合并基準")
        self.split_file_var = tk.StringVar()
        self.split_rows_var = tk.StringVar(value="10000") 
        self.split_info_var = tk.StringVar(value="請選擇待拆分的Excel文件")

        # 初始化日志
        setup_logging()
        
        # 創(chuàng)建 Notebook (標簽頁界面)
        self.notebook = ttk.Notebook(root)
        self.notebook.pack(pady=10, padx=10, expand=True, fill="both")

        # 創(chuàng)建標簽頁框架
        self.merge_frame = ttk.Frame(self.notebook, padding="15 15 15 15")
        self.split_frame = ttk.Frame(self.notebook, padding="15 15 15 15")
        
        self.notebook.add(self.merge_frame, text="文件智能合并")
        self.notebook.add(self.split_frame, text="文件按行拆分")

        # 構(gòu)建標簽頁 UI
        self._build_merge_tab()
        self._build_split_tab()

    # --- UI 構(gòu)建器 ---

    def _build_merge_tab(self):
        self.merge_frame.columnconfigure(1, weight=1)
        
        # 1. 文件選擇
        ttk.Label(self.merge_frame, text="選擇基準Excel文件:", font=('Arial', 10, 'bold')).grid(row=0, column=0, sticky=tk.W, pady=10)
        ttk.Entry(self.merge_frame, textvariable=self.merge_file_var, width=50).grid(row=0, column=1, padx=5, pady=10, sticky=(tk.W, tk.E))
        ttk.Button(self.merge_frame, text="瀏覽", command=self._select_merge_file).grid(row=0, column=2, padx=5, pady=10)

        # 2. 文件信息
        ttk.Label(self.merge_frame, textvariable=self.merge_info_var, foreground="#0056b3", font=("Arial", 10)).grid(row=1, column=1, sticky=tk.W, pady=5)

        # 3. 功能說明
        info_text = "功能說明:系統(tǒng)將根據(jù)文件名模式(例如:文件_1, 文件_2)自動查找同目錄下所有相似文件,并將它們合并。\n請確保所有文件的表頭結(jié)構(gòu)大致一致。"
        ttk.Label(self.merge_frame, text=info_text, foreground="gray", font=("Arial", 9)).grid(row=2, column=0, columnspan=3, sticky=tk.W, pady=10)

        # 4. 開始按鈕
        ttk.Button(self.merge_frame, text="? 開始智能合并 ?", command=self._start_merge, style='TButton').grid(row=3, column=1, pady=20)
    
    
    def _build_split_tab(self):
        self.split_frame.columnconfigure(1, weight=1)

        # 1. 文件選擇
        ttk.Label(self.split_frame, text="選擇待拆分的Excel文件:", font=('Arial', 10, 'bold')).grid(row=0, column=0, sticky=tk.W, pady=10)
        ttk.Entry(self.split_frame, textvariable=self.split_file_var, width=50).grid(row=0, column=1, padx=5, pady=10, sticky=(tk.W, tk.E))
        ttk.Button(self.split_frame, text="瀏覽", command=self._select_split_file).grid(row=0, column=2, padx=5, pady=10)

        # 2. 文件信息
        ttk.Label(self.split_frame, textvariable=self.split_info_var, foreground="#0056b3", font=("Arial", 10)).grid(row=1, column=1, sticky=tk.W, pady=5)

        # 3. 行數(shù)設(shè)置
        ttk.Label(self.split_frame, text="每份文件行數(shù):").grid(row=2, column=0, sticky=tk.W, pady=10)
        ttk.Entry(self.split_frame, textvariable=self.split_rows_var, width=15).grid(row=2, column=1, sticky=tk.W, padx=5, pady=10)
        ttk.Label(self.split_frame, text="行 (默認 10000)").grid(row=2, column=1, sticky=tk.W, padx=120, pady=10)

        # 4. 開始按鈕
        ttk.Button(self.split_frame, text="?? 開始拆分 ??", command=self._start_split, style='TButton').grid(row=3, column=1, pady=20)

    # --- 5. 事件處理器 ---

    def _select_file(self, file_var, info_var, mode="select"):
        """通用文件選擇邏輯,并自動讀取文件信息(總行數(shù))"""
        title = "選擇 Excel 文件"
             
        file_path = filedialog.askopenfilename(
            title=title,
            filetypes=[("Excel files", "*.xlsx *.xls *.xlsm"), ("All files", "*.*")]
        )
        if file_path:
            file_var.set(file_path)
            file_name = os.path.basename(file_path)
            
            try:
                # 嘗試讀取文件行數(shù)
                df = pd.read_excel(file_path, engine='openpyxl')
                total_rows = len(df)
                
                if mode == "split":
                    info_var.set(f"已選擇: {file_name} | 文件總行數(shù): {total_rows} 行")
                    logging.info(f"拆分文件已選擇: {file_path}. 總行數(shù): {total_rows}")
                else:
                    info_var.set(f"已選擇: {file_name} | 總行數(shù): {total_rows} 行")
                    logging.info(f"合并基準文件已選擇: {file_path}. 總行數(shù): {total_rows}")
            except Exception as e:
                info_var.set(f"已選擇: {file_name} | 無法讀取文件信息或文件損壞。")
                logging.error(f"讀取文件信息出錯: {e}")

    def _select_merge_file(self):
        self._select_file(self.merge_file_var, self.merge_info_var, mode="merge")

    def _select_split_file(self):
        self._select_file(self.split_file_var, self.split_info_var, mode="split")


    def _start_merge(self):
        file_path = self.merge_file_var.get()
        if not file_path or not os.path.exists(file_path):
            messagebox.showwarning("警告", "請先選擇有效的Excel文件!")
            return
        # 運行合并邏輯
        combine_similar_files(file_path)
        
    def _start_split(self):
        file_path = self.split_file_var.get()
        if not file_path or not os.path.exists(file_path):
            messagebox.showwarning("警告", "請先選擇有效的Excel文件!")
            return
        
        try:
            rows_per_file = int(self.split_rows_var.get())
            if rows_per_file <= 0:
                messagebox.showwarning("警告", "請輸入有效的行數(shù)(大于0)!")
                return
        except ValueError:
            messagebox.showwarning("警告", "每份文件行數(shù)必須是有效的數(shù)字!")
            return
        
        # 運行拆分邏輯
        split_excel(file_path, rows_per_file)


# --- 6. 主程序入口 ---
if __name__ == '__main__':
    root = tk.Tk()
    app = ExcelProcessorApp(root)
    root.mainloop()

執(zhí)行打包命令

pyinstaller --onefile --console --upx-dir D:\upx excel_tool.py

以上就是基于Python實現(xiàn)excel拆分和合并工具并打包的詳細內(nèi)容,更多關(guān)于Python excel拆分和合并的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Python3.8中如何使用print打印變量

    Python3.8中如何使用print打印變量

    這篇文章主要介紹了Python3.8中如何使用print打印變量問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-11-11
  • python列表與列表算法詳解

    python列表與列表算法詳解

    這篇文章主要介紹了Python的列表和列表算法,具有一定參考價值,需要的朋友可以了解下,希望能給你帶來幫助
    2021-08-08
  • python+pygame實現(xiàn)坦克大戰(zhàn)

    python+pygame實現(xiàn)坦克大戰(zhàn)

    這篇文章主要為大家詳細介紹了python+pygame實現(xiàn)坦克大戰(zhàn),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2019-09-09
  • PyTorch之torch.randn()如何創(chuàng)建正態(tài)分布隨機數(shù)

    PyTorch之torch.randn()如何創(chuàng)建正態(tài)分布隨機數(shù)

    這篇文章主要介紹了PyTorch之torch.randn()如何創(chuàng)建正態(tài)分布隨機數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • 使用tf.keras.MaxPooling1D出現(xiàn)錯誤問題及解決

    使用tf.keras.MaxPooling1D出現(xiàn)錯誤問題及解決

    這篇文章主要介紹了使用tf.keras.MaxPooling1D出現(xiàn)錯誤問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-12-12
  • pytorch dataloader 取batch_size時候出現(xiàn)bug的解決方式

    pytorch dataloader 取batch_size時候出現(xiàn)bug的解決方式

    今天小編就為大家分享一篇pytorch dataloader 取batch_size時候出現(xiàn)bug的解決方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-02-02
  • Flask SocketIO實現(xiàn)動態(tài)繪圖的示例詳解

    Flask SocketIO實現(xiàn)動態(tài)繪圖的示例詳解

    Flask-SocketIO 是基于 Flask 的一個擴展,用于簡化在 Flask 應(yīng)用中集成 WebSocket 功能,本文主要介紹了Flask SocketIO如何實現(xiàn)動態(tài)繪圖,需要的可以參考下
    2023-11-11
  • python如何利用joblib保存訓練模型

    python如何利用joblib保存訓練模型

    這篇文章主要介紹了python如何利用joblib保存訓練模型問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • 學點簡單的Django之第一個Django程序的實現(xiàn)

    學點簡單的Django之第一個Django程序的實現(xiàn)

    這篇文章主要介紹了學點簡單的Django之第一個Django程序的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • Python字符串對齊和判斷方法匯總

    Python字符串對齊和判斷方法匯總

    本教程將詳細介紹Python中的字符串對齊方法以及字符串判斷方法,這些方法在文本處理、格式化輸出和字符串匹配中非常實用,無論你是Python初學者還是想要鞏固基礎(chǔ)知識的程序員,這篇教程都能幫助你全面理解這些操作,需要的朋友可以參考下
    2025-04-04

最新評論

鹿泉市| 兴国县| 尤溪县| 格尔木市| 安庆市| 通山县| 宁明县| 开阳县| 交城县| 泰顺县| 芒康县| 秭归县| 固阳县| 龙陵县| 武定县| 武夷山市| 松江区| 宁波市| 商河县| 济阳县| 广东省| 荣成市| 响水县| 隆化县| 西吉县| 炉霍县| 新营市| 西和县| 儋州市| 平凉市| 广水市| 邻水| 凌源市| 林周县| 双牌县| 运城市| 乌拉特后旗| 图片| 海兴县| 鸡东县| 石景山区|