注意:本文的讨论建立在前文《EXCEL中,将十六进制转换为十进制》的基础上。
一、And运算符
在前一篇文章中,方法2的VBA子例程ConvertData_2中,有这样一段代码:
Do HexToDec Cells(cell.row, cell.column) Set cell = .FindNext(cell) On Error Resume Next ' 开启错误处理开关 ' 查找并转换完毕所有满足条件的单元格后,执行下面这行语句应该条件为假从而跳出循环; ' 但不知为何,实际情况是:此时会出错,所以特别增加了错误处理 Loop While Not cell Is Nothing And cell.Address <> firstAddress If Err.Number <> 0 Then ' 如果出错,表明已经查找并转换完毕,退出 Exit Sub End If On Error GoTo 0 ' 关闭错误处理开关(在函数结尾处,可以忽略)
这是一个简单的Do...Loop循环,但在Loop语句(条件判断)的周围却存在错误处理代码,正如其中的注释所说:“查找并转换完毕所有满足条件的单元格后,执行下面这行语句应该条件为假从而跳出循环;但不知为何,实际情况是:此时会出错,所以特别增加了错误处理”。
当时不仅不知道Loop语句在“查找完毕”时为何会执行出错,反而还感到非常奇怪,因为ConvertData_2例程中“使用Find方法查找以'0x'为前缀的单元格”的代码段其实是取自Excel 2007的帮助文档中关于“Range.Find方法”的示例:
示例
本示例在第一个工作表的单元格区域 A1:A500 中查找包含值 2 的所有单元格,并将这些单元格的值更改为 5。
Visual Basic for Applications |
---|
|
但事实是,“Loop While Not c Is Nothing And c.Address <> firstAddress
”这句代码在查找失败时(此时c Is Nothing)确实会出错:
很明显该错误是在c.Address处发生的,此时因为c为Nothing,引用Nothing对象的属性必然会出错。
但这就奇怪了,c为Nothing时,表达式“Not c Is Nothing”值为假,为什么还要去求值And后面的表达式呢?
后来我仔细查看了Excel 2007帮助文档中关于“And运算符”的说明,结果发现“VBA中的And运算符”与“C语言中的&&运算符”的求值规则是不同的:
1、我们习以为常的“C语言中的&&运算符”的求值规则是:如果&&左边的表达式为真,则继续求值&&右边的表达式,以便求取整个表达式的值;如果&&左边的表达式为假,则整个表达式的值为假,此时不需要继续求值&&右边的表达式;
2、“VBA中的And运算符”的求值规则是:无论And左边的表达式为何值,都将对And右边的表达式进行求值,整个表达式的值由And左右两边表达式的求值结果共同决定。
于是,前面所示ConvertData_2中的代码段就可以改为:
Do HexToDec Cells(cell.row, cell.column) Set cell = .FindNext(cell) If cell Is Nothing Then ' 首先单独判断cell是否为Nothing,如果是,则退出循环 Exit Do End If Loop While cell.Address <> firstAddress ' 然后再判断cell.Address的值(此时cell一定不为Nothing)
实验证明,以上修改后的代码就不会再出错了。这么说来,Excel 2007的帮助文档中关于“Range.Find方法”的示例应该是有问题的。实践出真知,目前的结论就是如此。
二、IF函数
在前一篇文章中,方法3的转换公式:
=HEX2DEC(RIGHT(A1, LEN(A1) - 2)) ' 针对A1单元格的转换公式
当时谈到方法3的缺点时,说到该方法缺乏灵活性。今天又研究了一下,结果发现有一个IF函数可以实现简单的条件判断,进而可以做到使方法3具有与方法1、2同样的“只转换满足格式的数据,不满足格式的数据不会受影响”的效果。新的转换公式如下:
=IF(LEFT(A1, 2)="0x", HEX2DEC(RIGHT(A1, LEN(A1) - 2)), A1) ' 针对A1单元格的转换公式
附:IF函数说明
函数:IF
语法:=IF(logical_test, [value_if_true], [value_if_false])
说明:判断是否满足条件,如果满足返回一个值,如果不满足则返回另一个值。