吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1049|回复: 4
收起左侧

[Python 原创] 电商手工单格式转换小工具

  [复制链接]
Erdon7c 发表于 2026-3-2 14:14
一个做电商的朋友不想用太多的打单ERP软件,就拜托我做这个手工打单格式转换的软件
就是一个非常小的功能,把它分享出来也顺便做一下记录,如果有需要的朋友可以拿去
大部分朋友应该用不到,所以这里就不发打包好的文件了,下面直接展示源码


只支持pdd和tb平台的手工单表格的互相转换
1.png
简洁模式就是只转换了打单需要的必要项

代码可能有点繁琐,是考虑到给朋友更好地操作体验,直接把源码放出来
[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_())

免费评分

参与人数 2吾爱币 +8 热心值 +1 收起 理由
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
wwzzdy + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

hechenxiao 发表于 2026-3-7 18:19
这个不错,支持一下
yxf515321 发表于 2026-3-8 21:30
VL008 发表于 2026-3-30 17:54
Alliswell9527 发表于 2026-4-20 09:31
又没有一键铺货的工具啊,从1688到其他平台的
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-7-15 02:27

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表