MyTetra Share
Делитесь знаниями!
Всё про VBA class module
Время создания: 12.10.2019 20:23
Раздел: !Закладки - VBA - Меню VB-справка
Запись: xintrea/mytetra_db_adgaver_new/master/base/1570882570soi4yq2z4d/text.html на raw.githubusercontent.com

Всё про VBA class module

Председатель Мао

Классовая борьба, одни классы побеждают, другие исключаются. Такова история

Содержание

  1. Краткое руководство по VBA Class Module
  2. Введение
  3. Почему мы используем объекты
  4. Преимущества использования объектов
  5. Недостатки использования объектов
  6. Создание простого Class Module
  7. Class Module против Объектов
  8. Class Module VBA против обычных модулей VBA
  9. Разница 1 — Как используются модули
  10. Разница 2 — Количество копий
  11. Части Class Module
  12. Методы Class Module
  13. Переменные-члены Class Module
  14. Свойства Class Module
  15. Формат свойств VBA
  16. Почему мы используем свойства
  17. Использование свойства вместо Function/Sub
  18. О Свойствах в двух словах
  19. Типы свойств VBA
  20. События Class Module
  21. Инициализация
  22. Завершение
  23. Class Module. Пример 1
  24. Class Module. Пример 2
  25. Заключение

Краткое руководство по VBA Class Module


Пункт

Пояснение

Class Module

Позволяет пользователю
создавать свои собственные
объекты.

Метод

Открытая функция или
подпрограмма в Class Module .

Переменная

Переменная, объявленная в Class Module.

Свойство

Специальная функция /
подпрограммы, которые ведут
себя как переменные при
использовании

Типы свойств

Get, Let и Set.

Событие — инициализация

Sub, который автоматически
запускается при создании
объекта Class Module.

Событие — завершение

Sub, который автоматически
запускается при удалении
объекта Class Module.

Объявление и создание —
статический

Dim o As New Class1

Объявление и создание —
динамический

Dim o As Class1 
Set o = New Class1 

Вызов подпрограммы Class
Module

o.WriteValues Total

Вызов функции Class Module

Amount = o.Calculate()

Использование свойства Class
Module

o.Amount = 1
Total = o.Amount

Введение

Class Module VBA позволяют пользователю создавать свои собственные объекты. Если вы не знакомы с объектами, я настоятельно рекомендую вам сначала ознакомиться с моей статьей Все об объектах VBA Objects.

В таких языках, как C # и Java, классы используются для создания объектов. Class Module являются VBA-эквивалентом этих классов. Основное отличие состоит в том, что Class Module VBA имеют очень ограниченный тип наследования * по сравнению с классами на других языках. В VBA наследование работает аналогично интерфейсам ** в C # \ Java.

В VBA у нас есть встроенные объекты, такие как Collection, Workbook, Worksheet и так далее. Целью Class Module VBA является предоставление нам возможности создавать собственные объекты.

Давайте начнем эту статью с рассмотрения того, почему мы используем объекты в первую очередь.

*Наследование использует существующий класс для создания нового класса.
**
Интерфейсы — это форма наследования, которая заставляет класс реализовывать специфические процедуры или свойства.

Почему мы используем объекты

Использование объектов позволяет нам создавать наши приложения так же, как мы используем строительные блоки.

Идея состоит в том, что код каждого объекта является автономным. Он полностью независим от любого другого кода в нашем приложении.

Это похоже на то, как все строится с использованием кирпичей Lego. Существует много различных типов компонентов Lego. Например, блок, руль и лазер — это разные вещи. Они ведут себя совершенно независимо друг от друга. Но мы можем соединить их вместе, чтобы создать здание, транспортное средство, космическую станцию ​​и так далее.

Если вам все еще неясно, не волнуйтесь. В остальной части этой статьи мы разберем все это на простые термины.

Преимущества использования объектов

Рассматривая части нашего кода как блоки, мы получаем много больших преимуществ.

  1. Это позволяет нам создавать приложения по одному блоку за раз.
  2. Намного проще протестировать отдельные части приложения.
  3. Обновление кода не вызовет проблем в других частях приложения.
  4. Легко добавлять объекты между приложениями.

Недостатки использования объектов

