一、 问题
由于工作需要,经常会有大量的excel表格需要合并,比如来自不同货代按月发过来的运费,还有来自ERP系统导出用来分析销售的订单表,这样的表格在工作其实有很多。不过他们大多数都是按月或者其他时间段分成了各自零散的文件,有时候要整理分析的时候就特别麻烦,而这时,快速合并这些文件,就变得很有必要的一个操作了。
二、 开始冒险
为了应对这个任务,我用上一个极为有用的工具,那就是Python,数据分析的神器呀,简直是哪里不爽点哪里,哈哈。
这里记录了,我从刚开始使用Python来解决这个问题,到后面一步一步提升,用上更好的方法或者说更简便的方法的过程,也是分享给新手的一个启发,看问题是怎么解决,又是怎么进化的。
这里没有记录怎么安装Python,默认是当作大家已经知道了,当然你如果真的还不知道的话也没关系,网上找找有很多资料,后期,我也会专门写一些入门的内容供大家学习参考。
问题分解
- 要合并文件夹内的excel
- 首先,要找到能够操作文件夹的库,这个库应该是能够遍历文件夹内的所有文件
- 然后,要找到能够操作excel的库,这个库应该是能够读写excel
下面就是做python菜鸟时期,做的其中一个版本,这时,对python才入门,就想着应该是找能操作excel的库,网上找到openpyxl:
import openpyxl
import os
'''
@author:steven
date: 2016-05-18
'''
def get_filenames(path):
filenames = []
for i in os.walk(path):
for filename in i[-1]:
full_filename = os.path.join(i[0],filename)
filenames.append(full_filename)
return filenames
def read_excel(path):
wb = openpyxl.load_workbook(path)
ws = wb.active
ncols = ws.max_column
nrows= ws.max_row
titles = []
info = {}
data = []
for i in range(1, ncols+1):
titles.append(ws.cell(row=1,column=i).value)
# print(titles)
for row in range(2,nrows+1):
temp_list = []
for col in range(1, ncols+1):
temp_list.append(ws.cell(row=row,column=col).value)
data.append(temp_list)
# print(data)
return data,titles
def save_excel(data,titles,path = None):
if path == None:
path = 'Total.xlsx'
wb = openpyxl.Workbook()
ws = wb.active
for index, title in enumerate(titles):
ws.cell(row=1,column=index+1,value=title)
for row,item in enumerate(data):
for col,value in enumerate(item):
ws.cell(row=row+2,column=col+1,value=value)
wb.save(path)
if __name__ == '__main__':
print('Program is running...')
path = r'./.'
target_path = r'./.'
data = []
titles = ''
for filename in get_filenames(path):
titles = read_excel(filename)[-1]
for item in read_excel(filename)[0]:
if item not in data:
data.append(item)
save_excel(data,titles,target_path+os.sep+'Total.xlsx')
print('Success!')
三、 第一次进化
这个时候,其实对于python已经熟悉了一段时间了,也开始学习用pandas这个库做数据分析了,接触到这个库,顿时惊为神作,实在是太好用了,好东西必须安利呀。想要做数据分析,一定要溶入挖掘这个库。
# coding:utf-8
'''
@auth: Steven
@date: 2016-07-27
func: 合并目录下的所有excel文件,去重后存入新的excel
'''
import os
import pandas as pd
def get_filenames(path):
获取目录内所有文件名
filenames = []
for i in os.walk(path):
for filename in i[-1]:
full_filename = os.path.join(i[0],filename)
filenames.append(full_filename)
return filenames
def read_excel(filename):
读入excel,返回dataFrame
df = pd.read_excel(filename, index_col=None, headers = 0, na_values=['NA'])
return df
def merge_excel(datas,index):
合并数据,index为参考去重的列名
return pd.concat(datas,ignore_index=True).drop_duplicates(index)
if __name__ == '__main__':
print('Program is running...')
path = r'E:\Work'
target_path = r'E:\Work'
data = []
for filename in get_filenames(path):
data.append(read_excel(filename))
df = merge_excel(data)
df.to_excel(target_path+os.sep+'All.xlsx',index=False)
print('Success!')
四、 第二次进化
上一个版本,虽然把操作分离成了三个函数,但是仔细一想,其实没有这个必要,安全可以更简洁,于是就有了下面这个版本。Python的一大特点,就是特别像人的语言,直接可以像是读英语一样,理解整段代码,因些,注释这些写的极少。
#!/usr/bin/env python3.5
# -*- coding:utf-8 -*-
Function:
合并目录下的所有excel文件,去重后存入新的excel
Version: 2016-10-10
Author: Steven
Contact: lucibriel (at) 163.com
import os
import glob
import pandas as pd
def merge_excel(path, on):
合并数据
all_data = pd.DataFrame()
for f in glob.glob(path):
df = pd.read_excel(f)
all_data = all_data.append(df, ignore_index=True)
return all_data.drop_duplicates(on)
if __name__ == '__main__':
print('Program is running...')
path = r'./*'
target_path = r'./.'
df = merge_excel(path)
df.to_excel(os.path.join(target_path,Total.xlsx),index=False)
print('Success!')
其实后面我又改了很多次,后面有时间,我会把新版本再分享出来。此时,这个函数已经是一个很好的工具了,后面我其他的项目中有用到这个函数,直接就可以导入了。