
Python实战:构建一个功能强大的Excel/CSV批量转换工具 (PyQt5 GUI版)
在数据处理的工作流中,我们经常需要将Excel文件 (.xlsx) 或不同编码的CSV文件统一转换为标准的UTF-8 CSV格式,以便于后续的数据分析或导入数据库。
今天,我们将介绍如何使用 Python 和 PyQt5 构建一个带有图形用户界面 (GUI) 的批量转换工具。这个工具不仅支持批量处理,还能自动识别CSV编码,并且可以将Excel文件中的每个Sheet单独保存为CSV文件。
Github:Excel多sheet转换csv
Github:Excel多sheet转换csv
Github:Excel多sheet转换csv
✨ 主要功能
- 双模式支持:支持“文件夹批量转换”和“单个文件转换”两种模式。
- 多Sheet处理:对于Excel文件,自动读取所有Sheet,并允许用户选择需要转换的Sheet。每个Sheet将保存为独立的CSV文件。
- 智能编码识别:在处理CSV文件时,利用
chardet库自动检测源文件编码,并统一转换为 UTF-8,彻底解决乱码问题。 - 高性能读取:使用
python_calamine库读取Excel文件,速度快且内存占用低。 - 多线程处理:转换任务在后台线程运行,保证界面流畅,带有实时进度条和状态反馈。
- 拖拽支持:支持直接将文件或文件夹拖入窗口进行快速加载。
🛠️ 环境准备
在开始之前,我们需要安装以下 Python 库:
pip install PyQt5 chardet python-calamine
- PyQt5: 用于构建图形界面。
- chardet: 用于检测文本文件的编码格式。
- python-calamine: 一个基于 Rust 的高性能 Excel 读取库 (Calamine 的 Python 绑定)。
🧠 代码核心解析
1. 转换核心逻辑 (ConversionWorker)
为了防止转换过程中界面卡顿,我们继承 QThread 创建了一个工作线程类。
class ConversionWorker(QThread):
progress_signal = pyqtSignal(int, int) # 进度信号
finished_signal = pyqtSignal(int, int) # 完成信号
log_signal = pyqtSignal(str, str, str) # 日志信号
def run(self):
# ... 遍历任务列表 ...
for i, item in enumerate(self.items):
try:
if item['type'] == 'csv':
self.convert_csv(item['path'])
elif item['type'] == 'sheet':
self.convert_sheet(item['path'], item['sheet'])
# ... 发送成功信号 ...
except Exception as e:
# ... 发送失败信号 ...
self.progress_signal.emit(i + 1, total)
CSV 转换与编码修复
convert_csv 方法首先读取文件的前10000字节进行编码检测,然后以检测到的编码读取,并以 UTF-8 重新写入。
def convert_csv(self, file_path):
# 检测编码
with open(file_path, 'rb') as f:
raw = f.read(10000)
result = chardet.detect(raw)
encoding = result['encoding'] or 'utf-8'
# 转码保存
with open(file_path, 'r', encoding=encoding, newline='', errors='replace') as f_r:
reader = csv.reader(f_r)
# ... 写入到新文件 ...
Excel Sheet 转换
convert_sheet 方法利用 python_calamine 读取指定 Sheet 的数据。
def convert_sheet(self, file_path, sheet_name):
with open(file_path, 'rb') as f:
workbook = python_calamine.CalamineWorkbook.from_filelike(f)
sheet = workbook.get_sheet_by_name(sheet_name)
data = sheet.to_python() # 获取所有数据
# 生成安全的文件名 (去除非法字符)
safe_sheet_name = "".join([c for c in sheet_name if c.isalnum() or c in (' ', '-', '_')]).strip()
save_name = f"{base_name}_{safe_sheet_name}.csv"
# ... 写入 CSV ...
2. 图形界面 (ExcelConverterApp)
主窗口类继承自 QMainWindow,主要包含以下几个部分:
- 设置区:选择模式(文件夹/文件)、源路径、保存路径。
- 文件列表区:使用
QTreeWidget展示扫描到的文件。如果是Excel文件,还会作为父节点展开显示其下的所有Sheet。支持复选框选择部分转换。 - 操作区:进度条和“开始转换”按钮。
动态扫描与树形展示
scan_source 方法会遍历目录,找到所有 .csv and .xlsx 文件。对于 Excel 文件,它会预读取 Sheet 名称并添加到树形列表中。
def scan_source(self):
# ...
if f.lower().endswith('.xlsx'):
# 添加 Excel 文件节点
item = QTreeWidgetItem(self.tree)
# ...
# 读取 Sheet 并添加为子节点
with open(full_path, 'rb') as f:
workbook = python_calamine.CalamineWorkbook.from_filelike(f)
for sheet_name in workbook.sheet_names:
child = QTreeWidgetItem(item)
child.setText(0, sheet_name)
# ...
拖拽交互
通过重写 dragEnterEvent 和 dropEvent,实现了便捷的拖拽加载功能。代码会自动判断拖入的是文件还是文件夹,并自动切换对应的模式。
def dropEvent(self, event):
urls = event.mimeData().urls()
if urls:
path = urls[0].toLocalFile()
# 自动判断是文件还是文件夹,并切换模式
if os.path.isdir(path):
self.radio_folder.setChecked(True)
elif os.path.isfile(path):
self.radio_file.setChecked(True)
self.source_edit.setText(path)
self.scan_source() # 自动扫描
🚀 如何使用
- 运行脚本:
python Excel_to_CSV_conversion.py - 选择模式:默认是“转换文件夹”模式,如果你只想转换一个文件,选择“转换单个文件”。
- 选择源:点击“浏览”选择文件夹或文件,或者直接把文件/文件夹拖进窗口。
- 选择保存位置:指定转换后的 CSV 文件存放目录。
- 筛选项目:在下方的列表中,勾选你需要转换的文件或 Sheet。
- 开始转换:点击绿色按钮,等待进度条走完。
📝 总结
这个工具展示了如何将 Python 强大的数据处理能力(csv, python_calamine)与成熟的 GUI 框架 (PyQt5) 结合。它不仅是一个实用的工具,也是学习 PyQt5 界面开发、多线程编程以及文件处理的一个很好的实战案例。
你可以根据需要进一步扩展它,例如添加对 .xls (老版Excel) 的支持,或者增加数据清洗的功能。
Happy Coding!