У большинства вещей в жизни есть свои плюсы и минусы. Использование Class Module VBA ничем не отличается. Ниже приведены недостатки использования Class Module для создания объектов.

  1. Первоначально для создания приложений требуется больше времени *.
  2. Не всегда легко четко определить, что такое объект.
  3. Люди, плохо знакомые с классами и предметами, могут сначала найти их трудными для понимания.

*Если вы создаете приложение с использованием объектов, на его создание уйдет больше времени, поскольку вам придется тратить больше времени на планирование и проектирование. Однако в долгосрочной перспективе это сэкономит вам огромное количество времени. Вашим кодом будет легче управлять, обновлять и использовать повторно.

Создание простого Class Module

Давайте рассмотрим очень простой пример создания Class Module и использования его в нашем коде.

Чтобы создать Class Module, мы щелкаем правой кнопкой мыши в окне Project и затем выбираем Insert и Class Module.

Наш новый класс называется Class1. Мы можем изменить имя в окне свойств, как показано на следующем скриншоте.

Давайте изменим имя модуля класса на clsCustomer. Затем мы добавим переменную в Class Module следующим образом.


1

Public Name As String


Теперь мы можем использовать этот Class Module в любом модуле (стандартном или классе) в нашей рабочей книге. Например:


1

2

3

4

5

6

7

8

' Создать объект из Class Module

Dim oCustomer As New clsCustomer

 

' Установите имя клиента

oCustomer.Name = "Иван"

 

' Напечатайте имя в Immediate Window(Ctrl + G)

Debug.Print oCustomer.Name

Class Module против Объектов

Люди, которые плохо знакомы с использованием классов и модулей классов VBA, часто путаются между тем, что такое класс и что является объектом.

Давайте посмотрим на пример из реального мира. Думайте о предмете массового производства как кофейная кружка. Дизайн кружки создается в первую очередь. Затем тысячи кофейных кружек создаются из этого дизайна.

Это похоже на работу Class Module и объектов.

Class Module можно рассматривать как дизайн.

Объект можно рассматривать как элемент, созданный из дизайна.

Ключевое слово New в VBA — это то, что мы используем для создания объекта из Class Module. Например:


1

2

3

4

' Создание объектов с использованием New

Dim oItem As New Class1

Dim oCustomer1 As New clsCustomer

Dim coll As New Collection

Примечание. Мы не используем New для таких элементов, как Workbooks и Worksheets. См. Когда New не требуется для получения дополнительной информации.

Class Module VBA против обычных модулей VBA

Написание кода в Class Module почти такое же, как написание кода в обычном модуле. Мы можем использовать тот же код, который мы используем в обычных модулях. То, как этот код используется, сильно отличается.

Давайте посмотрим на два основных различия между классом и обычным модулем. Это часто вызывает путаницу у новых пользователей.

Разница 1 — Как используются модули

Если вы хотите использовать подпрограмму / функцию и т.д. Из
Class Module, вы должны сначала создать объект.

Например, представьте, что у нас есть два идентичных Sub PrintCustomer. Один находится в Class Module, а другой — в обычном модуле…


1

2

3

4

' CLASS MODULE Код - clsCustomer

Public Sub PrintCustomer()

    Debug.Print "Пример вывода"

End Sub


1

2

3

4

' Код обычного модуля

Public Sub PrintCustomer()

    Debug.Print "Пример вывода"

End Sub

Вы заметите, что коды абсолютно одинаковые.

Чтобы использовать подпрограмму PrintCustomer из Class Module, вы должны сначала создать объект этого типа


1

2

3

4

5

6

7

' Другой модуль

Sub UseCustomer()

 

    Dim oCust As New clsCustomer

    oCust.PrintCustomer

 

End Sub

Чтобы использовать PrintCustomer из обычного модуля, вы можете вызвать его напрямую


1

2

3

4

5

6

' Другой модуль

Sub UseCustomer()

 

    PrintCustomer

 

End Sub

Разница 2 — Количество копий

Когда вы создаете переменную в обычном модуле, существует только одна ее копия. Для Class Module существует одна копия переменной для каждого создаваемого вами объекта.

Например, представьте, что мы создаем переменную StudentName как в классе, так и в обычном модуле.


1

2

' Обычный модуль

Public StudentName As String


1

2

' CLASS MODULE

