是否可以在VBA中使用不同的数据类型来进行获取和获取?

Sko*_*die 1 oop excel vba class

我目前正在使用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
Run Code Online (Sandbox Code Playgroud)

这是测试它的模块:

'Standard Module
Option Explicit

Sub test()
        Dim Project As Project
        Set Project = New Project

        Project.Priority = 1
        Debug.Print Project.Priority
End Sub
Run Code Online (Sandbox Code Playgroud)

我希望在运行此命令时看到“高”输出到控制台。

有没有办法在VBA中完成此操作,或者我的代码格式错误?

Mat*_*don 7

是的,您的代码格式错误。无论值多少钱,您也都不能在.NET中做到这一点-语法使之相当明确,无论是在C#中:

private string _priority;
public string Priority 
{
    get { return _priority; }
    private set { _priority = value; }
}
Run Code Online (Sandbox Code Playgroud)

...或在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
Run Code Online (Sandbox Code Playgroud)

一个属性是a Long或a String,不能同时是两者。Get/ Let/ Set存取必须是一致的,在VBA为好。

您可以通过丢失类型安全性和早期绑定来欺骗,通过将您的财产设为... 来欺骗,但这并不是真正开始使用OOP的好方法;-)Variant

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
Run Code Online (Sandbox Code Playgroud)

虽然这可以很好地工作并且表面上看起来很整洁,但是在您还没有编写代码时就使用它,这肯定会令人惊讶:如果设置Let)a Long,那么您当然也希望这样GetLong。此类请求一个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
Run Code Online (Sandbox Code Playgroud)

现在,早期绑定和类型安全(无论它一点你在VBA杠杆)的好处是显而易见:当你写代码来分配Priority这种类型的对象的属性,智能感知Enum型引导的写作表达:

可用的枚举成员显示在下拉列表中

而且,Enum表示抽象的基础数字值变得无关紧要:1该代码现在表示,而不是魔术性的硬编码HighPriority。而且,Get访问器非常简单,这非常好:Get访问器永远都不会引发任何错误,因此越简单越好。

故事的士气:如果可以的话,不要乱动类型安全,要尽一切可能使代码尽早绑定-避免ObjectVariant尽可能多;Object尽可能地将其转换为已知的类/接口。

例如,更喜欢这样:

Dim sheet As Worksheet
' Workbook.Worksheets(index) returns Object; casting it to Worksheet
Set sheet = ActiveWorkbook.Worksheets(1)
sheet.Range("A1").Value = 42
Run Code Online (Sandbox Code Playgroud)

对此:

' "Range("A1").Value" is entirely late-bound. Beware of typos!
ActiveWorkbook.Worksheets(1).Range("A1").Value = 42
Run Code Online (Sandbox Code Playgroud)