榴榴杂谈

[编程分享]用Python智能统计合并Excel数据,轻松搞定无脑统计等搬砖工作[3P]

榴榴杂谈 2023-04-05 08:57 出处:网络 作者:三民诛仙编辑:@榴榴
        最近人工智能聊天机器人很火,比起AI,好多搬砖同志,还在苦苦复制张贴EXCEL表格,做统计工作。比如,一个很大的表格,需各单位填写相关数据,然后一个部门汇总,每个单位填写只筛选自己主管事项,最后汇总的,需要按筛选一个一个对应复制粘贴,最后眼睛看花了,还容易粘错。在网上找了一些类似工具,不是收费,就是使用不顺手。有些单位还无法连接外网,无法下载。
        社区里面应该有不少干类似的搬砖活吧?
                                    汇总表格
序号        事件          责任单位          解决情况    闭环情况
1          XXX            单位1                  待填写
2          XXX            单位2             
3          XXX            单位2             
4          XXX            单位3                    待填写
……
99        XXX            单位6                  待填写
……
999        XXX          单位9              待填写
……

        干过上面操蛋的事后,开始琢磨怎么方便汇总,最后找到python,还有对应的xls操作库,开始自己写python脚本,没有GUI界面,又自己恶补了gui编程,使用wxFormBuilder 建立界面,自动生成GUI的代码,加入合并,完成了自己数据合并工具。(代码附后)

[编程分享]用Python智能统计合并Excel数据,轻松搞定无脑统计等搬砖工作[3P] 

[编程分享]用Python智能统计合并Excel数据,轻松搞定无脑统计等搬砖工作[3P] 

[编程分享]用Python智能统计合并Excel数据,轻松搞定无脑统计等搬砖工作[3P] 

上面这个还是我写比较原始的,没有加 多线程防界面卡死,日志输出框没有直接集成到GUI界面。

        Python的 xls操作库 不仅仅可以用合并数据,还有 对数据表格的内容进行分析,比如后面我的应用场景:
        1)web页面中有 部门的很多项工作,比如3000项,都有对应的最新工作进展,但是有60项是,一个单位的。发web管理系统的没有对应的单位划分可以进行筛选,我手头上有我的单位的60项工作内容的xls,内容又没有规律是我单位,以前是在系统中导出3000项的最新进展xls,采用查找的方式找出 单位的60项工作内容。
        解决方式:使用python 读取 60项工作内容,在 3000项中自动查找到该工作项目,再提取 最新进展。最后 输出 60项工作内容带最新进展的内容。

        2)一项表格中,内容需要导入WEB系统中数据库,web系统设置了一些原则,不符合该原则的数据表格,会提示错误,并阻止导入。  如果该系统一次把所有错误都报出,在第几行、几列,然后导入人员自己修改,还挺方便。但是,做系统需求的人,不是干具体活的人。如果数据只有几十行,填写人员熟悉规则,数据填写了,还不会出现太多的不符合规则的数据。一旦数据量大了,成百上千行后,特别是填写数据的人员又不太熟悉规则,整个几十上百处的不符合规则的数据,需要一次一次导入,反复让系统提示错误行、列。系统验收付款完成后,又不再修改了,作为普通的搬砖人员,只能忍受2B系统的设置。
解决方式:用python读取数据,规则写入python代码中,将每个数据与规则对比分析,一次性查找出所有的不符合规则的数据。

        工作中,还有其他类似的活,也使用了python进行了简化。就不在一一细说了。
        坛友有没有类似 无脑的活,可以交给python干的,也可以交流一下。我也可以看看能不能实现。
        有编程基础的可以参考我的代码自己修改。或者我有空了也可以帮忙修改一下,看看能不能实现。可以实现了,?给点USD作为报酬。
        环境:python3.6 +  openpyxl  wx 等库。(怎么使用python,请自行搜索,我也可以分享我编译好的exe文件,不知道能不能发分享链接)
1)  Hebing_main1.12.py
複製代码
#-------------------------------------------------------------------------------
# Name:        合并文件
# Purpose:
#
# Author:      Sanmin
#
# Created:    07-06-2020
# Copyright:  (c) Sanmin 2020
# Licence:    <your licence>
#-------------------------------------------------------------------------------

