不闪烁的跨表复制
昨天说到当我想用VBA把一个工作簿里面的某些工作表复制到另外一个工作簿的时候,如果要复制的工作表有多个,复制过程中就会出现闪烁。如果需要复制的工作表很多,闪烁的时间会比较长。我觉得批量选择,最后一次性复制是一个解决办法。如果不是用VBA,而是手动实现这个复制功能,的确会用批量选择,然后再复制。现在按住Ctrl,然后用鼠标选择需要复制的工作表,最后进行复制。如果要在VBA里面实现这个批量选择,该怎么做呢?
一个工作簿里的工作表该如何判断哪些是需要的,哪些是不需要的,对我来说只需要判定工作表的名称就可以,所以我可以对需要的工作表以某种方式结合起来,比如形成一个以固定分隔符的字符串。VBA里要表达批量选择,然后复制,到底该用什么东西呢?这一次我没有搜索,而是直接录制了个宏。结果发现原来批量选择再复制,在宏里默认是通过数组的。需要把目标工作表的名称组合成一个一维数组,然后用最普通的复制方式把拷贝到新的工作簿。所以我要做的就是把目标工作表的名称赋值给一个一维数组。因为不知道到底要复制多少个工作表,所以这个数组应该是一个动态数组,我马上想到的方式就是以默认分隔符打断字符串的方式赋值给一维的动态数组。这个操作非常高效,而且动态数组的大小完全不需要在一开始就定义好,字符串里面有多少东西就可以生成多大的一维数组。
接下来,我要做的是经过一轮循环筛选出某个工作簿里我需要的工作表的名称,然后把这些名称以固定分隔符的方式连接起来。最后在打断之前我还要干掉一个分隔符,因为无论我把分隔符放在最前面还是最后面,整个字符串还是会多一个分格符。我不知道多一个分隔符在赋值给一维数组的时候会不会失败,作为完美主义者,我宁愿手动把那个分隔符去掉。那不过是一个字符串取值的简单操作而已。处理好字符串以后,就可以打断那个字符串赋值给一维数组,最后通过经典的复制方式,把工作簿里的目标工作表拷贝到另外一个工作簿。
我没有测试过这样处理耗时跟基础经典处理有多大差别,但就肉眼来说,差别挺大。因为如果进行这般批量选择一次性复制,基本上可以秒杀完成,但如果使用经典的方法、工作表又比较多,我感觉得闪烁一秒钟以上。秒杀就能完成我感觉那个耗时会在0.3秒以内。
批量选择再复制的确可以秒杀实现拷贝工作表,但是光标会停留在最后一个被复制的工作表里,我需要光标仍然停留在我的点击VBA控件的工作表。所以最后我又增加了一个激活目标工作表,把鼠标锁定在某个单元格的功能。这个功能不是非如此不可的,没有也不影响数据处理本身,但就方便程度而言,这是显而易见的。就如没有初始化和拷贝数据那两个模块,核心功能没问题,但是多了这些贴心的小步骤。整个核对的过程会变得更顺手。
如果使用的时候能更顺畅,我宁愿把代码搞得复杂一些。毕竟复杂的代码是一次性的。
PS:测试
复制19个工作表:批量法0.85秒,经典法7.25秒。
复制8个工作表:批量法0.59秒,经典法3.02秒。
复制4个工作表:批量法0.48秒,经典法1.59秒。
Sub 批量拷贝工作表-批量法() Application.ScreenUpdating = False '关闭屏幕刷新 Dim book As Workbook Dim sht As Worksheet Dim my_name As String, stringArray() As String my_name = "" For Each book In Workbooks If book.Name <> "AAA.xlsm" Then For Each sht In book.Worksheets If Not sht.Name Like "*BBB*" Then my_name = my_name & sht.Name & "," End If Next my_name = Mid(my_name, 1, Len(my_name) - 1) stringArray = Split(my_name, ",") book.Sheets(stringArray).Copy before:=ThisWorkbook.Worksheets("条件") End If Next With ThisWorkbook .Worksheets("条件").Activate .Worksheets("条件").Range("A27").Select End With MsgBox "完成数据抓取!" Application.ScreenUpdating = True '打开屏幕刷新 End Sub ************************************ Sub 批量拷贝工作表-经典法() Application.ScreenUpdating = False '关闭屏幕刷新 Dim book As Workbook Dim sht As Worksheet For Each book In Workbooks If book.Name <> "AAA.xlsm" Then For Each sht In book.Worksheets If Not sht.Name Like "*BBB*" Then sht.Copy before:=ThisWorkbook.Worksheets("条件") End If Next End If Next With ThisWorkbook .Worksheets("条件").Activate .Worksheets("条件").Range("A27").Select End With MsgBox "完成数据抓取!" Application.ScreenUpdating = True '打开屏幕刷新 End Sub |