「VBAのFunctionで戻り値を複数返したいけれど、どう書くのが正解なのかわからない」と迷っていませんか。
VBAのFunctionは基本的に戻り値を1つしか返せないため、複数の結果を扱いたいときは少し工夫が必要です。
とはいえ、難しく考えなくても大丈夫です。
実際には、ByRef、配列、クラスの3つを使い分ければ、ほとんどのケースに対応できます。
ただし、どれも同じように見えて、読みやすさや保守のしやすさにはかなり差があります。
なんとなく選んでしまうと、あとから「この配列の0番って何だっけ」と自分でも困りやすくなります。
この記事では、VBAでFunctionの戻り値を複数にする代表的な方法を比較しながら、結局どの方法がおすすめなのかをやさしく解説します。
初心者の方でも判断しやすいように、コード例と選び方の基準までまとめているので、読み終えるころには自分に合った書き方が見つかるはずです。
| この記事のテーマ | 内容 |
|---|---|
| 悩み | Functionで複数の値を返したい |
| 原因 | VBAでは戻り値が基本1つだから |
| 解決策 | ByRef・配列・クラスを使い分ける |
| 結論 | 迷ったらまずByRefがおすすめ |
この記事でわかること
- VBAのFunctionで戻り値を複数にする基本的な考え方
- ByRef・配列・クラスそれぞれの違い
- 初心者におすすめの実装方法
- 実務で迷いにくい選び方の基準
VBAのFunctionで戻り値を複数にしたいときの結論
VBAでFunctionを使っていると、1つの処理から複数の結果を受け取りたい場面があります。
たとえば、氏名と年齢を同時に返したいときや、処理結果と判定フラグをまとめて受け取りたいときです。
このようなときに最初に知っておきたいのは、VBAのFunctionは基本的に戻り値を1つだけ返す仕組みだということです。
そのため、複数の値をそのまま返すのではなく、少し工夫して疑似的に複数の戻り値を実現します。
| 方法 | わかりやすさ | 実装の手軽さ | 向いている場面 |
|---|---|---|---|
| ByRef | 高い | 高い | 小〜中規模の処理 |
| 配列 | やや低い | 高い | 同じ種類の値をまとめる処理 |
| クラス | 高い | 低い | 項目が多い処理や拡張前提の設計 |
VBAのFunctionは基本的に戻り値を1つだけ返す
VBAのFunctionは、関数名に値を代入する形で戻り値を返します。
この書き方を見るとわかるように、基本形では戻せる値は1つです。
そのため、複数の値を返したいときは、最初から「1つの箱にまとめる」か「引数経由で返す」発想に切り替える必要があります。
複数の値が必要ならByRef・配列・クラスで対応できる
VBAでは、複数の値を扱いたいときに主に3つの方法がよく使われます。
1つ目はByRefの引数を使う方法です。
2つ目は配列にまとめて返す方法です。
3つ目はクラスを使って、意味のあるまとまりとして返す方法です。
どれも実現はできますが、読みやすさや保守性には差があります。
迷ったらByRefを第一候補にするのがおすすめ
結論からいうと、まず検討したいのはByRefです。
理由は、受け取る値の型や役割がコード上で見えやすく、初心者でも追いやすいからです。
特に戻したい値が2個から3個くらいであれば、ByRefはとても扱いやすい方法です。
一方で、返したい項目が多くなってきたときは、クラスのほうが整理しやすくなることもあります。

