实际使用Excel中会遇到这样的问题:新工作表的内容必须来自于原有的工作表,例如,学校在新学年要编班,而编班的实质就是将上学年的学生进行重新排布,原来建立的学生情况表需要按新的编班方案重做;再如教育部门的人员,每年都有人在部门下属的各个单位之间调动,这也与学生编班的问题相似,原来建立的各个单位的工资表也需要重做.此类问题的特点是:从全局看,人员并没有变动,从局部看,人员却是变动的;从工作表方面看,原有表不能再直接使用,但仍有可资利用的信息!如果用推倒重做的办法建立新表,工作量实在太大,况且原来的工作表不利用也真有点"可惜"!但仅凭"复制|粘贴"来利用原表中的"资源"也太辛苦.若能编写个程序,使之"自动"从原有工作表中"抽取原料".然后再自动重组工资表该多爽啊!你看,我的想法很不错吧?但问题是如何来实现这个"自动化呢"?
经过摸索,我使用了Excel的区域命名和链接功能,以上年的工作表为"原料",快速重作新工作表,经多次改进完善、并实际试验,效果良好.下面以重做一个部门各个单位的工资表为例,介绍具体的操作方法,请同行指正.如果要重做学生情况表,也与此完全类似.
第一步是将上年的工资表进行预处理:
打开上年工资工作薄后首先备份,然后在工作薄中只保留各个单位的工资表,其它如汇总表等统统删除,但完全空白的表不必删除.
一般每个人的工资记录占据一行,并且所有人员的记录占据的列数是相同的;预处理就是把每个人工资记录所在的单元格区域进行命名,单元格区域使用的名字就使用本人的姓名.例如:设每个人的工资记录都占据5列,并且员工张三位于"A2"单元格,那么就将"A2:E2"这部分单元格区域命名为"张三".特别注意这一步,千万不要不能使用其他名字,否则,我的这个法术就不灵了.命名那么多的区域,使用手工操作当然不行.我自己编写了一个宏程序,运行之后就可以自动对区域命名,如果没有这件宝贝,介绍这个方法也就意义不大了.
命名区域的宏程序:
Sub 命名区域的宏()
"将选定的单元格以同一行、A列中的姓名进行命名"
For Each Sheetx In Worksheets " Sheetx是工作表变量
Sheetx.Activate "激活当前工作表
For Each Rg1 In Columns(1).Cells "对A列所有单元格进行访问
If Rg1.Value = "" Then Exit For " 遇到空单元格,结束
Rg1.Activate "激活单元格
Range(Cells(Rg1.Row, 2), Cells(Rg1.Row, 5)).Select
"这里选定(同一行的)第二列到第五列,具体你的工资表选定列数,
"依据自己的情况决定.
Range(Cells(Rg1.Row, 2), Cells(Rg1.Row, 5)).Name = Rg1.Value "对选定的区域用该行A列中的姓名命名
Next
Next
End Sub
注意:必须在没有建立新表之前运行本程序.运行之后,第一步的命名工作就完成了.
第二步,人员调整之后,各单位人员的名单就被确定了,重做工资表时还是一个单位使用一张工作表.但新工作表应仍位于当前的工作薄中,这样比较方便.如果表不够,可以插入一些,工作表的名字就使用单位简称.从第一行就开始输入人员的姓名,不留表头!这是为了下一步方便,因为表头可以在链接成功之后统一添加.一个单位全部人员输入完.再开始另一个单位,依此类推.这一步是下一步的基础,不可省去.当将所有单位的人员姓名都输入完毕后,就可再进行下一步.
第三步,在完成全部命名、新的人员姓名分单位输入完毕、并确保原有工作表与新建立的工作表位于同一个工作薄中时,方可开始这一步.
这一步实际是利用第一步的命名进行链接.因为单元格区域的名字在工作薄中的所有工作表中都可以使用(这也就是为什么要求新表与老表必须共处于一个工作薄的原因).手工链接虽然也行但失之于太慢,所以几百甚至上千人的数据用只能使用自动链接.这里提供两种方法:第一种方法是:在新表的b1单元格(也就是第一个人的姓名右面)输入
=INDIRECT(A1) ,然后向右复制公式至E列,会发现除b1之外,别的单元格中都提示#REF!,这需要将这些单元格中的公式都修改得和B1中完全一样,数值就会显示出来了.接着在选定(B1:E1),向下复制公式到最下面一个人为止.某个人的工资记录不论原来位于哪个工作表,现在都可以自动搬到这里!是不是很爽啊?
第二种方法是再编写一个宏程序,将上述链接公式输入到合适的位置上,
Sub 建立链接公式的宏()
"运行该程序进行链接公式的填写
For Each Sheetx In Worksheets "访问所有工作表
Sheetx.Activate "激活当前工作表
For Each Rg1 In Columns(1).Cells "对A列访问
Rg1.Activate "激活当前单元格
If Rg1.Value = "" Or Rg1.Value = "姓名" Then Exit For
"如果是空单元格或A1中是"姓名"结束循环 ActiveCell.Offset(0, 1).Activate "向右移动一个单元格
ActiveCell.FormulaR1C1 = "=INDIRECT(RC[-1])" "填写公式
ActiveCell.Offset(0, 1).Activate ActiveCell.FormulaR1C1
= "=INDIRECT(RC[-2])"
ActiveCell.Offset(0, 1).Activate ActiveCell.FormulaR1C1
= "=INDIRECT(RC[-3])"
ActiveCell.Offset(0, 1).Activate ActiveCell.FormulaR1C1
= "=INDIRECT(RC[-4])"
Next
Next
End Sub
if语句是进行结束循环判别的,当遇到空的单元格,说明填写完毕了,如果是单元格中是"姓名"二字,说明这一张工作表是原表,不能填写公式,也要退出循环.这样可以确保只将公式填写在新建立的工作表中,这也是为什么新表中不要表头的原因所在.当然,这同时也要求原表中的A1单元格必须有姓名二字!
注意问题:
1、姓名不能写错.
2、有多人用同一个姓名的要事先加以处理.在命名程序运行之前,确保没有姓名重复现象.
3、用这种方法制作的工作表不会将原表中的计算公式"搬移"过来,这个问题有待以后改进.
4、新表与原表之间有引用关系,如果想去掉引用关系,可以使用复制之后选用"粘贴"|"数值"的办法除去引用.
5、新表的表头可以用插入行来制作,可以先按下Ctrl键,再用鼠标点击需要插入表头的工作表的标签,可以同时对所有选定表插入一行,输入表头文字之后,再次按下Ctrl键,鼠标点击各个表,解除表间的联系即可.本方法本人已经在Excel97中使用多次.完全可靠.