新建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)