VBA已经过时了吗?

论坛 期权论坛 期权     
匿名的论坛用户   2021-1-6 02:40   23197   11
分享到 :
0 人收藏

11 个回复

倒序浏览
2#
热心的小回应  16级独孤 | 2021-1-6 02:40:31
没有过时呀。有个小伙伴一直问我考勤系统脚本的代码。我在这里分享出来。
写这个脚本的背景是CTO和HR商量了下,整个信息中心和业务部门分开做考勤规则。
我们的考勤系统只是记录打卡,但不会判断迟到、漏打卡、加班等等的规则。
之前也是一个程序员帮HR写的程序,此次复杂度加倍。CTO问各位研发总监有木有人要开发下。
无人回应。
做数据的我,弱弱的举了小爪,说我可以帮忙写下。
花了半天就写好了,还设想了各种遇到的情况。HR惊叹于我的速度,说上个程序员花了两周...我汗颜。
HR们,如果还在为考勤烦恼,以下可以下载下来
百度网盘:链接:http://pan.baidu.com/s/1pLuRwoj 密码:w47g
以下截图,我的代码都详细写好了注释。大家可以按照注释修改





代码如下:
Sub Organize_Attendance()
On Error Resume Next
Application.ScreenUpdating = False
Dim Cus_FirstDay As Date, Cus_Lastday As Date, abcd As Date, Cus_Days, St2_Row, Arr_Pointer, Arr_Pointer2
Dim Sht, St1, St2, St3
Dim Arr(0 To 31000, 1 To 14), Date1, Date2, Date3, Record, Date4, Name

'整理表页名称,用于判断是否缺失
txt = ""
a = 0
b = 0
c = 0
For Each Sht In Sheets
   If Sht.Name = "控制表格" Then a = 1
   If Sht.Name = "出勤记录" Then b = 1
   If Sht.Name = "输出表格" Then c = 1
Next

'查找是否有“控制表格”和“出勤记录”两张表
If a  1 And b = 1 Then
   txt = "没有找到控制表格表页"
ElseIf a = 1 And b  1 Then
   txt = "没有找到出勤记录表页"
ElseIf a  1 And b  1 Then
   txt = "没有找到控制表格、出勤记录表页"
End If

If txt  "" Then
   MsgBox (txt)
   Exit Sub
End If

'如果有输出表格,则进行清空,如果没有新建一个
If c = 1 Then
   Sheets("输出表格").Cells.Delete
Else
   Sheets.Add
ActiveSheet.Name = "输出表格"
End If

Set St1 = Sheets("控制表格")
Set St2 = Sheets("出勤记录")
Set St3 = Sheets("输出表格")

'定义表头内容
Arr(0, 1) = "工号"
Arr(0, 2) = "姓名"
Arr(0, 3) = "单位名称"
Arr(0, 4) = "考勤日期"
Arr(0, 5) = "班次"
Arr(0, 6) = "上班"
Arr(0, 7) = "下班"
Arr(0, 8) = "是否跨天"
Arr(0, 9) = "在司时间"
Arr(0, 10) = "是否足够9小时"
Arr(0, 11) = "考勤是否合理"
Arr(0, 12) = "是否缺勤"
Arr(0, 13) = "备注"

'定义节假日、倒休等特殊日期字典
Set Date1 = CreateObject("Scripting.Dictionary")
Set Date2 = CreateObject("Scripting.Dictionary")
Set Date3 = CreateObject("Scripting.Dictionary")
For Each Rng In St1.Range("H2:H" & St1.Range("H65536").End(xlUp).Row)
   Date1.Add Rng.Value, Rng.Value
Next
For Each Rng In St1.Range("I2:I" & St1.Range("I65536").End(xlUp).Row)
   Date2.Add Rng.Value, Rng.Value
Next
For Each Rng In St1.Range("J2:J" & St1.Range("J65536").End(xlUp).Row)
   Date3.Add Rng.Value, Rng.Value
Next

'记录出勤记录行数
St2_Row = St2.Range("A65536").End(xlUp).Row

