だから、VBAの関数、サブ、またはタイプから複数の値を返すにはどうすればいいのだろうと思っていましたか?いくつかの関数からデータを収集することになっているこのメインサブを持っていますが、関数は1つの値しか返せないようです。それでは、どうすればサブに複数のものを返すことができますか?
本当に、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
VBAコレクションを返してみることができます。
「Version = 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
理にかなっていますか?
アイデア:
戻り値の結果としてバリアント配列を使用して、任意の値のシーケンスを返すこともできます。
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
呼び出し元は、結果を使用するために何が返されるかを知る必要があるため、glyくバグが発生しやすくなりますが、それでも役に立つ場合があります。
関数は1つの値を返しますが、任意の数の値を「出力」できます。サンプルコード:
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
エレガントではありませんが、メソッドを重複して使用しない場合は、コードの先頭のSubsの前にPublicステートメントで定義されたグローバル変数を使用することもできます。ただし、パブリック値を変更すると、すべてのSubsおよびFunctionのコード全体で保持されますので、注意する必要があります。
vBAの関数またはその他の視覚的に基本的なものに2つ以上の値を返すことができますが、Byrefというポインターメソッドを使用する必要があります。以下の例を参照してください。 5、6などの2つの値を加算および減算する関数を作成します
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
常にArrayList
を返すことにより、関数から複数の結果を返すアプローチを常に取っています。 ArrayList
を使用することにより、Strings
とIntegers
を混在させて、複数の値で構成される1つのアイテムのみを返すことができます。
メインサブで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
ファイルから必要なすべてのデータを単一の文字列に接続し、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