import wx
import openpyxl
import gc
import datetime
import logging
#import the newly created GUI file
import Heb
import time


class CalcFrame(Heb.HeBing):
    def __init__(self,parent):
        Heb.HeBing.__init__(self,parent)

#按键事件触发函数
    def yunxing(self, event):
        global huiz_file
        global heb_flie
        global huiz_sheet
        global heb_sheet
        huiz_file = str(self.m_textCtrl_hzfile.GetValue())
        heb_flie = str(self.m_textCtrl_huibfile.GetValue())

        huiz_sheet = int(self.m_textCtrl9.GetValue()) - 1
        heb_sheet = int(self.m_textCtrl10.GetValue()) - 1

        workbook1 = openpyxl.load_workbook(huiz_file)
        workbook2 = openpyxl.load_workbook(heb_flie,data_only=True)
        ws1 = workbook1.worksheets[huiz_sheet]
        ws2 = workbook2.worksheets[heb_sheet]
        nowTime = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S')
        log_flie = huiz_file.rstrip('.xlsx') + '_合并情况日志_' + nowTime + ".txt"
        logging.basicConfig(filename=log_flie,
                            format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
                            level=logging.DEBUG)
        i1 = ws1.max_row
        j1 = ws1.max_column
        print('表格中共 %d 行,%d列。' % (i1,j1))
        logging.info('表格中共 %d 行,%d列。' % (i1,j1))
        time.sleep(1)
        print('开始合并数据,程序可能出现假死现象,请耐心等待完成……')
        time.sleep(1)
        M_gauge_Value = 0
        for i in range(2, i1+1):
            for j in range(2, j1+1):
                if ws1.cell(row=i, column=j).value == None and  ws2.cell(row=i, column=j).value != None:
                    ws1.cell(row=i, column=j).value = ws2.cell(row=i, column=j).value
                    print('第 %d 行 %d 列内容[ %s ]填入汇总表!' % (i,j,ws2.cell(row=i, column=j).value))
                    logging.info('第 %d 行 %d 列内容[ %s ]填入汇总表!' % (i,j,ws2.cell(row=i, column=j).value))

            if M_gauge_Value != int(i / i1 * 100):
                self.m_gauge2.SetValue(M_gauge_Value)
            M_gauge_Value = int(i / i1 * 100)
            print('合并任务完成度:%d / 100'%(M_gauge_Value))
        self.m_gauge2.SetValue(M_gauge_Value)
        Db_flie = huiz_file.rstrip('.xlsx') + '_Merge_by_Python_' +  nowTime + ".xlsx"
        print('保存文件中……')
        time.sleep(2)
        workbook1.save(Db_flie)  # 保存修改
        del workbook1, workbook2  # wb为打开的工作表
        gc.collect()  # 马上内存就释放了。
        self.m_textCtrl_JieG2.SetValue(str('查看汇总文件目录下 带Merge_by_Python后缀文件和日志文件!'))
        print('查看汇总文件目录下 汇总文件:%s !'%(Db_flie))
        print('查看汇总文件目录下 日志文件:%s !'%(log_flie))

def main():
    a = """
                          **  **                           
                          **  **                           
      *****o  **    *o o*o* ******    *o-*    **oo*     
      **    *o  o*  **  o*  **  o*  o*    :*  **  +*   
      **  :**  o**o    **  **  +*  :*  -*  o*  -o 
      **ooo      **    *oo o+  ::.    o=*    *o  -o     
      *o        o*                                                                                                                   

帮助>>
    >>只支持两张表格行数量相同。
    >>分发给各单位填写的人员不能删除表格的内容,自能使用筛选功能,
      然后在要求填写的空白地方进行填报。
    >>为了方便汇总,在填写要求中一定要备注不能删除表格行数内容。   
        """
    print(a)
    app = wx.App(False)
    frame = CalcFrame(None)
    frame.Show(True)
    #start the applications
    app.MainLoop()

if __name__ == '__main__':
    main()

2) Heb.py
複製代码
# -*- coding: utf-8 -*-

