<think>根据提供的代码,我们有一个`FileMergeApp`类,它继承自`ttk.Frame`,用于创建一个文件合并和统计分析的界面。但是,代码中只实现了界面部分,具体的合并和统计分析功能尚未实现。我们需要完成以下任务:
1. 实现文件合并功能,包括三种合并方式:工作页合并、区块合并、按列合并。
2. 实现统计分析功能:汇总统计和计数统计。
3. 执行合并与分析后,将结果保存为Excel文件,文件名加上时间戳,并允许用户选择保存路径。
4. 保存后弹出一个文本浏览框(这里可能是弹出文件保存对话框,并允许用户选择路径和文件名)。
由于代码中使用了`filedialog`和`messagebox`,我们需要导入这些模块。
我们将使用`pandas`和`openpyxl`库来处理Excel文件。如果未安装,需要先安装:`pip install pandas openpyxl xlrd`(xlrd用于读取旧版.xls文件,但注意xlrd最新版不支持xlsx,所以我们使用openpyxl引擎)。
### 计划实现的功能
1. **合并选项**:
- **工作页合并**:每个Excel文件的工作表合并到同一个Excel文件的不同工作表中(每个文件作为一个工作表)。
- **区块合并**:将每个Excel文件的每个工作表中的数据(从第一行开始直到空行)追加到同一个工作表中(一个文件接一个文件)。
- **按列合并**:按照指定的列进行合并,对于数值列求和,字符串列去重并用顿号(、)连接。
2. **指定列不合并**:在按列合并时,某些列不参与合并(即保持原样,不进行求和或连接操作)。
3. **统计分析选项**:
- **汇总统计**:对数值列进行统计(如总和、平均值、最大值、最小值等)。
- **计数统计**:对每个字符串列进行计数统计(每个不同值出现的次数)。
4. **执行按钮**:点击后开始合并,然后进行统计分析,最后保存文件并弹出保存对话框。
### 实现步骤
1. 修改界面,增加合并方式的选择(目前只有追加数据和按列合并两个单选按钮,需要补充工作页合并和区块合并)。
2. 添加一个输入框用于输入指定不合并的列(例如:A,B,C)。
3. 实现`start_merge`方法,根据用户选择的合并方式调用不同的合并函数。
4. 实现不同的合并函数:
- `merge_by_sheet`: 工作页合并。
- `merge_by_block`: 区块合并。
- `merge_by_columns`: 按列合并(需要处理指定列不合并的情况)。
5. 实现统计分析函数,根据用户选择的统计选项生成统计结果。
6. 保存文件时,弹出文件保存对话框,让用户选择路径和文件名,然后加上时间戳保存。
### 修改界面
在合并选项中,我们需要增加两种合并方式,并且添加一个输入框用于输入指定不合并的列。
由于原界面中只有两个单选按钮(追加数据和按列合并),我们需要调整:
- 将“追加数据”改为“区块合并”(因为区块合并就是追加数据)。
- 增加一个“工作页合并”单选按钮。
- 另外,我们需要一个输入框来输入指定不合并的列(在按列合并时使用)。
另外,原界面中合并选项的变量`self.merge_var`的取值目前有"append"和"columns",我们增加一个"sheet"表示工作页合并。所以,合并方式有三种:区块合并(append)、按列合并(columns)、工作页合并(sheet)。
同时,我们需要一个输入框来输入指定不合并的列(可以是一个Entry组件)。
### 代码实现
由于代码较长,我们将分步骤实现:
1. 修改界面,增加工作页合并单选按钮,并添加指定列不合并的输入框。
2. 实现合并函数。
3. 实现统计函数。
4. 在`start_merge`中整合功能。
注意:由于Excel文件可能包含多个工作表,我们需要考虑多工作表的情况。
### 详细代码实现
#### 1. 修改界面
在合并选项区域,我们增加一个单选按钮用于工作页合并,并添加一个标签和输入框用于指定列不合并。
```python
# 在__init__方法中,修改合并选项部分
# 添加工作页合并单选按钮
ttk.Radiobutton(
options_frame,
text="工作页合并",
variable=self.merge_var,
value="sheet"
).grid(row=0, column=3, padx=10, pady=5, sticky="w") # 注意调整列位置
# 添加指定列不合并的输入框
ttk.Label(options_frame, text="指定列不合并:").grid(row=1, column=0, padx=10, pady=5, sticky="w")
self.exclude_cols_var = tk.StringVar()
exclude_entry = ttk.Entry(options_frame, textvariable=self.exclude_cols_var, width=20)
exclude_entry.grid(row=1, column=1, padx=10, pady=5, sticky="w")
```
#### 2. 实现合并函数
我们将实现三个合并函数:
- `merge_by_sheet`: 工作页合并。将每个文件的所有工作表合并到一个Excel文件中,每个文件作为一个工作表(如果文件名相同,则加上序号)。如果多个文件有同名工作表,则后面文件的工作表会覆盖前面文件的工作表?为了避免覆盖,我们可以将同一个文件的工作表命名为“原工作表名_文件名”或者按顺序命名。这里我们采用简单方式:每个文件只读取第一个工作表,并将该文件的名字作为工作表名(去掉扩展名)。如果用户需要合并多个工作表,我们可以考虑将每个文件的所有工作表都合并进来,但这样可能会产生很多工作表。这里我们先简化:每个文件只取第一个工作表。
- `merge_by_block`: 区块合并。将每个文件的每个工作表中的数据(从第一行开始)读取出来,然后按行追加到同一个工作表中(每个文件的数据块之间可以留一个空行,也可以不留,这里我们不留空行,连续追加)。
- `merge_by_columns`: 按列合并。需要指定一个合并列(比如第一列),然后按照该列的值进行合并。对于数值列,相同键的值相加;对于字符串列,相同键的值去重并用顿号连接。同时,用户可以指定某些列不参与合并(即直接取第一个出现的值,或者最后一个?这里我们取第一个)。
#### 3. 实现统计函数
在合并完成后,根据用户选择的统计选项,在同一个Excel文件中添加新的工作表来展示统计结果。
- 汇总统计:对数值列计算总和、平均值、最大值、最小值等。
- 计数统计:对字符串列计算每个值出现的次数。
#### 4. 保存文件
使用`tkinter.filedialog.asksaveasfilename`获取用户选择的保存路径,然后加上时间戳生成文件名。
由于时间关系,我们只实现核心功能,并注意处理异常。
### 代码实现
由于完整实现代码较长,我们将分步骤编写。注意:以下代码需要安装`pandas`和`openpyxl`。
在`start_merge`方法中,我们将实现:
1. 获取文件列表。
2. 根据合并方式选择合并函数。
3. 执行合并。
4. 根据统计选项生成统计结果(统计结果放在同一个Excel文件的不同工作表中)。
5. 保存文件。
由于按列合并需要指定合并的列,这里我们简化:按列合并时默认使用第一列作为合并列。在实际应用中,可能需要让用户选择按哪一列合并,但界面中未提供,所以我们暂时使用第一列。另外,指定列不合并的功能只在按列合并时有效。
### 代码示例
下面我们给出部分关键代码,由于整个程序较长,我们只给出框架和关键函数。
```python
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import pandas as pd
from datetime import datetime
import os
class FileMergeApp(ttk.Frame):
# ... 之前的初始化代码 ...
def start_merge(self):
if self.file_listbox.size() == 0:
messagebox.showwarning("警告", "请至少添加一个Excel文件")
return
files = self.file_listbox.get(0, tk.END)
merge_mode = self.merge_var.get()
exclude_cols = self.exclude_cols_var.get().strip()
if exclude_cols:
# 将输入的列(如A,B,C)转换为数字索引或列名?在pandas中,我们可以按列名操作,所以这里我们保留为列名字符串列表
exclude_cols = [col.strip() for col in exclude_cols.split(',')]
else:
exclude_cols = []
# 获取保存路径
file_path = filedialog.asksaveasfilename(
defaultextension=".xlsx",
filetypes=[("Excel文件", "*.xlsx"), ("Excel 97-2003 文件", "*.xls")]
)
if not file_path:
return # 用户取消了保存
# 在文件名后加上时间戳
base, ext = os.path.splitext(file_path)
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
new_file_path = f"{base}_{timestamp}{ext}"
try:
if merge_mode == "sheet":
self.merge_by_sheet(files, new_file_path)
elif merge_mode == "append":
self.merge_by_block(files, new_file_path)
elif merge_mode == "columns":
self.merge_by_columns(files, new_file_path, exclude_cols)
# 如果需要统计分析,则添加统计工作表
if any(var.get() for var in self.stats_vars.values()):
self.generate_statistics(new_file_path)
messagebox.showinfo("成功", f"文件已保存至:{new_file_path}")
# 这里可以添加打开文件所在目录或打开文件的代码
except Exception as e:
messagebox.showerror("错误", str(e))
def merge_by_sheet(self, files, output_path):
# 创建一个新的Excel writer
with pd.ExcelWriter(output_path, engine='openpyxl') as writer:
for i, file in enumerate(files):
# 读取第一个工作表
df = pd.read_excel(file, sheet_name=0)
# 生成工作表名,使用文件名(不含扩展名)
sheet_name = os.path.basename(file).split('.')[0][:30] # 工作表名最多31个字符
df.to_excel(writer, sheet_name=sheet_name, index=False)
def merge_by_block(self, files, output_path):
all_dfs = []
for file in files:
# 读取所有工作表
xls = pd.ExcelFile(file)
for sheet_name in xls.sheet_names:
df = pd.read_excel(xls, sheet_name=sheet_name)
all_dfs.append(df)
# 合并所有DataFrame
combined_df = pd.concat(all_dfs, ignore_index=True)
combined_df.to_excel(output_path, index=False, engine='openpyxl')
def merge_by_columns(self, files, output_path, exclude_cols):
# 假设按第一列合并,这里我们让用户输入合并列?但界面没有,所以暂时用第一列
merge_col = 0 # 第一列的索引为0
# 存储所有数据
data = {}
# 遍历所有文件
for file in files:
df = pd.read_excel(file, sheet_name=0)
# 将第一列作为合并键
for _, row in df.iterrows():
key = row[0]
if key not in data:
data[key] = row.to_dict()
else:
# 已存在该键,则合并
existing = data[key]
for col in df.columns:
if col in exclude_cols:
continue # 跳过指定列
# 如果当前列是数值类型,则相加
if pd.api.types.is_numeric_dtype(df[col].dtype):
existing[col] = existing.get(col, 0) + row[col]
else:
# 字符串类型,去重并用顿号连接
existing_val = existing.get(col, '')
if existing_val:
if row[col] not in existing_val.split('、'):
existing[col] = existing_val + '、' + row[col]
else:
existing[col] = row[col]
data[key] = existing
# 将字典转换为DataFrame
result_df = pd.DataFrame.from_dict(data, orient='index')
result_df.to_excel(output_path, index=False, engine='openpyxl')
def generate_statistics(self, file_path):
# 读取合并后的文件,我们假设合并后的数据在第一个工作表
df = pd.read_excel(file_path, sheet_name=0)
# 使用同一个ExcelWriter添加新的工作表
with pd.ExcelWriter(file_path, engine='openpyxl', mode='a') as writer:
# 汇总统计
if self.stats_vars["summary"].get():
# 只对数值列进行统计
numeric_cols = df.select_dtypes(include='number').columns
if not numeric_cols.empty:
summary_df = df[numeric_cols].describe().T # 转置
summary_df.to_excel(writer, sheet_name="汇总统计")
# 计数统计
if self.stats_vars["count"].get():
# 对每个非数值列进行计数
object_cols = df.select_dtypes(include='object').columns
for col in object_cols:
count_df = df[col].value_counts().reset_index()
count_df.columns = [col, '计数']
count_df.to_excel(writer, sheet_name=f"{col}计数统计", index=False)
```
### 注意事项
1. 按列合并函数`merge_by_columns`中,我们假设合并键是第一列,且该列的值是唯一的?实际上,我们使用该列的值作为键,如果重复则合并。但注意,该函数在处理大量数据时可能效率不高,因为使用了循环。对于大数据量,可以使用`groupby`进行优化,但这里为了清晰展示逻辑,使用了循环。
2. 在`merge_by_block`中,我们合并了所有工作表。如果工作表结构不同(列不同),`pd.concat`会自动按列名对齐,不存在的列用NaN填充。如果列名不同,则会产生很多列。所以,建议用户确保文件结构相同。
3. 在`generate_statistics`中,我们使用`mode='a'`来追加工作表,但如果原文件有多个工作表,可能会覆盖?这里我们直接读取合并后的文件,然后追加统计工作表。注意:如果原文件有多个工作表,我们只读取了第一个工作表(在`generate_statistics`中)。所以,工作页合并模式生成的文件,在统计时只统计第一个工作表?这需要调整。我们可以将合并后的整个Excel文件读入,然后对每个工作表进行统计?但这样比较复杂。这里我们简化:只统计第一个工作表。
4. 时间戳加在文件名后面,用户可以选择保存为.xls或.xlsx,但注意,如果保存为.xls,则不能使用openpyxl引擎,需要使用xlwt。我们这里主要使用.xlsx。
### 改进
由于时间关系,上述代码只是一个初步实现,实际应用中还需要考虑更多细节,例如:
- 按列合并时,合并列的选择(让用户输入合并列)。
- 工作页合并时,处理同一个文件中的多个工作表。
- 区块合并时,处理列名不一致的情况。
- 统计时,对每个工作表都进行统计(如果合并模式是工作页合并,那么每个工作表都应该单独统计)。
由于问题复杂,我们提供基本框架,后续可以根据需求扩展。
### 相关问题
§§相关问题§§:
1. 如何让用户选择按列合并的列名?
2. 如何处理合并时列名不一致的情况?
3. 在区块合并中,如何避免不同文件列顺序不一致导致的问题?
4. 如何优化按列合并函数的性能,以处理大数据量?</think>下面我将为您详细解释并完善文件合并统计分析界面的代码实现。这个界面允许用户添加多个Excel文件,选择不同的合并方式和统计分析选项,然后执行合并与分析操作。
### 完整代码实现
```python
import tkinter as tk
from tkinter import ttk, filedialog, messagebox
import pandas as pd
import numpy as np
import os
from datetime import datetime
import xlrd
import openpyxl
from openpyxl.utils.dataframe import dataframe_to_rows
class FileMergeApp(ttk.Frame):
"""文件合并统计分析界面"""
def __init__(self, master):
super().__init__(master)
self.pack(fill=tk.BOTH, expand=True)
# 创建标题
title_label = tk.Label(
self,
text="Excel文件合并统计分析",
font=("黑体", 16, "bold"),
fg="#2c3e50"
)
title_label.pack(pady=20)
# 创建说明标签
desc_label = tk.Label(
self,
text="此功能用于合并多个Excel文件并生成统计分析报告",
font=("宋体", 12),
fg="#7f8c8d"
)
desc_label.pack(pady=10)
# 创建功能容器
container = ttk.Frame(self)
container.pack(fill=tk.BOTH, expand=True, padx=50, pady=20)
container.columnconfigure(0, weight=1)
container.rowconfigure((0, 1, 2, 3), weight=1)
# 添加文件选择区域
file_frame = ttk.LabelFrame(container, text="选择Excel文件")
file_frame.grid(row=0, column=0, sticky="ew", pady=10)
self.file_listbox = tk.Listbox(file_frame, height=6)
self.file_listbox.pack(fill=tk.BOTH, expand=True, padx=10, pady=5)
btn_frame = ttk.Frame(file_frame)
btn_frame.pack(fill=tk.X, padx=10, pady=5)
add_btn = ttk.Button(btn_frame, text="添加文件", command=self.add_files)
add_btn.pack(side=tk.LEFT, padx=5)
remove_btn = ttk.Button(btn_frame, text="移除选中", command=self.remove_file)
remove_btn.pack(side=tk.LEFT, padx=5)
clear_btn = ttk.Button(btn_frame, text="清空列表", command=self.clear_files)
clear_btn.pack(side=tk.RIGHT, padx=5)
# 添加合并选项
options_frame = ttk.LabelFrame(container, text="合并选项")
options_frame.grid(row=1, column=0, sticky="ew", pady=10)
# 指定列不合并输入框
exclude_frame = ttk.Frame(options_frame)
exclude_frame.grid(row=0, column=0, columnspan=3, sticky="w", padx=5, pady=5)
ttk.Label(exclude_frame, text="指定列不合并:").pack(side=tk.LEFT)
self.exclude_cols = tk.StringVar()
exclude_entry = ttk.Entry(exclude_frame, textvariable=self.exclude_cols, width=15)
exclude_entry.pack(side=tk.LEFT, padx=5)
exclude_entry.insert(0, "A,B,C") # 默认值
# 合并方式选择
merge_frame = ttk.Frame(options_frame)
merge_frame.grid(row=1, column=0, columnspan=3, sticky="w", padx=5, pady=5)
self.merge_var = tk.StringVar(value="sheet")
ttk.Radiobutton(
merge_frame,
text="工作页合并",
variable=self.merge_var,
value="sheet"
).pack(side=tk.LEFT, padx=10)
ttk.Radiobutton(
merge_frame,
text="区块合并",
variable=self.merge_var,
value="block"
).pack(side=tk.LEFT, padx=10)
ttk.Radiobutton(
merge_frame,
text="按列合并",
variable=self.merge_var,
value="column"
).pack(side=tk.LEFT, padx=10)
# 添加统计选项
stats_frame = ttk.LabelFrame(container, text="统计分析")
stats_frame.grid(row=2, column=0, sticky="ew", pady=10)
self.stats_vars = {
"summary": tk.BooleanVar(value=True),
"count": tk.BooleanVar(value=True),
}
ttk.Checkbutton(
stats_frame,
text="汇总统计",
variable=self.stats_vars["summary"]
).grid(row=0, column=0, padx=10, pady=5, sticky="w")
ttk.Checkbutton(
stats_frame,
text="计数统计",
variable=self.stats_vars["count"]
).grid(row=0, column=1, padx=10, pady=5, sticky="w")
# 添加执行按钮
execute_btn = ttk.Button(
container,
text="开始合并与分析",
command=self.start_merge,
style="Accent.TButton"
)
execute_btn.grid(row=3, column=0, pady=20)
# 配置样式
self.style = ttk.Style()
self.style.configure("Accent.TButton",
foreground="white",
background="#3498db",
font=("Arial", 10, "bold"),
padding=6)
def add_files(self):
files = filedialog.askopenfilenames(
filetypes=[("Excel文件", "*.xls *.xlsx")]
)
for file in files:
if file not in self.file_listbox.get(0, tk.END):
self.file_listbox.insert(tk.END, file)
def remove_file(self):
selected = self.file_listbox.curselection()
if selected:
self.file_listbox.delete(selected[0])
def clear_files(self):
self.file_listbox.delete(0, tk.END)
def start_merge(self):
if self.file_listbox.size() == 0:
messagebox.showwarning("警告", "请至少添加一个Excel文件")
return
# 获取文件列表
files = self.file_listbox.get(0, tk.END)
# 获取合并选项
merge_type = self.merge_var.get()
exclude_cols = [col.strip() for col in self.exclude_cols.get().split(',') if col.strip()]
# 获取统计选项
do_summary = self.stats_vars["summary"].get()
do_count = self.stats_vars["count"].get()
try:
# 执行合并
if merge_type == "sheet":
result = self.merge_by_sheet(files)
elif merge_type == "block":
result = self.merge_by_block(files, exclude_cols)
elif merge_type == "column":
result = self.merge_by_column(files, exclude_cols)
else:
messagebox.showerror("错误", "无效的合并类型")
return
# 执行统计分析
stats_results = {}
if do_summary:
stats_results["summary"] = self.summary_statistics(result)
if do_count:
stats_results["count"] = self.count_statistics(result)
# 保存文件
self.save_results(result, stats_results, merge_type)
messagebox.showinfo("成功", "文件合并与分析完成!")
except Exception as e:
messagebox.showerror("错误", f"处理过程中发生错误:\n{str(e)}")
def merge_by_sheet(self, files):
"""工作页合并:每个文件作为单独的工作表"""
result = {}
for file in files:
# 获取文件名(不带扩展名)作为工作表名
filename = os.path.basename(file)
sheet_name = os.path.splitext(filename)[0]
# 读取Excel文件
if file.endswith('.xlsx'):
df = pd.read_excel(file, sheet_name=None)
for sheet, data in df.items():
result[f"{sheet_name}_{sheet}"] = data
else:
df = pd.read_excel(file)
result[sheet_name] = df
return result
def merge_by_block(self, files, exclude_cols):
"""区块合并:所有文件数据合并到同一个工作表"""
combined_df = pd.DataFrame()
for file in files:
# 读取Excel文件
if file.endswith('.xlsx'):
df_dict = pd.read_excel(file, sheet_name=None)
for df in df_dict.values():
# 排除指定列
df_filtered = df.drop(columns=exclude_cols, errors='ignore')
combined_df = pd.concat([combined_df, df_filtered], ignore_index=True)
else:
df = pd.read_excel(file)
df_filtered = df.drop(columns=exclude_cols, errors='ignore')
combined_df = pd.concat([combined_df, df_filtered], ignore_index=True)
return {"合并数据": combined_df}
def merge_by_column(self, files, exclude_cols):
"""按列合并:相同列的数值相加,字符串合并"""
# 确定所有文件的列
all_columns = set()
for file in files:
if file.endswith('.xlsx'):
df_dict = pd.read_excel(file, sheet_name=None)
for df in df_dict.values():
all_columns.update(df.columns)
else:
df = pd.read_excel(file)
all_columns.update(df.columns)
# 创建合并结果DataFrame
result_df = pd.DataFrame()
# 处理每个文件
for file in files:
if file.endswith('.xlsx'):
df_dict = pd.read_excel(file, sheet_name=None)
for df in df_dict.values():
self.merge_dataframe(result_df, df, exclude_cols)
else:
df = pd.read_excel(file)
self.merge_dataframe(result_df, df, exclude_cols)
return {"按列合并": result_df}
def merge_dataframe(self, result_df, df, exclude_cols):
"""合并单个DataFrame到结果中"""
if result_df.empty:
result_df = df.copy()
return
# 处理每列
for col in df.columns:
if col in exclude_cols:
continue
if col in result_df.columns:
# 数值列:相加
if np.issubdtype(df[col].dtype, np.number):
result_df[col] = result_df[col].add(df[col], fill_value=0)
# 字符串列:合并
elif df[col].dtype == object:
# 合并字符串,用顿号分隔
result_df[col] = result_df[col].astype(str) + "、" + df[col].astype(str)
# 去重
result_df[col] = result_df[col].apply(
lambda x: "、".join(sorted(set(x.split('、')), key=x.split('、').index))
)
else:
# 新列直接添加
result_df[col] = df[col]
def summary_statistics(self, data_dict):
"""生成汇总统计"""
stats_dict = {}
for sheet_name, df in data_dict.items():
# 只处理数值列
numeric_cols = df.select_dtypes(include=[np.number]).columns
if not numeric_cols.empty:
stats = df[numeric_cols].describe().T
stats_dict[sheet_name] = stats
return stats_dict
def count_statistics(self, data_dict):
"""生成计数统计"""
count_dict = {}
for sheet_name, df in data_dict.items():
# 只处理非数值列
non_numeric_cols = df.select_dtypes(exclude=[np.number]).columns
col_counts = {}
for col in non_numeric_cols:
counts = df[col].value_counts()
col_counts[col] = counts
if col_counts:
count_dict[sheet_name] = col_counts
return count_dict
def save_results(self, data_dict, stats_dict, merge_type):
"""保存结果到Excel文件"""
# 获取保存路径
file_path = filedialog.asksaveasfilename(
defaultextension=".xlsx",
filetypes=[("Excel文件", "*.xlsx"), ("Excel 97-2003 文件", "*.xls")]
)
if not file_path:
return # 用户取消保存
# 添加时间戳
base, ext = os.path.splitext(file_path)
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
new_file_path = f"{base}_{timestamp}{ext}"
# 根据文件类型选择引擎
engine = 'openpyxl' if new_file_path.endswith('.xlsx') else 'xlwt'
# 创建Excel writer
with pd.ExcelWriter(new_file_path, engine=engine) as writer:
# 保存合并的数据
for sheet_name, df in data_dict.items():
# 处理过长的sheet名称
safe_sheet_name = sheet_name[:31] # Excel限制31个字符
df.to_excel(writer, sheet_name=safe_sheet_name, index=False)
# 保存统计结果
if stats_dict:
# 汇总统计
if "summary" in stats_dict:
for sheet_name, stats_df in stats_dict["summary"].items():
safe_sheet_name = f"汇总_{sheet_name}"[:31]
stats_df.to_excel(writer, sheet_name=safe_sheet_name)
# 计数统计
if "count" in stats_dict:
for sheet_name, col_counts in stats_dict["count"].items():
for col_name, counts in col_counts.items():
safe_sheet_name = f"计数_{sheet_name}_{col_name}"[:31]
counts_df = counts.reset_index()
counts_df.columns = ['值', '计数']
counts_df.to_excel(writer, sheet_name=safe_sheet_name, index=False)
# 显示保存成功信息
messagebox.showinfo("保存成功", f"文件已保存至:\n{new_file_path}")
# 创建主窗口
if __name__ == "__main__":
root = tk.Tk()
root.title("Excel文件合并分析工具")
root.geometry("800x600")
app = FileMergeApp(root)
root.mainloop()
```
### 代码功能详细解释
#### 1. 界面布局与组件
- **标题区域**:显示应用名称和功能描述
- **文件选择区域**:
- 列表框显示已添加的Excel文件
- "添加文件"、"移除选中"、"清空列表"按钮
- **合并选项区域**:
- 指定列不合并输入框(默认A,B,C)
- 三种合并方式单选按钮(工作页合并、区块合并、按列合并)
- **统计分析区域**:
- 汇总统计和计数统计复选框
- **执行按钮**:"开始合并与分析"
#### 2. 核心功能实现
**文件操作函数**:
- `add_files()`: 打开文件对话框添加Excel文件
- `remove_file()`: 移除选中的文件
- `clear_files()`: 清空文件列表
**合并功能实现**:
1. **工作页合并(`merge_by_sheet`)**:
- 每个Excel文件作为一个单独的工作表
- 文件名作为工作表名
- 支持多工作表的Excel文件(.xlsx格式)
2. **区块合并(`merge_by_block`)**:
- 所有文件的数据合并到同一个工作表
- 可以排除指定列
- 自动处理不同文件的结构差异
3. **按列合并(`merge_by_column`)**:
- 数值列:相同列的数值相加
- 字符串列:去重后用顿号(、)连接
- 排除指定列不参与合并
**统计分析功能**:
1. **汇总统计(`summary_statistics`)**:
- 计算数值列的基本统计量(计数、均值、标准差、最小值、最大值等)
- 使用Pandas的describe()函数
2. **计数统计(`count_statistics`)**:
- 统计非数值列中每个值的出现次数
- 使用value_counts()函数
**文件保存功能**:
- 弹出保存对话框让用户选择保存位置
- 文件名自动添加时间戳
- 根据文件后缀选择适当的引擎(.xlsx用openpyxl,.xls用xlwt)
- 合并结果和统计结果分别保存在不同工作表
#### 3. 异常处理
- 添加了全面的异常捕获,防止程序崩溃
- 用户友好的错误提示信息
- 文件操作时的错误检查(如空文件列表)
### 使用说明
1. 添加需要合并的Excel文件(支持.xls和.xlsx格式)
2. 选择合并方式:
- 工作页合并:每个文件作为单独的工作表
- 区块合并:所有数据合并到同一工作表
- 按列合并:相同列的数据进行合并(数值相加,字符串连接)
3. 指定不需要合并的列(如A,B,C)
4. 选择需要的统计分析选项
5. 点击"开始合并与分析"按钮执行操作
6. 选择保存位置,文件将自动添加时间戳保存