本节介绍几个比较实用的综合实例,通过实战来加强对Excel VBA和Python xlwings包的学习和理解。
批量新建和删除工作表
Excel脚本开发的好处之一就是可以让计算机自动处理批量任务,大幅提高工作效率,避免出错。本小节使用Excel VBA和Python xlwings包批量新建和删除工作表。
一、批量新建工作表
下面使用for循环,利用Worksheets对象的Add方法批量新建工作表。
图1-26 批量新建工作表
【Excel VBA】
示例文件的存放路径为Samples\ch013\Excel VBA\示例1\批量创建和删除工作表.xlsm。
Sub ShtAdd10()
Dim intI As Integer
For intI = 1 To 10 '批量新建10个工作表
'新建的工作表放在所有工作表的最后面
Sheets.Add After:=Sheets(Sheets.Count)
Next
End Sub
运行过程,批量新建10个工作表如图1-26所示。
【Python】
本示例的py文件保存路径为Samples\ch13\Python\示例1-1中,文件名为sam1-101.py。
import xlwings as xw #导入xlwings包,别名为xw
app=xw.App() #创建Excel应用对象
bk=app.books(1) #获取工作簿对象
for i in range(1,11): #批量新建10个工作表
#新建的工作表放在所有工作表的最后面
bk.api.Worksheets.Add(After=bk.api.Worksheets(bk.api.Worksheets.Count))
在Python IDLE文件脚本窗口,在"Run"菜单中单击"Run Module"选项,批量新建10个工作表如图1-所示。
二、批量删除工作表
【Excel VBA】
示例文件的存放路径为Samples\ch013\Excel VBA\示例1\批量创建和删除工作表.xlsm。注意删除工作表时必须是从后往前删,这样删剩下的工作表的索引号不会变。
Sub ShtDelete10()
Dim intI As Integer
Application.DisplayAlerts = False
For intI = 11 To 2 Step -1 '批量删除10个工作表
Sheets(intI).Delete
Next
Application.DisplayAlerts = True
End Sub
运行过程,批量删除10个工作表。
【Python】
本例使用for循环,利用Sheets对象的Delete方法批量删除指定工作簿中的工作表。该工作簿文件的存放路径为Samples\ch13\Python\示例1-2\test01.xlsx,其中共有11个工作表,编号从1-11从前往后依次排列。本示例的py文件保存路径为Samples\ch13\Python\示例1-2中,文件名为sam1-102.py。注意删除工作表时是从后往前删的。
import xlwings as xw #导入win32com包
import os #导入os包
root=os.getcwd() #获取本py文件当前目录
#创建Excel应用对象,可见,不添加工作簿
app=xw.App(visible=True, add_book=False)
#打开当前目录下的test01.xlsx文件,返回工作簿对象
bk=app.books.open(fullname=root+r"\test01.xlsx",read_only=False)
app.display_alerts=False #后面删除工作表的时候不弹出提示信息对话框
for i in range(11,1,-1): #批量删除10个工作表
bk.api.Sheets(i).Delete()
app.display_alerts=True
在Python IDLE文件脚本窗口,在"Run"菜单中单击"Run Module"选项,从后往前批量删除10个工作表。
按工作表某列分类拆分到多个工作表
现有各部门工作人员信息如图1-27处理前工作表中所示。现在要根据第1列的值对工作表数据进行拆分,每个部门的人员信息归总到一起组成一个新表,表的名称为该部门的名称。拆分的思路是遍历工作表的每一行,如果以部门名称命名的工作表不存在,则创建该名称的新表;如果已经存在,则将该行信息追加到该已经存在的工作表中。
图1-27 按部门拆分工作表到多个新表
下面用Excel VBA和xlwings包进行拆分。
【Excel VBA】
示例文件的存放路径为Samples\ch013\Excel VBA\示例2\各部门员工.xlsm。
Sub CF()
'按工作表A列分类拆分到多个工作表
Dim lngI As Long, lngJ As Long
Dim strT As String, strS As String
Dim lngN As Long, lngR As Long
Application.ScreenUpdating = False '取消窗口重画
Application.DisplayAlerts = False '取消警告提示信息对话框的显示
'遍历数据表的每一行
For lngI = 2 To Range("A" & Rows.Count).End(xlUp).Row
Worksheets("汇总").Select
strT = Range("A" & lngI).Text '获取该行所属部门名称
If InStr(strS, strT) = 0 Then '
'如果是新部门,添加名称到strS,复制表头和数据
strS = strS & strT & " "
Worksheets.Add after:=Worksheets(Worksheets.Count)
ActiveSheet.Name = strT
Worksheets("汇总").Rows(1).Copy ActiveSheet.Rows(1)
Worksheets("汇总").Rows(lngI).Copy ActiveSheet.Rows(2)
Else
'如果是已经存在的部门名称,直接追加数据行
Worksheets(strT).Select
lngR = ActiveSheet.Range("A" & ActiveSheet.Rows.Count).End(xlUp).Row + 1
Worksheets("汇总").Rows(lngI).Copy ActiveSheet.Rows(lngR)
End If
Next
'删除新生成的工作表的第一列
For intI = 2 To Worksheets.Count
Worksheets(intI).Columns(1).Delete
Next
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
运行过程,拆分工作表,效果如图1-27所示。
【Python】
使用xltings包进行拆分的代码如下所示。本示例的数据文件存放路径为Samples\ch13\ Python\示例2\各部门员工.xlsx,py文件保存在相同目录下,文件名为sam1-103.py。
import xlwings as xw #导入xlwings包
#导入xlwings.constants模块中的Direction类
from xlwings.constants import Direction
import os # 导入os模块
root = os.getcwd() #获取当前工作目录,即本py文件所在目录
#创建Excel应用对象,可见,不添加工作簿
app=xw.App(visible=True, add_book=False)
#打开当前目录下的各部门员工.xlsx文件,可写,返回工作簿对象
bk=app.books.open(fullname=root+r"\各部门员工.xlsx",read_only=False)
app.screen_updating=False #取消窗口重画
app.display_alerts=False #取消警告提示信息对话框的显示
sht=bk.sheets(1) #获取“汇总”工作表
#获取该工作表中数据区域的行数
irow=sht.api.Range("A"+str(sht.api.Rows.Count)).End(Direction.xlUp).Row
strs=[] #创建空列表strs
for i in range(2,irow+1): #遍历数据表的每一行
sht2=bk.api.Worksheets("汇总") #获取“汇总”工作表
strt=sht2.Range("A"+str(i)).Text #获取该行所属部门名称
if(strt not in strs):
#如果是新部门,添加名称到strs列表,复制表头和数据
strs.append(strt)
bk.api.Worksheets.Add(After=bk.api.Worksheets(bk.api.Worksheets.Count))
bk.api.ActiveSheet.Name = strt
bk.api.Worksheets("汇总").Rows(1).Copy(bk.api.ActiveSheet.Rows(1))
bk.api.Worksheets("汇总").Rows(i).Copy(bk.api.ActiveSheet.Rows(2))
else:
#如果是已经存在的部门名称,直接追加数据行
bk.api.Worksheets(strt).Select()
r=bk.api.ActiveSheet.Range("A"+\
str(bk.api.ActiveSheet.Rows.Count)).\
End(Direction.xlUp).Row + 1
bk.api.Worksheets("汇总").Rows(i).\
Copy(bk.api.ActiveSheet.Rows(r))
#删除新生成的工作表的第一列
for i in range(1,bk.api.Worksheets.Count+1):
bk.api.Worksheets(i).Columns(1).Delete()
app.screen_updating=True
app.display_alerts=True
在Python IDLE文件脚本窗口,在"Run"菜单中单击"Run Module"选项,进行工作表拆分。拆分效果如图1-27中处理后各工作表中所示。
将多个工作表分别保存为工作簿
现有各部门工作人员信息如图1-28处理前工作表中所示。不同部门工作人员的信息单独放在一个工作表中,现在要将不同工作表中的数据单独保存为工作簿文件。
图1-28 将多个工作表分别保存为工作簿文件
下面用Excel VBA和xlwings包将各工作表数据保存为单独的工作簿文件。
【Excel VBA】
示例文件的存放路径为Samples\ch013\Excel VBA\示例3\各部门员工.xlsm。
Sub SaveToFile()
Application.ScreenUpdating = False '取消窗口重画
Dim strFolder As String
strFolder = ThisWorkbook.Path '获取当前目录
Dim shtT As Worksheet
For Each shtT In Worksheets '遍历每个工作表,分别保存
'创建一个新的工作簿并将原始工作表中的数据拷贝过来
'新创建的工作簿即为活动工作簿
shtT.Copy
'保存到文件,文件名称为原始工作表的名称
ActiveWorkbook.SaveAs strFolder & "\" & shtT.Name & ".xlsx", 51
ActiveWorkbook.Close
Next
Application.ScreenUpdating = True
End Sub
运行过程,保存各工作表中的数据。处理效果如图1-28中处理后各工作表中所示。
【Python】
使用xlwings包来实现的代码如下所示。本示例的数据文件存放路径为Samples\ch13\ Python\示例3\各部门员工.xlsx,py文件保存在相同目录下,文件名为sam1-104.py。
import xlwings as xw #导入xlwings包
import os #导入os包
root = os.getcwd() #获取py文件所在的目录,即当前目录
#创建Excel应用对象,可见,不添加工作簿
app=xw.App(visible=True, add_book=False)
#打开当前目录下的各部门员工.xlsx文件,可写,返回工作簿对象
bk=app.books.open(fullname=root+r"\各部门员工.xlsx",read_only=False)
app.screen_updating=False #取消窗口重画
for sht in bk.api.Worksheets: #遍历每个工作表,分别保存
#创建一个新的工作簿并将原始工作表中的数据拷贝过来
#新创建的工作簿即为活动工作簿
sht.Copy()
#保存到文件,文件名称为原始工作表的名称
app.api.ActiveWorkbook.SaveAs(root+"\\"+sht.Name+".xlsx", 51)
app.api.ActiveWorkbook.Close()
app.screen_updating=True
在Python IDLE文件脚本窗口,在"Run"菜单中单击"Run Module"选项,保存各工作表中的数据。处理效果如图1-28中处理后各工作表中所示。
将多个工作表合并到一个工作表
1.6.2小节将一个工作表根据某个列的值拆分为多个工作表,这里反过来,将多个工作表中的数据合并到一个工作表。
现有各部门工作人员信息如图1-29处理前工作表中所示。不同部门工作人员的信息单独放在一个工作表中,现在要将不同工作表中的数据合并到“汇总”工作表中,并添加“部门”列,列的值为数据来源工作表的表名。
图1-29 多个工作表合并为一个工作表
下面用Excel VBA和xlwings包将各工作表数据合并到“汇总”工作表。
【Excel VBA】
示例文件的存放路径为Samples\ch013\Excel VBA\示例4\各部门员工.xlsm。
Sub CombineSheets()
Dim shtT As Worksheet, lngRow As Long, rngT As Range
Dim lngRT As Long, lngRT2 As Long, lngI As Long
Worksheets("汇总").Select '选择“汇总”工作表
Cells.Clear '清空“汇总”表
Range("A1").Value = "部门"
Worksheets(1).Range("A1:D1").Copy Range("B1") '复制表头
For Each shtT In Worksheets '遍历“汇总”工作表外的每个工作表
If shtT.Name <> "汇总" Then
'将各部门工作表的数据复制粘贴到“汇总”工作表
Set rngT = Range("A65536").End(xlUp).Offset(1, 1)
lngRow = shtT.Range("A1").CurrentRegion.Rows.Count - 1
shtT.Range("A2").Resize(lngRow, 4).Copy rngT
'在“汇总”工作表第一列添加部门名称
lngRT = Range("A65536").End(xlUp).Row + 1
lngRT2 = lngRT + lngRow – 1
'将当前工作表的名称作为“部门”列的值进行添加
For lngI = lngRT To lngRT2
Cells(lngI, 1).Value = shtT.Name
Next
End If
Next
End Sub
运行过程,处理效果如图1-29中处理后“汇总“工作表中所示。
【Python】
使用xlwings包来实现的代码如下所示。本示例的数据文件存放路径为Samples\ch13\ Python\示例4\各部门员工.xlsx,py文件保存在相同目录下,文件名为sam1-105.py。
import xlwings as xw #导入xlwings包
#导入xlwings.constants模块的Direction类
from xlwings.constants import Direction
import os #导入os包
root = os.getcwd() #获取py文件所在的目录,即当前目录
#创建Excel应用对象,可见,不添加工作簿
app=xw.App(visible=True, add_book=False)
#打开当前目录下的各部门员工.xlsx文件,可写,返回工作簿对象
bk=app.books.open(fullname=root+r"\各部门员工.xlsx",read_only=False)
sht= bk.api.Worksheets("汇总") #获取“汇总”工作表
sht.Cells.Clear() #清空“汇总”表
sht.Range("A1").Value = "部门"
bk.api.Worksheets(1).Range("A1:D1").Copy(sht.Range("B1")) #复制表头
for shtt in bk.api.Worksheets: #遍历"汇总"工作表外的每个工作表
if shtt.Name!= "汇总":
#将各部门工作表的数据复制粘贴到“汇总”工作表
rngt=shtt.Range("A2",shtt.Cells(shtt.\
Range("A"+str(shtt.Rows.Count)).\
End(Direction.xlUp).Row,4))
row=sht.Range("A1").CurrentRegion.Rows.Count+1
rngt.Copy(sht.Cells(row,2)) #复制数据
#在“汇总”工作表的第一列添加部门名称
rt=sht.Range("A"+str(sht.Rows.Count)).\
End(Direction.xlUp).Row + 1
row2=shtt.Range("A1").CurrentRegion.Rows.Count-1
rt2=rt+row2
#将当前工作表的名称作为“部门”列的值进行添加
for i in range(rt,rt2):
sht.Cells(i,1).Value=shtt.Name
在Python IDLE文件脚本窗口,在"Run"菜单中单击"Run Module"选项,合并各工作表中的数据到”汇总“工作表,并添加”部门“列。处理效果如图1-29中处理后“汇总“工作表中所示。