'定义月份第一天,当月天数
'Cus_FirstDay = DateSerial(St1.[b2].Value, St1.[b3].Value, 1)
'Cus_Lastday = DateSerial(St1.[b2].Value, St1.[b3].Value + 1, 0)

For i = 2 To St2_Row
   abcd = St2.Cells(i, 4).Value
   If Cus_FirstDay = #12:00:00 AM# Or Cus_FirstDay > abcd Then
       Cus_FirstDay = abcd
   End If
   If Cus_Lastday = #12:00:00 AM# Or Cus_Lastday < abcd Then
       Cus_Lastday = abcd
   End If
Next
Cus_Days = DateDiff("d", Cus_FirstDay, Cus_Lastday) + 1

'定义当月班次数组
ReDim Date4(1 To Cus_Days, 1 To 2)
For i = 1 To Cus_Days
   a = DateAdd("d", i - 1, Cus_FirstDay)
   Date4(i, 1) = a
   If Date1.Exists(a) Then
       Date4(i, 2) = "三倍节假日"
   ElseIf Date2.Exists(a) Then
       Date4(i, 2) = "周末"
   ElseIf Date3.Exists(a) Then
       Date4(i, 2) = "工作日"
   ElseIf WorksheetFunction.Weekday(a, 2) = 6 Then
       Date4(i, 2) = "周六"
   ElseIf WorksheetFunction.Weekday(a, 2) = 7 Then
       Date4(i, 2) = "周日"
   Else
       Date4(i, 2) = "工作日"
   End If
Next

'定义员工工号字典
Set Name = CreateObject("Scripting.Dictionary")

'定义当前员工第一行指针
Arr_Pointer = -Cus_Days

'开始按照出勤记录每行循环处理数据,记录工号、姓名、公司、班次、日期、上下班时间、是否跨天的数据
For i = 2 To St2_Row
   '将出勤记录当前行转换为数组
   Record = WorksheetFunction.Transpose(WorksheetFunction.Transpose(St2.Range("A" & i & ":E" & i).Value))
   '检测是否是录入过该员工
   If Not Name.Exists(Record(1)) Then
    '如果是第一次录入,增加工号字典,更改第一行指针,在数组内添加该员工一整月天数的前5列数据
       Name.Add Record(1), Record(1)
       Arr_Pointer = Arr_Pointer + Cus_Days
       For n = 1 To Cus_Days
           Arr(Arr_Pointer + n, 1) = Record(1)
           Arr(Arr_Pointer + n, 2) = Record(2)
           Arr(Arr_Pointer + n, 3) = Record(3)
           Arr(Arr_Pointer + n, 4) = Date4(n, 1)
           Arr(Arr_Pointer + n, 5) = Date4(n, 2)
       Next
   End If

   '判断时间属性,填入数组
   Arr_Pointer2 = Arr_Pointer + Day(St2.Cells(i, 4).Value)
   If St2.Cells(i, 5).Value >= TimeValue("13:00:00") Then '如果打卡时间超过13点
       If Arr(Arr_Pointer2, 7) = "" Then
           Arr(Arr_Pointer2, 7) = St2.Cells(i, 5).Value '如果数组里还没有记录,则将单元格写入数组
       ElseIf Arr(Arr_Pointer2, 7) < St2.Cells(i, 5).Value Then
           Arr(Arr_Pointer2, 7) = St2.Cells(i, 5).Value '如果数组的记录小于单元格,则将单元格写入数组(下班打卡取较大数据)
       End If
   ElseIf St2.Cells(i, 5).Value < TimeValue("6:00:00") Then '如果打卡时间早于6点
       If Day(Record(4)) = 1 Then
           Arr(Arr_Pointer2, 13) = "上个月末最后一天有加班"
       Else
           Arr_Pointer2 = Arr_Pointer2 - 1 '指针时间提前一天
           If Arr(Arr_Pointer2, 7) = "" Then
               Arr(Arr_Pointer2, 7) = St2.Cells(i, 5).Value '如果数组里还没有记录,则将单元格写入数组
           ElseIf Arr(Arr_Pointer2, 7) >= TimeValue("13:00:00") Then
               Arr(Arr_Pointer2, 7) = St2.Cells(i, 5).Value '如果数组里的记录是前一天晚上的记录,则将单元格写入数组(凌晨打卡要晚于前一天晚上)
           ElseIf St2.Cells(i, 5).Value > Arr(Arr_Pointer2, 7) Then
               Arr(Arr_Pointer2, 7) = St2.Cells(i, 5).Value '如果数组里的记录是凌晨的,并且小于单元格,则将单元格写入数组(下班打卡取较大数据)
           End If
           Arr(Arr_Pointer2, 8) = "是"
       End If
   Else '如果打卡时间介于6点到13点
       If Arr(Arr_Pointer2, 6) = "" Then
           Arr(Arr_Pointer2, 6) = St2.Cells(i, 5).Value '如果数组里还没有记录,则将单元格写入数组
       ElseIf Arr(Arr_Pointer2, 6) > St2.Cells(i, 5).Value Then
           Arr(Arr_Pointer2, 6) = St2.Cells(i, 5).Value '如果数组的记录大于单元格,则将单元格写入数组(上班打卡取较小数据)
       End If
   End If