###########################################################################
## Python code generated with wxFormBuilder (version Oct 26 2018)
## http://www.wxformbuilder.org/
##
## PLEASE DO *NOT* EDIT THIS FILE!
###########################################################################
import os
import wx
# import wx.xrc

###########################################################################
## Class HeBing
###########################################################################


class HeBing ( wx.Frame ):

    def __init__( self, parent ):
        wx.Frame.__init__ ( self, parent, id = wx.ID_ANY, title = u"数据合并工具 -Powered By SanMin", pos = wx.DefaultPosition, size = wx.Size( 560,510 ), style = wx.CAPTION|wx.CLOSE_BOX|wx.MINIMIZE_BOX|wx.TAB_TRAVERSAL )

        self.SetSizeHints( wx.DefaultSize, wx.DefaultSize )
        self.SetBackgroundColour( wx.SystemSettings.GetColour( wx.SYS_COLOUR_WINDOW ) )
        # 设置窗口标题的图标
        #self.icon = wx.Icon('gg.ico', wx.BITMAP_TYPE_ICO)
        #self.SetIcon(self.icon)

        bSizer2 = wx.BoxSizer( wx.VERTICAL )

        sbSizer7 = wx.StaticBoxSizer( wx.StaticBox( self, wx.ID_ANY, u"1.打开文件" ), wx.VERTICAL )


        fgSizer31 = wx.FlexGridSizer( 0, 3, 0, 0 )
        fgSizer31.SetFlexibleDirection( wx.BOTH )
        fgSizer31.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )

        self.m_staticText8 = wx.StaticText( sbSizer7.GetStaticBox(), wx.ID_ANY, u"汇总文件", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText8.Wrap( -1 )

        fgSizer31.Add( self.m_staticText8, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )

        self.m_textCtrl_hzfile = wx.TextCtrl( sbSizer7.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.Size( 320,-1 ), 0 )
        fgSizer31.Add( self.m_textCtrl_hzfile, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )

        self.m_button4 = wx.Button( sbSizer7.GetStaticBox(), wx.ID_ANY, u"打开", wx.DefaultPosition, wx.DefaultSize, 0 )
        fgSizer31.Add( self.m_button4, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5 )

        self.m_staticText9 = wx.StaticText( sbSizer7.GetStaticBox(), wx.ID_ANY, u"待读取数据文件", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText9.Wrap( -1 )

        fgSizer31.Add( self.m_staticText9, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )

        self.m_textCtrl_huibfile = wx.TextCtrl( sbSizer7.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition,wx.Size( 320,-1 ), 0 )
        fgSizer31.Add( self.m_textCtrl_huibfile, 0, wx.ALL|wx.ALIGN_CENTER_VERTICAL, 5 )

        self.m_button5 = wx.Button( sbSizer7.GetStaticBox(), wx.ID_ANY, u"打开", wx.DefaultPosition, wx.DefaultSize, 0 )
        fgSizer31.Add( self.m_button5, 0, wx.ALL|wx.ALIGN_RIGHT|wx.ALIGN_CENTER_VERTICAL, 5 )


        sbSizer7.Add( fgSizer31, 1, wx.EXPAND, 5 )


        bSizer2.Add( sbSizer7, 1, wx.EXPAND, 5 )

        sbSizer8 = wx.StaticBoxSizer( wx.StaticBox( self, wx.ID_ANY, u"2.参数设置" ), wx.VERTICAL )

        fgSizer3 = wx.FlexGridSizer( 0, 4, 0, 0 )
        fgSizer3.SetFlexibleDirection( wx.BOTH )
        fgSizer3.SetNonFlexibleGrowMode( wx.FLEX_GROWMODE_SPECIFIED )


        self.m_staticText81 = wx.StaticText( sbSizer8.GetStaticBox(), wx.ID_ANY, u"汇总表sheet项", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText81.Wrap( -1 )

        fgSizer3.Add( self.m_staticText81, 0, wx.ALL, 5 )

        self.m_textCtrl9 = wx.TextCtrl( sbSizer8.GetStaticBox(), wx.ID_ANY, u"1", wx.DefaultPosition, wx.DefaultSize, 0 )
        fgSizer3.Add( self.m_textCtrl9, 0, wx.ALL, 5 )

        self.m_staticText91 = wx.StaticText( sbSizer8.GetStaticBox(), wx.ID_ANY, u"读取文件sheet项", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText91.Wrap( -1 )

        fgSizer3.Add( self.m_staticText91, 0, wx.ALL, 5 )

        self.m_textCtrl10 = wx.TextCtrl( sbSizer8.GetStaticBox(), wx.ID_ANY, u"1", wx.DefaultPosition, wx.DefaultSize, 0 )
        fgSizer3.Add( self.m_textCtrl10, 0, wx.ALL, 5 )

        sbSizer8.Add( fgSizer3, 1, wx.EXPAND, 5 )

        bSizer2.Add( sbSizer8, 1, wx.EXPAND, 5 )

        sbSizer9 = wx.StaticBoxSizer( wx.StaticBox( self, wx.ID_ANY, u"3.运行程序" ), wx.VERTICAL )

        self.m_button6 = wx.Button( sbSizer9.GetStaticBox(), wx.ID_ANY, u"运行", wx.DefaultPosition,wx.Size( 200,-1 ), 0 )
        sbSizer9.Add( self.m_button6, 0, wx.RIGHT|wx.ALIGN_CENTER_HORIZONTAL, 5 )

        bSizer2.Add( sbSizer9, 1, wx.EXPAND, 5 )

        sbSizer5 = wx.StaticBoxSizer( wx.StaticBox( self, wx.ID_ANY, u"4.运行进度" ), wx.VERTICAL )

        self.m_gauge2 = wx.Gauge( sbSizer5.GetStaticBox(), wx.ID_ANY, 100, wx.DefaultPosition, wx.DefaultSize, wx.GA_HORIZONTAL )
        self.m_gauge2.SetValue( 0 )
        sbSizer5.Add( self.m_gauge2, 0, wx.ALL|wx.EXPAND, 5 )


        bSizer2.Add( sbSizer5, 1, wx.EXPAND, 5 )

        sbSizer6 = wx.StaticBoxSizer( wx.StaticBox( self, wx.ID_ANY, u"5.运行情况" ), wx.VERTICAL )

        self.m_textCtrl_JieG2 = wx.TextCtrl( sbSizer6.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_textCtrl_JieG2.Enable( False )
        sbSizer6.Add( self.m_textCtrl_JieG2, 0, wx.ALL|wx.EXPAND, 5 )


        bSizer2.Add( sbSizer6, 1, wx.EXPAND, 5 )

        self.m_staticText7 = wx.StaticText( self, wx.ID_ANY, u"Copyright(C)2023 SanMin. All Rights Reserved.", wx.DefaultPosition, wx.DefaultSize, 0 )
        self.m_staticText7.Wrap( -1 )

        self.m_staticText7.Enable( False )

        bSizer2.Add( self.m_staticText7, 0, wx.ALL|wx.ALIGN_RIGHT, 5 )


        self.SetSizer( bSizer2 )
        self.Layout()

        self.Centre( wx.BOTH )

        # Connect Events
        self.m_button4.Bind( wx.EVT_BUTTON, self.dakai1 )
        self.m_button5.Bind( wx.EVT_BUTTON, self.dakai2 )
        self.m_button6.Bind( wx.EVT_BUTTON, self.yunxing )

    def __del__( self ):
        pass


    # Virtual event handlers, overide them in your derived class
    def dakai1( self, event ):
        wildcard = 'All files(*.xlsx)|*.xlsx'

        dialog = wx.FileDialog(None, 'select', os.getcwd(), '', wildcard, wx.FD_OPEN)  #####这个部分新旧版本有变化

        if dialog.ShowModal() == wx.ID_OK:
            self.m_textCtrl_hzfile.SetValue(dialog.GetPath())

    def dakai2( self, event ):
        wildcard = 'All files(*.xlsx)|*.xlsx'

        dialog = wx.FileDialog(None, 'select', os.getcwd(), '', wildcard, wx.FD_OPEN)  #####这个部分新旧版本有变化

        if dialog.ShowModal() == wx.ID_OK:
            self.m_textCtrl_huibfile.SetValue(dialog.GetPath())

    def yunxing( self, event ):
        event.Skip()




0

精彩评论