Вопрос

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

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

Это было полезно?

Решение

Это зависит от того, кто будет разрабатывать и поддерживать код.Типичные авторы макросов "Опытных пользователей", взламывающие небольшие специальные приложения, вполне могут запутаться при использовании классов.Но для серьезной разработки причины использования классов те же, что и в других языках.У вас те же ограничения, что и у 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 

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

Другие советы

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

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

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

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

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

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

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

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

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

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

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

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.

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

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

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

VBCode.mysub(param1, param2)

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top