有时候我们需要将来自各个部分的数据进行汇总,例如一个工作簿(workbook)里面有20个工作表(worksheet),每个工作表代表一个班级不同学生的成绩(包括语文、数学、英语),每个工作表都有相同的格式。现在要将所有班级的学生进行汇总。如果一个一个进行手工复制会显得很麻烦。如果这样的工作表有几百甚至上千个,更不可能用手工复制,此时用代码怎么实现呢?
使用VBA代码的优点
使用代码的优点是我们可以把那些重复的操作用代码固定下来,当以后我们需要进行相同的操作时,就可以直接运行代码,这要就能节约大量的时间,提高工作效率。下面我们来看看如何用代码实现。
例子
为了便于讲解,我们以汇总4个班的成绩为例。成绩如下图所示:
代码及注解
Sub 单工作簿合并()
dim i
Worksheets.Add after:=Worksheets(Worksheets.Count)
Worksheets(Worksheets.Count).Name = "汇总表"
Worksheets(1).UsedRange.Copy Worksheets("汇总表").Cells(1)
For i = 2 To Worksheets.Count - 1
Worksheets(i).UsedRange.Offset(1, 0).Copy Worksheets("汇总表").Cells(Worksheets("汇总表").Rows.Count, 1).End(xlUp).Offset(1, 0)
Next i
End Sub
运行上述代码后,我们会得到下图的汇总工作表。
这些代码是怎么实现这一功能的呢?
我们的整体思路是先新建一个工作表,并命名为“汇总表”。然后把每个工作表的内容复制到汇总工作表里面去。
Worksheets.Add 表示新建一个工作表
Worksheets.Count表示工作表的数量
Worksheets(Worksheets.Count)表示最后一个工作表
after:=Worksheets(Worksheets.Count)表示把新建的工作表放在最后一个工作表之后。
Worksheets(Worksheets.Count).Name= "汇总表" 表示命名汇总工作表为 "汇总表" 。
Worksheets(1)表示第一个工作表
Worksheets(1).UsedRange表示第一个工作表中已经使用的整个矩形数据区域
Worksheets(1).UsedRange.Copy表示将区域进行复制,后面跟想到复制到的那个单元格区域。
Worksheets("汇总表").Cells(1)表示汇总表的第一个单元格
所以Worksheets(1).UsedRange.Copy Worksheets("汇总表").Cells(1)的意思是将第一个表的所有内容复制到汇总表中的第一个单元格。
要点:现在汇总工作表里有一班各个同学的成绩,以及第一行显示的变量名(姓名,语文,数学,英语)。在复制其它班级成绩的过程中,我们只需要复制各班成绩,而不要第一行。操作是相同的,所以我们使用循环来完成。
第一个工作表(一班)的内容已经复制到最后一个工作表(汇总表),我们还需要复制第2个到倒数第2个工作表的内容到汇总表。循环形式如下:
dim i
For i = 2 To Worksheets.Count - 1
循环体
Next i
在循环中我们使用了变量i,用来代表我们循环到的工作表。比如i=2时,Worksheets(i)表示第2个工作表。在使用变量前我们需要声明我们使用了这个变量,可以在代码的最上面使用dim i来完成。循环体就是我们要对每一个工作表要进行的相同操作。
循环体该怎么写呢?
Worksheets(i).UsedRange表示i为特定值时,所对应工作表的已使用区域。
在所有循环的工作表中,我们并不需要第一行,可以通过把整个区域向下移动一行来实现。可以使用下面的代码:
Worksheets(i).UsedRange.Offset(1,0)
offset表示偏移引用,第一个参数1表示向下偏移1行,第二个参数0表示向右偏移0列。向下偏移1行后,第一行就不会被选择。
我们再来看循环体中copy后面的部分
Worksheets("汇总表").Rows.Count表示汇总工作表中所有单元格的行数。
Worksheets("汇总表").Cells(Worksheets("汇总表").Rows.Count, 1)表示汇总工作表中第一列的最后一个单元格。
Worksheets("汇总表").Cells(Worksheets("汇总表").Rows.Count, 1).End(xlUp)表示第一列的最后一个单元格,往上走遇到的第一个非空单元格。
为什么要使用end(xlup)呢?
因为在循环其它工作表到汇总工作表的时候,我们要把某个班的成绩复制到汇总表已有数据的最下方,但我们在循环的时候,并不知道已有数据的最下方是哪个单元格。所以我们使用Worksheets("汇总表").Cells(Worksheets("汇总表").Rows.Count, 1).End(xlUp),它的意思是从A列的最后一个单元格开始往上看,直到遇到非空单元格为止,这样得到的单元格肯定是已有数据区域最后一行的单元格。
如果我们直接将循环工作表中的内容复制到上面end(xlup)得到的单元格上,会把汇总表最后一行的数据给覆盖掉,所以还需要向下偏移一行,最后得到下面代码:
Worksheets(i).UsedRange.Offset(1, 0).Copy Worksheets("汇总表").Cells(Worksheets("汇总表").Rows.Count, 1).End(xlUp).Offset(1, 0)
总结
上面就是对单工作簿汇总代码的解释,通过上面的解释我们可以发现这一代码模板的特点:
1 变量名只有一行,如果是多行需要修改相应的代码
2 汇总的工作表可以是做任意个,虽然上例以4个班为例,但如果有40个班,也完全可以用这一模板
3 每个班的工作表格式(如都只有4列,第列是姓名,语文,数学,英语,顺序一致)要完全一样,不然出错是必然的。
结语
今天讲的是单个工作簿内不同工作表的汇总模板,如果不同班的成绩是放在不同的工作簿里面的时候,应该怎样写代码呢?如果喜欢,请看下次的讲解。
(本文为原创,未经允许,不得转载)