VBA: функция, которая принимает несколько типов ввода?

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

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

Как мне это сделать? Я попытался взять параметр какFunction Foo(Param As Object) , но затем он терпит неудачу, когда я пытаюсь передать в функцию определяемый пользователем тип.

#
Источник
  • 1
    Подойдет variant
  • 3
    Но не будет. Обратите внимание, что TypeName нельзя использовать и в UDT.
Codelisting
за 6 против

Типы, определяемые пользователем ( UDT ), не являются классами (они похожи наStructures в C илиRecords в Паскале), поэтому экземпляры UDT не являются объектами - поэтому вы не можете использовать их в качестве аргумента своей функции.foo .

VBA имеет универсальный тип данныхVariant . Итак, когда у вас естьFunction Foo(Param As Variant) , вы можете передать в функцию что угодно,Foo 3 илиFoo ActiveSheet илиFoo "Hello world" . Что угодно, кроме UDT ... Если вы попытаетесь это сделать, вы получите ошибку компилятора, в которой говорится: «Только определенные пользователем типы, определенные в общедоступных объектных модулях, могут быть принудительно преобразованы в вариант или из него или переданы в функции с поздним связыванием». :

Public Type tMyType
    i As Integer
    s As String
End Type

Sub Test
    Dim bar as tMyType
    ' Compiler complains
    foo bar

    Dim myUniversalVariant as Variant
    ' Compiler complains also
    myUniversalVariant = bar
End Sub

Официальная документацияVariant заявляет, что «типы вариантов теперь поддерживают типы, определяемые пользователем». , однако, по крайней мере, в Excel 2016 это не работает (или, по крайней мере, я не смог этого сделать).

Лучше всего использовать классы. Если вы ленивы, просто создайте модуль класса (для каждого типа) и поместите все члены типа как общедоступные, больше ничего не нужно (я не буду начинать описывать плюсы и минусы геттера и сеттера ). Вам просто нужно помнить, что теперь вы должны использовать оператор New для создания и Set для назначения экземпляра.

В модуле класса (я назвал егоclsMyType ):

 public i As Integer
 public s As String

В штатном модуле:

 Sub Test
    Dim bar as clsMyType
    Set bar = new clsMyType
    foo bar

    Dim myUniversalVariant as Variant
    Set myUniversalVariant = bar
    foo myUniversalVariant 
End Sub

Теперь, в зависимости от того, хочет ли ваша функция получать только объект или также другие вещи (например, целые числа или строки), тип параметра может быть Variant или Object

Function foo(Param as Object) 
    Debug.Print TypeName(Param)
End Function 
  • 1
    Красиво и правильно. Проголосовал ...
Codelisting
Популярные категории
На заметку программисту