各类Excel表格批量合并问题的实现思路与案例
作者:小小明
在日常工作中,可能会遇到各类表格合并的需求。这类需求只要搞懂核心原理都很简单,本质都是万变不离其宗,相信大部分读者都能解决大部分需求。
基本思路:
- 遍历需要被合并的文件
- 读取数据,并合并数据(使用pandas最简单便捷)
- 保存数据
- 对样式无要求,使用Pandas对象直接写出
- 对样式有要求,使用openpyxl加载模板
- 要求样式与原始表格完全一致,使用VBA复制粘贴(本文未实现)
首先我们看下遍历文件比较简单的方法:
遍历文件示例
遍历当前目录下以xlsx为后缀的Excel,排除以~或r开头的文件:
from glob import globglob("[!~r]*.xlsx")
['合并结果.xlsx', '多sheet表格合并.xlsx', '带表头样式合并.xlsx']
同时还想包含xls格式的文件:
glob("[!~r]*.xls*")
['test.xls', '合并结果.xlsx', '多sheet表格合并.xlsx', '带表头样式合并.xlsx']
递归遍历当前文件夹,包含子文件夹:
glob("**/[!~r]*.xls*", recursive=True)
['test.xls','合并结果.xlsx','多sheet表格合并.xlsx','带表头样式合并.xlsx','Excel多sheet合并\\excel3.xlsx','Excel多sheet合并\\excel4.xlsx','Excel多sheet合并\\新建文件夹\\excel3.xlsx','Excel多sheet合并\\新建文件夹\\excel4.xlsx','Excel多sheet合并\\新建文件夹\\新建文件夹\\excel3.xlsx','Excel多sheet合并\\新建文件夹\\新建文件夹\\excel4.xlsx','带样式合并\\HB区.xlsx','带样式合并\\HN区.xlsx','带样式合并\\XN区.xlsx','带样式合并\\汇总表.xlsx']
递归遍历指定文件夹(例如搜索本机所有登录过的微信接收到的Excel文件):
import os
path = os.path.expanduser("~/Documents/WeChat Files")
glob(f"{path}/**/[!~r]*.xls*", recursive=True)
掌握了遍历文件的基本用法,我们就可以正式开始进行文件合并了:
无样式单文件合并示例
案例1:有一堆gzip压缩的csv文件,需要合并成新的csv文件
解压后的文本格式:
合并一堆gzip压缩的csv文件最终合并成一个gzip压缩的csv文件:
from glob import glob
import pandas as pddfs = [pd.read_csv(file, skiprows=1, sep="|", compression="gzip")for file in glob("gzip/*.csv.gz")]
df = pd.concat(dfs, ignore_index=True)
df.to_csv("合并后的csv压缩文件.csv.gz", index=False, compression="gzip")
最终合并结果:
案例2:一堆csv文件,只取其中三列,表名不固定,但相对顺序一致
from glob import glob
import pandas as pd
import numpy as npcolumns = ['Date_ID', 'erbs', 'EUtranCell']
dfs = [pd.read_csv(file, usecols=[0, 2, 3]).values for file in glob("csv/*.csv")]
df = pd.DataFrame(np.vstack(dfs), columns=columns)
df.to_csv("合并后的csv文件.csv", index=False)
案例3:一堆csv文件,列非常多,仅一列列名存在变动
import pandas as pd
import globdfs = [pd.read_csv(file).rename(columns=lambda x:"EUtranCell" if x.startswith("EUtranCell") else x)for file in glob.glob("csv/*.csv")
]
df = pd.concat(dfs, ignore_index=True)
df.to_csv("合并后的csv文件2.csv", index=False)
其他方法(一般不会这么写):
在预先能够定义好列名时,推荐以下两种写法:
案例4:寄存器数据处理并合并
需求说明:
- 需要读取0xa17~0xa20这10个寄存器的数据,前4个寄存器数据保存到R,GR,RB,B这四列中
- 0xa1b~0xa20后6个寄存器,两两合并到RG_L_H,BG_L_H,GG_L_H这三列中
- 标识每行数据所读取的文件名
如下所示:
特殊情况:
为了方便获取文件名,我们使用pathlib来进行glob遍历:
import pandas as pd
from pathlib import Pathresult = []
for file in Path("csv/PT0004B_LOG").glob("*.csv"):df = pd.read_csv(file, header=None, usecols=[1, 2], index_col=0)t = df[2].str[2:]r = [str(file.name[:-4])]r.extend(t.loc["0xa17":"0xa1a"].values)r.extend(t.loc["0xa1c":"0xa20":2].values +t.loc["0xa1b":"0xa20":2].str.zfill(2).values)result.append(r)
df = pd.DataFrame(result, columns=["file", "R", "GR", "GB", "B", "RG_L_H", "BG_L_H", "GG_L_H"])
df.to_excel("combine.xlsx", index=False)
df.head()
无样式同名多sheet表格合并
如果只递归合并一个文件夹下的所有Excel的默认sheet,会非常简单,仅需4行代码搞定:
path = "Excel多sheet合并"
dfs = [pd.read_excel(file) for file in glob.glob(f"{path}/**/[!~]*.xls*", recursive=True)]
df = pd.concat(dfs, ignore_index=True)
df.to_excel("合并结果.xlsx", index=False)
下面要求对一个文件夹下所有Excel表格,要求所有的sheet分别合并。
数据示例如下:
假设被合并的文件夹名称是Excel多sheet合并
,合并代码如下:
import pandas as pd
from glob import globpath = "Excel多sheet合并"
data = {}
for file in glob(f"{path}/**/[!~]*.xls*", recursive=True):for name, df in pd.read_excel(file, sheet_name=None).items():data.setdefault(name, []).append(df)with pd.ExcelWriter("多sheet表格合并.xlsx") as write:for name, dfs in data.items():pd.concat(dfs).to_excel(write, name, index=False)
合并结果:
保留表头样式同名多sheet表格合并
如果要求完全带有原有样式合并会比较麻烦,本文就不作演示了,存在具体真实需求时再考虑单独开文。
需求说明:
有很多区域表:
现在需要将每个区域的表格黄色的sheet合并到一张汇总表中。
为了保持表头样式的一致性,我们可以事先建立好模板,或者直接任选一个被合并的文件作为模板。
首先我们读取数据:
import pandas as pd
from glob import globpath = "带样式合并"
# 定义被读取的sheet名和跳过的行数
sheet_start_num = {'03': 3, '06': 2, '07': 3, '08': 3}
data = {}
for file in glob(f"{path}/**/[!~r汇]*.xls*", recursive=True):for sheet_name, skiprows in sheet_start_num.items():excel = pd.ExcelFile(file)df = excel.parse(sheet_name=sheet_name, skiprows=skiprows, header=None)data.setdefault(sheet_name, []).append(df.values)
然后通过openpyxl加载模板,将数据写入各个子表中:
from openpyxl import load_workbookworkbook = load_workbook(filename="带样式合并/汇总表.xlsx")for sheet_name, sheet_data in data.items():sheet = workbook[sheet_name]sheet.delete_rows(sheet_start_num[sheet_name] + 1, sheet.max_row)for row in np.vstack(sheet_data).tolist():sheet.append(row)
workbook.save(filename="带表头样式合并.xlsx")
最终就实现了带表头样式多sheet合并。
图形化界面选择指定的目录
如果我们希望将其做成图形化界面,可以使用tk的如下组件选择被合并的目录,或保存的位置:
from tkinter import filedialogfiledialog.askdirectory(initialdir=".")
filedialog.asksaveasfilename(title="保存",initialdir=".",defaultextension="xlsx",filetypes=[("Excel 工作簿", "*.xlsx"),("Excel 97-2003 工作簿", "*.xls")])
我们以多Excel多Sheet合并为例,可以编写如下代码的py脚本:
from tkinter import filedialog
import pandas as pd
from glob import globpath = filedialog.askdirectory(initialdir=".")
data = {}
for file in glob(f"{path}/**/[!~]*.xls*", recursive=True):for name, df in pd.read_excel(file, sheet_name=None).items():data.setdefault(name, []).append(df)save_name = filedialog.asksaveasfilename(title="保存",initialdir=".",defaultextension="xlsx",filetypes=[("Excel 工作簿", "*.xlsx"),("Excel 97-2003 工作簿", "*.xls")])
with pd.ExcelWriter(save_name) as write:for name, dfs in data.items():pd.concat(dfs).to_excel(write, name, index=False)
也可以考虑使用Gooey工具转换为图形化界面:
from glob import glob
import pandas as pdfrom gooey import Gooey, GooeyParserdef combine_excel(path, save_name):data = {}for file in glob(f"{path}/**/[!~]*.xls*", recursive=True):for name, df in pd.read_excel(file, sheet_name=None).items():data.setdefault(name, []).append(df)with pd.ExcelWriter(save_name) as write:for name, dfs in data.items():pd.concat(dfs).to_excel(write, name, index=False)@Gooey
def main():parser = GooeyParser(description="多Excel多Sheet合并程序 - @小小明")parser.add_argument('path', help="被合并的Excel文件目录", widget="DirChooser")parser.add_argument('save_name', help="合并后保存的文件(以Excel文件形式保存)", widget="FileSaver")args = parser.parse_args()print("输入路径:", args.path)print("保存位置:", args.save_name)combine_excel(args.path, args.save_name)print("合并完成!")if __name__ == '__main__':main()
还可以通过Gooey展示合并进度:
from glob import glob
import pandas as pdfrom gooey import Gooey, GooeyParserdef combine_excel(path, save_name):data = {}files = glob(f"{path}/**/[!~]*.xls*", recursive=True)for i, file in enumerate(files, 1):for name, df in pd.read_excel(file, sheet_name=None).items():data.setdefault(name, []).append(df)yield f"合并进度:{i}/{len(files)}"with pd.ExcelWriter(save_name) as write:items = data.items()for i, (name, dfs) in enumerate(items, 1):pd.concat(dfs).to_excel(write, name, index=False)yield f"保存进度:{i}/{len(items)}"@Gooey(progress_regex=r"^..进度:(?P<current>\d+)/(?P<total>\d+)$",progress_expr="current / total * 100",timing_options={'show_time_remaining': False,'hide_time_remaining_on_complete': True,})
def main():parser = GooeyParser(description="多Excel多Sheet合并程序 - @小小明")parser.add_argument('path', help="被合并的Excel文件目录", widget="DirChooser")parser.add_argument('save_name', help="合并后保存的文件(以Excel文件形式保存)", widget="FileSaver")args = parser.parse_args()print("输入路径:", args.path)print("保存位置:", args.save_name)for msg in combine_excel(args.path, args.save_name):print(msg)print("合并完成!")if __name__ == '__main__':main()
各类Excel表格批量合并问题的实现思路与案例相关推荐
- excel表格批量合并单元格很难?教你3秒做好
Excel表格合并单元格很简单,但是需要合并为成百上千的单元格就很累很麻烦了,这里教你3秒搞定! 欢迎关注.收藏.点赞.评论.转发! 首先用wps打开excel表格 我们来看看下面的表格 我们需要把部 ...
- 上传excel表格批量插入到数据库
前因 最近在做的项目是在线考核平台(目前已经在测试阶段),里面涉及到的业务复杂度很深(公司项目,不便多说),业务逻辑和需求契合度也很高,在开发过程中就遇到了很多很多的问题. 我的计划是在开发结束后把自 ...
- 【游戏开发】Excel表格批量转换成CSV的小工具
一.前言 在工作的过程中,我们有时可能会面临将Excel表格转换成CSV格式文件的需求.这尤其在游戏开发中体现的最为明显,策划的数据文档大多是一些Excel表格,且不说这些表格在游戏中读取的速度,但就 ...
- 通过Excel表格批量生成汉信码
汉信码是我国自主知识产权的一种二维条码.具有超强的汉字表示能力和高效的汉字编码效率,信息密度高,容量大,抗污损和畸变能力强,支持加密技术,修正错误能力强,纠错能力可以达到30%.汉信码的外观美观,在视 ...
- Excel表格批量更改出生年月格式
Excel表格批量更改日期格式 1.先把要更改的数据放到编辑器 Notepad++ 里面 如上图,我们要把日期格式更改为:1995/05/25 2.先把光标停在需要更改的地方,然后按住 Alt 键,同 ...
- excel表格内容合并的技巧?
今天跟大家分享一下excel表格内容合并的技巧? 1.打开演示文件,如下图要求将多个表格合并到一起. 2.首先我们点击下图选项 3.点击[汇总拆分]-[合并多表] 4.勾选要合并的工作表 5.然后根据 ...
- EXCEL表格数据合并
EXCEL表格数据合并 主要针对同一个excel文件中包含多个sheet,需要将所有的数据进行汇总. 1.表格数据展示: 2.数据合并步骤: 打开excel表格(当前表格或者新建表格均可),选择数据- ...
- 如何通过VB合并Excel单元格以及设置Excel行高?VB创建Excel表格,合并单元格,生成图形等操作
如何通过VB合并Excel单元格以及设置Excel行高? 例如:我想把第一列的第4,5,6,7行合并...我在怎样让合并单元格里的字居中,怎样改变字体. 请不吝赐教... ============== ...
- Excel表格批量将文本转换为超链接 批量文本转链接 一键转URL
Excel表格批量将文本转换为超链接 批量文本转链接 一键转URL 想实现表格里的文本链接点击直接打开浏览器 方案对比 效果 工具 想实现表格里的文本链接点击直接打开浏览器 方案对比 逐个单元格双击. ...
最新文章
- mysql安装教程8.0.21安装,mysql 8.0.21 安装配置方法图文教程
- WPF 3D和光照学习1
- C/Cpp / 如何定义一个只能在堆上(栈上)生成对象的类?
- 疫情之下的科技普惠:阿里云科技驱动中小企业数字化
- jpa避免n+1_JPA技巧:避免N + 1选择问题
- Error:The supplied javaHome seems to be invalid. I cannot find the java executable
- linux 编辑器_Linux的vi编辑器详细总结
- ASP.NET MVC 过滤器(五)
- pycharm远程调试python_使用PyCharm进行Python远程调试
- SmallMQ实现发布
- 万元奖金 , 百万流量 , 助你成为CSDN超级红人 !
- match和exec的对比
- 怎样用计算机制作思维导图,如何使用电脑制作成思维导图,这个方法简单又实在...
- 关于Si24r1调试的总结
- 图像检索哈希算法综述
- c语言中eof的作用,eof在c语言中表示什么
- Markdown超链接本地文件
- 顺丰快递单号查询API接口调试demo【快递100API接口】
- 华为ensp防火墙nat64案例配置
- HTML+CSS项目实践四:给html网页标题栏添加logo图标(ico格式图片)
热门文章
- 华脉智联正式发布基于谷歌浏览器和微信的无插件音视频全功能二次开发包
- 使用vs2008c++语言开发activex控件教程,使用VS2010 C#开发ActiveX控件(上)
- 直线检测——对比M-LSD直线检测(基于深度学习)与霍夫曼直线检测
- Redis?它主要用来什么的
- 方舟服务器最多127人,TapTap 9.7分,超127万人预约,《方舟:生存进化》值得期待...
- python 语音输入
- Android开发中的第三方支付SDK的接入与使用(支付宝+微信支付+银联)
- IOException异常:使用exec()方法,必须捕捉此异常
- 泛在电力物联网建设大纲解读及落地建议
- 菜鸟学习C语言——指针