吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 23190|回复: 219
上一主题 下一主题
收起左侧

[原创工具] 【Python】Excel表格汇总Excel

    [复制链接]
跳转到指定楼层
楼主
lijt16 发表于 2021-3-8 22:31 回帖奖励
本帖最后由 lijt16 于 2021-6-10 10:04 编辑

之前发了【Python】Word表格汇总Excel ,没想到挺受欢迎,由此看来需求还是有的。其实我自己工作倒是没有这个需求,都是帮朋友写的。
前两天看到了 请给位大神推荐个好用excel提取汇总工具,然后我试了下几个Excel插件,汇总的基本都是全部数据(可能是我潦草试了没有用对),对于只需要部分数据的人来说还是不够方便的。
之前也有人写过了 Excel提取汇总 ,不过楼主表示软件兼容性不太好,我就趁闲写了个python版的,使用了xlwings,功能比较简单,也没有费劲整图形界面,增加了进度条。用法也和我之前那个相似。

【功能】
1. 将多个Excel表格数据汇总到Excel表格;

【使用】【更新】
1. 数据备份;
2. [模板]: 在相应单元格填Excel列数并删除其他所有内容;
3. [数字前加单引号]: 可避免手机号等科学记数法;
4. [对日期格式化]: 将各种格式的日期统一格式;
5. [来源工作簿及工作表名称]:在模板文件随意单元格填写b-m-n,其中m为工作簿名称要填入的列数,n为工作表名称要填入的列数,相同时以-连接;
6. 增加工作簿多工作表情况:
①所有工作表格式相同,全部汇总到同一目标表格,此时目标表格和模板文件都只有一个工作表;
②工作表格式不同(或相同),需要分别汇总到目标表格对应的目标工作表,此时目标表格和模板文件有和原表格相同数量的工作表。

7. 空表不汇总;
8. 处理xls格式;




【示例】
1. 现在需要汇总形如以下格式的Excel表格:


2. 需要汇总的Excel格式如下:


3. 根据需要提取的数据所处的Excel列数制作模板如下(单工作表或多工作表):


4. 然后运行选择目录和模板文件即可。

【源码】【更新】
[Python] 纯文本查看 复制代码
# -*- coding: UTF-8 -*-
import os, re, sys
import xlwings as xw
import tkinter as tk
from tkinter import filedialog

