先po一下原文网址,毕竟这里仅记录一下具体的代码:
https://blog.csdn.net/Imagine_Dragon/article/details/78025144
以下为原文的完整代码段:
# coding:utf-8
import xlrd
import os
import xlwt
from xlutils.copy import copy
"""
将文件夹下所有excel文件合并成一个文件
注意:
本代码仅支持合并excel文件第一个sheet,如果合并的excel文件有多个sheet,只会读取和合并第一个sheet,
需要合并的excel文件如果有多个sheet需要修改代码的merge_excel()函数
思路:
1.获取路径下所有文件,注意 本代码没有异常处理
2.新建一个excel文件,用于存储全部数据
3.逐个打开需要合并的excel文件,逐行读取数据,再用一个列表来保存每行数据。最后该列表中会存储所有的数据
4.向excel文件中逐行写入
"""
def get_allfile_msg(file_dir):
for root, dirs, files in os.walk(file_dir):
'''
print(root) #当前目录路径
print(dirs) #当前路径下所有子目录
print(files) #当前路径下所有非目录子文件
'''
return root, dirs, [file for file in files if file.endswith('.xls') or file.endswith('.xlsx')]
def get_allfile_url(root, files):
"""
将目录的路径加上'/'和文件名,组成文件的路径
:param root: 路径
:param files: 文件名称集合
:return: none
"""
allFile_url = []
for file_name in files:
file_url = root + '/' + file_name
allFile_url.append(file_url)
return allFile_url
def all_to_one(root, allFile_url, file_name='allExcel.xls', title=None, have_title=True):
"""
合并文件
:param root: 输出文件的路径
:param allFile_url: 保存了所有excel文件路径的集合
:param file_name: 输出文件的文件名
:param title: excel表格的表头
:param have_title: 是否存在title(bool类型),默认为true,不读取excel文件的第0行
:return: none
"""
# 首先在该目录下创建一个excel文件,用于存储所有excel文件的数据
file_name = root + '/' + file_name
create_excel(file_name, title)
list_row_data = []
for f in allFile_url:
# 打开excel文件
print('打开%s文件' % f)
excel = xlrd.open_workbook(f)
# 根据索引获取sheet,这里是获取第一个sheet
table = excel.sheet_by_index(0)
print('该文件行数为:%d,列数为:%d' % (table.nrows, table.ncols))
# 获取excel文件所有的行
for i in range(table.nrows):
# 如果存在表头,则跳过第0行,否则不跳过
if have_title and i == 0:
continue
else:
row = table.row_values(i) # 获取整行的值,返回列表
list_row_data.append(row)
print('总数据量为%d' % len(list_row_data))
# 写入all文件
add_row(list_row_data, file_name)
# 创建文件名为file_name,表头为title的excel文件
def create_excel(file_name, title):
print('创建文件%s' % file_name)
a = xlwt.Workbook()
# 新建一个sheet
table = a.add_sheet('sheet1', cell_overwrite_ok=True)
# 写入数据
for i in range(len(title)):
table.write(0, i, title[i])
a.save(file_name)
# 向文件中添加n行数据
def add_row(list_row_data, file_name):
# 打开excel文件
allExcel1 = xlrd.open_workbook(file_name)
sheet = allExcel1.sheet_by_index(0)
# copy一份文件,准备向它添加内容
allExcel2 = copy(allExcel1)
sheet2 = allExcel2.get_sheet(0)
# 写入数据
i = 1
for row_data in list_row_data:
for j in range(len(row_data)):
sheet2.write(sheet.nrows + i, j, row_data[j])
i += 1
# 保存文件,将原文件覆盖
allExcel2.save(file_name)
print('合并完成')
if __name__ == '__main__':
# 设置文件夹路径,
file_dir = 'D:\SoftWare\PythonWorkSpace\excel-test'
# 获取文件夹的路径,该路径下的所有文件夹,以及所有文件
root, dirs, files = get_allfile_msg(file_dir)
# 拼凑目录路径+文件名,组成文件的路径,用一个列表存储
allFile_url = get_allfile_url(root, files)
# 设置文件名,用于保存数据
file_name = 'output.xls'
# 设置excle文件表头
title = ['a', 'b', 'c', 'd']
# have_title参数默认为True,为True时不读取excel文件的首行
all_to_one(root, allFile_url, file_name=file_name, title=title, have_title=True)
以下为最近几天折腾测试上面这段代码的一些感想,本文作用仅为记录。
一,通过最近的实测,在文件夹中的原始文件,格式全为.xls,以及全为.xlsx的情况,都能够成功运行。
这里并未测试以下两种情况:
1,同一个文件夹中同时存在.xls文件和.xlsx文件,甚至还带有csv文件。
2,同一个文件夹中的不同文件,列数不一样。
二,输出的文件就有点意思了。
1,无论第122行的代码中,文件名命名为“output.xlsx”还是“output.xls”,都能够生成文件。
2,只是直接生成为.xlsx文件,那么就会把合并的文件“命名为”了“以.xlsx结尾的文件名”,而并不是生成了一个.xlsx格式的文件。
这样说的原因很简单:
2.1,如果直接生成了.xlsx文件,是没办法直接打开的,系统会提示你“Excel无法打开文件“excel3.xlsx”,因为文件格式或文件扩展名无效。请确定文件未损坏,并且文件扩展名与文件的格式匹配。”
2.2,然后,我尝试将文件名从“output.xlsx”改为“output.xls”,文件却被成功打开。
3,追加一点,我不清楚xlwt和xlrd这两个包,现在有没有更新了功能,但之前我在寻找python处理表格的时候,忘了在哪看到过这么一句话:pandas只能处理xlsx文件,而xlwt & xlrd只能处理xls文件。
所以,综上得出推论,应该说xlwt和xlrd应该不是“只能处理xls文件”,而是“只能输出xls文件”。
三,关于代码第126行里,有个have_title的参数:
如果是True,就会自动将原文件中的表头全部去掉,注意,是全部去掉哦~
如果是False,就会将原文件中所有内容一起合并。比如说有10个文件,合并后的文件中,就会有10行表头,这个也值得注意。
*后续还会继续摸索,毕竟如果能够直接输出只有一行表头的表格,那就更好了。
*另外一个状况,代码中第124行是设置title的,这样出来的结果里,title行下面会有一行空行,不晓得是怎么回事。
再来点小提醒:
经常处理excel文件的朋友,xlwt和xlrd两个包应该都是常备的了。但在用这段代码前,记得把xlutils这个包给装上哈~
以上,向原文作者@Imagine_Dragon致敬~