使用这种方式合并上万个excel表不要1分钟

一、 问题

由于工作需要,经常会有大量的excel表格需要合并,比如来自不同货代按月发过来的运费,还有来自ERP系统导出用来分析销售的订单表,这样的表格在工作其实有很多。不过他们大多数都是按月或者其他时间段分成了各自零散的文件,有时候要整理分析的时候就特别麻烦,而这时,快速合并这些文件,就变得很有必要的一个操作了。

二、 开始冒险

为了应对这个任务,我用上一个极为有用的工具,那就是Python,数据分析的神器呀,简直是哪里不爽点哪里,哈哈。

这里记录了,我从刚开始使用Python来解决这个问题,到后面一步一步提升,用上更好的方法或者说更简便的方法的过程,也是分享给新手的一个启发,看问题是怎么解决,又是怎么进化的。

这里没有记录怎么安装Python,默认是当作大家已经知道了,当然你如果真的还不知道的话也没关系,网上找找有很多资料,后期,我也会专门写一些入门的内容供大家学习参考。

问题分解

  1. 要合并文件夹内的excel
  2. 首先,要找到能够操作文件夹的库,这个库应该是能够遍历文件夹内的所有文件
  3. 然后,要找到能够操作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!')

其实后面我又改了很多次,后面有时间,我会把新版本再分享出来。此时,这个函数已经是一个很好的工具了,后面我其他的项目中有用到这个函数,直接就可以导入了。

猜你喜欢

转载自blog.csdn.net/lucibriel/article/details/90200367