Когда использовать класс в VBA?

35

Когда целесообразно использовать класс в Visual Basic для приложений (VBA)?

Я предполагаю, что ускоренная разработка и сокращение появления ошибок является общим преимуществом для большинства языков, поддерживающих ООП. Но с VBA существует ли конкретный критерий?

Теги:
class
oop

11 ответов

48
Лучший ответ

Это зависит от того, кто будет разрабатывать и поддерживать код. Типичные макрокоманды "Power User", взламывающие небольшие специальные приложения, вполне могут быть смущены с помощью классов. Но для серьезного развития причины использования классов такие же, как на других языках. У вас те же ограничения, что и у VB6 - нет наследования, но вы можете иметь полиморфизм с помощью интерфейсов.

Хорошим использованием классов является представление сущностей и наборов объектов. Например, я часто вижу код VBA, который копирует диапазон Excel в двумерный массив, а затем манипулирует двухмерным массивом с кодом типа:

Total = 0
For i = 0 To NumRows-1
    Total = Total + (OrderArray(i,1) * OrderArray(i,3))
Next i

Более читаемо скопировать диапазон в коллекцию объектов с соответствующими свойствами, например:

Total = 0
For Each objOrder in colOrders
    Total = Total + objOrder.Quantity * objOrder.Price
Next i

Другим примером является использование классов для реализации шаблона проектирования RAII (для него Google). Например, мне может потребоваться снять защиту с листа, сделать некоторые манипуляции, а затем снова защитить его. Использование класса гарантирует, что рабочий лист всегда будет защищен снова, даже если в вашем коде произошла ошибка:

--- WorksheetProtector class module ---

Private m_objWorksheet As Worksheet
Private m_sPassword As String

Public Sub Unprotect(Worksheet As Worksheet, Password As String)
    ' Nothing to do if we didn't define a password for the worksheet
    If Len(Password) = 0 Then Exit Sub

    ' If the worksheet is already unprotected, nothing to do
    If Not Worksheet.ProtectContents Then Exit Sub

    ' Unprotect the worksheet
    Worksheet.Unprotect Password

    ' Remember the worksheet and password so we can protect again
    Set m_objWorksheet = Worksheet
    m_sPassword = Password
End Sub

Public Sub Protect()
    ' Protects the worksheet with the same password used to unprotect it
    If m_objWorksheet Is Nothing Then Exit Sub
    If Len(m_sPassword) = 0 Then Exit Sub

    ' If the worksheet is already protected, nothing to do
    If m_objWorksheet.ProtectContents Then Exit Sub

    m_objWorksheet.Protect m_sPassword
    Set m_objWorksheet = Nothing
    m_sPassword = ""
End Sub

Private Sub Class_Terminate()
    ' Reprotect the worksheet when this object goes out of scope
    On Error Resume Next
    Protect
End Sub

Затем вы можете использовать это для упрощения кода:

Public Sub DoSomething()
   Dim objWorksheetProtector as WorksheetProtector
   Set objWorksheetProtector = New WorksheetProtector
   objWorksheetProtector.Unprotect myWorksheet, myPassword

   ... manipulate myWorksheet - may raise an error

End Sub 

Когда это Sub выходит, objWorksheetProtector выходит за пределы области видимости, и рабочий лист снова защищен.

  • 2
    Это хороший пример причины использования классов в VBA. Не уверен, что я когда-нибудь действительно это сделаю, но, тем не менее, хороший пример.
  • 1
    Действительно полезно знать.
Показать ещё 3 комментария
8

Я думаю, что критерии такие же, как и другие языки

Если вам нужно связать несколько фрагментов данных и некоторые методы, а также конкретно обработать то, что происходит, когда объект создан/завершен, классы идеальны

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

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

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

Другим примером может быть, если вам не нравится доступ к группе пользователей Access, вы можете создать свой собственный класс пользователя с помощью методов для входа и выхода и функций для контроля доступа/аудита на уровне группы/определенных действий/ошибок отслеживания и т.д.

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

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

5

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

Например, функции GetOpenFileName() и GetSaveFileName() имеют структуру OPENFILENAME со многими членами. вам может не понадобиться использовать все из них, но они есть и должны быть инициализированы.

Мне нравится обертывать структуру (UDT) и декларации функций API в класс CfileDialog. Событие Class_Initialize устанавливает значения по умолчанию для членов структуры, поэтому, когда я использую класс, мне нужно только установить элементы, которые я хочу изменить (через процедуры Property). Константы флагов реализованы как Enum. Так, например, чтобы выбрать электронную таблицу для открытия, мой код может выглядеть следующим образом:

Dim strFileName As String
Dim dlgXLS As New CFileDialog

With dlgXLS
  .Title = "Choose a Spreadsheet"
  .Filter = "Excel (*.xls)|*.xls|All Files (*.*)|*.*"
  .Flags = ofnFileMustExist OR ofnExplorer

  If OpenFileDialog() Then
    strFileName = .FileName
  End If