Public StudentName As String

Для обычной переменной модуля в нашем приложении будет только одна копия этой переменной.


1

StudentName = "Иван"

Для Class Module новая копия переменной StudentName создается каждый раз, когда создается новый объект.


1

2

3

4

5

Dim student1 As New clsStudent

Dim student2 As New clsStudent

 

student1.StudentName = "Петр"

student2.StudentName = "Василий"

Когда вы полностью поймете Class Module VBA, эти различия будут казаться очевидными.

Части Class Module

В Class Module есть четыре разных предмета. Это:

  1. Методы — функции / подводные лодки.
  2. Переменные-члены — переменные.
  3. Свойства — типы функций / подпрограмм, которые ведут себя как переменные.
  4. События — подводные лодки, которые запускаются событием

Вы можете видеть, что они все или функции, подпрограммы или переменные.

Давайте кратко рассмотрим некоторые примеры, прежде чем разбираться с ними по очереди.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

' CLASS MODULE Код

 

' Переменная

Private dBalance As Double

 

' Свойства

Property Get Balance() As Double

    Balance = dBalance

End Property

 

Property Let Balance(dValue As Double)

    dBalance = dValue

End Property

 

' Событие - срабатывает при создании класса

Private Sub Class_Initialize()

    dBalance = 100

End Sub

 

' Методы

Public Sub Withdraw(dAmount As Double)

    dBalance = dBalance - dAmount

End Sub

 

Public Sub Deposit(dAmount As Double)

    dBalance = dBalance + dAmount

End Sub

Теперь, когда мы увидели примеры, давайте рассмотрим каждый из них по очереди.

Методы Class Module

Методы относятся к процедурам класса. В VBA есть процедуры и функции. Как и переменные-члены, они могут быть Public или Private.

Давайте посмотрим на пример:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

' CLASS MODULE Код

 

' Имя класса: clsSimple

 

' Публичные процедуры могут быть вызваны извне объекта

Public Sub PrintText(sText As String)

    Debug.Print sText

End Sub

 

Public Function Calculate(dAmount As Double) As Double

    Calculate = dAmount - GetDeduction

End Function

 

' частные процедуры могут быть вызваны только из Class Module

Private Function GetDeduction() As Double

    GetDeduction = 2.78

End Function

Мы можем использовать Class Module clsSimple следующим образом


1

2

3

4

5

6

7

8

9

10

11

12

Sub ClassMembers()

     

    Dim oSimple As New clsSimple

     

    oSimple.PrintText "Hello"

      

    Dim dTotal As Double

    dTotal = oSimple.Calculate(22.44)

      

    Debug.Print dTotal

 

End Sub

Переменные-члены Class Module

Переменная-член очень похожа на обычную переменную, которую мы используем в VBA. Разница в том, что мы используем Public или Private вместо Dim.


1

2

3

4

' CLASS MODULE Код

 

Private Balance As Double

Public AccountID As String

Примечание: Dim и Private делают одно и то же, но соглашение заключается в том, чтобы использовать Dim в sub / functions и использовать Private за пределами sub / functions.

Ключевое слово Public означает, что переменная может быть доступна вне Class Module. Например:


1

2

3

4

5

6

7

Dim oAccount As New clsAccount

 

' Действительный - AccountID открыт

oAccount.AccountID = "499789"

 

' Ошибка - Баланс является частным

oAccount.Balance = 678.90

В приведенном выше примере мы не можем получить доступ к Балансу, потому что он объявлен, как Частный. Мы можем использовать только приватную переменную внутри Class Module. Мы можем использовать функцию / подпрограмму в Class Module, например:


1

2

3

4

5

6

7

' CLASS MODULE Код

Private Balance As Double

 

Public Sub SetBalance()

    Balance = 100

    Debug.Print Balance

End Sub

Считается плохой практикой иметь публичные переменные-члены. Это потому, что вы позволяете коду вне объекта мешать работе класса. Цель использования классов состоит в том, чтобы скрыть происходящее от вызывающего.

Чтобы пользователь не общался напрямую с нашими переменными-членами, мы используем Свойства.

Свойства Class Module

  1. Get — возвращает объект или значение из класса
  2. Let — устанавливает значение в классе
  3. Set — устанавливает объект в классе

Формат свойств VBA