ByRefで複数の値を返す方法
ByRefは、VBAで複数の値を返したいときに最初に覚えたい書き方です。
コードの見通しがよく、あとから見返したときにも意味を理解しやすいのが魅力です。
「とりあえず動けばOK」で終わらせず、読みやすさまで意識したい方に向いています。
ByRefを使うと呼び出し元の変数へ値を渡せる
ByRefで受け取った引数は、プロシージャの中で代入した内容が呼び出し元にも反映されます。
つまり、見た目は引数ですが、実質的には戻り値のように使えます。
そのため、通常の戻り値とは別に、補助的な結果を複数返したいときに便利です。
たとえば、処理結果の文字列と件数を一緒に返すような場面と相性がよいです。
ByRefで複数の戻り値を受け取るコード例
まずはシンプルな例を見てみましょう。
Sub SampleMain()
Dim userName As String
Dim itemCount As Long
Call GetUserInfo("田中", userName, itemCount)
Debug.Print userName
Debug.Print itemCount
End Sub
Sub GetUserInfo(ByVal baseName As String, ByRef resultName As String, ByRef resultCount As Long)
resultName = baseName & "さん"
resultCount = 3
End Sub
このコードでは、resultNameとresultCountがByRefになっています。
つまり、GetUserInfoの中で代入した値を、呼び出し元の変数でそのまま受け取れます。
どの変数に何が返るのかが宣言部分を見れば伝わりやすいので、保守しやすいのが大きなメリットです。
ByRefが向いているケースと注意点
ByRefは、返したい値が少なめで、意味がはっきりしているときに向いています。
たとえば、「整形後の文字列」と「成功フラグ」のような組み合わせです。
反対に、ByRefの引数が増えすぎると、今度は引数一覧が長くなって読みにくくなります。
そのため、4個も5個も返したくなったら、設計自体を見直すサインと考えるのがおすすめです。
| 向いている | あまり向いていない |
|---|---|
| 戻したい値が2〜3個 | 戻したい値が多すぎる |
| 型を明確にしたい | 意味のまとまりが複雑 |
| すぐ実装したい | 将来項目が増える前提 |
配列を戻り値にして複数返す方法
配列を使う方法は、手早く実装したいときに目に入りやすい書き方です。
1つの戻り値に複数の要素を詰め込めるため、見た目としてはFunctionらしく書きやすいです。
ただし、使いやすさと引き換えに、読みにくさが出やすい点には注意が必要です。
配列やVariantを使えば1つの戻り値にまとめられる
VBAでは、配列やVariantを戻り値として返すことができます。
そのため、複数の値を1つの配列に入れてから返すことで、疑似的に複数戻り値を実現できます。
特に、順番に意味があるデータや、同じ種類の値をまとめたい場合には使いやすいです。
配列を返すコード例と受け取り方
次のような書き方です。
Sub SampleArrayMain()
Dim ret As Variant
ret = GetValues()
Debug.Print ret(0)
Debug.Print ret(1)
Debug.Print ret(2)
End Sub
Function GetValues() As Variant
GetValues = Array("りんご", "みかん", 10)
End Function
この方法なら、Functionの戻り値を1つに保ったまま複数の情報を返せます。
実装そのものはとても簡単です。
ただし、ret(0)が何で、ret(1)が何なのかは、コードを読まないと伝わりにくくなります。
配列の戻り値が読みにくくなりやすい理由
配列で返す方法の弱点は、要素の意味が番号に埋もれやすいことです。
たとえばret(0)が氏名、ret(1)が年齢、ret(2)が状態フラグだったとしても、その意味は見ただけではわかりにくいです。
さらに、文字列と数値を混在させるとVariantに寄りやすくなり、型の見通しも落ちます。
小さな処理なら成立しますが、長く使うコードほど読み解きにくさが出やすい方法です。

クラスを戻り値にして複数の情報をまとめる方法
返したい情報が多いときや、項目それぞれに意味を持たせたいときはクラスが便利です。
最初は少し手間に感じますが、あとから見返したときの整理しやすさはとても高いです。
「一時的に動くコード」より、長く使えるコードを意識するなら候補に入ります。
クラスモジュールを使うと意味のあるまとまりで返せる
クラスモジュールを使うと、独自のオブジェクトを作れます。
その中に名前、件数、成功可否のような項目を持たせれば、戻り値を意味のある単位でまとめられます。
単なる配列と違って、どの値が何を表しているかがわかりやすくなるのが大きな利点です。
クラスを戻り値にするコード例
たとえば、クラスモジュールにUserResultという名前を付けて、次のようにします。
' クラスモジュール: UserResult
Public UserName As String
Public ItemCount As Long
Public IsSuccess As Boolean
続いて、標準モジュール側で次のように返します。
Sub SampleClassMain()
Dim ret As UserResult
Set ret = GetUserResult()
Debug.Print ret.UserName
Debug.Print ret.ItemCount
Debug.Print ret.IsSuccess
End Sub
Function GetUserResult() As UserResult
Dim result As UserResult
Set result = New UserResult
result.UserName = "田中さん"
result.ItemCount = 3
result.IsSuccess = True
Set GetUserResult = result
End Function
このようにしておくと、ret.UserNameのようにプロパティ名で意味が伝わるので、とても読みやすくなります。
大規模な処理や拡張性を重視するなら有力
クラスは、戻したい値が増えるほど真価を発揮します。
あとから項目を追加しやすく、配列のように「何番目に何が入るか」を覚える必要もありません。
その一方で、クラスモジュールを作る手間や、Setを使う記述が増えるため、ちょっとした処理には重たく感じることもあります。
そのため、拡張性を取るならクラス、手軽さを取るならByRefと考えると整理しやすいです。

