Модули VBA и передача аргументов

#vba #ms-access

#vba #ms-access

Вопрос:

У меня есть модуль, который можно вызвать из любой части моего приложения, чтобы проверить, установлен ли определенный шрифт в системе пользователя, а если нет — установите шрифт и проверьте еще раз, прежде чем продолжить

Основное приложение

 if RequiredFont.Run(strFontName) = FALSE Then '(error message and exit sub)
  

Модуль «RequiredFont»

 Public Function Run(Font As String) As Boolean
    if check(Font) = FALSE Then
        Run = FALSE
        Install(Font)
        if check(Font) = TRUE Then Run = TRUE
    Else
        Run = TRUE
    End If


Private Function Check(Font as String) as Boolean
'code to check the font exists on the users localmachine, returns true/false
End Sub

Private Sub Install(Font as String)
'code to install the font on the users localmachine,
End Sub
  

Мой первый вопрос:

Это лучший способ сделать аргументы доступными для всех функций и вспомогательных модулей, чтобы передавать их при каждом вызове? (как показано выше) …. или есть простой способ объявить аргумент как переменную для всего модуля при вызове Run()?

Мой второй вопрос:

Есть ли способ избежать выполнения () все вместе и просто напрямую вызвать имя модуля «RequiredFont», я помню, что на других языках вызов sub по определенному имени автоматически запускает этот sub при вызове модуля

Спасибо

РЕДАКТИРОВАТЬ — так теперь выглядит мой код:

 Private FontName As String
Private FontFile As String


Public Function Run(strFontName As String, strFontFile As String) As Boolean

    FontName = strFontName
    FontFile = strFontFile
    Run = False

    If CheckFont() = False Then InstallFont
    If CheckFont() = True Then
        Run = True
    Else
        'message error"
    End If

End Function


Private Function CheckFont() As Boolean
    'code to check if the font is installed
    On Error Resume Next
    'Create a temporary StdFont object
    With New StdFont
        ' Assign the proposed font name
        .Name = FontName
        ' Return true if font assignment succeded
        If (StrComp(FontName, .Name, vbTextCompare) = 0) = False Then
            CheckFont = False
        Else
            CheckFont = True
        End If
    End With
End Function

Private Sub InstallFont()
' code to install the font
    MsgBox "You need the following font installed to continue." _
    amp; vbNewLine _
    amp; vbNewLine amp; "'" amp; FontName amp; "'" _
    amp; vbNewLine _
    amp; vbNewLine amp; "Click OK to launch the font. Please click the INSTALL button at the top"
    OpenFile (PATH_TO_FONTS amp; FontFile)

End Sub
  

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

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

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

Ответ №1:

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

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

 'could also be Private to hide it from other modules
Public myFont As String

Public Function Run(Font As String) As Boolean
    myFont = Font
    '...
End Sub


Private Function Check() as Boolean
' you can access myFont here
End Sub

Private Sub Install()
'idem
End Sub
  

Что касается вашего второго вопроса, я не думаю, что вы можете.

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

1. будет ли это код, который лучше подходит для модуля класса?

2. @IanJackson Если вы хотите проверить несколько шрифтов, то да, безусловно, но только для одного это кажется неэффективным.

Ответ №2:

Вы можете объявлять необязательные функции и устанавливать значения по умолчанию:

 Public Function fxMyFunction _
    (Optional lngProj As Variant, _
     Optional strFruit As Variant = "banana", _
     Optional booTest As Boolean = False) As String

   '' IsMissing requires that lngProj be a Variant
   booNoProject = IsMissing(lngProj)  

   fxMyFunction = strFruit

End Function
  

Optional Аргументы должны следовать за необязательными аргументами.

О функциях, которые «запускаются при включении»

Вам нужно вызывать функции и вспомогательные модули по имени. Для стандартного модуля VBA нет функции «автономного запуска». VBA «включает» все модули при компиляции.

Модули класса VBA — это то, где вы найдете эквивалент конструкторов. Инвестирование в версию объектной ориентации VBA не кажется полезным для ваших текущих потребностей. Если вы пойдете в этом направлении, некоторые аспекты начнут казаться вам знакомыми (хотя, возможно, достаточно, чтобы разочароваться, поскольку OO остается функцией, которая была добавлена позже и выглядит со стороны).

Ответ №3:

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

Что касается вопроса 2, вы можете присвоить своей функции уникальное имя и не называть свой модуль для его запуска, например

 findOrInstallFont(Fontname)
  

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

1. Не знаю, почему я этого не учел…. Я просто назову основную функцию «RequiredFont ()» так же, как и модуль, и поскольку я не буду ссылаться на определенную часть этого модуля — она никогда не должна быть rwuiredfont.requiredfont()

2. Однако в целом хорошей практикой является явный вызов функций по модулю. Это обеспечивает ясность позже. Я живу этим. Поэтому, хотя я могу представить, как назвать функцию «main» после ее модуля, я бы все равно назвал ее as RequiredFont.RequiredFont() . На практике это выглядело бы так vbRequiredFont.RequiredFont() , потому что для меня короткий префикс для указания типа объекта — еще одна незаменимая практика. Опять же, специфично для Access.