Next

For i = 1 To Arr_Pointer + Cus_Days
   '备注周末or节假日
'    If Arr(i, 5) = "周末" Or Arr(i, 5) = "三倍节假日" Then
'        If Arr(i, 6) = "" And Arr(i, 7) = "" Then Arr(i, 13) = Arr(i, 13) & " 周末or节假日 "
'    End If
   '如果上下班都有时间,则填充在司时间
   If Arr(i, 6)  "" And Arr(i, 7)  "" Then
       If Arr(i, 8) = "是" Then
           Arr(i, 9) = Arr(i, 7) + 1 - Arr(i, 6)
       Else
           Arr(i, 9) = Arr(i, 7) - Arr(i, 6)
       End If
       Arr(i, 9) = Application.WorksheetFunction.RoundDown(Arr(i, 9) * 24, 2)
       If Arr(i, 9) >= 9 Then Arr(i, 10) = "是"
   End If
   '判断是否缺上下班打卡记录
   If Arr(i, 5) = "工作日" Then
       '判断总部考勤是否合理
       If Arr(i, 3) = "总部" Then
           If Arr(i, 6) = "" And Arr(i, 7) = "" Then
               Arr(i, 12) = "缺勤"
           ElseIf Arr(i, 6) = "" Or Arr(i, 7) = "" Then
               Arr(i, 12) = "漏打卡"
           ElseIf Arr(i, 6) = TimeValue("17:30:00") Or Arr(i, 7) = TimeValue("22:00:00") And _
           Arr(i, 6) = TimeValue("18:00:00") Then
               Arr(i, 11) = "合理"
           Else
               Arr(i, 11) = "迟到or早退"
           End If
       End If
   End If

Next

'设置输出表的格式
St3.Columns("A:A").NumberFormatLocal = "@"
St3.Columns("D:D").NumberFormatLocal = "[$-F800]dddd, mmmm dd, yyyy"
St3.Columns("F:G").NumberFormatLocal = "[$-F400]h:mm:ss AM/PM"
St3.Columns("I:I").Style = "Comma"
St3.Columns("B:M").ColumnWidth = 12

'结果数组输出到表格内
St3.Range("A1:N" & Arr_Pointer + Cus_Days) = Arr()

'清除无打卡记录的休息日行
'St3.Columns("N:N").SpecialCells(xlCellTypeConstants, 23).EntireRow.Delete

Application.ScreenUpdating = True
St3.Select
St3.Range("a2").Select
ActiveWindow.FreezePanes = True


