Код Excel VBA — Глобальный модуль/Вспомогательный ООП дружественный?

#vba #readability #maintainability

Вопрос:

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

Фрагмент ниже.

Модуль: MCommon

 Option Explicit

Public wrkshtInput As Object
Public rngPartSize As Range
Public rngPart2Size As Range

Sub CommonDefinitions()

    Set wrkshtInput = Worksheets("INPUT (BOM)")
    Set rngPartSize = Range("C5")
    Set rngPartSize2 = Range("C6")
End Sub
 

Модуль: mUI

 Option Explicit

Sub PartToggle()
'OBJECT REF(S):     Sheet2 (INPUT (BOM))
'METHOD REF(S):     mCommon.CommonDefinitions
'VARIABLE REF(S):   mCommon.wrkshtInput, mCommon.rngPartSize

    'COMMON VARIABLE DEFINITIONS:
    Call mCommon.CommonDefinitions

    'DEFINE VARIABLES:
    Set rngBlueACM = Range("H129:H134, H136:H141, H144:H147")
    Set rngRedACM = Range("H149:H154, H156:H161, H164:H167")

    'PART TOGGLE: ON
    If mCommon.wrkshtInput.tglbtnPartToggle.Value = True Then
        mCommon.rngPartSize.Value = ""
        rngBlueACM.Value = "MANUAL"
        rngRedACM.Value = "MANUAL"
    End If

    'PART TOGGLE: OFF
    If mCommon.wrkshtInput.tglbtnPartToggle.Value = False Then
        mCommon.rngPartSize.Value = "--"
        rngBlueACM.Value = "--"
        rngRedACM.Value = "--"
    End If
    
End Sub

Sub Part2Toggle()
'OBJECT REF(S):     Sheet2 (INPUT (BOM))
'METHOD REF(S):     mCommon.CommonDefinitions
'VARIABLE REF(S):   mCommon.wrkshtInput, mCommon.rngPart2Size

    'COMMON VARIABLE DEFINITIONS:
    Call mCommon.CommonDefinitions

    'DEFINE VARIABLES
    Set rngWhiteACM = Range("H107:H108")

    'PART2 TOGGLE: ON
    If mCommon.wrkshtInput.tglbtnPart2Toggle.Value = True Then
        mCommon.rngPart2Size.Value = ""
        rngWhiteACM.Value = "MANUAL"
    End If

    'PART2 TOGGLE: OFF
    If mCommon.wrkshtInput.tglbtnPart2Toggle.Value = False Then
        mCommon.rngPart2Size.Value = "--"
        rngWhiteACM.Value = "--"
    End If
    
End Sub
 

Комментарии:

1. Почему бы вам не работать с именованными диапазонами вместо их жесткого кодирования?

Ответ №1:

Этот

 Set rngPartSize = Range("C5") 
 

имеет недостаток в том, что у него нет квалификатора рабочего листа, поэтому он возвращает диапазон от того, что является активным листом.

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

Если вы хотите быть «объектно-ориентированным», то лучший подход (IMO) заключается в том, чтобы:

Во-первых: измените кодовое имя(имена) вашего рабочего листа(ов) вместо того, чтобы постоянно запускать такие вещи, как:

 Set wsData = ThisWorkbook.Worksheets("Data")
 

вы можете просто напрямую ссылаться на Data и т. Lists Д. В своем коде.

Далее: используйте модули кода рабочего листа, чтобы определить методы, которые «принадлежат» этим листам. Хорошим примером этого может служить лист «Входные данные», в который вводятся различные параметры. Итак, допустим, у вас есть «Номер учетной записи», который вы можете поместить в свой модуль рабочего листа для Inputs :

 Const RNG_ACCT_NUM As string = "D10"

Property Get Accountnumber()
    Accountnumber = Me.Range(RNG_ACCT_NUM).Value
End Property
Property Let Accountnumber(v)
    Me.Range(RNG_ACCT_NUM).Value = v
End Property
 

Теперь вы можете использовать это в своем коде:

 Dim acct
acct = Inputs.AccountNumber
'or
Inputs.AccountNumber = "AB3456"
 

вместо

 Dim wsInputs As Worksheet, acct 
Set wsInputs = ThisWorkbook.Worksheets("Inputs")

acct = wsInputs.Range("D10")
'....
wsInputs.Range("D10") = "AB3456"