【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)

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