[Python] 纯文本查看 复制代码
import sys
import os
import pandas as pd
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
QPushButton, QLabel, QComboBox, QFileDialog, QMessageBox, QStatusBar
)
from PyQt5.QtCore import Qt
class OrderConverter(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('手工单转换工具')
self.setGeometry(100, 100, 800, 400)
# 中央部件
central_widget = QWidget()
self.setCentralWidget(central_widget)
# 主布局
main_layout = QVBoxLayout(central_widget)
# 转换方式选择
convert_layout = QHBoxLayout()
convert_label = QLabel('转换方式:')
self.convert_combo = QComboBox()
self.convert_combo.addItems(['淘宝转拼多多', '拼多多转淘宝'])
self.convert_combo.setCurrentIndex(0) # 默认淘宝转拼多多
# 转换模式选择
mode_label = QLabel('转换模式:')
self.mode_combo = QComboBox()
self.mode_combo.addItems(['简洁模式', '全转换'])
self.mode_combo.setCurrentIndex(0) # 默认简洁模式
convert_layout.addWidget(convert_label)
convert_layout.addWidget(self.convert_combo)
convert_layout.addWidget(mode_label)
convert_layout.addWidget(self.mode_combo)
convert_layout.addStretch()
main_layout.addLayout(convert_layout)
# 文件选择
file_layout = QHBoxLayout()
self.file_label = QLabel('未选择文件')
select_button = QPushButton('选择文件')
select_button.clicked.connect(self.select_file)
file_layout.addWidget(self.file_label)
file_layout.addWidget(select_button)
main_layout.addLayout(file_layout)
# 操作按钮
button_layout = QHBoxLayout()
self.convert_export_button = QPushButton('转换并导出')
self.convert_export_button.clicked.connect(self.convert_and_export)
self.export_unconverted_button = QPushButton('导出未转换')
self.export_unconverted_button.clicked.connect(self.export_unconverted)
self.export_unconverted_button.setEnabled(False)
button_layout.addWidget(self.convert_export_button)
button_layout.addWidget(self.export_unconverted_button)
main_layout.addLayout(button_layout)
# 状态栏
self.status_bar = QStatusBar()
self.setStatusBar(self.status_bar)
# 数据存储
self.file_path = None
self.df = None
self.converted_df = None
self.unconverted_df = None
self.conversion_count = 0
def detect_file_format(self, df):
# 检测文件格式
columns = df.columns.tolist()
# 淘宝格式特征
taobao_columns = ['订单编号', '收货人姓名', '收货地址', '联系手机', '商品标题', '商品属性SKU', '宝贝总数量']
taobao_match = sum(1 for col in columns if any(taobao_col in col for taobao_col in taobao_columns))
# 拼多多格式特征
pdd_columns = ['收件人', '手机号', '收货地址', '平台订单号', '商品信息', '规格信息', '商品数量']
pdd_match = sum(1 for col in columns if any(pdd_col in col for pdd_col in pdd_columns))
if taobao_match > pdd_match:
return '淘宝'
elif pdd_match > taobao_match:
return '拼多多'
else:
return '未知'
def select_file(self):
options = QFileDialog.Options()
file_path, _ = QFileDialog.getOpenFileName(
self, "选择需要转换的文件", "", "Excel文件 (*.xlsx *.xls);;CSV文件 (*.csv)", options=options
)
if file_path:
self.file_path = file_path
self.file_label.setText(os.path.basename(file_path))
self.status_bar.showMessage(f'已选择文件: {os.path.basename(file_path)}')
# 读取文件
try:
if file_path.endswith('.csv'):
self.df = pd.read_csv(file_path)
else:
self.df = pd.read_excel(file_path)
# 检测文件格式
file_format = self.detect_file_format(self.df)
if file_format == '未知':
QMessageBox.warning(self, '警告', '文件格式错误,不是淘宝或拼多多格式')
self.file_path = None
self.file_label.setText('未选择文件')
return
# 检查转换方式是否匹配
convert_type = self.convert_combo.currentText()
if (convert_type == '淘宝转拼多多' and file_format != '淘宝') or \
(convert_type == '拼多多转淘宝' and file_format != '拼多多'):
reply = QMessageBox.question(
self, '转换方式确认',
f'您选择的文件是{file_format}格式,但选择的转换方式是{convert_type}。\n是否继续使用当前转换方式?',
QMessageBox.Yes | QMessageBox.No, QMessageBox.No
)
if reply == QMessageBox.No:
self.file_path = None
self.file_label.setText('未选择文件')
return
self.status_bar.showMessage(f'文件读取成功,共 {len(self.df)} 条记录')
except Exception as e:
QMessageBox.critical(self, '错误', f'文件读取失败: {str(e)}')
self.file_path = None
self.file_label.setText('未选择文件')
def convert_and_export(self):
if not self.file_path or self.df is None:
QMessageBox.warning(self, '警告', '请先选择文件')
return
convert_type = self.convert_combo.currentText()
convert_mode = self.mode_combo.currentText()
total_count = len(self.df)
try:
if convert_type == '淘宝转拼多多':
self.convert_taobao_to_pdd(convert_mode)
suffix = 't-p'
else:
self.convert_pdd_to_taobao(convert_mode)
suffix = 'p-t'
unconverted_count = len(self.unconverted_df)
self.export_unconverted_button.setEnabled(True)
# 显示转换统计
QMessageBox.information(
self, '转换统计',
f'共: {total_count} 条\n已转换: {self.conversion_count} 条\n未转换: {unconverted_count} 条'
)
# 自动导出转换结果
if self.converted_df is not None and len(self.converted_df) > 0:
# 生成导出文件名
base_name = os.path.basename(self.file_path)
name_without_ext = os.path.splitext(base_name)[0]
ext = os.path.splitext(base_name)[1]
if convert_mode == '全转换':
export_file_name = f"{name_without_ext}_已全转换{suffix}{ext}"
else:
export_file_name = f"{name_without_ext}_已转换{suffix}{ext}"
export_path = os.path.join(os.path.dirname(self.file_path), export_file_name)
try:
if ext.lower() == '.csv':
self.converted_df.to_csv(export_path, index=False, encoding='utf-8-sig')
else:
self.converted_df.to_excel(export_path, index=False)
QMessageBox.information(self, '成功', f'转换结果已导出到: {export_path}')
self.status_bar.showMessage(f'转换结果已导出,共 {len(self.converted_df)} 条记录')
except Exception as e:
QMessageBox.critical(self, '错误', f'导出失败: {str(e)}')
self.status_bar.showMessage(f'转换完成,成功转换 {self.conversion_count} 条记录')
except Exception as e:
QMessageBox.critical(self, '错误', f'转换失败: {str(e)}')
def convert_taobao_to_pdd(self, convert_mode):
# 淘宝表头:订单编号,收货人姓名,收货地址,联系手机,商品标题,商品属性SKU,宝贝总数量
# 拼多多表头:收件人(必填),手机号(必填),收货地址(必填),平台订单号(非必填),商品信息(非必填),规格信息(非必填),商品数量(非必填)
# 创建新的DataFrame
new_columns = ['收件人(必填)', '手机号(必填)', '收货地址(必填)', '平台订单号(非必填)', '商品信息(非必填)', '规格信息(非必填)', '商品数量(非必填)']
self.converted_df = pd.DataFrame(columns=new_columns)
self.unconverted_df = self.df.copy()
# 转换逻辑
valid_count = 0
converted_rows = []
for idx, row in self.df.iterrows():
# 检查必填字段
if pd.notna(row.get('收货人姓名')) and pd.notna(row.get('联系手机')) and pd.notna(row.get('收货地址')) and pd.notna(row.get('商品属性SKU')):
if convert_mode == '简洁模式':
new_row = {
'收件人(必填)': row.get('收货人姓名'),
'手机号(必填)': row.get('联系手机'),
'收货地址(必填)': row.get('收货地址'),
'商品信息(非必填)': row.get('商品属性SKU'),
'平台订单号(非必填)': '',
'规格信息(非必填)': '',
'商品数量(非必填)': ''
}
else: # 全转换
new_row = {
'收件人(必填)': row.get('收货人姓名'),
'手机号(必填)': row.get('联系手机'),
'收货地址(必填)': row.get('收货地址'),
'平台订单号(非必填)': row.get('订单编号'),
'商品信息(非必填)': row.get('商品属性SKU'),
'规格信息(非必填)': row.get('商品属性SKU'),
'商品数量(非必填)': row.get('宝贝总数量')
}
converted_rows.append(new_row)
valid_count += 1
else:
# 保留未转换的行
pass
# 使用pd.concat替代append
if converted_rows:
self.converted_df = pd.concat([self.converted_df, pd.DataFrame(converted_rows)], ignore_index=True)
# 更新未转换数据
self.unconverted_df = self.df.iloc[[i for i in range(len(self.df)) if i not in self.converted_df.index]]
self.conversion_count = valid_count
def convert_pdd_to_taobao(self, convert_mode):
# 拼多多表头:收件人(必填),手机号(必填),收货地址(必填),平台订单号(非必填),商品信息(非必填),规格信息(非必填),商品数量(非必填)
# 淘宝表头:订单编号,收货人姓名,收货地址,联系手机,商品标题,商品属性SKU,宝贝总数量
# 创建新的DataFrame
new_columns = ['订单编号', '收货人姓名', '收货地址', '联系手机', '商品标题', '商品属性SKU', '宝贝总数量']
self.converted_df = pd.DataFrame(columns=new_columns)
self.unconverted_df = self.df.copy()
# 转换逻辑
valid_count = 0
converted_rows = []
for idx, row in self.df.iterrows():
if convert_mode == '简洁模式':
new_row = {
'收货人姓名': row.get('收件人(必填)'),
'联系手机': row.get('手机号(必填)'),
'收货地址': row.get('收货地址(必填)'),
'商品属性SKU': row.get('规格信息(非必填)') or row.get('商品信息(非必填)'),
'订单编号': '',
'商品标题': '',
'宝贝总数量': ''
}
else: # 全转换
new_row = {
'订单编号': row.get('平台订单号(非必填)'),
'收货人姓名': row.get('收件人(必填)'),
'收货地址': row.get('收货地址(必填)'),
'联系手机': row.get('手机号(必填)'),
'商品标题': row.get('商品信息(非必填)'),
'商品属性SKU': row.get('规格信息(非必填)') or row.get('商品信息(非必填)'),
'宝贝总数量': row.get('商品数量(非必填)')
}
# 检查是否有有效信息
if any(pd.notna(v) for v in new_row.values()):
converted_rows.append(new_row)
valid_count += 1
else:
# 保留未转换的行
pass
# 使用pd.concat替代append
if converted_rows:
self.converted_df = pd.concat([self.converted_df, pd.DataFrame(converted_rows)], ignore_index=True)
# 更新未转换数据
self.unconverted_df = self.df.iloc[[i for i in range(len(self.df)) if i not in self.converted_df.index]]
self.conversion_count = valid_count
def export_unconverted(self):
if self.unconverted_df is None or len(self.unconverted_df) == 0:
QMessageBox.warning(self, '警告', '没有未转换的记录')
return
options = QFileDialog.Options()
file_path, _ = QFileDialog.getSaveFileName(
self, "保存未转换记录", "", "Excel文件 (*.xlsx);;CSV文件 (*.csv)", options=options
)
if file_path:
try:
if file_path.endswith('.csv'):
self.unconverted_df.to_csv(file_path, index=False, encoding='utf-8-sig')
else:
self.unconverted_df.to_excel(file_path, index=False)
QMessageBox.information(self, '成功', f'未转换记录已导出到: {file_path}')
self.status_bar.showMessage(f'未转换记录已导出,共 {len(self.unconverted_df)} 条记录')
except Exception as e:
QMessageBox.critical(self, '错误', f'导出失败: {str(e)}')
if __name__ == '__main__':
app = QApplication(sys.argv)
window = OrderConverter()
window.show()
sys.exit(app.exec_())