辦公自動(dòng)化

從多層文件夾的多個(gè)excel中統(tǒng)計(jì)匯總各個(gè)文件夾和各個(gè)excel的全部SHEET中的指定數(shù)據(jù)。

一個(gè)文件夾,里面有多個(gè)子文件夾和多個(gè)excel表格,每個(gè)子文件夾里面也有多個(gè)子文件夾和多個(gè)excel表格,每個(gè)excel表格中有若干個(gè)SHEET。
每個(gè)excel表是每個(gè)員工自己制作的表格,其中每個(gè)sheet存儲(chǔ)著每個(gè)月的報(bào)銷(xiāo)清單,每個(gè)文件夾分類存放著每個(gè)小組的表格,這些小組的表格又放在他們的部門(mén)文件夾里,每個(gè)部門(mén)的文件夾放在分公司的文件夾里,再按分公司命名后放到總公司的文件夾里。
現(xiàn)在要統(tǒng)計(jì)里面的金額和條目數(shù),金額所在的列名,有的叫“(金 額)”,有的叫“B_A.金額”,這種里面只有“金額”兩個(gè)漢字的要統(tǒng)計(jì),還有的列叫“已報(bào)銷(xiāo)金額”,這種的不能被統(tǒng)計(jì)。
(總之,文件夾很多,層次很深,表格文件很多,可能還有其他非表格文件,SHEET很多,奇葩列名也有)
統(tǒng)計(jì)結(jié)果要按分公司、部門(mén)、小組、員工的層級(jí)分組。

實(shí)現(xiàn)

我把各個(gè)分公司的文件夾放在同一個(gè)文件夾中,給這個(gè)文件夾起個(gè)名字,叫“文件放這里”,然后用python編程來(lái)搞定這個(gè)統(tǒng)計(jì)任務(wù),運(yùn)行之前保證這個(gè)文件夾的所有文件沒(méi)有被其他軟件占用。

import os
import re
import pandas as pd


class 目錄樹(shù):
    def __init__(self):
        self.當(dāng)前目錄=''
        self.子樹(shù)=[]
        self.表格文件=[]
        self.各文件的總金額=[]
        self.各文件的總?cè)舜?[]

def 構(gòu)建樹(shù)(目錄):
    樹(shù) = 目錄樹(shù)()
    樹(shù).當(dāng)前目錄 = 目錄
    for i in os.listdir(目錄):
        path = 目錄+os.sep+i
        #print('讀取目錄',path)
        if os.path.isdir(path):
            樹(shù).子樹(shù).append(構(gòu)建樹(shù)(path))
        elif os.path.isfile(path):
            if len(i)> 4 and i[-4:]=='.xls'or len(i)> 5 and i[-5:]=='.xlsx':
                樹(shù).表格文件.append(path)
                總金額=0
                總?cè)舜?0
                #讀一下表格
                for df in pd.read_excel(path,sheet_name=None).values():
                    cs = df.columns.to_list()
                    #統(tǒng)計(jì)一下金額和人次(條目數(shù))
                    for i in cs:
                        if '金額' == ''.join(re.findall("[^A-Za-z0-9_().\s]",i)):
                            總金額 += df[i].sum()
                            總?cè)舜?+= df[i].count()
                            break
                樹(shù).各文件的總金額.append(總金額)
                樹(shù).各文件的總?cè)舜?append(總?cè)舜?
    return 樹(shù)

def 遍歷樹(shù)(節(jié)點(diǎn),索引表,索引棧,金額列表,人次列表):
    #節(jié)點(diǎn)入棧
    索引棧.append(os.path.basename(節(jié)點(diǎn).當(dāng)前目錄))
    #遍歷子節(jié)點(diǎn)
    for 子節(jié)點(diǎn) in 節(jié)點(diǎn).子樹(shù):
        遍歷樹(shù)(子節(jié)點(diǎn),索引表,索引棧,金額列表,人次列表)
    #遍歷文件
    for i in zip(節(jié)點(diǎn).表格文件,節(jié)點(diǎn).各文件的總金額,節(jié)點(diǎn).各文件的總?cè)舜?:
        索引棧.append(os.path.basename(i[0]).rstrip('.xlsx').rstrip('.xls'))
        索引表.append(tuple(索引棧[1:]))
        金額列表.append(i[1])
        人次列表.append(i[2])
        索引棧.pop(-1)
    #節(jié)點(diǎn)出棧
    索引棧.pop(-1)

path = os.getcwd()
l1 = os.listdir(path)
if '文件放這里' in l1:
    path = path+os.sep+'文件放這里'
    根節(jié)點(diǎn) = 構(gòu)建樹(shù)(path)
    索引表=[]
    索引棧=[]
    人次列表=[]
    金額列表=[]
    遍歷樹(shù)(根節(jié)點(diǎn),索引表,索引棧,金額列表,人次列表)

df = pd.DataFrame(索引表)
df['人次']=人次列表
df['金額']=金額列表
df = df.set_index([0,1,2,3])#分組層級(jí)有四層
df#這個(gè)df就是我要的結(jié)果

把多個(gè)excel文件中的SHEET1按其中的一列分組,每一組創(chuàng)建一個(gè)以該組的名稱命名的文件夾,把每一組的數(shù)據(jù)放進(jìn)一個(gè)excel表格(文件名還是原來(lái)的),再分別放到對(duì)應(yīng)組的文件夾中。

解決方法就像是郵遞員送信,把原始數(shù)據(jù)存放的文件夾(沒(méi)有子文件夾)和新的文件夾、代碼運(yùn)行目錄放在同一目錄下,然后運(yùn)行下面這個(gè)即可。有些列可能會(huì)從文本變?yōu)閿?shù)字,如果不想改變需要在讀取表格時(shí)設(shè)置converters。

import pandas as pd
import os
分組的列名="什么"
原始表格所在的文件夾='原始數(shù)據(jù)文件夾'
新表格存放的文件夾 = '新建文件夾'
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的時(shí)候,遇到換行符會(huì)被認(rèn)為是不同的行,然而,有的數(shù)據(jù)項(xiàng)本身就存在換行符“\n”……

辦法是加一個(gè)字段數(shù)校驗(yàn),每次必須讀入足夠的內(nèi)容:

with open('a.csv','r') as f:
    for line in f:
        s = line.split(',')
        print(s)
        l = len(s)
        break
    n0=eval('['+input('輸入要統(tǒng)計(jì)求和的每個(gè)統(tǒng)計(jì)量的索引,用半角逗號(hào)分割:')+']')
    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)

輸出表格的格式怎么修改

參考這個(gè):改to_excel()格式
寫(xiě)成python函數(shù)——直接在原有的表格上改變格式:

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:
                #對(duì)長(zhǎng)整數(shù)轉(zhuǎn)換存儲(chǔ)格式,避免精度丟失
                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))

(未完待續(xù),更過(guò)功能,持續(xù)更新)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容