【python】自动化办公之excel常用操作实战详解(xlwings)

新建excel?获取最大行列?复制行列?复制sheet页?sheet页重命名?多文件整合?

本篇结合实际工作内容,使用xlwings包实现excel表格相关最最常用功能。

介绍

py版本:python 3.7

目标在历史账期文件的基础上,把一堆文件按照格式整合成一个文件。
在这里插入图片描述
每个文件包含’报表-内部’, ‘报表-局方’, ‘数据与部署’, ‘汇总’,'功能矩阵’sheet页。整合方式各不相同,‘报表-局方’页内容直接复制到新页,'汇总’页按照行复制新表,‘功能矩阵’页按照列复制新表。

结果:
红色为一堆文件中直接复制的,非红框为取部分有用数据整行或整列复制,其中绿色框中有历史附件复制来的。
在这里插入图片描述

思路

  1. 新建excel。方法名new_excel(acctmonth),参数账期,,返回新文件路径。
  2. 上月账期部分内容复制新建excel中。方法名copy_lastmonth_data(lastmfilePath, newfilePath),参数历史账期文件路径和新文件路径。
  3. 一堆文件获取有用信息复制到新文件中。方法名copy_totalexcel(acctmonth,newfilePath),参数为账期和新文件路径。先遍历文件,后遍历sheet页,将信息分批存到对应页中。
  4. 通用方法,获取sheet页中最大行和最大列。方法名get_row_col(fileName, sheetName),参数为文件名和sheet页名,返回最大行数和列数。

脚本

# encoding=utf-8
import os,re
import pywintypes

os.chdir(r'E:\work\7.***\**使用情况')
path = os.getcwd()
import xlwings as xw


def new_excel(acctmonth):
    "创建新账期文件"
    newfileName = '**使用情况-' + acctmonth + '.xlsx'
    wb = xw.Book()
    try:
        wb.save(newfileName)
    except pywintypes.com_error:
        print('同名文件已打开' + newfileName)
        wb2 = xw.Book(newfileName)
        wb2.close()
        wb.save(newfileName)
        print('文件创建成功')
    else:
        print('文件创建成功')
    finally:
        newfilePath = path + '\\' + newfileName
        print(newfilePath)
        wb.close()
    return newfilePath


def copy_lastmonth_data(lastmfilePath, newfilePath):
    "上月账期部分内容复制新建excel中"
    sheetnames = [u'数据与部署', '内部', '局方', '总结']
    wbLast = xw.Book(lastmfilePath)
    wbNew = xw.Book(newfilePath)
    wbNew.sheets('sheet1').name = '功能矩阵'
	#自带sheet1页重命名成'功能矩阵'
    for sheetname in sheetnames:
        wsLast = wbLast.sheets(sheetname)
        wsLast.api.Copy(Before=wbNew.sheets(1).api)
        #将wsLast也直接复制到wbNew文件中


def get_row_col(fileName, sheetName):
    "获取fileName文件中sheetName页有数据的最大行数和列数"

    wb = xw.Book(fileName)
    ws = wb.sheets(sheetName)

    info = ws.used_range
    nrows = info.last_cell.row
    ncols = info.last_cell.column

    return nrows, ncols

以下是最复杂的方法了,由于存在敏感信息,所以过滤掉部分信息,可能不太好理解实际效果,尽量还原需求和结果。


