闲来无事,写个给表格分组或合并的小工具

查看 53|回复 0
作者:tkdahai   
玩python 时间也不长,有时办公要用到EXCEL里不断重复的分组,合并数据,ctrl+v,ctrl+c ,搞的手指发麻,于是就抽空搞了这么个小工具,用的是pandas,网上,同时也借用了一些大佬的作品,揉合而成。放在这与大家共勉,一起学习,bug不断,欢迎留下脚印。
[Python] 纯文本查看 复制代码      
from PyQt5.QtNetwork import QLocalSocket, QLocalServer  # 实例化程式,只许一个运行
from PyQt5 import QtCore
from PyQt5.QtGui import QTextCursor, QColor
from PyQt5.QtWidgets import *
#from PyQt5.QtWidgets import QApplication, QFileDialog
import sys,os
import pandas as pd
from PyQt5.QtWidgets import QApplication, QComboBox, QDialog, QVBoxLayout, QLabel, QPushButton,QFileDialog
from win32com.client import Dispatch
import openpyxl
class ComboCheckBox(QComboBox):
    def __init__(self, items: list):
         """
         initial function
         :param items: the items of the list
         """
         super(ComboCheckBox, self).__init__()
         self.items = ["全选"] + items  # items list
         self.box_list = []  # selected items
         self.text = QLineEdit()  # use to selected items
         self.state = 0  # use to record state
         q = QListWidget()
         for i in range(len(self.items)):
             self.box_list.append(QCheckBox())
             self.box_list[i].setText(self.items[i])
             item = QListWidgetItem(q)
             q.setItemWidget(item, self.box_list[i])
             if i == 0:
                 self.box_list[i].stateChanged.connect(self.all_selected)
             else:
                 self.box_list[i].stateChanged.connect(self.show_selected)
         q.setStyleSheet("font-size: 30px; font-weight: bold; height: 50px; margin-left: 15px")
         #self.setStyleSheet("width: 300px; height: 50px; font-size: 21px; font-weight: bold")
         self.text.setReadOnly(True)
         self.setLineEdit(self.text)
         self.setModel(q.model())
         self.setView(q)
    def all_selected(self):
         """
         decide whether to check all
         :return:
         """
         # change state
         if self.state == 0:
             self.state = 1
             for i in range(1, len(self.items)):
                 self.box_list[i].setChecked(True)
         else:
             self.state = 0
             for i in range(1, len(self.items)):
                 self.box_list[i].setChecked(False)
         self.show_selected()
    def get_selected(self) -> list:
         """
         get selected items
         :return:
         """
         ret = []
         for i in range(1, len(self.items)):
             if self.box_list[i].isChecked():
                 ret.append(self.box_list[i].text())
         return ret
    def show_selected(self):
         """
         show selected items
         :return:
         """
         self.text.clear()
         ret = '; '.join(self.get_selected())
         self.text.setText(ret)
