为了公司DSR写的,有多个重复动作,所以把大方向定义成def函数,最后四次调用,最大限度让代码美观一点
import xlwings as xw
import win32com.client as win32
import datetime
# 程序运行的时候不显示在前端,也不新建Excel窗口
app = xw.App(visible=False, add_book=False)
# 定义一个时间函数,用来生成文件名的一部分
def yesterday():
today = datetime.date.today()
oneday = datetime.timedelta(days=1)
yesterday = today - oneday
return yesterday
# 时间定义结束
ywb = ['福建部',"浙江部", "河南部", "江西部", "海南部", "广东部"]
syb = ['事业一部合计', '事业二部合计', '事业三部合计']
yys = ['厦门所', '杭州所', '济南所']
fjq = ['浙江区']
# -----------------以下是一个DSR()函数,函数有2个参数,a和b-----------------------------------------
# 第一个参数a:表达组织机构(ywb,syb,yys,fjq)
# 第二个参数b:表示在哪一列寻找匹配a的数值,syb应输入1,fuq、ywb和yys应输入2
def DSR(a, b):
for i in range(0, len(a)): # 这是循环的开始,读取业务部的数量,每个业务部作为一个最大的循环
# print(i)
iw = app.books.open(r'E:\Documnet\工作\07_数据分析\临时文件\副本.xlsm')
sheet_count = iw.sheets.count # 读取整个工作簿的sheet数量
# 由于源文件里还有很多隐藏的工作表不可以下发给各区域,而所有文件格式都#是一样,因此这里定义了一个函数first_sheet()
# 用来读取第一个“全品项销额”在工作表中的位置,并以此作为下发给区域的第一个表格
def first_sheet():
for ii in range(0, sheet_count):
if iw.sheets[ii].name == "全品项销额":
return ii
# break # 写代码的时候测试用,阶段性中断程序
# range左闭右开,所以需要需要页面总数+1,与python计数序列从0开始的习惯不同,xlwings的行列计数都是从1开始,下面会用到
for sht in range(first_sheet(), sheet_count + 1): # 开始对每个页面做循环
oldsht = iw.sheets(sht)
# print(oldsht.name)
rownumber = oldsht.range('A10000').end('up').row
# 另一个写法是rownumber = oldsht.used_range.last_cell.row
# print(rownumber)
# 由于暂无法实现先复制再粘贴,所以我用的是直接在源文件里改动,然后另存为的办法
# 以下这个循环是先从最后一行往上找,直到找到对应的单元格,rownumber和1表示范围, -1表示每次循环的step
if a == yys: # 当a是业务所时,根据以下规则进行判断
for fj in range(rownumber, 4, -1): # 先把福建区删除
if oldsht.cells(fj, b).value == '福建区':
oldsht.range(str(fj) + ':' + str(fj)).delete()
break
if i == 0:
oldsht.range('6:500').delete()
else:
for r3 in range(rownumber,4,-1):
if oldsht.cells(r3,b).value == a[i]:
oldsht.range(str(r3 + 1) + ':' + str(500)).delete()
oldsht.range('5' + ':' + str(r3-1)).delete()
break
elif a == fjq:
for r5 in range(rownumber, 1, -1):
if oldsht.cells(r5, b).value == a[i]:
oldsht.range(str(r5 + 1) + ':' + str(500)).delete()
break
else:
# 当a为ywb和syb时根据以下规则
for fj in range(rownumber, 4, -1): # 先把浙江区删除
if oldsht.cells(fj, b).value == '浙江区':
oldsht.range(str(fj) + ':' + str(fj)).delete()
break
for r1 in range(rownumber, 1, -1):
# print(oldsht.cells(r,2).value)
# print(oldsht.cells(r,2).value)
# print(ywb[i])
if oldsht.cells(r1, b).value == a[i]:
# 可以用range直接表示行或者列,但是无论是行还是列都应以文本形式出现,字母指代列,数字指代行
oldsht.range(str(r1 + 1) + ':' + str(500)).delete()
break
# 由于目标业务部的上方还有可能有其他的业务部,因此,还需要从上往下再删一次
# print('阶段一完成')
while i != 0:
for r2 in range(5, rownumber):
if oldsht.cells(r2, b).value == a[i - 1]:
oldsht.range('5' + ':' + str(r2)).delete()
break
break
# print('阶段二完成')
# ----以上就是把不需要的行都删除了
# -----以下是调用宏,把原有的组合取消,并取消隐藏的行,宏代码如下:
'''
Sub ungroup()
Rows("3:150").ClearOutline
Rows("3:150").EntireRow.Hidden = False
Range("B5").Select
End Sub
'''
oldsht.activate()
ungroup = iw.macro('ungroup')
ungroup()
# -----然后下面的循环是把多余的sheet删除,一共有多少个sheet,就删多少次
for iii in range(0, first_sheet()):
iw.sheets[0].delete()
print('sheet操作完成')
# -----多余sheet删除完毕
# 最后让第一个sheet成为active sheet
iw.sheets[0].activate()
# 由于试了很多办法,都没有简便的办法先将sheet带格式复制出来再粘贴,只好反其道而行之,直接在源文件
# 中做改变,然后将改变后的源文件另存为并关闭
iw.save(r'E:\Documnet\工作\07_数据分析\临时文件\test' + '\\' + a[i] + '.xlsm')
iw.close()
# 到这里改造基本完成,但问题是由于源工作簿中有宏,所以必须另存为xlsm格式,xlwings暂时没找到直接另存为xlsx的办法
# 因此只能用win32com模块调用excel本身的saveas接口进行另存为操作,正好发邮件也得用到win32com
# --------------以下是另存为xlsx
xlApp = win32.DispatchEx("Excel.Application")
xlApp.Visible = False
xlApp.DisplayAlerts = 0
xlBook = xlApp.Workbooks.Open(r'E:\Documnet\工作\07_数据分析\临时文件\test' + '\\' + a[i] + '.xlsm', False)
xlBook.SaveAs(r'E:\Documnet\工作\07_数据分析\临时文件\test' + '\\' + a[i] + '.xlsx', FileFormat=51)
# 上面的FileFormat是调用了Excel本身的SaveAs接口,51就是xlsx的代码
xlBook.Close(False)
xlApp.Quit()
# -------------另存为结束
# ---------以上是获取工作簿并进行操作,以下是进行邮件操作,用到的模块为win32----------#
outlook = win32.Dispatch('Outlook.Application')
Mail_Item = outlook.CreateItem(0)
Mail_Item.Recipients.Add('[email protected]')
# 应先在邮箱通讯录中建立邮件组,直接输入邮件组名字可以发送
Mail_Item.Subject = str(yesterday()) + '日报表' + a[i]
Mail_Item.BodyFormat = 2
Mail_Item.HtmlBody = '''
Hello Guys,
This a Mail send by Jerry'''
Mail_Item.Attachments.Add(r'E:\Documnet\工作\07_数据分析\临时文件\test' + '\\' + a[i] + '.xlsx')
Mail_Item.Save()
# ------------邮件发送完成----------------------------------------------------------#
print(a[i] + '完成')
app.quit()
DSR(syb,1)
DSR(ywb,2)
DSR(yys,2)
DSR(fjq,2)