Обычный формат для свойств выглядит следующим образом:


1

2

3

4

5

6

7

8

Public Property Get () As Type

End Property

 

Public Property Let (varname As Type )

End Property

 

Public Property Set (varname As Type )

End Property

Мы уже видели, что свойство это просто тип sub. Назначение свойства — позволить вызывающей стороне получать и устанавливать значения.

Почему мы используем свойства

Почему мы не можем просто сделать переменные общедоступными и использовать их напрямую?

Давайте объясним с некоторыми примерами. Представьте, что у нас есть класс, который ведет список стран. Мы могли бы сохранить список в виде массива:


1

2

3

4

5

6

7

' Использовать массив для хранения стран

Public arrCountries As Variant

 

' Установить размер массива при инициализации класса

Private Sub Class_Initialize()

    ReDim arrCountries(1 To 1000)

End Sub

Когда пользователь хочет получить количество стран в списке, он может сделать это:


1

2

3

4

5

' Код обычного модуля

Dim oCountry As New clsCountry

 

' Получить количество элементов

NumCountries = UBound(oCountry.arrCountries) + 1

С приведенным выше кодом есть две основные проблемы

  1. Чтобы узнать количество стран, вам необходимо знать, как хранится список, например, Массив.
  2. Если мы изменим массив на коллекцию, нам нужно будет изменить весь код, который напрямую ссылается на массив

Для решения этих проблем мы можем создать функцию, возвращающую количество стран:


1

2

3

4

5

6

7

' CLASS MODULE Код - clsCountryList

' Массив

Private arrCountries() As String

 

Public Function Count() As Long

    Count = UBound(arrCountries) + 1

End Function

Затем мы используем это так


1

2

3

4

' Код модуля

Dim oCountries As New clsCountries

 

Debug.Print "Количество стран " & oCountries.Count

Этот код решает две проблемы, которые мы перечислили выше. Мы можем изменить наш массив на коллекцию, и код вызывающего абонента все равно будет работать. Например:


1

2

3

4

5

6

7

' CLASS MODULE Код

' Коллекция

Private collCountries() As Collection

 

Public Function Count() As Long

    Count = collCountries.Count

End Function

Вызывающий не замечает, как хранятся страны. Все, что нужно знать вызывающему — это то, что функция Count будет возвращать количество стран.

Как мы только что видели, подпрограмма или функция обеспечивает решение вышеуказанных проблем. Однако использование свойства может обеспечить более элегантное решение.

Использование свойства вместо Function/Sub

Вместо создания функции Count мы можем создать свойство Count. Как вы можете видеть ниже, они очень похожи:


1

2

3

4

5

6

7

8

9

' Замени это

Public Function Count() As Long

    Count = UBound(arrCountries) + 1

End Function

 

' На это

Property Get Count() As Long

    Count = UBound(arrCountries) + 1

End Function

В этом сценарии нет большой разницы между использованием свойства и использованием функции. Тем не менее, есть различия. Обычно мы создаем свойство Get и Let так:


1

2

3

4

5

6

7

8

9

10

' CLASS MODULE Код - clsAccount

Private dTotalCost As Double

 

Property Get TotalCost() As Long

     TotalCost= dTotalCost

End Property

 

Property Let TotalCost(dValue As Long)

     dTotalCost = dValue

End Property

Использование Let позволяет нам рассматривать свойство, как переменную. Таким образом, мы можем сделать это:


1

oAccount.TotalCost = 6

Второе отличие состоит в том, что использование Let и Get позволяет нам использовать одно и то же имя при обращении к свойству Get или Let. Таким образом, мы можем использовать свойство, как переменную. Это цель использования свойств над подпрограммой и функцией.


1

2

oAccount.TotalCost = 6

dValue = oAccount.TotalCost

Если мы использовали функцию и подпрограмму, то мы не можем получить поведение переменной. Вместо этого мы должны вызвать две разные процедуры, например:


1

2

oAccount.SetTotalCost 6

dValue = oAccount.GetTotalCost

Вы также можете видеть, что когда мы использовали Let, мы можем присвоить значение, как переменную. Когда мы используем SetTotalCost, мы должны были передать его в качестве параметра.