class MyDialog(QDialog):
    def __init__(self):
        #定义列名列表大A-Z
        col_list = list(map(chr, range(65, 91)))
        self.file_name = ''
        self.output = 'output.xlsx'  # 输出OUT表
        #self.win__dir = os.environ['HOMEPATH'] + '//' + 'Desktop'  # 打开文件默认活动桌面
       # RC = read.read_config(self=read)  # 传总参,导入配置文件,为后面的参数做基础
        # 传参,导入压缩图片类和其参数(参数读取自配置文件)
        # self.Result = result.Compress_img(RC.get('api', 'rate'), RC.get('api', 'quality'), RC.get('api', 'way'))
        # self.url = RC.get('api', 'url')  #从配置文件提参数get示例
        ####sytext水印文字
        # sytext = RC.get('sylogo','sytime')+'\n'+RC.get('sylogo', 'syadd')+'\n'+RC.get('sylogo', 'syen')
        super().__init__()
        """控件的创建和布局"""
        ########1。先创建按键筐
        #self.lineEdit = QLineEdit("")  # 路经显示
        self.textEdit = QTextEdit()  # 富文本显示
        ###################################
        self.pushExcel = QLabel("Excel表:")
        #self.pushExcel.setMinimumWidth(100)
        self.lineExcel = QLineEdit("")  # 路经显示
        #self.lineExcel.setMinimumWidth(100)
        self.selExcel = QPushButton("请选择")
        #self.selExcel.setMinimumWidth(100)
        ################################
        self.pushGroup = QLabel("分组列: ")
        #self.pushGroup.setMinimumWidth(50)
        #self.listGroup = QLineEdit("")  # 路经显示
        self.listGroup = ComboCheckBox(col_list)
       # self.listGroup.setMinimumWidth(300)
        ########################
        self.pushMerge = QLabel("合并列: ")
        #self.pushMerge.setMinimumWidth(50)
        #self.listMerge = QLineEdit("")  # 路经显示
        self.listMerge = ComboCheckBox(col_list)
        #self.listMerge.setMinimumWidth(50)
        #########################
        self.pushGO = QPushButton("开始处理")
        #self.pushGO.setMinimumWidth(50)
        self.pushSee = QPushButton("结果查询")
        #self.pushSee.setMinimumWidth(50)
        ######################2.创建第一排水平表单布局
        self.hflo0 = QFormLayout()  # 创建水平表单布局
        self.hflo1 = QFormLayout()  # 创建水平表单布局
        self.hflo2 = QFormLayout()  # 创建水平表单布局
        ######################2.1创建第二排水平表单布局
        self.hflo11 = QFormLayout()  # 创建水平表单布局
        self.hflo12 = QFormLayout()  # 创建水平表单布局
        ######################2.1创建第三排水平表单布局
        self.hflo21 = QFormLayout()  # 创建水平表单布局
        self.hflo22 = QFormLayout()  # 创建水平表单布局
        ######################2.1创建第四排水平表单布局
        self.hflo31 = QFormLayout()  # 创建水平表单布局
        self.hflo32 = QFormLayout()  # 创建水平表单布局
        ###############3.将第一排水平表单和按键结合
        self.hflo0.addRow(self.pushExcel)
        self.hflo1.addRow(self.lineExcel)
        self.hflo2.addRow(self.selExcel)
        ###############3.1将第二排水平表单和按键结合
        self.hflo11.addRow(self.pushGroup)
        self.hflo12.addRow(self.listGroup)
        ###############3.1将第三排水平表单和按键结合
        self.hflo21.addRow(self.pushMerge)
        self.hflo22.addRow(self.listMerge)
        ###############3.1将第4排水平表单和按键结合
        self.hflo31.addRow(self.pushGO)
        self.hflo32.addRow(self.pushSee)
        ################4.创建垂直表单布局 路经显示和富文本
        self.vflo = QFormLayout()  # 创建垂直表单布局 路经显示和富文本
        #self.vflo.addRow(self.lineEdit)
        self.vflo.addRow(self.textEdit)
        ################5. 添加水平布局第一排(也可以再加一排)
        self.hbox = QHBoxLayout()
        self.hbox.addLayout(self.hflo0)
        self.hbox.addLayout(self.hflo1)
        self.hbox.addLayout(self.hflo2)
        self.hbox.setSpacing(0)
        ################5.1 添加水平布局第二排(也可以再加一排)
        self.hbox2 = QHBoxLayout()
        self.hbox2.addLayout(self.hflo11)
        self.hbox2.addLayout(self.hflo12)
        self.hbox2.setSpacing(0)
        ################5.1 添加水平布局第三排(也可以再加一排)
        self.hbox3 = QHBoxLayout()
        self.hbox3.addLayout(self.hflo21)
        self.hbox3.addLayout(self.hflo22)
        self.hbox3.setSpacing(0)
        ################5.1 添加水平布局第4排(也可以再加一排)
        self.hbox4 = QHBoxLayout()
        self.hbox4.addLayout(self.hflo31)
        self.hbox4.addLayout(self.hflo32)
        self.hbox4.setSpacing(0)
        ###############6. 添加垂直布局
        self.vbox = QVBoxLayout()
        self.vbox.addLayout(self.vflo)
        # self.vbox.addLayout( self.vfl1 )
        ###################### 添加布局
        vlayout = QVBoxLayout()  # 整个程序的灵魂,将QVBoxLayout改成QHBoxLayout可以改变hbox和vbox的布局从垂直布局到水平布局
        vlayout.addLayout(self.hbox)  # 组合第一排
        vlayout.addLayout(self.hbox2)  # 组合第二排
        vlayout.addLayout(self.hbox3)  # 组合第二排
        vlayout.addLayout(self.hbox4)  # 组合第二排
        vlayout.addLayout(self.vbox)  # 组合第三列
        self.setLayout(vlayout)
        self.textEdit.setFontPointSize(15)  # 设置富文本的字体大小
        self.textEdit.setReadOnly(False)  # 设置为只读、可写
        self.textEdit.setTextBackgroundColor(QColor(80, 80, 80))  # 设置文字背景色
        self.textEdit.setTextColor(QColor(200, 220, 180))  # 设置文字颜色
        ################################################
        """信号绑定"""  ###信号绑定必须也函数一一对应,否则不显示窗口
        self.selExcel.clicked.connect(self.choose_file)  # 选择文件
        self.pushGO.clicked.connect(self.load_file)  #执行文件
        self.pushSee.clicked.connect(self.load_See)  #查绚结果
        # # self.jsGO.clicked.connect(self.__onClickejyGO)    #极速录单
        # self.chromedebug.clicked.connect(self.__chromedebug)  # 谷歌浏览器
        # self.pushIMGSY.clicked.connect(self.__pushIMGSY)  # 图片压缩
        # #self.lineEdit.clicked.connect(self.__lineEdit)  # 图片压缩
        # self.lineEdit.returnPressed.connect(self.__lineEdit)#路经显示回车激活函数
    #####################################################################
    def choose_file(self):
        try:
            '''选择EXCEL文件'''
            options = QFileDialog.Options()
            options |= QFileDialog.DontUseNativeDialog
            file_name, _ = QFileDialog.getOpenFileName(self, "选择文件", "", "Excel files (*.xlsx)", options=options)
            if file_name:
               # print(file_name)
                self.lineExcel.setText(file_name)
                self.file_name = file_name
                df = pd.read_excel(self.file_name)
                # 读取原表的列名并生成列表
                list_df = list(df)
                # 以原列列表为基础,生成大写字母的同量列表
                list_dfmap = list(map(chr, range(65, 65 + len(list_df))))
                # 交两个列表合并生成新的对应字典,方便后面以大写字母调用列名
                Clist = dict(zip(list_dfmap, list_df))
                print(Clist)
                self.textEdit.setText('提示:从下面的对应关系上选择分组与合并列\n'  + str(Clist))
        except:
            print('文件选择出错')
    def load_file(self):
        try:
            self.close_excel_file(self.output)
            '''加载EXCEL文件,写入列表名'''
            print('开始载入列名')
            # 读取Excel文件
            if len(self.file_name) = 1:
                    QMessageBox.information(self, '提示', "分组与合并列不能有重合{}".format(list_c))
                else:
                    print('开始进行分组合并操作')
                    if len(see_Group) >=1:
                        print('分组列非空,执行下面代码')
                        if len(see_Merge) >=1:
                            print('合并列非空,执行分组合并任务')
                            # 生成合并字典式,value_y为合并里面的代码,只能用字典
                            value_y = {'one': lambda x: '、'.join(set(x))}
                            # print(value_y)
                            print(value_y)
                            # 通常用来初始化字典, 设置value的默认值,
                            value = dict.fromkeys(hb_value, value_y.get('one'))
                            # 按照hb_name列进行分组,并将hb_value里的所有列分别合并为一个逗号分隔的字符串,同时去重,转换为DataFrame
                         #   result = df.groupby(hb_name).agg(value)
                            result = df.groupby(hb_name).agg(value)
                            # 将原数据按名子分组
                            df1 = df.drop_duplicates(subset=hb_name)
                            # 将result与原始数据按照name列进行合并,保留其他列的内容
                            result = pd.merge(df1.drop(columns=hb_value).drop_duplicates(), result, on=hb_name)
                            # 按最原表的列顺序展示新表,list_df为原表的列表
                            result = result[list_df]
                            print(result)
                            result.to_excel(self.output, index=False)
                            QMessageBox.information(self, '提示', "以{}分组,以{}合并完成".format(hb_name,hb_value))
                        else:
                            print('合并列为空,单执行分组任务')
                            # 将原数据按名子分组
                            hb_Group = df.drop_duplicates(subset=hb_name)
                            print(hb_Group)
                            hb_Group.to_excel(self.output, index=False)
                            QMessageBox.information(self, '提示', "以{}分组完成".format(hb_name))
                    else:
                        print('分组列为空,请选择')
                        QMessageBox.information(self, '提示', "分组列为空,请选择")
        except:
            print('执行分组合并出错')
    def load_See(self):
        try:
            #查询结果
            print("查询结果开始")
            # 打开查询到的数据表格
            print(self.output)
            os.startfile(self.output)
            #self.close_excel_file(self.output)  # 关掉OUT表
        except:
            print('查询结果出错')
    def close_excel_file(self,closeexcel):
        #关掉指定的表格文件
        xlApp = Dispatch('Excel.Application')
        xlApp.DisplayAlerts = False  # 设置不显示警告和消息框
        # xlBook = xlApp.Workbooks.Open(file)
        workbooks_n = xlApp.Workbooks.Count
        print(f'已打开工作簿的数量为:{workbooks_n}个')
        if workbooks_n

布局, 表单

您需要登录后才可以回帖 登录 | 立即注册

返回顶部