class Xlsx2Xlsx(object):
    def __init__(self):
        super(Xlsx2Xlsx, self).__init__()
        self.pattern = re.compile(r"(\d{2,4})\D*(\d{0,2})\D*(\d{0,2})")

    # files path
    def filePath(self):
        root = tk.Tk()
        root.withdraw()
        path = filedialog.askdirectory(title = "选择Excel文件目录")
        model = filedialog.askopenfilename(title="选择Excel模板",filetypes=(('File', '*.*'),('XLSX', '*.xlsx'),('XLS','*.xls')))
        xls = [i for i in os.listdir(path) if (i.endswith(".xlsx") or i.endswith(".xls")) and not i.startswith("~$")]
        return path, xls, model

    # xlsx 2 xlsx
    def xlsx2xlsx(self, path, xls, model):
        app = xw.App(visible=False, add_book=False)

        #获取模板数据
        wb_model = app.books.open(model)
        data = []
        for i in range(len(wb_model.sheets)):
            ws_model = wb_model.sheets[i]
            info = ws_model.used_range
            nrows = info.last_cell.row
            ncols = info.last_cell.column            
            data.append(ws_model.range((1, 1), (nrows, ncols)).value) #所有行数据
        wb_model.close()

        wb_result=app.books.add() #新建表格
        row = 1
        nums = len(xls)
        size = 40      #符号数量即进度条长度

        for r, x in enumerate(xls):
            wb_xl = app.books.open(path + r"/" + x)
            for s in range(len(wb_xl.sheets)):
                #判断是否为空表
                ws_xl = wb_xl.sheets[s]
                ws_range = ws_xl.used_range
                ws_info = ws_xl.range((1, 1), (ws_range.last_cell.row, ws_range.last_cell.column)).value
                if ws_info is None or all(i is None for j in ws_info for i in j): #空表
                    continue

                flag = 0 if len(data) == 1 else s              #模板是否只有一个工作表
                line = row if len(data) == 1 else r + 1
                d = data[flag]
                wsnames = [i.name for i in wb_result.sheets]
                shtname = "Sheet%d" %(flag + 1)
                ws_result = wb_result.sheets[shtname] if shtname in wsnames else wb_result.sheets.add(shtname, after = wsnames[-1])
                for i, m in enumerate(d):
                    if any(m):
                        for j, n in enumerate(m):
                            if n:  #需要提取该单元格
                                val = ws_xl.range((i + 1, j + 1)).value
                                if isinstance(n, float): #我这里如果模板为纯数字,读取后为1.0这样的浮点数,若报错回复我修改
                                    ws_result.range((line, int(n))).value = val
                                elif "'" in n or "‘" in n or "’" in n or n.isdigit(): #存在单引号(这里半角单引号其实并无法读取,只显示为字符串的数字),防止错输入为全角
                                    ser = int(n) if n.isdigit() else int(n[1:])
                                    ws_result.range((line, ser)).value = r"'" + str(int(val)) if val else ''
                                elif "d" in n or "D" in n: #日期
                                    sym = n[-1] if n[-1] != "d" and n[-1] != "D" else ""
                                    ser = int(n.split("d")[0]) if "d" in n else int(n.split("D")[0])
                                    if val:
                                        date = self.pattern.findall(str(val))[0]
                                        if date[2]:
                                            date = "{}{}{:0>2s}{}{:0>2s}".format(date[0], sym, date[1], sym, date[2]) 
                                        elif date[1]:
                                            date = "{}{}{:0>2s}".format(date[0], sym, date[1])
                                        else:
                                            date = date[0]
                                        ws_result.range((line, ser)).value = date
                                    else:
                                        ws_result.range((line, ser)).value = ''
                                elif "b" in n or "B" in n:
                                    ser1 = int(n.split("-")[1])
                                    ser2 = int(n.split("-")[2])
                                    if ser1 != ser2:
                                        ws_result.range((line, ser1)).value = x
                                        ws_result.range((line, ser2)).value = ws_xl.name
                                    else:
                                        ws_result.range((line, ser1)).value = x + "-" + str(ws_xl.name)
                row += 1
            wb_xl.close()
            
            bar = "\r{:>3.0f}%| ".format((r+1)/nums*100) + "{{:\u0020<{}s}}".format(size).format("\u2588"*int((r+1)/nums*size)) + " {{:0>{}d}}|{}".format(len(str(nums)), nums).format(r+1)
            # sys.stdout.write(bar) #不换行打印,需环境支持
            # sys.stdout.flush()
            print(bar)

        wb_result.save(os.path.dirname(model) + "/" + "result.xlsx") #保存到与模板文件相同位置
        wb_result.close()
        app.quit()
                
if __name__ == '__main__':
    x2x = Xlsx2Xlsx()
    path, xls, model = x2x.filePath()    x2x.xlsx2xlsx(path, xls, model)[s]



【链接】【更新】
https://lykisun.lanzoui.com/b00ubl0ib
密码:52pj
【链接已更新,打不开的搜索一下蓝奏链接打不开的问题】


【问题】
1、出错注意仔细查看有没有按照说明制作模板,或者翻一下评论看看有没有自己的问题;
2、来源表有隐藏工作表;
3、Excel为精简版等非正式版或未装Excel;

免费评分