О Свойствах в двух словах

  1. Свойство скрывает детали реализации от вызывающей стороны.
  2. Свойство позволяет нам обеспечивать то же поведение, что и переменная.

Типы свойств VBA

Есть три типа свойств. Мы уже видели Get и Let. Но мы еще не рассмотрели Set.

Set похож на Let, но он используется для объекта (подробнее об этом см. Назначение объектов VBA).

Первоначально в Visual Basic ключевое слово Let использовалось для назначения переменной. На самом деле, мы можем использовать его, как захотим.


1

2

3

' Эти строки эквивалентны

Let a = 7

a = 7

Поэтому мы используем Let, чтобы присвоить значение переменной, и мы используем Set, чтобы назначить объект переменной объекта.


1

2

3

4

5

6

7

8

' Используем Let

Dim a As Long

Let a = 7

 

' Используем Set

Dim coll1 As Collection, coll2 As Collection

Set coll1 = New Collection

Set coll2 = coll1

  • Let используется для присвоения значения базовому типу переменной.
  • Set используется для назначения объекта переменной объекта

В следующем примере мы используем свойства Get и Let для строковой переменной


1

2

3

4

5

6

7

8

9

10

11

12

13

' CLASS MODULE Код

 

' Свойства SET/LET для переменной

Private m_sName As String

 

' свойства Get/Let

Property Get Name() As String

    Name = m_sName

End Property

 

Property Let Name(sName As String)

    m_sName = sName

End Property

Затем мы можем использовать свойства Name так:


1

2

3

4

5

6

7

8

9

10

11

12

13

Sub TestLetSet()

 

    Dim sName As String   

    Dim coll As New Collection

    Dim oCurrency As New clsCurrency

     

    ' Свойство Let

    oCurrency.Name = "USD"

     

    ' Свойство Get

    sName = oCurrency.Name

 

End Sub

В следующем примере мы используем свойства Get и Set для переменной объекта


1

2

3

4

5

6

7

8

9

10

11

12

' CLASS MODULE Код

 

Private m_collPrices As Collection

 

' Свойства Get/Set

Property Get Prices() As Collection

    Set Prices = m_collPrices

End Property

 

Property Set Prices(collPrices As Collection)

    Set m_collPrices = collPrices

End Property

Затем мы можем использовать свойства так:


1

2

3

4

5

6

7

8

9

10

11

12

13

Sub TestLetSet()

     

    Dim coll1 As New Collection

    Dim oCurrency As New clsCurrency

     

    ' Свойство Set

    Set oCurrency.Prices = coll1

 

    ' Свойство Get

    Dim coll2 As Collection

    Set Coll2 = oCurrency.Prices

     

End Sub

Мы используем свойство Get, чтобы вернуть значения для обоих элементов. Обратите внимание, что даже если мы используем свойство Get для возврата коллекции, нам все равно нужно использовать ключевое слово Set для его назначения.

События Class Module

Class Module имеет два события:

  1. Инициализировать — происходит при создании нового объекта класса.
  2. Завершить — происходит, когда объект класса удален.

В объектно-ориентированных языках, таких как C ++, эти события называются Конструктором и Деструктором. В большинстве языков вы можете передавать параметры конструктору, но не в VBA. Мы можем использовать Class Factory, чтобы обойти эту проблему, как показано ниже.

Инициализация

Давайте создадим очень простой Class Module с именем clsSimple с событиями Initialize и Terminate.


1

2

3

4

5

6

7

8

9

10

11

12

' CLASS MODULE Код

Private Sub Class_Initialize()

    MsgBox "Класс инициализируется"

End Sub

 

Private Sub Class_Terminate()

    MsgBox "Класс прекращается"

End Sub

 

Public Sub PrintHello()

    Debug.Print "Привет"

End Sub

В следующем примере мы используем Dim и New для создания объекта.

В этом случае oSimple не создается, пока мы не ссылаемся на него в первый раз, например:


1

2

3

4

5

6

7

8

Sub ClassEventsInit2()

 

    Dim oSimple As New clsSimple

     

    ' Инициализация происходит здесь

    oSimple.PrintHello

 

End Sub

Когда мы используем Set и New вместе, поведение отличается. В этом случае объект создается при использовании Set, например:


1

2

3

4

5

6

7

8

9

10

