购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

6.1 程序错误的类型与排查

程序错误可以分为多种类型,在调试过程中需要区别对待。具体来说,VBA中的程序错误一般被划分为“编译错误”“运行时错误”和“逻辑错误”三种。

6.1.1 编译错误

在程序设计领域中,“编译”这个术语一般代表“将程序代码翻译为计算机指令”的过程,也就是将“x=5”这种人类能够看懂的语言,翻译成“mov eax,0x5”乃至“b805000000”这种只有计算机才能理解的指令。

因此,编译错误(Compile Errors或Syntax Erros)的含义,就是由于代码不符合语法等,导致 VBA 无法将我们书写的代码转换为计算机指令去运行。换句话说,因为存在语法错误,VBA读不懂我们书写的程序代码。

其实在前面几章的学习中,我们已经多次遇到过编译错误。如图6.1所示,在写判断结构时忘记书写“End If”,或者在字符串连接操作中忘记在“&”连接符前面加上空格,都有可能引发编译错误。由于这种错误太过明显,VBA会拒绝运行程序,并直接弹出错误警告。

图6.1 由于语法错误(在If结构中忘记书写

不过,虽然 VBA 能够及时发现编译错误并预警,但是往往无法准确地告诉我们错误原因。比如在图6.1的例子中,明明是因为没有书写“End If”导致的错误,可是VBA弹出的警告框中却认为是“Next 没有 For”。

为什么会出现这种情况呢?还是我们反复强调的那句话:“计算机并不聪明,它只会死板地按照语法规则逐字理解”。以上面的代码错误为例,当VBA发现For语句后,根据语法规则从下面一行开始都属于循环体内容。接下来它看到了If 语句,于是再次查阅语法规则,知道从这一行直到End If之间的内容均属于这个判断结构。然后VBA继续向下检查代码并发现了“Next i”这一句话。可是直到这时还没有看到“End If”字样,所以VBA认为“Next i”语句也是位于判断结构之内的。

我们在第4章中曾经讲过,程序语法中禁止交叉嵌套。所以VBA理所当然地认为“Next i”语句所对应的“For i=x to y”也必须处于If结构之内,否则就会形成交叉嵌套,违反语法规则。可是在图6.1的If语句后面没有发现任何For语句,因此VBA认定“Next i”语句没有与之匹配的For语句,所以弹出提示“Next没有For”。

换言之,虽然我们很清楚“Next i”语句对应的For语句就是“For i=2 To 10”,但是VBA却无法从开发人员的视角去思考。它只能逐行逐字地根据所读到的局部信息去理解代码,因此认定既然还没有遇到“End If”语句,那么“Next i”语句就是判断结构内部的内容,与If结构外面的For语句完全无关。

所以当读者遇到这种编译错误警告时,请保持耐心,并按照 VBA 语法规则去逐行分析,一定能够查找出错误的真正原因。而这种摒弃人类视角,尝试按照计算机的视角去理解代码的习惯,也是程序设计学习过程中最重要的一条最佳实践:

把自己当作计算机,忠实而严格地遵循语法,在大脑中逐行执行程序代码。

6.1.2 运行时错误

在某些情况下,虽然我们编写的代码符合语法,不会导致编译错误,但是在运行时却会导致程序出错,使程序无法继续运行。这种错误就被称为“运行时错误(Runtime Errors)”,即只有在程序实际运行中才会被发现的错误。

最典型的运行时错误就是“除零”,也就是在除法算式中将0作为除数,如图6.2所示。

图6.2 用0做除数导致的运行时错误

这段程序代码看上去没有任何问题,而且也正确计算出了表格第3行到第5行的人均经费。但是当循环变量i 等于 7,也就是计算第7行人均经费时,由于技术支持部门无人参加春游活动,所以Cells(7,4)的数值为0。于是循环体内的代码就是要求计算机计算“3000÷0”这个算式,并将结果写入其对应的E列单元格。可是基本算术规则中禁止使用0作为除数,所以计算机无法完成这个语句,程序也就无法继续执行下去,最终只能中断程序运行,并提示“除数为零”的错误。

显然,上面这种错误不可能像编译错误那样在运行程序之前就被分析出来,因为 VBA 根本不知道用户会在Excel表格中输入什么样的数字。这也是它被称为“运行时错误”的原因。

需要补充说明的是,当程序执行中发生运行时错误时,VBA弹出的警告框里给我们提供了两种处理办法,也就是“结束”和“调试”两个按钮(见图6.2)。如果单击“结束”按钮,那么就会停止程序运行,回到开发状态。如果单击“调试”按钮,程序并不会就此结束,而是转入调试模式的“单步执行”状态,暂停在发生错误的代码上。此时读者可以使用各种调试工具细致分析错误原因。在发现错误原因后,先单击“重新设置”按钮(见图6.3)使程序完全终止,然后修改代码即可重新运行程序。

图6.3 进入调试模式后的VBE及“重新设置”按钮的位置

6.1.3 逻辑错误

编译错误和运行时错误并不可怕,它们迟早会因为影响程序运行而被 VBA 发现和报警。真正危险的是允许程序正常运行,但又输出错误结果的情况,正所谓“真正的敌人往往隐藏在内部”。

出现这种错误的原因,在于代码虽然完全符合语法,也不会发生类似“除零”的运行时错误,但是在设计思路也就是逻辑流程上发生了差错或笔误。因此,这种错误被统称为“逻辑错误(Logical Errors或Logic Errors)”,比如案例6-1中演示的代码。

案例6-1: 在图6.4所示的工作表中存有一列小数数字,请编写程序将它们的符号(正数或负数)写入C列,并将这些数字以百分比的形式写入D列。

图6.4 案例6-1示例代码及运行效果(运行结果不正确)

上图中的代码能够正常执行,并且其输出结果看上去也没有什么问题。不过仔细查看,却发现D列所有百分数都与B列的小数数值相差10倍,这是非常严重的计算错误。错误的原因就是代码不小心把乘以“100”写成了乘以“1000”。

由于逻辑错误不违反 VBA 语法和计算规则,所以即使运行结果有误也不会收到任何警示,只能依靠我们根据程序输出结果自行排查。大家经常听说的软件“Bug”,指的主要就是这种错误,本章接下来介绍的各种调试工具,主要也用于逻辑错误的诊断。 1V2f3jGnwoq4NMZxmdOu09XI3/l9nKMJ4/ep4YOqT/D2JSjfgH6tM5fKNDbo6dBm

点击中间区域
呼出菜单
上一章
目录
下一章
×