Возвращать несколько значений из функции, суб или типа?

Итак, мне было интересно, как я могу вернуть несколько значений из функции, sub или типа в VBA? У меня есть этот главный юг, который должен собирать данные из нескольких функций, но функция может возвращать только одно значение. Итак, как я могу вернуть несколько из них?

Ответ 1

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

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

' this is the VB6/VBA equivalent of a struct
' data, no methods
Private Type settings
    root As String
    path As String
    name_first As String
    name_last As String
    overwrite_prompt As Boolean
End Type


Public Sub Main()

    Dim mySettings As settings
    mySettings = getSettings()


End Sub

' if you want this to be public, you're better off with a class instead of a User-Defined-Type (UDT)
Private Function getSettings() As settings

    Dim sets As settings

    With sets ' retrieve values here
        .root = "foo"
        .path = "bar"
        .name_first = "Don"
        .name_last = "Knuth"
        .overwrite_prompt = False
    End With

    ' return a single struct, vb6/vba-style
    getSettings = sets

End Function

Ответ 2

Вы можете попробовать вернуть коллекцию VBA.

Пока вы используете значения пары, например "Версия = 1.31", вы можете сохранить идентификатор в виде ключа ( "Версия" ) и фактического значения (1.31) в качестве самого элемента.

Dim c As New Collection
Dim item as Variant
Dim key as String
key = "Version"
item = 1.31
c.Add item, key
'Then return c

Доступ к значениям после этого - легкий:

c.Item("Version") 'Returns 1.31
or
c("Version") '.Item is the default member

Имеет ли смысл?

Ответ 3

Идеи:

  • Использовать pass by reference (ByRef)
  • Создайте пользовательский тип, чтобы сохранить материал, который хотите вернуть, и верните его.
  • Подобно 2 - создайте класс для представления возвращаемой информации и верните объекты этого класса...

Ответ 4

Вы также можете использовать вариантный массив в качестве возвращаемого результата для возврата последовательности произвольных значений:

Function f(i As Integer, s As String) As Variant()
    f = Array(i + 1, "ate my " + s, Array(1#, 2#, 3#))
End Function

Sub test()
    result = f(2, "hat")
    i1 = result(0)
    s1 = result(1)
    a1 = result(2)
End Sub

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

Ответ 5

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

Ответ 6

Функция возвращает одно значение, но может "выводить" любое количество значений. Пример кода:

Function Test (ByVal Input1 As Integer, ByVal Input2 As Integer, _
ByRef Output1 As Integer, ByRef Output2 As Integer) As Integer

  Output1 = Input1 + Input2
  Output2 = Input1 - Input2
  Test = Output1 + Output2

End Function

Sub Test2()

  Dim Ret As Integer, Input1 As Integer, Input2 As Integer, _
  Output1 As integer, Output2 As Integer
  Input1 = 1
  Input2 = 2
  Ret = Test(Input1, Input2, Output1, Output2)
  Sheet1.Range("A1") = Ret     ' 2
  Sheet1.Range("A2") = Output1 ' 3
  Sheet1.Range("A3") = Output2 '-1

End Sub

Ответ 7

вы можете вернуть 2 или более значения функции в VBA или любой другой визуальный базовый материал, но вам нужно использовать метод указателя Byref. См. Мой пример ниже. Я сделаю функцию для добавления и вычитания 2 значений, например 5,6

sub Macro1
    ' now you call the function this way
    dim o1 as integer, o2 as integer
    AddSubtract 5, 6, o1, o2
    msgbox o2
    msgbox o1
end sub


function AddSubtract(a as integer, b as integer, ByRef sum as integer, ByRef dif as integer)
    sum = a + b
    dif = b - 1
end function

Ответ 8

Я всегда подхожу к возврату более одного результата из функции, всегда возвращая ArrayList. Используя ArrayList, я могу вернуть только один элемент, состоящий из множества нескольких значений, смешивания между Strings и Integers.

Как только у меня есть ArrayList, возвращаемый в моем основном разделе, я просто использую ArrayList.Item(i).ToString, где i - это индекс значения, которое я хочу вернуть из ArrayList

Пример:

 Public Function Set_Database_Path()
        Dim Result As ArrayList = New ArrayList
        Dim fd As OpenFileDialog = New OpenFileDialog()


        fd.Title = "Open File Dialog"
        fd.InitialDirectory = "C:\"
        fd.RestoreDirectory = True
        fd.Filter = "All files (*.*)|*.*|All files (*.*)|*.*"
        fd.FilterIndex = 2
        fd.Multiselect = False


        If fd.ShowDialog() = DialogResult.OK Then

            Dim Database_Location = Path.GetFullPath(fd.FileName)

            Dim Database_Connection_Var = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=""" & Database_Location & """"

            Result.Add(Database_Connection_Var)
            Result.Add(Database_Location)

            Return (Result)

        Else

            Return (Nothing)

        End If
    End Function

И затем вызовите функцию следующим образом:

Private Sub Main_Load()
  Dim PathArray As ArrayList

            PathArray = Set_Database_Path()
            My.Settings.Database_Connection_String = PathArray.Item(0).ToString
            My.Settings.FilePath = PathArray.Item(1).ToString
            My.Settings.Save()
End Sub

Ответ 9

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

Sub CP()
Dim ToolFile As String

Cells(3, 2).Select

For i = 0 To 5
    r = ActiveCell.Row
    ToolFile = Cells(r, 7).Value
    On Error Resume Next
    ActiveCell.Value = CP_getdatta(ToolFile)

    'seperate data by "-"
    Selection.TextToColumns Destination:=Range("C3"), DataType:=xlDelimited, _
        TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=True, _
        Semicolon:=False, Comma:=False, Space:=False, Other:=True, OtherChar _
        :="-", FieldInfo:=Array(Array(1, 1), Array(2, 1)), TrailingMinusNumbers:=True

Cells(r + 1, 2).Select
Next


End Sub

Function CP_getdatta(ToolFile As String) As String
    Workbooks.Open Filename:=ToolFile, UpdateLinks:=False, ReadOnly:=True

    Range("A56000").Select
    Selection.End(xlUp).Select
    x = CStr(ActiveCell.Value)
    ActiveCell.Offset(0, 20).Select
    Selection.End(xlToLeft).Select
    While IsNumeric(ActiveCell.Value) = False
        ActiveCell.Offset(0, -1).Select
    Wend
    ' combine data to 1 string
    CP_getdatta = CStr(x & "-" & ActiveCell.Value)
    ActiveWindow.Close False

End Function