VBA
Creación de una clase personalizada
Buscar..
Observaciones
Este artículo mostrará cómo crear una clase personalizada completa en VBA. Utiliza el ejemplo de un objeto DateRange
, porque las fechas de inicio y finalización a menudo se pasan juntas a las funciones.
Agregar una propiedad a una clase
Un procedimiento de Property
es una serie de sentencias que recupera o modifica una propiedad personalizada en un módulo.
Hay tres tipos de accesores de propiedad:
- Una
Get
procedimiento que devuelve el valor de una propiedad. - Un procedimiento
Let
que asigna un valor (no deObject
) a un objeto. - Un procedimiento
Set
que asigna una referencia deObject
.
Los accesores de propiedades a menudo se definen en pares, utilizando tanto Get
como Let
/ Set
para cada propiedad. Una propiedad con sólo una Get
procedimiento sería de sólo lectura, mientras que una propiedad con sólo una Let
/ Set
procedimiento sería de sólo escritura.
En el siguiente ejemplo, se definen cuatro DateRange
propiedades para la clase DateRange
:
-
StartDate
( lectura / escritura ). Valor de fecha que representa la fecha anterior en un rango. Cada procedimiento utiliza el valor de la variable del módulo,mStartDate
. -
EndDate
( lectura / escritura ). Valor de fecha que representa la fecha posterior en un rango. Cada procedimiento utiliza el valor de la variable del módulo,mEndDate
. -
DaysBetween
( solo lectura ). Valor entero calculado que representa el número de días entre las dos fechas. Como solo hay un procedimiento deGet
, esta propiedad no se puede modificar directamente. -
RangeToCopy
( solo escritura ). Un procedimiento deSet
utilizado para copiar los valores de un objetoDateRange
existente.
Private mStartDate As Date ' Module variable to hold the starting date
Private mEndDate As Date ' Module variable to hold the ending date
' Return the current value of the starting date
Public Property Get StartDate() As Date
StartDate = mStartDate
End Property
' Set the starting date value. Note that two methods have the name StartDate
Public Property Let StartDate(ByVal NewValue As Date)
mStartDate = NewValue
End Property
' Same thing, but for the ending date
Public Property Get EndDate() As Date
EndDate = mEndDate
End Property
Public Property Let EndDate(ByVal NewValue As Date)
mEndDate = NewValue
End Property
' Read-only property that returns the number of days between the two dates
Public Property Get DaysBetween() As Integer
DaysBetween = DateDiff("d", mStartDate, mEndDate)
End Function
' Write-only property that passes an object reference of a range to clone
Public Property Set RangeToCopy(ByRef ExistingRange As DateRange)
Me.StartDate = ExistingRange.StartDate
Me.EndDate = ExistingRange.EndDate
End Property
Agregando Funcionalidad a una Clase
Se puede llamar a cualquier Sub
, Function
, o Property
pública dentro de un módulo de clase precediendo a la llamada con una referencia de objeto:
Object.Procedure
En una clase de DateRange
, se puede usar un Sub
para agregar un número de días a la fecha de finalización:
Public Sub AddDays(ByVal NoDays As Integer)
mEndDate = mEndDate + NoDays
End Sub
Una Function
podría devolver el último día del próximo fin de mes (tenga en cuenta que GetFirstDayOfMonth
no sería visible fuera de la clase porque es privada):
Public Function GetNextMonthEndDate() As Date
GetNextMonthEndDate = DateAdd("m", 1, GetFirstDayOfMonth())
End Function
Private Function GetFirstDayOfMonth() As Date
GetFirstDayOfMonth = DateAdd("d", -DatePart("d", mEndDate), mEndDate)
End Function
Los procedimientos pueden aceptar argumentos de cualquier tipo, incluidas las referencias a los objetos de la clase que se está definiendo.
El siguiente ejemplo prueba si el objeto DateRange
actual tiene una fecha de inicio y una fecha de finalización que incluye la fecha de inicio y finalización de otro objeto DateRange
.
Public Function ContainsRange(ByRef TheRange As DateRange) As Boolean
ContainsRange = TheRange.StartDate >= Me.StartDate And TheRange.EndDate <= Me.EndDate
End Function
Tenga en cuenta el uso de la notación Me
como una forma de acceder al valor del objeto que ejecuta el código.
Ámbito del módulo de clase, creación de instancias y reutilización.
De forma predeterminada, un nuevo módulo de clase es una clase privada, por lo que solo está disponible para la creación de instancias y su uso dentro del VBProject en el que está definido. Puede declarar, crear instancias y usar la clase en cualquier lugar del mismo proyecto:
'Class List has Instancing set to Private
'In any other module in the SAME project, you can use:
Dim items As List
Set items = New List
Pero a menudo escribirá clases que le gustaría usar en otros proyectos sin copiar el módulo entre proyectos. Si define una clase llamada List
en ProjectA
, y desea usar esa clase en ProjectB
, entonces deberá realizar 4 acciones:
Cambie la propiedad de
PublicNotCreatable
instancias de la claseList
enProjectA
en la ventana Propiedades, dePrivate
aPublicNotCreatable
Cree una función pública de "fábrica" en
ProjectA
que cree y devuelva una instancia de una clase deList
. Normalmente, la función de fábrica incluiría argumentos para la inicialización de la instancia de clase. La función de fábrica es necesaria porqueProjectB
puede usar la clase, peroProjectB
no puede crear directamente una instancia de la clase deProjectA
.Public Function CreateList(ParamArray values() As Variant) As List Dim tempList As List Dim itemCounter As Long Set tempList = New List For itemCounter = LBound(values) to UBound(values) tempList.Add values(itemCounter) Next itemCounter Set CreateList = tempList End Function
En
ProjectB
agregue una referencia aProjectA
usando el menúTools..References...
En
ProjectB
, declare una variable y asígnele una instancia deList
usando la función de fábrica deProjectA
Dim items As ProjectA.List Set items = ProjectA.CreateList("foo","bar") 'Use the items list methods and properties items.Add "fizz" Debug.Print items.ToString() 'Destroy the items object Set items = Nothing