VBAで複数戻り値を使い分ける判断基準
ここまで見ると、どの方法にも良さがあるように感じるかもしれません。
実際、その通りです。
大切なのは「どれが絶対に正しいか」ではなく、今の処理に合っているかで選ぶことです。
小さな処理ならByRefが使いやすい
たとえば、文字列整形の結果と件数だけ返したいような場面では、ByRefがもっとも扱いやすいです。
宣言を見ただけで戻り値の役割を追いやすく、余計な仕組みを増やさずに済みます。
迷ったときは、まずByRefで書けるかを考えると失敗しにくいです。
順番のあるデータなら配列が合う場合もある
配列は常に避けるべき、というわけではありません。
たとえば、同じ種類のデータをまとめて返したいときや、順番そのものに意味がある場合は相性がよいです。
ただし、用途がはっきりしていることが前提です。
読み手が迷う余地があるなら、別の方法を選んだほうが安心です。
項目数が多いならクラス設計が向いている
返したい項目が増えてきたら、クラスでまとめる方法が一気に使いやすくなります。
特に、データベースの取得結果や、複数項目を持つ解析結果などでは、クラスの恩恵が大きいです。
少し準備は必要ですが、そのぶん後から読み返したときの理解しやすさは高くなります。
| 状況 | おすすめ |
|---|---|
| 2〜3個の値をすぐ返したい | ByRef |
| 同種データを並びで返したい | 配列 |
| 項目が多く意味づけが必要 | クラス |
VBAで複数戻り値を扱うときによくある疑問
最後に、初心者の方がつまずきやすいポイントも整理しておきます。
ここを先に知っておくと、実装後の混乱をかなり減らせます。
FunctionではなくSubを使ったほうがよい場面はある?
あります。
戻り値そのものが不要で、処理結果をByRefの引数だけで返すなら、Subのほうが自然なこともあります。
FunctionにするかSubにするかは、「メインの戻り値があるか」で考えると選びやすいです。
ByValとByRefはどう使い分ければいい?
変更してほしくない引数はByValにします。
呼び出し元へ結果を返したい引数はByRefにします。
全部をなんとなくByRefにする書き方は、あとから誤解を生みやすいので避けるのがおすすめです。
初心者が避けたい書き方のポイント
初心者のうちは、意味が見えにくいVariantの多用をできるだけ避けると読みやすくなります。
また、配列の添字に意味を持たせすぎると、少し時間が空いただけで自分でも読みにくくなります。
「あとで見てもわかるか」を基準に選ぶことが、結果的にいちばん失敗しにくいです。
まとめ
VBAでFunctionの戻り値を複数にしたいときは、1つの正解だけがあるわけではありません。
ただし、迷ったまま書き始めると、あとで読みにくいコードになりやすいです。
そのため、戻したい値の数とその値の意味のわかりやすさを基準に選ぶのが大切です。
特に初心者の方は、まずByRefを基準に考えると整理しやすいです。
そこから、項目が多ければクラス、同じ種類の値をまとめたいなら配列、という流れで判断すると失敗しにくくなります。
この記事のポイントをまとめます。
- VBAのFunctionは基本的に戻り値を1つだけ返す仕組みです。
- 複数の値を返したいときはByRef・配列・クラスの3つが代表的です。
- もっとも手軽でわかりやすい方法はByRefです。
- ByRefは呼び出し元の変数へ値を返せるのが特徴です。
- 配列を使うと1つの戻り値に複数の値をまとめられます。
- ただし配列は要素番号だけでは意味が伝わりにくくなりがちです。
- クラスを使うと項目名で意味を表現できるため保守しやすいです。
- 項目数が多い処理や拡張前提の設計ではクラスが有力です。
- 変更したくない引数はByVal、返したい値はByRefで整理するとわかりやすいです。
- 迷ったときは「あとから見ても理解しやすいか」で選ぶのがおすすめです。
複数戻り値の実装は、最初は少しややこしく感じるかもしれません。
ですが、考え方はとてもシンプルです。
すぐ使いたいならByRef、意味のあるまとまりで返したいならクラス、同じ種類の値をまとめたいなら配列、と覚えておけば十分です。
大切なのは、動くだけのコードではなく、後から見ても理解しやすいコードにすることです。
ぜひ今回の考え方をもとに、あなたのVBAでも扱いやすい戻り値の設計を選んでみてください。

