我有一个VBA代码,需要在其中定义一个包含非Unicode字符(£)的常量字符串。如某些人所知,VBA编辑器不支持非unicode,并使用区域和语言设置中的Windows“系统区域设置”设置来解析/映射这些字符。我开发代码的机器设置为英语系统区域设置,但某些用户将该设置设置为其他语言,例如中文,它将字符串常量变为问号(£->?)。
现在,£= chr(163),但是,不能将chr用作在VBA中定义常量的一部分。因此,虽然允许:
public const mystring = "reference constant string with £"
在VBA中不允许”
public const mystring = "reference constant string with " & chr(163).
一种解决方法是将mystring定义为公共/全局变量:
Constants.bas
public mystring as string
,然后在开始运行代码或打开Excel时设置公共变量。
此工作簿
Private Sub Workbook_Open()
mystring = "reference constant string with " & chr(163).
End Sub
此过程的一个问题是,发生错误或代码停止时,将清除公共变量。为了保持价值,我遇到的另一个选择是避免使用公共变量,而是使用公共属性get。请注意,我必须将此内容包含在类中。
**。cls
Public Property Get mystring () As String
mystring = "\R;;" & Chr(163)
End Property
那么,现在我想知道这种方法是否会有任何问题?或者也许有更好的方法来处理具有非Unicode字符的常量。
答案 0 :(得分:1)
主要问题是模块的名称Constants
-具有误导性,因为既没有公共/全局变量,也没有公共获得的属性是常量。
端节点,常量不能分配给非常量表达式不是VBA特有的限制。
在标准模块中,属性是完全合法的,而公开获取属性是暴露需要在运行时构造的只读值的绝佳方法。
在发生错误或代码停止时清除公共变量
假设“发生错误时”涉及单击 End 并有效地结束执行上下文,这对在任何地方公开的一切都是正确的,无论它是全局变量,公共属性,对象或运行时内存中存在的任何内容……那只是正常现象-该值随时随地都可以按需提供。
同样,无需为此使用类模块,这在标准模块中完全合法:
Option Explicit
Public Property Get MyString() As String
MyString = "\R;;" & Chr(163)
End Property
如果每次访问属性getter时都重新创建字符串是一个问题,那么您需要一种方法来将其值保留在支持字段中-但是,此支持字段(无论是在类还是标准模块中)仅当执行上下文存在时才有一个值,这意味着它具有与全局变量完全相同的问题:执行停止,它消失了。
一种解决方法是使用将VB_PredeclaredId
属性设置为True
(默认值为False
)的类。
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
END
Attribute VB_Name = "Class1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = True
Option Explicit
Private internalString As String
Private Sub Class_Initialize()
internalString = "\R;;" & Chr(163)
End Sub
Public Property Get MyString() As String
MyString = internalString
End Property
现在,VBA会在被引用时自动创建Class1
的实例,被引用后立即 ,并且该实例保持“有效”状态,直到End
语句被明确执行,否则执行上下文终止。就像UserForm
类一样,您可以使用类名称作为标识符来访问此默认实例:
Debug.Print Class1.MyString
如果在引用Class1
时存在默认实例,则返回internalString
。如果没有,则执行Class_Initialize
,然后返回internalString
。