End Sub
3#
热心的小回应  16级独孤 | 2021-1-6 02:40:32
虽然VBA不是高校里面的正式课程,但我十几年来一直都在向经管社科方向的同学推荐和介绍这个很实用的技术,所以也经常遇到同学询问类似的问题。这里引用我以前发过的一篇博文,希望对题主能有些启发:
“VBA已经过时了吗?VBA是不是很快就要被淘汰了?” 这是任何一个初学计算机技术的同学都会关心的问题,杨老师在讲授其他课程比如Java设计方法、关系型数据库、网络通信技术等课程中,也一样会听到同学们问同样的问题。
其实这个问题很有意思。如果你经常浏览程序员们的网站,特别是中文论坛,你就会发现“XX技术是不是过时了?”、“论XX语言不如XX语言”之类的话题永远层出不穷,而且总能引起一大片激烈的争论。比如用C语言的说Java太慢,用Java的说C++太乱,C++的说有本事你也给我写个游戏引擎,结果搞汇编的跳出来说;你也好意思在我面前提“性能”;接下来搞Python的、Ruby的纷纷表示自己才是新一代发展方向,不过玩JS的说我才是函数式编程,结果再被大家一顿鄙视…… 看这些帖子时候的感觉,就跟看郭德纲师徒斗嘴一样,会觉得原来程序界也是山头林立、门派纷争,谁都想给自己争个“道传正统”的法旗
总之这些争论永远存在,但其实都没有任何实际意义,最后也都是不了了之。道理很简单:工具技术各有特色,适用于不同场合,没有任何一种技术可以自称是“万灵丹”。所以互相之间无所谓优劣,只有适用性的不同。
不过话说回来,凡是技术终归要有被淘汰的一天。确实有很多当年我们接触过的语言和工具,现在除了遗留系统外,已经很少看到踪迹了,比如 COBOL,PowerBuilder,C++Builder等等。所有技术都如此,VBA当然也概莫能外。事实上,我记得2012年前后,确实曾经风传微软将停止支持VBA,不过随着新版OFFICE推出,该谣言也不攻自破。
不过我觉得大家倒不必为此担忧,因为:
首先,对于非计算机专业的白领人士,直到目前,Office软件中没有比VBA更强大又好学的编程工具。所以只要你想玩转Office,就只能学习VBA。客观地说,开发Office的更加专业的工具还有很多,比如用.Net开发工具直接开发Office插件,无论外观还是性能都超出VBA一个档次。不过这些工具都是供给专业人员使用的,如果你也能掌握这个技术,那么已经可以直接改行做专业开发人员了。
其次,退一万步讲,即使下一版Office中停止支持VBA,那么微软也必须提供一个替代性的宏开发工具。而既然是宏编程,又是VBA的继承者,那么大家现在掌握的VBA知识将会使你非常顺利的切换到新语言环境,无非就是For/If等保留字的写法发生变化,或者稍微增加一些新的语言结构(比如强面向对象)而已,本质上都是相通的。比如我前几天帮朋友开发时使用了一下Google Doc(Google提供的完全类似MS Office的云端办公软件)的宏语言,它基于Javascript语法,但是写起来的手感跟VBA是一样的,无非还是传统的程序代码配上各种表格对象的使用。如果熟悉VBA,完全可以一边上网查文档,一边就把程序写出来。
最后,我还是一贯的观点:工具万千,实用为王。不必把自己拘泥于某一个技术上,而是根据工作需要,什么方便用什么。能用公式就用公式;公式不给力就上透视图,实在没办法就来VBA;VBA也不能用,又必须要求写程序,那就熬几个夜学学C#,然后上网抄一段代码改一改,反正大家思路上都差不多;如果还是不行,那就请领导批预算委外开发;如果领导不批准还要出活,那就辞职吧 ……
说跑题了。总之我个人的意见是:在可以预见的几年里,VBA不会被替代;即使有一天VBA会被替代,你通过学习VBA所积累的经验也会帮助你迅速转到新工具中。
4#
热心的小回应  16级独孤 | 2021-1-6 02:40:33
完全没有。

VBA虽然被计算机专业学生鄙视,但在金融领域很强大,因为彭博、路透都可以跟excel对接,实时取到数据,这是最最简单的一种获取数据并引入模型的方法了。但受限于excel本身函数有限,且没办法缓存数据和支持多维数组,这时候就需要VBA来帮忙。有人会觉得C++或者python更洋气,可是要知道光是把excel中的数据与C++对接就要一阵子,而且还有什么语言比VBA操作excel读写和工作表之间的运算更方便的呢?

所以具体问题具体分析,在我的工作环境中,1)彭博路透跟excel自由对接、2)不可能让公司出钱安装其他软件、3)就算免费软件也不能随便安装。综上VBA就是最好的编程语言,其他的连挑战的机会都没有。