参与人数 55吾爱币 +47 热心值 +46 收起 理由
Megix + 1 + 1 谢谢@Thanks!
liiyii00 + 1 + 1 用心讨论,共获提升!
yxdx180 + 1 + 1 把lanzous后的s改成x打开了,谢谢
右行天下 + 1 + 1 热心回复!
清风不败 + 1 链接打不开了?
缘晓龙 + 1 + 1 谢谢@Thanks!
shili180 + 1 + 1 谢谢@Thanks!
470891974 + 1 我很赞同!
空白昵称 + 1 无法汇总xls格式的,可以先转换格式然后再汇总,希望可以加到程序里面
sun041620 + 1 + 1 我很赞同!
xgr2002 + 1 + 1 我很赞同!
Coonly + 1 + 1 谢谢@Thanks!
chengang5301 + 1 谢谢@Thanks!
锦川 + 1 谢谢@Thanks!
阿傻0818 + 1 我很赞同!
bies + 1 热心回复!
jnez112358 + 1 + 1 谢谢@Thanks!
XSZbruno + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
PEKO16 + 1 谢谢@Thanks!
zhanghdong + 1 谢谢@Thanks!
bluefluke + 1 + 1 谢谢@Thanks!
guoruihotel + 1 + 1 谢谢@Thanks!
Lsygood + 1 + 1 谢谢@Thanks!
yanyyuan + 1 谢谢,刚好有用
徐凯 + 1 + 1 我很赞同!
dreambird1314 + 1 + 1 谢谢@Thanks!
liulu815 + 1 + 1 我很赞同!
Woody1211 + 1 热心回复!
student_big + 1 我很赞同!
S靳言 + 1 + 1 谢谢@Thanks!
DaiTian + 1 + 1 谢谢@Thanks!
hexiaomo + 1 + 1 谢谢@Thanks!
andrewi + 1 + 1 谢谢@Thanks!
heze + 1 用心讨论,共获提升!
易朽的红衫木 + 1 + 1 用心讨论,共获提升!
Antik1 + 1 + 1 用心讨论,共获提升!
happyzss + 1 + 1 谢谢@Thanks!
popkun222 + 1 谢谢@Thanks!
lww52188 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
kissfast + 1 + 1 谢谢@Thanks!
mcgee214 + 1 + 1 我很赞同!
火焰加鲁鲁 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
风之暇想 + 7 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
abil + 1 鼓励转贴优秀软件安全工具和文档!
maruiyun + 1 在印象中,有一个Excel插件中的“报表形式数据结构转标准数据源”可以达成.
pepete + 1 + 1 谢谢@Thanks!
9981难 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
Laney + 1 热心回复!
hackxml + 1 + 1 我很赞同!
yy9910 + 1 热心回复!
hqingh21 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
science2011 + 1 + 1 谢谢@Thanks!
yanglinman + 1 谢谢@Thanks!
wjr0060 + 1 谢谢@Thanks!
miqi1314 + 1 + 1 谢谢@Thanks!

查看全部评分

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

推荐
liiyii00 发表于 2021-6-9 09:34
本帖最后由 liiyii00 于 2021-6-9 09:38 编辑
lijt16 发表于 2021-6-8 15:33
特殊情况太多,不可能按每个人的特殊情况改,你这种情况不能当成sheet为空表制作模板的时候加一个空sheet ...

这应该不是特殊情况啊,需要汇总的有N个工作簿,每个工作簿有sheet1、sheet2、sheet3三个工作表(模板也有三个工作表),只有sheet1里有数据(只需要汇总sheet1,模板的sheet1也进行了相应设置),现在的情况是程序在汇总完第一个工作簿的sheet1后就卡死了,需要汇总的第一个工作簿处于打开只读状态,同时新建了一个工作簿,sheet1里有已经汇总的第一个工作簿的一条数据,指针在sheet2的A1单元格里,无法完成后续的汇总。如果把需要汇总的N个工作簿里的sheet2、sheet3工作表删掉(模板不用删除sheet2|、sheet3)就能正常运行汇总。
推荐
wj37 发表于 2021-4-8 23:36
lijt16 发表于 2021-4-8 08:52
你是用的代码还是exe文件?不应该啊
Traceback (most recent call last):
  File "C:/Users/PC LIVE/PycharmProjects/pythonProject4/main.py", line 97, in <module>
    x2x.xlsx2xlsx(path, xls, model)
  File "C:/Users/PC LIVE/PycharmProjects/pythonProject4/main.py", line 55, in xlsx2xlsx
    val = ws_xl.range((i + 1, j + 1)).value
AttributeError: 'Sheets' object has no attribute 'range'
Process finished with exit code 1
你好楼主,上面提示这个和EXE有关吗?请教如何处理
沙发
miqi1314 发表于 2021-3-8 22:34
3#
ma4907758 发表于 2021-3-8 23:46
感谢,好好学习
4#
zhengxinjun 发表于 2021-3-9 00:22
不错 最近我也在学
5#
rotion 发表于 2021-3-9 00:50
学习PYTHON中,前排占位
6#
fjhscpc 发表于 2021-3-9 01:02
这个不错,最近在了解python,这个能当学习资料
7#
wangzhenuen 发表于 2021-3-9 08:11
最近我也在学
8#
t711s 发表于 2021-3-9 08:23
收下,谢谢!
9#
皮雪球儿 发表于 2021-3-9 08:50
好东西,谢谢楼主分享!
10#
血色天空 发表于 2021-3-9 08:52
实用,谢谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

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

GMT+8, 2024-11-28 09:14

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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