Пользовательская форма VBA устанавливает элементы управления как частные вместо общедоступных

Резюме: в пользовательской форме vba есть ли способ установить элементы в форме как частные, а не общедоступные?

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

Пример метки lblInformation:

Sub Test()
    Dim MyProgressBar As New frmProgressBar
    MyProgressBar.Show vbModeless

Что я заставлю их использовать:

    MyProgressBar.setInformation = "Running ..."

Чего я хочу избежать:

    MyProgressBar.lblInformation.Caption = "Running ..."

Как установить для lblInformation значение Private вместо Public?

(остальная часть кода)

    Unload ProgressBar
End Sub

Приложение (какое не важно): VBA7 в Autodesk Inventor 2014


person sir KitKat    schedule 12.09.2013    source источник
comment
создайте оболочку для стандартной пользовательской формы. ваш собственный класс с частными свойствами   -  person    schedule 12.09.2013


Ответы (1)


Из того, что я читал (в Professional Excel Development от Bovey и др., а также в других источниках), стандартное решение VBA для этого: 1) использовать модуль класса для определения интерфейса, в котором перечислены функции (свойства, сабвуферы и т. д.), которые вы хотите выставить. 2) В своем модуле формы поместите оператор «Реализует», а затем добавьте код, к которому будут обращаться общедоступные подпрограммы, объявленные в интерфейсе. 3) Затем в своем приложении используйте интерфейс, а не саму форму.

Итак, в модуле класса, называемом, скажем, iProgressBar, перечислите то, что вы хотите сделать общедоступным:

Public Property Let Information(ByVal sNew As String)
End Property

Public Property Get Information() As String
End Property

Public Sub UpdateProgress(ByVal dNew As Double)
End Sub

'etc...

Это ваш интерфейс. Затем в верхней части модуля frmProgressBar поместите

Implements iProgressBar

Получив этот оператор, посмотрите на раскрывающиеся списки в верхней части окна кода. Выберите iProgressBar из левого раскрывающегося списка. Затем выберите один из его общедоступных элементов в правом раскрывающемся списке, и будет вставлен блок кода (как показано ниже). В этом блоке вы указываете, что делает каждый общедоступный элемент вашего индикатора выполнения.

Private Property Let iProgressBar_Information(ByVal str As String)

    Me.lblInformation.Caption = str 

    'Refresh the form
    Me.Repaint

End Property

Private Sub iProgressBar_UpdateProgress(ByVal dNew As Double)

    'Code to update progress on the form

End Property

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

Sub Test()
    Dim MyProgressBar As iProgressBar
    Set MyProgressBar = New frmProgressBar

    'More code

    'This will work MyProgressBar was dim'ed as iProgressBar, which has an Information property
    MyProgressBar.Information = "Running ..."

    'This will not work because iProgressBar has no lbl...
    MyProgressBar.lblInformation.Caption = "Running ..."

    'More code
End Sub

Единственным ограничением здесь является то, что кто-то все еще может присоединиться к вашему проекту и начать использовать форму напрямую, а не интерфейс. Я не думаю, что есть простой способ заставить людей делать то, что вы хотите, только с помощью VBA. Это всего лишь «лучшая практика» VBA, помогающая облегчить совместную работу и избежать ошибок. (Возможно, просто заставить поведение, которое вы хотите, скомпилировать библиотеку, но это выводит вас за пределы VBA).

РЕДАКТИРОВАТЬ:

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

If Not TypeOf Me Is iProgressBar Then

    'Clever code that will cause initialization to fail.

End If
person alrm3000    schedule 30.09.2013
comment
Особенно ловушка инициализации мне нравится больше всего :) - person sir KitKat; 01.10.2013