//2015年9月新增内容
一个编程语言的发明是有意义的,VB当年的出现可是轰动性的,号称“西雅图夜空的雷电”。2000年前那基本是叱咤风云,但随着软件工程等专业的发展,VB一些缺点也显露了出来,说白了就是VB有一些简单。。学起来简单,用起来简单,但硬件性能突飞猛进,软件肯定不满足于一些简单的功能了吧,就好比你不能玩扫雷和空当接龙一辈子吧。大型开发上面VB就跟不上时代的节奏了。

于是VB就变成今天人们心中的这样了。但是说实话,你用excel,还能指着用excel编个游戏不成。。虽然真有大神这么做。但大部分人所需要的功能,要达到的目标,VB语言已经可以应付了,所以VB过时不了的,放心吧
5#
热心的小回应  16级独孤 | 2021-1-6 02:40:34
我觉得没有过时,我在EXCEL上写了很多小工具:时间管理、数据文件格式转换、贪吃蛇小游戏......VBA有自己的局限性,但在它适用的领域里,很强大。也许有一天微软会把它去掉,但肯定也是用其他更好的工具代替它(vsto啥的),那个时候你用那个工具相信 上手也会非常容易。
6#
热心的小回应  16级独孤 | 2021-1-6 02:40:35
其实这种担心大可不必,VBA最大的好处就在于可以帮你节省时间,有时候当碰到EXCEL公式无法实现自己的需求时,按ALT-F11写一段代码就可以轻松解决,是不是很神奇,下面我们来了解一下,VBA在Excel中有哪些优势

1、VBA的应用前景
很多时候,当我们提起VBA,首先想到和Excel有关,其实这里所提到的VBA是依附在Excel平台上进行的二次开发,当然它还可以大量应用在其他的软件中,包括机械设计软件AutoCAD,平面设计软件与排版软件CoreDraw, 办公排版软件Word(这个相信大家应该是最熟悉的 了),还有网页设计软件Frontpage,甚至我们的国产Office软件WPS,也是可以用VBA进行二次开发。

对于我们最常使用的Excel,VBA可以使程序自动执行、批量执行、定时执行,类似于DOS操作系统的批处理文件,但它比DOS系统的批处理功能更强大。从这点看,首先VBA的应用前景是相当广阔的吧。

2、VBA的有用性
初次学习某个编程软件,很多人都会问一个万年不变的问题:我学了它用处大不大。其实有时候,小柔我也会提这个小白问题,就好比当年我也曾纠结过是先学matlab,还是先学ptyhon语言。其实任何软件它其实都是有用,只是看你学到什么程度了。如果学完后能给你提升工带来很大经济效益,那还等什么?

就拿用Excel做一份财务报表作为例子,会VBA的那个人在做报表时,根本不需要用到函数,运行一下之前编好的代码,几分钟一份报表就完事了,每天按时上下班,下了班去健身房健健身,或者是利用晚上的时间继续充电,形成一个良性循环。而如果你不懂VBA,J就要做很久,有时候还要加班个一两个小时,当然这种加班,你的老板可不会给你加班费哦!

3、VBA的必要性
像低端标题,隔N行插入M行,数据类型的批量转换等等,用Excel的内置函数,是根本做不到的。又或者是,你对函数CONCATENATE不能合并数组也不能合并区域不满意,对Vlookup函数只能返回第一个找到的对象不满意,对SUM函数不能实现按照颜色汇总不满意,等等这些都之后,这些问题都可以轻松化解。

4、VBA的优点
(1) 批量执行任务
逐个激活工作表,然后定位错误值所在的单元格,再删除错误值。如果你改用VBA的话,删除100个工作表中的错误值就可以一键完成,整个过程不超过1秒钟。更强大的地方在于,删除错误值的代码可以重复使用,一键调用,而且自动适应数据变化。
(2) 将复杂的任务简单化
Excel的诸多功能其实是可以搭配使用的,从而实现比单个工具更强大的功能。就比如讲,公式,定位,插入行这三者如果搭配使用的话,就可以实现工作表中隔行插入行。是不是觉得很烦,对于我这种连公式有时候都不高兴输入的人来讲,这种操作是绝不能忍受的,更致命的一点是,对于操作的不熟的人来讲,操作时间久。这时候,如果你会VBA开发一个隔行插入的工具,则可以一键完成,大大提升了自己的工作效率,减少了时间成本。

