新建excel?獲取最大行列?複製行列?複製sheet頁?sheet頁重命名?多文件整合?
本篇結合實際工作內容,使用xlwings包實現excel表格相關最最常用功能。
介紹
py版本:python 3.7
目標在歷史賬期文件的基礎上,把一堆文件按照格式整合成一個文件。
每個文件包含’報表-內部’, ‘報表-局方’, ‘數據與部署’, ‘彙總’,'功能矩陣’sheet頁。整合方式各不相同,‘報表-局方’頁內容直接複製到新頁,'彙總’頁按照行復制新表,‘功能矩陣’頁按照列複製新表。
結果:
紅色爲一堆文件中直接複製的,非紅框爲取部分有用數據整行或整列複製,其中綠色框中有歷史附件複製來的。
思路
- 新建excel。方法名new_excel(acctmonth),參數賬期,,返回新文件路徑。
- 上月賬期部分內容複製新建excel中。方法名copy_lastmonth_data(lastmfilePath, newfilePath),參數歷史賬期文件路徑和新文件路徑。
- 一堆文件獲取有用信息複製到新文件中。方法名copy_totalexcel(acctmonth,newfilePath),參數爲賬期和新文件路徑。先遍歷文件,後遍歷sheet頁,將信息分批存到對應頁中。
- 通用方法,獲取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)