我目前正在使用Excel VBA加载项来处理从一个系统到利益相关者想要查看的格式的CSV导出。我对OOP还是陌生的,但我认为这可能在Let代码中转换优先级类型,并以与输出时相同的格式存储数据。
我写了以下课程:
'Class Module "Project"
Option Explicit
Private m_sPriority As String
Property Let Priority(lInput As Long)
Select Case lInput
Case 1
m_sPriority = "High"
Case 2
m_sPriority = "Medium"
Case 3
m_sPriority = "Low"
Case Else
m_sPriority = "No Priority"
End Select
End Property
Property Get Priority() As String
Priority = m_sPriority
End Property
这是测试它的模块:
'Standard Module
Option Explicit
Sub test()
Dim Project As Project
Set Project = New Project
Project.Priority = 1
Debug.Print Project.Priority
End Sub
我希望在运行此命令时看到“高”输出到控制台。
是否可以在VBA中完成此操作,或者我的代码格式错误?
答案 0 :(得分:6)
是的,您的代码格式不正确。无论值多少钱,您都无法在.NET中做到这一点-无论是在C#中,语法都使它变得毫不含糊:
private string _priority;
public string Priority
{
get { return _priority; }
private set { _priority = value; }
}
...或在VB中:
Private _priority As String
Public Property Priority() As String
Get
Return _priority
End Get
Private Set(ByVal value As String)
_priority = value
End Set
End Property
属性是Long
或String
,不能同时是两者。 Get
/ Let
/ Set
访问者在VBA中也必须保持一致。
您可以通过失去类型安全性并尽早绑定,将您的财产设为Variant
来作弊,但这并不是真正的好方法从OOP开始;-)
Public Enum PriorityLevel
NoPriority = 0
HighPriority
MediumPriority
LowPriority
End Enum
Private Type InstanceState
Priority As PriorityLevel
'...
End Type
Private this As InstanceState
Public Property Get Priority() As Variant
Priority = PriorityName(this.Priority)
End Property
Public Property Let Priority(ByVal value As Variant)
this.Priority = value
End Property
Private Function PriorityName(ByVal value As PriorityLevel) As String
Select Case value
Case HighPriority
PriorityName = "High"
Case MediumPriority
PriorityName = "Medium"
Case LowPriority
PriorityName= "Low"
Case Else
PriorityName= "Undefined"
End Select
End Function
虽然这可以很好地工作并且表面看上去很整洁,但是当您没有编写该类时就使用它,这肯定令人惊讶:如果您 set (Let
Long
,您理所当然也希望Get
和Long
也是如此。此类请求PriorityName
的只读属性:
Public Property Get Priority() As PriorityLevel
Priority = this.Priority
End Property
Public Property Let Priority(ByVal value As PriorityLevel)
this.Priority = value
End Property
Public Property Get PriorityName() As String
Select Case this.Priority
Case HighPriority
PriorityName = "High"
Case MediumPriority
PriorityName = "Medium"
Case LowPriority
PriorityName = "Low"
Case Else
PriorityName = "Undefined"
End Select
End Property
现在,早期绑定和类型安全(无论您在VBA中利用了什么)的好处显而易见:在编写分配该类型对象的Priority
属性的代码时,<用于Enum
类型的em> IntelliSense 指导表达式的编写:
此外,Enum
是抽象的基础数字值,这变得无关紧要:代码现在说{{1},而不是神奇的硬编码1
}。另外,HighPriority
访问器非常简单,这非常好:Get
访问器永远都不会引发任何错误,因此越简单越好。
故事的寓言:如果可以帮助的话,请不要乱动类型安全,应尽一切努力使代码早日绑定-尽可能避免使用Get
和Object
;尽可能将Variant
投射到已知的类/接口。
例如,更喜欢此:
Object
对此:
Dim sheet As Worksheet
' Workbook.Worksheets(index) returns Object; casting it to Worksheet
Set sheet = ActiveWorkbook.Worksheets(1)
sheet.Range("A1").Value = 42