(3) 提升数据的准确性
当我们还是实习小白时,最常做的一件事情就是录入数据,但是有时候在录入数值的时候,误录入了两个小数点,你当时没有发现,等到在后面进行其他操作的时候,被告知数据有问题,然后就是大量的进行回查纠错。在这点上,VBA可以做到对用户录入的数据执行限制,这就避免了用户意外录入了不规范的字符。
其次使用公式统计数据时,公式不会随着数据增减变化而变化,比如说,当我们使用公式统计所有工作表B列的产量,你会发现,当新建一个工作表后,公式的计算结果无法自动更新,而VBA可以做到自动适应数据的增减变化,这是VBA独有的一个优势。
(4) 完成Excel本身无法完成的任务
当你想在录入阿拉伯数字时自动转换层英语大写形式的金额、录入公历日期自动提示对应的农历日期、行程安排与预告,或者修改注册表等需求,这些都是你用Excel的常规方法无法弯沉过的,而VBA处理此类问题都是得心应手。

其他回答:
如何更有效率的背单词:
Excel 有什么神奇用途?如何制作一份收盘报表:
Excel 到底有多厉害?
7#
热心的小回应  16级独孤 | 2021-1-6 02:40:36
只要Office还流行,VBA就不会过时,而且会越发强大。

想想,有什么语言可以比一个不依赖于操作系统、不依赖于编译环境、不依赖于IDE的类似“胶水”,而且还能和Office完美整合的语言,更加吸引人?

————————————————————
更多文章关注我的专栏:数据冰山 - 社区专栏
8#
热心的小回应  16级独孤 | 2021-1-6 02:40:37
刚看到空白大佬的回答,想起以前做运营的时候每对着Excel,基本上需要重复劳动的工作都用VBA解决了。刚翻了翻保留下来的文件有这些:


xlsx文件是自己做的和学习到的一些图标总结,xlsm文件是自己做的带VBA的表格文件。


后来因为科技解放了生产力,空余的时间多了出来又用VBA自娱自乐做了很多小游戏。

有一些纯娱乐向的2048、扫雷什么的,有一些算法向的迷宫、数独、KMeans聚类,还有爬虫向的票房数据分析。
大部分文件及代码我都放到专栏里了,扯乎。有兴趣看看就行,不用关注了,因为找不到题材所以很久没更新了……
9#
热心的小回应  16级独孤 | 2021-1-6 02:40:38
10#
热心的小回应  16级独孤 | 2021-1-6 02:40:39
vba一点也不过时,而且它的回报会远远高于你学习的代价。

只要和excel打交道,都会用上它。别人两三天完成的重复性工作量,又累又枯燥,到你这里点点按钮15分钟解决。毫不夸张。并且,数据越多,越能提现vba的快速方便的特点。

__________________________________________
铁路设计里面有一个参数叫压缩模量,而这个参数是做实验一个钻孔一个钻孔做的。你需要对每个钻孔查每个土层深度的压缩模量。如果手动查取,不仅枯燥繁琐,而且浪费时间。刚工作的时候感觉这个过程真是个麻烦的过程,如果能用程序执行就行了,自己也是各种搜如何批量对比查找并提取数据,最后搜到vba可以最简单的做到这一点。而且入门快,你用到批量提取数据,实际上你可以直入主题,字典数组暂时不用学。自己买书看书,百度摸索。不忙的时候就编程,编出来了一个读取压缩模量的小程序。


分享给同事之后,自豪感爆棚啊 ,时间在这个年代是多么的重要。能用vba解决的绝对不浪费时间手动解决。

11#
热心的小回应  16级独孤 | 2021-1-6 02:40:40
作为一种工具 实用就好,无所谓过不过时
12#
银河流  1级新秀 | 2022-2-17 15:27:55
楼主 链接失效了
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3118703
帖子:623848
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP