VBA:使用公共属性代替Const(用于非Unicode字符)

时间:2019-01-15 16:48:46

标签: vba properties const

我有一个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字符的常量。

1 个答案:

答案 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