Renvoyer plusieurs valeurs à partir d'une fonction, sous-type?

alors je me demandais, comment retourner plusieurs valeurs d'une fonction, d'un sous ou d'un type dans VBA? J'ai ce principal sous lequel est censé recueillir des données à partir de plusieurs fonctions, mais une fonction ne peut retourner qu'une seule valeur, il me semble. Alors comment je peux en rendre plusieurs à un sous-marin?

29
demandé sur Robert 2011-03-17 16:40:31

9 réponses

Vous pourriez vouloir repenser la structure de votre application, si vous voulez vraiment, vraiment une méthode pour renvoyer plusieurs valeurs.

soit briser les choses, donc des méthodes distinctes renvoient des valeurs distinctes, soit comprendre un groupement logique et construire un objet pour tenir ces données qui peuvent à leur tour être retournées.

' 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
47
répondu Michael Paulukonis 2011-03-17 14:26:35

vous pourriez essayer de retourner une Collection VBA.

tant que vous avez affaire à des valeurs de paire, comme "Version=1.31", vous pouvez stocker l'identifiant comme une clé ("Version") et la valeur réelle (1.31) comme l'article lui-même.

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

Accéder aux valeurs après c'est un jeu d'enfant:

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

est-ce logique?

15
répondu Oneide 2011-03-17 16:15:18

des Idées :

  1. Utiliser le passage par référence (ByRef)
  2. Construisez Un Type Défini par L'utilisateur pour tenir les choses que vous voulez retourner, et retourner cela.
  3. similaire à 2 - construire une classe pour représenter les informations retournées, et retourner les objets de cette classe...
12
répondu Martin Milan 2011-03-17 13:43:29

Vous pouvez également utiliser un tableau variant comme résultat de retour pour retourner une séquence de valeurs arbitraires:

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

laid et sujet aux bogues parce que votre interlocuteur a besoin de savoir ce qui est retourné pour utiliser le résultat, mais parfois utile néanmoins.

8
répondu dlm 2013-09-20 20:44:51

une fonction retourne une valeur, mais elle peut "sortir" n'importe quel nombre de valeurs. Un exemple de code:

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
3
répondu Givi 2014-04-22 20:19:02

Pas très élégant, mais si vous n'utilisez pas votre méthode overlappingly vous pouvez également utiliser des variables globales, définies par la déclaration Publique au début de votre code, avant les Subs. Vous devez être prudent cependant, une fois que vous changez une valeur publique, il sera tenu tout au long de votre code dans tous les sous et fonctions.

2
répondu robotik 2013-10-10 10:49:15

Vous pouvez retourner 2 valeurs ou plus à une fonction dans VBA ou n'importe quel autre truc visuel de base mais vous devez utiliser la méthode de pointeur appelée Byref. Voir mon exemple ci-dessous. Je vais faire une fonction pour ajouter et soustraire 2 valeurs dites 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
1
répondu Drl Sherif Omran 2015-05-07 14:56:18

j'approche toujours en retournant plus d'un résultat d'une fonction en retournant toujours un ArrayList. En utilisant un ArrayList Je ne peux retourner qu'un seul article, composé de plusieurs valeurs multiples, mélangeant entre Strings et Integers.

une Fois que j'ai l' ArrayList retourné dans mon sous-marin principal, j'utilise simplement ArrayList.Item(i).ToStringi est l'index de la valeur que je veux le retour de l' ArrayList

Un exemple:

 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

Et ensuite appeler la Fonction comme ceci:

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
1
répondu SilverShotBee 2016-08-02 20:21:34

Vous pouvez connecter toutes les données dont vous avez besoin du fichier à une chaîne simple, et dans la feuille excel le séparer avec le texte à la colonne. voici un exemple que j'ai fait pour le même numéro, enjoy:

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
0
répondu Nirr 2014-12-09 15:03:10