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?
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
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?
des Idées :
- Utiliser le passage par référence (ByRef)
- Construisez Un Type Défini par L'utilisateur pour tenir les choses que vous voulez retourner, et retourner cela.
- similaire à 2 - construire une classe pour représenter les informations retournées, et retourner les objets de cette classe...
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.
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
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.
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
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).ToString
où i
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
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