End With
Set dlgXLS = Nothing

Класс устанавливает каталог по умолчанию в "Мои документы", хотя, если бы я хотел, я мог бы изменить его с помощью свойства InitDir.

Это всего лишь один пример того, как класс может быть чрезвычайно полезен в приложении VBA.

5

Я бы не сказал, что есть определенный критерий, но я никогда не нашел полезного места для использования Классы в коде VBA. На мой взгляд, он настолько привязан к существующим моделям приложений Office, что добавление дополнительной абстракции за пределами этой объектной модели просто путает вещи.

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

  • 0
    -1: я не согласен - так как модель Office основана на классах, вполне логично использовать классы в вашем коде.
  • 0
    Должным образом отметил, хотя я особо отметил, что, в частности, я никогда не нахожу их все, что полезно; не то чтобы они не могли быть полезными.
Показать ещё 1 комментарий
3

Вы также можете повторно использовать код VBA без использования реальных классов. Например, если у вас есть вызов, VBACode. Вы можете получить доступ к любой функции или суб в любом модуле со следующим синтаксисом:

VBCode.mysub(param1, param2)

Если вы создаете ссылку на шаблон /doc (как и на dll), вы можете одинаково ссылаться на код из других проектов.

2

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

2

Я использую классы, когда мне нужно что-то делать, и класс будет делать это лучше всего:) Например, если вам нужно отвечать на (или перехватывать) события, тогда вам нужен класс. Некоторые люди ненавидят UDT (пользовательские типы), но мне они нравятся, поэтому я использую их, если мне нужен простой код для самостоятельного документирования. Pharmacy.NCPDP гораздо легче читать, а затем strPhrmNum:) Но UDT ограничен, так что скажите, что я хочу иметь возможность устанавливать Pharmacy.NCPDP и иметь все остальные свойства. И я также хочу сделать так, чтобы вы не могли случайно изменить данные. Тогда мне нужен класс, потому что у вас нет свойств readonly в UDT и т.д.

Еще одно соображение - простая читаемость. Если вы выполняете сложные структуры данных, часто полезно знать, что вам просто нужно позвонить в Company.Owner.Phone.AreaCode, затем попытаться отслеживать, где все структурировано. Особенно для людей, которые должны поддерживать эту кодовую базу через 2 года после того, как вы ушли:)

Мои собственные два цента - "Код с целью". Не используйте класс без причины. Но если у вас есть причина, то сделайте это:)

2

Для рекурсии данных (обработка спецификаций a.k.a.) специальный класс критически полезен, и я думаю, что это иногда необходимо. Вы можете сделать рекурсивную функцию без модуля класса, но многие проблемы с данными не могут быть эффективно решены.

(Я не знаю, почему люди не продают библиотеки BOM-наборов для VBA. Возможно, инструменты XML имеют значение.)

Несколько экземпляров форм - это общее приложение класса (многие проблемы автоматизации в противном случае неразрешимы), я предполагаю, что вопрос о пользовательских классах.

  • 0
    Мой вопрос касается пользовательских классов.
2

Разработка программного обеспечения даже при использовании Microsoft Access с использованием объектно-ориентированного программирования, как правило, является хорошей практикой. Это позволит масштабируемость в будущем, позволяя объектам свободно подключаться вместе с рядом преимуществ. Это в основном означает, что объекты в вашей системе будут менее зависимы друг от друга, поэтому рефакторинг становится намного проще. Вы можете достичь этого, используя классы. Недостатком является то, что вы не можете выполнять наследование класса или полиморфизм в VBA. В конце концов, нет жесткого и быстрого правила об использовании классов, а также лучших практик. Но имейте в виду, что по мере роста вашего приложения легче поддерживать использование классов.

0

Вы можете определить класс оболочки sql в доступе, который более удобен, чем наборы записей и querydef. Например, если вы хотите обновить таблицу на основе критериев в другой связанной таблице, вы не сможете использовать объединения. Вы могли бы построить vba recorset и querydef, чтобы сделать это, но мне легче с классом. Кроме того, ваше приложение может иметь некоторую концепцию, которая требует больше двух таблиц, поэтому лучше использовать классы для этого. Например. Вы применяете отслеживание инцидентов. Инцидент имеет несколько атрибутов, которые будут храниться в нескольких таблицах {пользователи и их контакты или профили, описание инцидента; отслеживание состояния; Контрольные списки, чтобы помочь сотруднику службы поддержки ответить на инцидент; Ответить...}. Чтобы отслеживать все связанные запросы и отношения, oop может быть полезен. Это облегчение, чтобы иметь возможность выполнять Incident.Update(xxx) вместо всего кодирования...

-2

Я не понимаю, почему критерии для VBA будут отличаться от другого языка, особенно если вы ссылаетесь на VB.NET.

  • 4
    Может быть, я ошибаюсь, но я не думаю, что это будет большой кандидат, если вы ищете Наследство.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню