人类语言中的每个文字,比如一个英文字母、一个数字符号、一个汉字等,在 VBA 中都被视作一个“字符”。所以顾名思义,“字符串(String)”就是把任意个字符“串”在一起形成的内容,可以容纳人类语言中的一个词、一句话,甚至一篇文章。
在 VBA 中表示字符串非常简单,只要在字符的两边“套上”一对半角双引号,就可以像使用数字一样使用它,比如使用赋值语句将字符串赋值给某个单元格,从而在表格中显示这段文本内容。图5.1所示的代码,就是通过这种方式在工作表中连续输出5行相同的文本内容。
图5.1 在单元格中写入字符串示例
对于VBA来说,字符串与数字一样,都是可以赋值给变量的合法内容。所以图5.1中的程序还可以使用变量改写为如图5.2所示的代码。
图5.2 将字符串赋值给变量示例
同样,也可以像比较数字一样使用等号比较两个字符串是否相等。比如在案例5-1的代码中,就是通过检查单元格中的字符串来决定采用哪种汇率数值。
案例5-1: 在图5.3左侧所示的工作表中存有多个商品的进口价格,但是各自采用不同的货币单位计价。请编写一个VBA程序,将所有价格都换算为人民币价格,具体换算汇率为:1USD=6.5RMB、1EUR=8.2 RMB、1CAD=5.1RMB、1JPY=0.07RMB。预期效果如图5.3右侧的表格所示。
图5.3 案例5-1的数据、预期效果及参考答案
在参考答案中,我们使用了一个多分支If结构对每行数据的币种进行判断。如果这行D列单元格中的字符串等于“USD”,就让变量rate等于6.5;否则如果该行D列等于“EUR”,就让变量rate等于8.2,以此类推。当然,也可以使用Select…Case结构代替If … ElseIf结构,代码如下:
从语法上看,字符串最重要的标识就是括在两端的双引号。然而初学者在书写字符串时往往会忘记写这对双引号,结果就会导致一些莫名其妙的错误。比如图5.4所示的两个程序,除了有无双引号的区别,其他完全相同,运行效果却迥然不同。
图5.4 使用双引号与不使用双引号的区别
在图5.4左边的程序中,最后一行代码在Hello两边套上了双引号,因此这一句的含义就是把字符串“Hello”赋值给B2单元格,所以运行程序之后,B2单元格中显示的内容就是“Hello”。
但是在图5.4右边的程序中,最后一行代码没有在Hello两边套上双引号,因此VBA不会把它当作一个字符串,而是把它当作一个普通变量,就如前面所举的例子那样。巧合的是,在这个程序的第一行就定义了一个名为 Hello 的变量,并在第二行中给它赋值为“你好”这个字符串。所以这句代码的含义就是:将变量Hello的值赋予B2单元格,也就是在B2单元格中显示“你好”。
换句话说,在VBA代码中,如果一段文本两端有双引号,那么VBA会把它当作一个字符串值;反之,VBA就会把它当作一个变量的名字。
进一步思考 假如图5.4右侧的程序没有使用Dim事先声明一个名为Hello的变量会怎么样呢?这就要看是否在该模块的最前面书写了“Option Explicit”语句。如果没有写“Option Explicit”语句,也就是不要求强制声明变量,那么尽管VBA在执行到最后一行代码时找不到名为Hello的变量,也会自动创建一个名为“Hello”的变量,并将其内容默认为“空”。所以程序的执行效果就是在B2单元格中输出一个空字符串,结果就是表格没有任何变化。反之,如果在模块中写有“Option Explicit”语句,要求使用变量前必须事先声明,那么VBA执行到最后一行代码时发现并不存在名为Hello的变量,就会直接提示出错。
此外,经常使用中文输入法的读者还要注意,字符串两边要求使用半角双引号,而不是输入中文时常用的全角双引号。尽管后者看起来漂亮许多,但是与VBA语法完全无关,千万不要混淆。
如前所述,双引号代表一个字符串或者说一段文本的开始和结束,那么假如文本中间含有双引号这个字符,程序该怎样分辨呢?显然,像书写其他字符一样直接书写双引号,很可能会导致VBA理解混乱,使程序无法执行,就像图5.5所示的情况一样。
图5.5 在字符串中直接书写半角双引号导致的语法错误
引发语法错误的原因在于,当VBA看到等号后面第一个“"”时,意识到从这里开始将是一个字符串,“"”就是该字符串的起点。当看到冒号后面的“"”时,根据语法,VBA 认为这就是该字符串的结束位置,也就是说,需要赋值给变量 s的字符串就是“他说:”。既然如此,赋值语句到此就理应结束,可事实却是第二个“"”后面还有很多内容,即“俺们……”。因此VBA认为这行代码在第二个“"”后面缺少一个语句结束标识(比如可以将两个语句分隔开的冒号),提示出错。
那么当字符串中确实需要出现双引号时,应该怎样避免出错呢?最简单的办法就是像图5.6一样,在字符串内部使用单引号或全角双引号。由于它们与半角双引号完全不是同一个字符,所以就不会引起VBA的误解。
图5.6 在字符串中使用全角双引号(请注意半角双引号
如果必须在字符串中出现半角双引号,那么只要把它连写两次,VBA就会知道这是一个仅用于文本内容的半角双引号,并且不会把它看作字符串的起始标识。图5.7就演示了这种用法。
这种通过连写等模式改变某些特殊符号含义的方法,一般被称作“字符转义”,在各种编程语言及工具中都很常见,在讲解正则表达式时会遇到类似用法。
图5.7 使用连续书写方式表示仅用于文本内容的双引号
另一个常见问题是:怎样书写一个包含多行文本的字符串,或者说,怎样在一个字符串中插入换行符。
如果在编写VBA代码时直接在一个字符串中间按回车键,并不代表该字符串含有多行文本。根据 VBA 语法的规定,一个字符串只能书写在同一行代码中,不允许跨行书写。所以当我们按回车键后,VBA会自动尝试在每行补全双引号,使其成为两个字符串,以便保持语法正确,如图5.8所示。
图5.8 在字符串中直接按回车键后的代码变化
在图 5.8 中,由于VBA要求字符串不能跨行书写,所以自动为字符串的第一行补足引号,使其成为一个完整的字符串赋值语句;同时在第二行中间的合适位置也补足了引号,从而使这行看上去像一个“过程调用”语句 ,让这行在形式上也符合VBA语法。
那么怎样在字符串中表示换行呢?首先需要理解的是:从计算机的角度来看,如同英文字母或标点符号一样,换行也是一个字符 。所以只要能够在字符串中间插入表示换行的字符,就能够表明该字符串在这个位置需要换行显示。
关于换行字符的详细内容,本书将在数据类型章节中讲解字符串数据类型时详细介绍。这里大家只要知道VBA已经事先定义了一些“系统常量”,可以代表各种换行字符即可。
所谓“系统常量”,就如同使用“Const”关键字在程序中定义的常量,可以使其代表一些特定值并且不允许修改。只不过系统常量并非由我们定义,而是微软公司的开发人员在设计 VBA系统时已经定义好的,用于代表一些常用数值。由于不同操作系统使用不同字符表示换行,所以VBA提供了多个表示换行符的常量,具体如表5-1所示。
表5-1 各种操作系统中代表换行符的VBA系统常量
根据表5-1所示,在Windows操作系统的Office软件中,可以使用vbCrLf或vbNewLine两个系统常量在VBA中表示换行。那怎样把这些系统常量插入一个字符串中呢?比如在图5.8所示的例子中,如果直接写“注意:vbNewLine 前方高能”,那么由于vbNewLine位于双引号之内,VBA就会把它看作一个普通的文本内容,也就是一连串英文字母,而非一个变量或常量。所以实际的输出结果中会出现“vbNewLine”这个单词,而不会有任何换行效果。
正确的做法是把vbNewLine写在双引号之外,并使用字符串连接符将它与字符串其他部分连接在一起,如图5.9所示。
图5.9 使用VBA系统常量实现字符串换行