Sub ClassEventsInit()

 

    Dim oSimple As clsSimple

     

    ' Инициализация происходит здесь

    Set oSimple = New clsSimple

     

    oSimple.PrintHello

    

End Sub

Примечание: Для получения дополнительной информации о различиях между использованием New с Dim и использованием New с Set см. Тонкие различия Dim и Set

Как я уже говорил ранее, вы не можете передать параметр в Initialize. Если вам нужно сделать это, вам нужна функция, чтобы сначала создать объект.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

' CLASS MODULE - clsSimple

Public Sub Init(Price As Double)

 

End Sub

 

' обычный модуль

Public Sub Test()

 

    ' использование функции CreateSimpleObject

    Dim oSimple As clsSimple

    Set oSimple = CreateSimpleObject(199.99)

 

End Sub

 

Public Function CreateSimpleObject(Price As Double) As clsSimple

 

    Dim oSimple As New clsSimple

    oSimple.Init Price

 

    Set CreateSimpleObject = oSimple

 

End Function

Мы расширим CreateSimpleObject в Примере 2, чтобы создать фабрику классов.

Завершение

Событие Terminate наступает при удалении класса. Это происходит, когда мы устанавливаем значение Nothing.


1

2

3

4

5

6

7

8

9

Sub ClassEventsTerm()

 

    Dim oSimple As clsSimple

    Set oSimple = New clsSimple

     

    ' Завершение происходит здесь

    Set oSimple = Nothing

    

End Sub

Если мы не установим объект в Nothing, VBA автоматически удалит его, когда он выйдет из области видимости.

Это означает, что если мы создадим объект в процедуре, когда эта процедура завершится, VBA удалит все созданные объекты.


1

2

3

4

5

6

7

8

9

Sub ClassEventsTerm2()

 

    Dim oSimple As New clsSimple

     

    ' Инициализация происходит здесь

    oSimple.PrintHello

 

   ' oSimple удаляется, когда мы выходим из этого Sub-вызова Terminate

End Sub

Class Module. Пример 1

В этом примере мы рассмотрим очень распространенное использование Class Module.

Представьте, что у нас есть следующие данные:

Мы хотим читать альбомы по разным годам, а затем создавать различные отчеты.

Мы могли бы использовать для этого 2D-массив или коллекцию коллекций, например:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

For i = 2 To rg.Rows.Count

     

    Year = rg.Cells(i, 3)

    If startYear <= Year And endYear >= Year Then

         

        ' Создать новую коллекцию для каждой строки

        Set rowColl = New Collect

  

        ' Добавить исполнителя

        rowColl.Add rg.Cells(i, 1).Value

        ' Добавить заголовок

        rowColl.Add rg.Cells(i, 2).Value

         

        ' и так далее

 

        ' Добавить коллекцию строк в основную коллекцию

        coll.Add rowColl

 

    End If

     

Next i

Как вы можете себе представить, этот код очень быстро запутался.

К счастью для нас, у нас есть Class Module VBA, чтобы сделать нашу жизнь проще. Мы можем создать Class Module для хранения элементов.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

' clsAlbum class module

Private m_sArtist As String

Private m_sTitle As String

Private m_sYear As String

Private m_sGenre As String

Private m_sSales As String

 

' Свойства

Public Property Get Artist() As String

    Artist = m_sArtist

End Property

Public Property Let Artist(ByVal sArtist As String)

    m_sArtist = sArtist

End Property

 

' и т.д.

Каждый раз, когда мы хотим добавить запись, мы можем сделать это следующим образом:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

' Объявить переменную

Dim oAlbum As clsAlbum

 

' Создать новый альбом

Set oAlbum = New clsAlbum

 

' Добавить детали

oAlbum.Artist = rg.Cells(i, 1)

oAlbum.Title = rg.Cells(i, 2)

oAlbum.Year = rg.Cells(i, 3)

oAlbum.Genre = rg.Cells(i, 4)

oAlbum.Sales = rg.Cells(i, 5)

 

' Добавить объект альбома в коллекцию

coll.Add oAlbum

Как видите, это делает наш код более читабельным. Понятно, для чего используются Artist, Title и т.д.

Затем мы можем легко использовать эти данные для создания отчетов, записи в файлы и т.д.


1

2

3

4

5

6

7

8

9

10

