在数据分析和处理过程中,数据格式的多样性常常带来不同的技术挑战。例如,历史数据或日志数据可能存储在 .his
格式的文件中。为了便于分析和操作,我们通常需要将这些文件转为更常见的表格格式如 Excel 文件(.xlsx
)。在本文中,我们将介绍一个基于 Python 和 PyQt5 的 GUI 工具,展示如何实现 .his
文件到 Excel 的批量转换,并实现动态 UI 美化和多线程功能。
功能特点
-
支持单个文件或文件夹批量转换:用户可以选择单个
.his
文件或包含多个.his
文件的文件夹进行批量转换。 - 动态 UI 美化:使用随机颜色和渐变背景实现界面美化,增强用户体验。
- 进度条显示和日志更新:转换过程中,进度条实时更新,且日志输出转换结果和状态信息。
- 多线程支持:避免阻塞 UI 界面,提高程序响应速度。
pandas
用于处理表格数据和生成 Excel 文件,而 PyQt5
用于实现 GUI 界面。
核心代码解析
以下是项目的完整代码,并逐步讲解关键部分。
1. UI 美化类 UIStyler
首先,我们定义了一个用于美化界面的类 UIStyler
,通过随机颜色和渐变背景实现一个视觉吸引力的用户界面。
import random
class UIStyler:
def __init__(self, widget):
self.widget = widget
self.apply_styles()
def apply_styles(self):
colors = ["#3498db", "#2ecc71", "#e74c3c", "#9b59b6", "#e67e22"]
random_color = random.choice(colors)
self.widget.setStyleSheet(f"""
QWidget {{
background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:1, stop:0 {random_color}, stop:1 #ffffff);
}}
QLabel {{
color: {random_color};
font-size: 18px;
font-weight: bold;
}}
QPushButton {{
background-color: {random_color};
color: white;
border-radius: 8px;
padding: 8px;
}}
QPushButton:hover {{
background-color: #2980b9;
}}
QProgressBar {{
border: 2px solid #dce4ec;
border-radius: 5px;
background: white;
color: black;
}}
QProgressBar::chunk {{
background-color: {random_color};
width: 20px;
}}
QTextEdit {{
border: 2px solid {random_color};
background-color: #f0f8ff;
color: black;
}}
""")
2. 数据转换类 ConverterThread
ConverterThread
使用 QThread
实现多线程操作,保证文件转换过程不会阻塞 UI 界面。通过 log_message
和 progress
信号,我们可以在 UI 中实时更新日志和进度条状态。
from PyQt5 import QtCore
import pandas as pd
class ConverterThread(QtCore.QThread):
progress = QtCore.pyqtSignal(int)
log_message = QtCore.pyqtSignal(str)
def __init__(self, input_path, output_folder, is_single_file):
super().__init__()
self.input_path = input_path
self.output_folder = output_folder
self.is_single_file = is_single_file
def run(self):
if self.is_single_file:
self.convert_single_his_to_excel(self.input_path)
else:
self.convert_folder_his_to_excel(self.input_path)
def convert_single_his_to_excel(self, his_file):
if not os.path.exists(self.output_folder):
os.makedirs(self.output_folder)
excel_file_path = os.path.join(self.output_folder, os.path.basename(his_file).replace('.his', '.xlsx'))
try:
with open(his_file, 'r', encoding='utf-8') as file:
lines = file.readlines()
header = lines[1].strip().split('\t')
data = [line.strip().split('\t') for line in lines[2:]]
df = pd.DataFrame(data, columns=header)
df.to_excel(excel_file_path, index=False)
self.log_message.emit(f"已转换: {his_file} -> {excel_file_path}")
except Exception as e:
self.log_message.emit(f"转换 {his_file} 失败: {e}")
def convert_folder_his_to_excel(self, input_folder):
files = [f for f in os.listdir(input_folder) if f.endswith('.his')]
total_files = len(files)
for i, filename in enumerate(files):
his_file_path = os.path.join(input_folder, filename)
self.convert_single_his_to_excel(his_file_path)
progress_value = int((i + 1) / total_files * 100)
self.progress.emit(progress_value)
3. 主界面类 HISConverterUI
HISConverterUI
是主界面类,包含文件选择、日志显示、进度条等界面元素。它负责与用户的交互。
from PyQt5 import QtWidgets, QtCore
from PyQt5.QtWidgets import QFileDialog, QMessageBox, QVBoxLayout, QHBoxLayout, QLabel, QProgressBar, QTextEdit
class HISConverterUI(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.init_ui()
def init_ui(self):
self.setWindowTitle('HIS文件转Excel工具')
self.setGeometry(100, 100, 500, 600)
main_layout = QVBoxLayout()
self.title_label = QLabel('HIS 文件转换工具', self)
self.title_label.setAlignment(QtCore.Qt.AlignCenter)
self.title_label.setStyleSheet("font-size: 18px; font-weight: bold; margin-bottom: 20px;")
main_layout.addWidget(self.title_label)
btn_layout = QHBoxLayout()
self.select_file_btn = QtWidgets.QPushButton('选择单个文件')
self.select_file_btn.clicked.connect(self.select_file)
btn_layout.addWidget(self.select_file_btn)
self.select_folder_btn = QtWidgets.QPushButton('选择文件夹')
self.select_folder_btn.clicked.connect(self.select_folder)
btn_layout.addWidget(self.select_folder_btn)
main_layout.addLayout(btn_layout)
self.progress_bar = QProgressBar(self)
main_layout.addWidget(self.progress_bar)
self.his_file_list = QTextEdit(self)
self.his_file_list.setReadOnly(True)
main_layout.addWidget(self.his_file_list)
self.convert_btn = QtWidgets.QPushButton('开始转换')
self.convert_btn.clicked.connect(self.start_conversion)
main_layout.addWidget(self.convert_btn)
self.add_footer_info(main_layout)
self.setLayout(main_layout)
self.ui_styler = UIStyler(self)
self.input_path = ''
self.output_folder = './output'
self.is_single_file = False
self.thread = None
def select_file(self):
file_path, _ = QFileDialog.getOpenFileName(self, "选择一个.his文件", "", "HIS Files (*.his);;All Files (*)")
if file_path:
self.input_path = file_path
self.is_single_file = True
self.his_file_list.clear()
self.his_file_list.append(f"已选择文件: {file_path}")
QMessageBox.information(self, "文件选择", f"已选择文件: {file_path}")
def select_folder(self):
folder_path = QFileDialog.getExistingDirectory(self, "选择文件夹")
if folder_path:
self.input_path = folder_path
self.is_single_file = False
self.show_his_files_in_folder(folder_path)
def start_conversion(self):
if self.input_path:
self.progress_bar.setValue(0)
self.thread = ConverterThread(self.input_path, self.output_folder, self.is_single_file)
self.thread.progress.connect(self.update_progress)
self.thread.log_message.connect(self.append_log)
self.thread.start()
QMessageBox.information(self, "转换进行中", "文件转换已开始!")
else:
QMessageBox.warning(self, "警告", "请先选择文件或文件夹!")
def update_progress(self, value):
self.progress_bar.setValue(value)
def append_log(self, message):
self.his_file_list.append(message)
def add_footer_info(self, layout):
self.footer_label = QLabel(self)
self.footer_label.setText("版权所有 © 2024 贵州安然智行科技有限责任公司\n联系方式: gzarzx@163.com | 电话: +085183865795")
self.footer_label.setAlignment(QtCore.Qt.AlignCenter)
self.footer_label.setStyleSheet("font-size: 12px; color: black; padding: 2px;")
layout.addWidget(self.footer_label)
总结
本文提供了一个完整的 .his
文件批量转换为 Excel 工具,并通过动态美化、进度显示、多线程等技术提升了用户体验。希望该工具能为您的数据处理工作提供便利。