function - varias - Devuelve múltiples valores de una función, sub o tipo?
vba excel function return multiple values (9)
Entonces me preguntaba, ¿cómo puedo devolver múltiples valores desde una función, sub o escribir en VBA? Tengo este sub principal que se supone que recopila datos de varias funciones, pero una función solo puede devolver un valor que parece. Entonces, ¿cómo puedo devolver múltiples a un sub?
Es posible que desee replantear la estructura de su aplicación, si realmente desea que un método devuelva varios valores.
O separan las cosas, por lo que los distintos métodos devuelven valores distintos, o resuelven una agrupación lógica y crean un objeto para contener los datos que a su vez pueden ser devueltos.
'' 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
Ideas:
- Usar pase por referencia (ByRef)
- Cree un Tipo definido por el usuario para guardar las cosas que desea devolver, y devuelva eso.
- Similar a 2: crea una clase para representar la información devuelta y devuelve objetos de esa clase ...
No es elegante, pero si no utiliza su método de forma simultánea, también puede usar variables globales, definidas por la declaración pública al comienzo de su código, antes de los subs. Sin embargo, debe tener cuidado, una vez que cambie un valor público, se mantendrá en todo su código en todos los Subs y funciones.
Podría intentar devolver una Colección VBA.
Siempre que trabaje con valores de pares, como "Versión = 1.31", podría almacenar el identificador como una clave ("Versión") y el valor real (1.31) como el elemento mismo.
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
Acceder a los valores después de eso es muy sencillo:
c.Item("Version") ''Returns 1.31
or
c("Version") ''.Item is the default member
¿Tiene sentido?
Siempre me planteo devolver más de un resultado de una función devolviendo siempre una ArrayList
. Al utilizar una ArrayList
, puedo devolver solo un elemento, que consta de muchos valores múltiples, mezclando Strings
e Integers
.
Una vez que tengo ArrayList
devuelto en mi sub principal, simplemente uso ArrayList.Item(i).ToString
donde i
es el índice del valor que quiero devolver desde ArrayList
Un ejemplo:
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
Y luego llame a la función de esta manera:
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
También puede usar una matriz variante como el resultado de retorno para devolver una secuencia de valores arbitrarios:
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
Feo y propenso a errores porque la persona que llama necesita saber qué se devuelve para usar el resultado, pero de todos modos útil de todos modos.
Una función devuelve un valor, pero puede "generar" cualquier cantidad de valores. Un código de muestra:
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
puede conectar todos los datos que necesita del archivo a una sola cadena, y en la hoja de Excel separarlos con texto a columna. aquí hay un ejemplo que hice para el mismo problema, disfrute:
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
puede devolver 2 o más valores a una función en VBA o cualquier otra cosa visual básica pero necesita usar el método de puntero llamado Byref. Vea mi ejemplo a continuación. Voy a hacer una función para sumar y restar 2 valores, por ejemplo 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