Sub PrintAlbum(coll As Collection)

     

    Dim oAlbum As clsAlbum

 

    For Each oAlbum In coll

        ' Распечатайте название и исполнителя для каждого альбома

        Debug.Print oAlbum.Title, oAlbum.Artist

    Next

     

End Sub

Ниже приведен полный код для этого примера


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

Sub CreateReport()

 

    Dim coll As Collection

    ' читать данные

    Set coll = ReadAlbums(1990, 2001)

     

    ' Распечатать информацию об альбоме

    PrintAlbum coll

 

    ' Распечатать общий объем продаж

    PrintTotalSales coll

     

End Sub

 

Function ReadAlbums(startYear As Long, endYear As Long) _

              As Collection

     

    Dim rg As Range

    Set rg = Sheet1.Range("A1").CurrentRegion

     

    ' Создать коллекцию для хранения альбомов

    Dim coll As New Collection

    Dim oAlbum As clsAlbum

     

    Dim i As Long, Year As Long

    For i = 2 To rg.Rows.Count

         

        Year = rg.Cells(i, 3)

        If startYear <= Year And endYear >= Year Then

            ' Создать новый альбом

            Set oAlbum = New clsAlbum

            ' Добавить детали

            oAlbum.Artist = rg.Cells(i, 1)

            oAlbum.Title = rg.Cells(i, 2)

            oAlbum.Year = Year

            oAlbum.Genre = rg.Cells(i, 4)

            oAlbum.sales = rg.Cells(i, 5)

            ' Добавить объект альбома в коллекцию

            coll.Add oAlbum

        End If

         

    Next i

     

    Set ReadAlbums = coll

     

End Function

 

Sub PrintAlbum(coll As Collection)

     

    Dim oAlbum As clsAlbum

    For Each oAlbum In coll

        Debug.Print oAlbum.Title, oAlbum.Artist

    Next

     

End Sub

 

Sub PrintTotalSales(coll As Collection)

     

    Dim oAlbum As clsAlbum, sales As Double

    For Each oAlbum In coll

        sales = sales + oAlbum.sales

    Next

     

    Debug.Print "Общее количество продаж составляет " &amp; sales

     

End Sub

Class Module. Пример 2

В этом примере мы пойдем дальше. Мы собираемся взглянуть на некоторые хитрые приемы при использовании объектов.

Представьте, что у вас есть список продуктов, как на картинке ниже.

Продукты имеют разные поля, поэтому нам нужно использовать разные модули классов для каждого типа продуктов. Один тип для строки Книги, один тип для строки Фильмы.

Сначала мы создадим наши модули классов. Они очень похожи для обоих типов продуктов.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

' CLASS MODULE - clsBook

' Переменные

Private m_Title As String

Private m_Year As Long

 

' Свойства

Property Get ItemType() As String

    ItemType = "Book"

End Property

Property Get Title() As String

    Title = m_Title

End Property

Property Get Year() As Long

    Year = m_Year

End Property

 

' Методы

Public Sub Init(rg As Range)

    m_Title = rg.Cells(1, 2)

    m_Year = CLng(rg.Cells(1, 4))

End Sub

 

Public Sub PrintToImmediate()

    Debug.Print ItemType, m_Title, m_Year

End Sub


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

' CLASS MODULE - clsFilm

' Переменные

Private m_Title As String

Private m_Year As Long

 

' Свойства

Property Get ItemType() As String

    ItemType = "Film"

End Property

Property Get Title() As String

    Title = m_Title

End Property

Property Get Year() As Long

    Year = m_Year

End Property

 

' Методы

Sub Init(rg As Range)

    m_Title = rg.Cells(1, 2)

    m_Year = CLng(rg.Cells(1, 5))

End Sub

 

Public Sub PrintToImmediate()

    Debug.Print ItemType, m_Title, m_Year

End Sub

Как видите, единственная реальная разница — это инициализация.

Когда мы читаем каждую запись, нам нужно определить, книга это или фильм. Затем мы создаем соответствующий объект. Представьте, что нам нужно создать переменную для каждого типа, например:


1

2

3

4

5

6

7

8

9

' Для каждого типа требуется одна переменная

Dim oBook As clsBook

Dim oFilm As clsFilm

 

' Если Книга сделать это