def copy_totalexcel(acctmonth, newfilePath):
    "项目文件数据迁移处理"

    projectnames = ['辽宁', '山西','吉林', '广西', '河北', '宁夏', '黑龙江']
    #一堆文件后缀内容,遍历文件使用

    sheetnames = ['报表-内部', '报表-局方', '数据与部署', '汇总','功能矩阵']
    #一堆文件的sheet页名,遍历使用
    sheetnameNb = '内部'
    sheetnameJf = '局方'
    num = 0
    row_col2 = []
    row_col3 = []
    row_col4 = []
    wbNew = xw.Book(newfilePath)

    for projectname in reversed(projectnames):
        # 项目文件路径
        fileProPath = path + '\\' + acctmonth + '\\**使用情况-' + projectname + '.xlsx'
        try:
            wbPro = xw.Book(fileProPath)

            for index in range(len(sheetnames) ):
                # 1. 将外部/内部页复制新文件中
                if '-' in sheetnames[index]:
                    # 页面名称,如:辽宁-局方
                    newsheet = projectname + '-' + sheetnames[index].split('-')[1]

                    # 获取项目文件中局方和内部的报表页
                    wsPro1 = wbPro.sheets(sheetnames[index])
                    # 将wb1页复制到wb2里
                    wsPro1.api.Copy(Before=wbNew.sheets(1).api)
                    # 复制后的页面重命名
                    wbNew.sheets(1).name = newsheet

                # 2. 将'数据与部署'分别复制到新文档中
                elif sheetnames[index] == '数据与部署':
                    
                    try:
                        #获取项目文件中A2:N2的数据
                        wsPro2 = wbPro.sheets(sheetnames[index])
                        infoPro = wsPro2.range('A2:N2')
                        #复制到新文件的最后一行
                        wsNew2 = wbNew.sheets(sheetnames[index])

                        if num == 0:
                        #因为此sheet页有历史账期内容,不能从第一行开始粘贴数据,所以初次先获取此页做大行数
                            row_col2 = get_row_col(newfilePath, sheetnames[index])
                        wsNew2.api.Rows(row_col2[0] + 1).Insert()
                        #从此页最后一行插入一条
                        wsNew2.range('A' + str(row_col2[0] + 1)).value = infoPro.value
                        #从此页最后一行粘贴新数据

                    except pywintypes.com_error:
                        print(projectname+'文件没有sheet页:'+sheetnames[index])
                        #由于文件不规范,可能存在sheet页命名错误情况,忽略不计
                        continue

                    # 3. 将'局方汇总和内部汇总'分别复制到新文档中
                elif sheetnames[index] == '汇总':
                    try:
                        # 获取项目文件中的数据
                        wsPro3 = wbPro.sheets(sheetnames[index])
                        if wsPro3.range('A2').value == sheetnameJf:
                            # 获取项目文件中的内部行到新文件中'局方'sheet页
                            wsNew3 = wbNew.sheets(sheetnameJf)
                            infoPro = wsPro3['E2:P2']

                            if num == 0:
                                row_col3 = get_row_col(newfilePath, sheetnameJf)
                            wsNew3.api.Rows(row_col3[0] + 1).Insert()
                            wsNew3.range('A' + str(row_col3[0] + 1)).value = acctmonth
                            wsNew3.range('B' + str(row_col3[0] + 1)).value = projectname
                            #前两列数据比较特殊直接赋值即可
                            wsNew3.range('C' + str(row_col3[0] + 1)).value = infoPro.value
                            

                        if wsPro3.range('A3').value == sheetnameNb:
                            # 获取项目文件中的内部行到新文件中'内部'sheet页
                            wsNew4 = wbNew.sheets(sheetnameNb)
                            infoPro = wsPro3['B3:P3']

                            if num == 0:
                                row_col4 = get_row_col(newfilePath, sheetnameNb)

                            wsNew4.api.Rows(row_col3[0] + 1).Insert()
                            wsNew4.range('A' + str(row_col3[0] + 1)).value = infoPro.value

                    except pywintypes.com_error:
                        print(projectname + '文件没有sheet页:' + sheetnames[index])
                        continue

                # 4. 将功能矩阵加到新文件中
                elif sheetnames[index] == '功能矩阵':
                    wsPro4 = wbPro.sheets(sheetnames[index])
                    wsNew5 = wbNew.sheets(sheetnames[index])
                    if num == 0:
                    #前四列是列数据的表头格式统一,所以在第一次操作时复制,之后不必操作
                        wsPro4.api.Columns(1).Copy(wsNew5.api.Columns(1))
                        wsPro4.api.Columns(2).Copy(wsNew5.api.Columns(2))
                        wsPro4.api.Columns(3).Copy(wsNew5.api.Columns(3))
                        wsPro4.api.Columns(4).Copy(wsNew5.api.Columns(4))
                        # 复制wsPro4列值到wsNew5列中,可以带格式复制
                    wsNew5.api.Columns(5).Insert()
                    wsPro4.api.Columns(5).Copy(wsNew5.api.Columns(5))

            num = num + 1
        except FileNotFoundError:
            print('No such file:' + fileProPath)
            #存在文件不全情况,忽略继续
            continue

    # 删除sheet页
    #wbNew.sheets('sheet1').delete()
    wbNew.save()
    #保存文件
    wbNew.app.quit()
    #退出

    print('SUCCESS!')
    #大功告成!

调用代码

if __name__ == '__main__':

    acctmonth = '202004'
    # 新建文件
    newfilePath = new_excel(acctmonth)
    lastmfilePath = path + '\\**使用情况-202003.xlsx'
    # 历史账期数据迁移
    copy_lastmonth_data(lastmfilePath, newfilePath)
    # 一堆文件获取有用信息复制到新文件中
    copy_totalexcel(acctmonth,newfilePath)

相关文章:
【python】自动化办公之定时发送邮件实战详解(apscheduler+smtplib)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章