办公自动化

从多层文件夹的多个excel中统计汇总各个文件夹和各个excel的全部SHEET中的指定数据。

一个文件夹,里面有多个子文件夹和多个excel表格,每个子文件夹里面也有多个子文件夹和多个excel表格,每个excel表格中有若干个SHEET。
每个excel表是每个员工自己制作的表格,其中每个sheet存储着每个月的报销清单,每个文件夹分类存放着每个小组的表格,这些小组的表格又放在他们的部门文件夹里,每个部门的文件夹放在分公司的文件夹里,再按分公司命名后放到总公司的文件夹里。
现在要统计里面的金额和条目数,金额所在的列名,有的叫“(金 额)”,有的叫“B_A.金额”,这种里面只有“金额”两个汉字的要统计,还有的列叫“已报销金额”,这种的不能被统计。
(总之,文件夹很多,层次很深,表格文件很多,可能还有其他非表格文件,SHEET很多,奇葩列名也有)
统计结果要按分公司、部门、小组、员工的层级分组。

实现

我把各个分公司的文件夹放在同一个文件夹中,给这个文件夹起个名字,叫“文件放这里”,然后用python编程来搞定这个统计任务,运行之前保证这个文件夹的所有文件没有被其他软件占用。

import os
import re
import pandas as pd


class 目录树:
    def __init__(self):
        self.当前目录=''
        self.子树=[]
        self.表格文件=[]
        self.各文件的总金额=[]
        self.各文件的总人次=[]

def 构建树(目录):
    树 = 目录树()
    树.当前目录 = 目录
    for i in os.listdir(目录):
        path = 目录+os.sep+i
        #print('读取目录',path)
        if os.path.isdir(path):
            树.子树.append(构建树(path))
        elif os.path.isfile(path):
            if len(i)> 4 and i[-4:]=='.xls'or len(i)> 5 and i[-5:]=='.xlsx':
                树.表格文件.append(path)
                总金额=0
                总人次=0
                #读一下表格
                for df in pd.read_excel(path,sheet_name=None).values():
                    cs = df.columns.to_list()
                    #统计一下金额和人次(条目数)
                    for i in cs:
                        if '金额' == ''.join(re.findall("[^A-Za-z0-9_().\s]",i)):
                            总金额 += df[i].sum()
                            总人次 += df[i].count()
                            break
                树.各文件的总金额.append(总金额)
                树.各文件的总人次.append(总人次)
    return 树

def 遍历树(节点,索引表,索引栈,金额列表,人次列表):
    #节点入栈
    索引栈.append(os.path.basename(节点.当前目录))
    #遍历子节点
    for 子节点 in 节点.子树:
        遍历树(子节点,索引表,索引栈,金额列表,人次列表)
    #遍历文件
    for i in zip(节点.表格文件,节点.各文件的总金额,节点.各文件的总人次):
        索引栈.append(os.path.basename(i[0]).rstrip('.xlsx').rstrip('.xls'))
        索引表.append(tuple(索引栈[1:]))
        金额列表.append(i[1])
        人次列表.append(i[2])
        索引栈.pop(-1)
    #节点出栈
    索引栈.pop(-1)

path = os.getcwd()
l1 = os.listdir(path)
if '文件放这里' in l1:
    path = path+os.sep+'文件放这里'
    根节点 = 构建树(path)
    索引表=[]
    索引栈=[]
    人次列表=[]
    金额列表=[]
    遍历树(根节点,索引表,索引栈,金额列表,人次列表)

df = pd.DataFrame(索引表)
df['人次']=人次列表
df['金额']=金额列表
df = df.set_index([0,1,2,3])#分组层级有四层
df#这个df就是我要的结果

把多个excel文件中的SHEET1按其中的一列分组,每一组创建一个以该组的名称命名的文件夹,把每一组的数据放进一个excel表格(文件名还是原来的),再分别放到对应组的文件夹中。

解决方法就像是邮递员送信,把原始数据存放的文件夹(没有子文件夹)和新的文件夹、代码运行目录放在同一目录下,然后运行下面这个即可。有些列可能会从文本变为数字,如果不想改变需要在读取表格时设置converters。

import pandas as pd
import os
分组的列名="什么"
原始表格所在的文件夹='原始数据文件夹'
新表格存放的文件夹 = '新建文件夹'
for i in os.listdir(原始表格所在的文件夹):
    df = pd.read_excel('{}{}'.format(原始表格所在的文件夹,os.sep+i),converters={i:str for i in ['必需保留原文的列1的字段名','必需保留原文的列2的字段名']})
    a = df[分组的列名].drop_duplicates()
    for j in a.values:
        k = df[df[分组的列名]==j]
        r = k.set_index(df.columns.values[0])
        new_dir ='{}{}'.format(新表格存放的文件夹,os.sep+j)
        if not os.path.exists(new_dir):
            os.mkdir(new_dir)
        r.to_excel(new_dir+'{}.xlsx'.format(os.sep+i.split('.')[0]))

合并excel

在逐行读取CSV的时候,遇到换行符会被认为是不同的行,然而,有的数据项本身就存在换行符“\n”……

办法是加一个字段数校验,每次必须读入足够的内容:

with open('a.csv','r') as f:
    for line in f:
        s = line.split(',')
        print(s)
        l = len(s)
        break
    n0=eval('['+input('输入要统计求和的每个统计量的索引,用半角逗号分割:')+']')
    sum0=[0 for i in n0]
    is_all=True
    for line in f:
        print(line)
        if is_all:
            s = line.split(',')
        else:
            new = line.split(',')
            s[-1] = s[-1]+new[0]
            s += new[1:]
        if len(s)==l:
            is_all=True
            j=0
            for i in n0:
                sum0[j]+=eval(s[i])
                j+=1
        else:
            is_all=False
    print(sum0)

输出表格的格式怎么修改

参考这个:改to_excel()格式
写成python函数——直接在原有的表格上改变格式:

def format_excel(filepath):
    if filepath[-4:].lower()=='.xls' or filepath[-5:].lower()=='.xlsx':
        dfs= pd.read_excel(filepath,sheet_name=None)
        writer = pd.ExcelWriter(filepath,engine="xlsxwriter")
        for sname,df in dfs.items():
            for cname in df:
                #对长整数转换存储格式,避免精度丢失
                if df[cname].dtype == 'int64' and (df[cname]>9999999).any():
                    df[cname] = df[cname].astype('object')
            df.to_excel(writer, sheet_name=sname,index=False)
        #格式化输出
        workbook = writer.book
        worksheets = writer.sheets
        #在这里自定义表头格式
        header_format = workbook.add_format({'font_size': 9,'border': 0,'bold':True})
        ##在这里自定义每一列的单元格格式
        cell_format = workbook.add_format({'font_size': 9,'border': 0})
        for sname, df in dfs.items():
            worksheet = worksheets[sname]
            #每列改一遍
            for col_num, value in enumerate(df.columns.values):
                worksheet.write(0, col_num, value, header_format)
                worksheet.set_column(col_num,col_num, len(value)*1.6, cell_format)
        writer.save()
        writer.close()
        print('文件“{}”格式化已完成'.format(filepath))
    else:
        print('文件“{}”不是电子表格'.format(filepath))

(未完待续,更过功能,持续更新)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,311评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,339评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,671评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,252评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,253评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,031评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,340评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,973评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,466评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,937评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,039评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,701评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,254评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,259评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,485评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,497评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,786评论 2 345