Set oBook = New clsBook

 

' Если фильм сделать это

Set oFilm = New clsFilm

Если бы у нас было много разных типов, это было бы действительно очень грязно. Хорошей новостью является то, что нам нужно использовать только одну переменную!

В VBA мы можем объявить переменную как вариант. Когда мы используем Variant, мы, по сути, говорим: «Мы определим тип переменной во время выполнения кода».

Это очень полезно при работе с объектами и позволяет нам избежать использования одной переменной, например:


1

2

3

4

5

6

7

8

' Требуется только одна переменная

Dim oItem As Variant

 

' Если книга, указать тип clsBook

Set oItem = New clsBook

 

' Если фильм, указать тип clsFilm

Set oItem = New clsFilm

Это действительно полезно, так как нам нужна только одна переменная, независимо от того, сколько у нас объектов.

Второе преимущество использования Variant заключается в следующем. Если у каждого Class Module есть подпрограмма / функция с одинаковым именем и параметрами, мы можем использовать одну и ту же переменную для ее вызова.

Представьте, что в clsBook есть функция InitBook, а в clsFilm есть функция InitFilm. Нам нужно сделать это:


1

2

3

4

5

' Если clsBook

If Type = "Book" Then

    oItem.InitBook

ElseIf Type = "Film" Then

    oItem.InitFilm

Однако, если они имеют одинаковое имя, например, Init, мы можем заменить строки кода If \ ElseIf одной строкой:


1

2

' это вызовет подпрограмму Init любого типа oItem, установленного в

  oItem.Init

Теперь мы можем создать функцию для создания соответствующего объекта. В объектно-ориентированном программировании мы имеем то, что называется фабрикой классов. Это просто функция, которая создает объект на основе заданного типа.

Ранее мы видели, что событие Initialize не принимает параметры. Мы можем позвонить в Init на фабрике классов, чтобы обойти эту проблему.

Полный код для функции ClassFactory здесь:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

Function ClassFactory(rg As Range) As Variant

 

    ' Получить тип продукта

    Dim sType As String

    sType = rg.Cells(1, 1)

 

    ' Создать объект на основе типа

    Dim oItem As Variant

    Select Case sType

     

        Case "Book":

            Set oItem = New clsBook

        Case "Film":

            Set oItem = New clsFilm

        Case Else

            MsgBox "Invalid type"

     

    End Select

     

    ' Разобрать поля на правильные переменные класса

    oItem.Init rg

     

    ' Вернуть объект продукта

    Set ClassFactory = oItem

         

End Function

Это следующее наше начало. В этом разделе мы читаем таблицу и передаем диапазон в ClassFactory.

Создает объект, передает диапазон в метод Parse объекта. Затем он возвращает объект, который мы добавляем в нашу коллекцию.


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

Sub ReadProducts()

     

    ' Создать коллекцию

    Dim coll As New Collection

    Dim product As Variant

     

    Dim rg As Range

 

 

    ' Читайте продукты с листа

    Dim i As Long

    For i = 1 To 2

        Set rg = Sheet1.Range("A" &amp; i &amp; ":E" &amp; i)

        Set product = ClassFactory(rg)

        coll.Add product

    Next

 

    ' Распечатать информацию о продукте в Immediate Window(Ctrl + G)

    PrintCollection coll

 

End Sub

Мы также можем использовать вариант объекта для печати элементов. Пока оба объекта имеют подпрограмму с одинаковым именем и параметрами (например, PrintToImmediate), мы можем вызывать ее, используя тип Variant.


1

2

3

4

5

6

7

8

9

Public Sub PrintCollection(ByRef coll As Collection)

     

    Dim v As Variant

    For Each v In coll

        ' Печать элементов

        v.PrintToImmediate

    Next

     

End Sub

Заключение

На этом я заканчиваю свою статью о Class Module VBA. В этой статье мы рассмотрели части Class Module VBA и два примера, в которых вы могли бы их использовать.

Важно понимать, что классы и объекты — это обширная тема. Существует множество типов объектов, которые вы можете создавать, и способы их использования.

Если вы планируете использовать Class Module, то я советую начать с основ и ознакомиться с тем, как создать простой. Как только вы освоите основы, вам будет намного легче переходить к более сложным сценариям.

Источник

Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования