neolee / pilot

进入编程世界的第一课
588 stars 842 forks source link

自动化案例中读文件目录下多个文件并汇总到总表 #1192

Open denzii818 opened 4 years ago

denzii818 commented 4 years ago

老师,帮忙看下这个代码错在哪里?怎么改才能将我目录下的所有excel文件里的数据洗出、汇总到row里再存到All里面去? 说明:按照视频,前面的按照写死的方法是可以读出目录下文件一个excel,并且将其中的想要的数据洗出来放到row[]里面,并且另存为All。但是,不能多多个表格再汇总。

for q in p.glob("**/[!All]*.xlsx"):
   print(q.name)

如何将改呢?我试了几遍,但是都报错,找不到相应文件,前面代码是按照老师视频步骤进行的。 p = Path(CWD)了。

试法1:

for q in p.glob("**/[!All]*.xlsx"):
    df = pd.read_excel('C:/Users/dengyajun/Code/lear-git/assets/expenses/q.name',header=None)
    total = df.loc[df[0] == "总计"]

    row ={}
    row["姓名"] = df.iloc[2,0]

结果1:报错,找不着路径

试法2:

for q in p.glob("**/[!All]*.xlsx"):
    df = pd.read_excel('p/q.name',header=None)
    total = df.loc[df[0] == "总计"]

    row ={}
    row["姓名"] = df.iloc[2,0]

结果2:错误,找不着路径

neolee commented 4 years ago

如果你的 p 是指向存放你的 Excel 文件们的目录的 Path 对象的话,那么:

for q in p.glob('**/[!All]*.xlsx'):
    print(q.name)

这段代码应该能打印出该目录下所有的 .xlsx 文件(除了 All 打头的)。这一步有没有问题?

你在后面列出的代码都有问题,问题就是你组装 pq 的方法不对,下面两种方法都可以:

for q in p.glob('**/[!All]*.xlsx'):
    df = pd.read_excel(q, header=None)
    ...
for q in p.glob('**/[!All]*.xlsx'):
    df = pd.read_excel(p / q.name, header=None)
    ...

思考一下为什么这两个都可以,你的写法错在哪里。必要的话去学习下 pathlib 的文档。

denzii818 commented 4 years ago

可以了,谢谢老师!分析下错误: 了解了下:pandas.read_excel(io,sheet_name = 0,header = 0,names = None,index_col = None,usecols = None,squeeze = False,dtype = None, ...) io:字符串,文件的路径对象。 前面代码已经:

CWD = "C:/Users/dengyajun/Code/lear-git/assets/expenses"
from pathlib import Path
p = Path(CWD)

因为p已经指向存放Excel 文件们的目录 Path 对象,所以,直接p就实际已经指向到对应文件夹。 通过运行: for q in p.glob("**/[!All]*.xlsx"): 使得q指向了p路径下(文件夹)对应符合条件的excel文件对象,所以再通过 pd.read_excel()函数去读指定的q所指向的excel文件中的数据时,只需要将pd.read_excel()函数中的第一个参数直接用q就行,q已经指定了到了文件的路径对象。 而,若传入参数是:p / q.name,则是不是这样理解:将一个完整路径/文件名传给read_excel()函数第一个参数,也是指定了对应文件路径下的一个具体的文件。因为通过文件名可以找到这个excel文件。

所以,我改完以后,下面这段代码就实现了将多个excel文件整合成我想要的一个数据总表,并存成一个新的excel文件。

rows = []

for q in p.glob("**/[!All]*.xlsx"):
    df = pd.read_excel(q,header=None)
#    df = pd.read_excel(p / q.name,header=None)
    total = df.loc[df[0] == "总计"]

    row ={}

    row["电子审批单号"] = q.name
    row["姓名"] = df.iloc[2,1]
    row["部门"] = df.iloc[2,3]
    row["月份"] = df.iloc[2,29]
    row["报销时间"] = df.iloc[2,2].to_pydatetime()
    row["预算编号"] = df.iloc[2,4]
    row["差旅费"] = total.iloc[0,5]
    row["交通费"] = total.iloc[0,6]
    row["招待费"] = total.iloc[0,7]
    row["总计"] = total.iloc[0,27]

    print(row)
    rows.append(row)

df_all = pd.DataFrame(rows)  
df_all

writer = pd.ExcelWriter("C:/Users/dengyajun/Code/lear-git/assets/expenses/zongbiao.xls",engine="xlwt")
df_all.to_excel(writer,sheet_name='报销汇总表')
#df_all.to_excel(writer)
writer.save()

但是,在调试过程中,发现两个问题: 1、上面函数的写入地址可否简化? pd.ExcelWriter("C:/Users/dengyajun/Code/lear-git/assets/expenses/zongbiao.xls",engine="xlwt") 除了: pd.ExcelWriter("./assets/expenses/zongbiao.xls",engine="xlwt") 之外,还否有如读函数时用到的已有路径p,为什么p/zongbiao.xls不行呢?提示zongbiao.xls没有定义。 2、在save()时,若文件夹已有文件zongbiao.xls,直接会将源文件覆盖,有什么办法提示可以选择替换或者另存为。

neolee commented 4 years ago
  1. pd.ExcelWriter 的参数可以是绝对路径也可以是相对路径;如果要使用 pathlib,假定你的工作根目录保存在一个 Path 类型的对象 p 里,而你要使用 p 下面 /1/working.xls 的文件,你要这么写:

    file_str = str(p / "1/working.xls")
    pd.ExcelWriter(file_str)
  2. 这个需要你在调用 save 之前自己去检查下要 save 的文件是不是已经存在。