【VBA】変数引き渡しが10倍理解できる!ByRefとByValの使い分け完全マスター

【VBA】変数引き渡しが10倍理解できる!ByRefとByValの使い分け完全マスター

別のプロシージャに変数の情報を引き渡したい!!

 

複雑なマクロを作っていると、こんな問題に直面することってありますよね。

 

プロシージャを越えて変数を引き渡すことは可能ですが、

「値渡し(ByVal)」と「参照渡し(ByRef)」の使い分けが必要

になります。

 

この記事では、「値渡し(ByVal)」、「参照渡し(ByRef)」の違いや使い道を詳しく解説。

 

「変数なんて適当に宣言しても、思い通りのVBAコードを書くことができる」

このように思っている方もいらっしゃると思います。

 

ですが、

 

「値渡し(ByVal)」、「参照渡し(ByRef)」を自由に使いこなすことで、後々確認のしやすいスマートなVBAコードに仕上げることができます。

 

 

Left Caption

ガッツポーズの人

VBAスキルがワンランクアップすること間違いなし。

 

広告

VBA変数引き渡しの基本概念を理解しよう

VBAプログラミングにおいて、変数の引き渡し方法を理解することは非常に重要です。

 

なぜなら、

関数やプロシージャ間でのデータのやり取りが正確にでき、思わぬバグを防ぐことができるから

です。

 

変数引き渡しには「値渡し(ByVal)」と「参照渡し(ByRef)」の2つの方法があり、それぞれ異なる動作をします。

 

変数引き渡しとは?初心者でもわかる基本の仕組み

変数引き渡しとは、

メインプロシージャから別のプロシージャに変数の値を渡すこと

です。

 

これは郵便物を送るようなもので、送り方によって相手に届く内容が変わります。

 

たとえば、

写真を送る場合、オリジナルをそのまま送るか、コピーを送るかで相手が受け取るものが違うのと同じです。

 

VBAでは、この「送り方」を指定することで、データの扱い方を制御できます。

 

値渡し(ByVal)と参照渡し(ByRef)の根本的違い

値渡しと参照渡しの違いは、データの渡し方にあります。

値渡し(ByVal)は、変数の「コピー」を渡すため、呼び出し先で値を変更しても元の変数には影響しません

一方、参照渡し(ByRef)は、変数の「住所」を教えるため、呼び出し先での変更が元の変数に直接反映されます

 

これは銀行の通帳を例にすると、値渡しは残高をメモして渡すこと、参照渡しは通帳そのものを渡すことと同じです。

 

VBAで変数引き渡しが重要な理由とメリット

変数引き渡しを正しく理解することで、効率的で安全なVBAコードが書けるようになります。

 

適切な引き渡し方法を選ぶことで、メモリ使用量を最適化し、意図しない変数の変更を防ぐことが可能。

特に、実行速度が重要となる大量のデータを処理する場合、正しい参照渡しが重要です。

また、

複数の値を一度に変更したい場合は参照渡しを、元の値を保護したい場合は値渡しを使い分けることで、バグの少ない堅牢なコードが作成できます。

 

ByVal(値渡し)の使い方と動作原理

値渡し(ByVal)は、VBAにおけるデフォルトの引き渡し方法で、変数のコピーを作成して渡す仕組みです。

この方法を使うことで、呼び出し先のプロシージャで変数を変更しても、元の変数は影響を受けません。

 

値渡しは、元のデータを保護したい場合や、一時的な計算に使用する場合に最適です。

 

ByValの基本構文と書き方

ByValの基本構文は、

引数の前に「ByVal」キーワードを付けるだけ

です。

 

VBAでは引数にキーワードを指定しない場合、自動的にByValが適用されますが、

引数リストでByValを明示的に記述することで、コードの意図を明確に示すことになります。

Sub MainProc()
Dim originalValue As Integer
originalValue = 5
Call ChangeValue(originalValue)
Debug.Print "originalValue:" & originalValue ' 結果:5(変更されない)
End Sub

 

Sub ChangeValue(ByVal inputValue As Integer)
Debug.Print "inputValueの1回目:" & inputValue
inputValue = 50 ' コピーを変更
Debug.Print "inputValueの2回目:" & inputValue
End Sub

 

上記のコードの実行結果がこちら

引数リストでByValを使ったサンプルコードの実行結果

 

「originalValue」の値が呼び出し先のプロシージャで50になっても、最終的に元のプロシージャで最初に格納された5という値になります。

 

値渡しのメモリ動作を図解で完全理解

値渡しでは、メモリ上に元の変数とは別の領域が確保され、そこに値がコピーされます。

 

元の変数を「A」、プロシージャ内の引数を「B」とすると、AとBは全く別の場所に存在します。

プロシージャ内でBを変更しても、Aには一切影響しません。

これは2つの独立した箱があるようなもので、一方の箱の中身を変えても、もう一方には影響しないのです。

 

この仕組みにより、データの安全性が保たれ、予期しないデータ変更を防げます。

Sub DemoValueCopy()
Dim mainVar As String
mainVar = "元の値"
Debug.Print "メイン:" & mainVar ' 結果:「元の値」
Call ModifyString(mainVar)
Debug.Print "メイン:" & mainVar ' 結果:「元の値」
End Sub

 

Sub ModifyString(ByVal copyStr As String)
copyStr = "変更後の値"
MsgBox "コピー:" & copyStr ' 結果:「変更後の値」
End Sub

 

上記のコードの実行結果がこちら

値渡しのメモリ動作VBAの実行結果

 

「mainVar」の値が「元の値」のまま変更されることはありません。

 

ByValを使った実践的なサンプルコード3選

値渡しの実践的な活用例として、計算処理、データ検証、文字列処理の3つのパターンを紹介します。

 

これらの例では、元のデータを保護しながら様々な処理を行っています。

' 例1:計算処理(元の値を保護)
Function CalculateTax(ByVal price As Double) As Double
price = price * 1.1 ' 税込み計算(元の価格は変更されない)
CalculateTax = price
End Function

 

' 例2:データ検証
Function ValidateAge(ByVal age As Integer) As Boolean
If age < 0 Then age = 0 ' 負の値を0に補正
ValidateAge = (age >= 18)
End Function

 

' 例3:文字列処理
Function FormatName(ByVal name As String) As String
name = Trim(name) ' 前後の空白を削除
FormatName = UCase(Left(name, 1)) & LCase(Mid(name, 2))
End Function

 

上記のサンプルコードはエクセル業務でよく活用されるコードです。

業務内容に合わせてアレンジして使ってみてください。

 

ByRef(参照渡し)の使い方と動作原理

参照渡し(ByRef)は、

変数のメモリアドレスを渡す方法で、呼び出し先で変数を変更すると元の変数も変更

されます。

 

この仕組みを使うことで、複数の値を同時に変更したり、大きなデータを効率的に処理できます。

ただし、意図しない変更を避けるため、使用時は注意が必要です。

 

ByRefの基本構文と書き方

ByRefの構文は、

引数の前に「ByRef」キーワードを明示的に記述

します。

 

参照渡しを使用する場合は、必ずByRefを記述しましょう。

記述を省略すると、値渡し「ByVal」の処理になってしまします。

Sub MainProcess()
Dim myNumber As Integer
myNumber = 10
Debug.Print "1回目のmyNumberの値:" & myNumber
Call ModifyNumber(myNumber)
Debug.Print "3回目のmyNumberの値:" & myNumber ' 結果:100(変更されている)
End Sub

 

Sub ModifyNumber(ByRef num As Integer)
num = 100 ' 元の変数を直接変更
Debug.Print "呼び出し先myNumberの値:" & num ' 結果:100
End Sub

 

上記のコードの実行結果がこちら

ByRef(参照渡し)を使ったサンプルコードの実行結果

 

元プロシージャ内のmyNumberの値が「10」から「100」に変更されています。

 

参照渡しのメモリ動作を図解で完全理解

参照渡しでは、メモリ上の同じ場所を元の変数とプロシージャ内の引数が共有します。

これは同じ家に2つの鍵があるようなもので、どちらの鍵を使っても同じ家に入ることができ、家の中を変更すると両方の鍵の持ち主に影響します。

 

プロシージャ内で引数を変更すると、実際には元の変数のメモリ領域が変更されるため、呼び出し元でも変更が反映されます。

この仕組みにより、効率的なデータ処理と複数値の同時変更が可能になります。

Sub DemoReference()
Dim sharedData As String
sharedData = "共有データ"

Call UpdateSharedData(sharedData)
MsgBox "メイン:" & sharedData ' 結果:「更新済みデータ」
End Sub

 

Sub UpdateSharedData(ByRef data As String)
data = "更新済みデータ" ' 元の変数を直接変更
MsgBox "プロシージャ:" & data ' 結果:「更新済みデータ」
End Sub

 

上記のコードを実行した様子がこちら

参照渡しVBAの実行結果

「F8」キーで1行ずつコードを実行すると、変数の状態変化がよく理解できます。

 

関連記事「デバックの方法」では、VBAコードを実行する方法や効率的なデバック方法が紹介されています。

 

併せてチェックしてみてください。

 

ByRefを使った実践的なサンプルコード3選

参照渡しの実践的な活用例として、複数値の交換、データの初期化、配列処理の3つのパターンを示します。

 

これらの例では、効率的なデータ操作と複数の値の同時変更を実現しています。

' 例1:2つの値を交換
Sub SwapValues(ByRef a As Integer, ByRef b As Integer)
Dim temp As Integer
temp = a
a = b
b = temp
End Sub

 

' 例2:複数のデータを同時に初期化
Sub InitializeData(ByRef name As String, ByRef age As Integer, ByRef score As Double)
name = "未設定"
age = 0
score = 0.0
End Sub

 

' 例3:配列の要素を変更
Sub UpdateArray(ByRef arr As Variant, ByVal index As Integer, ByVal newValue As String)
If index >= 0 And index <= UBound(arr) Then
arr(index) = newValue
End If
End Sub

 

参照渡し「ByRef」は元プロシージャの変数が変更されてしまうので注意しながら活用してください。

 

ByRefとByValの使い分け判断基準

ByRefとByValの適切な使い分けは、VBAコードの品質と性能に大きく影響します。

正しく使い分けることで、効率的で安全なコードに仕上げることが可能です。

 

使い分けの判断は、データの性質、処理の目的、パフォーマンス要件によって決まります。

 

どちらを選ぶべき?5つの判断ポイント

使い分けの判断には5つの重要なポイントがあります。

まず、元の変数を変更したいかどうかを考えましょう。変更が必要な場合はByRef、保護したい場合はByValを選択。

 

次に、データサイズを考慮し、大きなデータはByRefで効率化を図ります。

また、複数の値を同時に返したい場合はByRefが適しています。安全性を重視する場合はByVal、処理速度を重視する場合はByRefを選ぶのが基本です。

' 判断例1:元の値を保護したい場合(ByVal)
Function CalculateDiscount(ByVal originalPrice As Double) As Double
CalculateDiscount = originalPrice * 0.9
End Function

安全に変数を別のプロシージャに引き渡すことのできる方法です。

 

' 判断例2:複数の値を変更したい場合(ByRef)
Sub GetNameAndAge(ByRef userName As String, ByRef userAge As Integer)
userName = InputBox("名前を入力してください")
userAge = CInt(InputBox("年齢を入力してください"))
End Sub

複雑な処理のマクロを作成するときに活用されます。

 

パフォーマンスに影響する場面とその対処法

パフォーマンスが重要な場面では、データサイズと処理回数を考慮した選択が必要です。

大きな配列や文字列を頻繁に渡す場合、ByValではコピー作成のオーバーヘッドが発生し処理速度が低下します。

 

この場合、ByRefを使用することで大幅な性能向上が期待できます。

ただし、ByRefを使用する際は、意図しない変更を防ぐため、プロシージャ内でのデータ操作に注意が必要です。

' パフォーマンス改善例:大きな配列の処理
Sub ProcessLargeArray(ByRef dataArray As Variant)
Dim i As Long
For i = 0 To UBound(dataArray)
dataArray(i) = dataArray(i) * 2 ' 効率的な処理
Next i
End Sub

 

' 安全性重視の場合
Function SafeCalculation(ByVal inputValue As Double) As Double
SafeCalculation = inputValue + 100 ' 元の値を保護
End Function

 

バグを防ぐための使い分けルール

バグを防ぐためには、明確なルールに基づいた使い分けが重要です。

読み取り専用のデータや計算結果を返すだけの場合はByValを使用し、データの変更や複数値の取得が必要な場合のみByRefを使用します。

また、

デバッグ時は、変数の値がどこで変更されているかを追跡しやすくするため、ByRefの使用箇所を最小限に抑えることが重要です。

' バグ防止の良い例
Sub UpdateUserData(ByRef userData As Variant)
' 明確にデータ更新の意図を示す
userData(0) = "更新済み"
userData(1) = Now()
End Sub

 

Function GetTotalAmount(ByVal price As Double, ByVal quantity As Integer) As Double
' 計算のみ、元の値は保護
GetTotalAmount = price * quantity
End Function

 

これらのテクニックを業務内容に合わせて使い分けてください。

 

VBA初心者が効率化マクロを導入する方法

VBA初心者が効率化マクロを導入する方法

 

VBAなんて扱ったことないけど、業務内容に合わせた『データ抽出VBA』を導入したい!

 

こんな問題を解決する方法がこちら

  • マクロの開発を外注に依頼する
  • マクロが設定されたエクセルファイルをダウンロードする
  • 参考書やネットでVBAスキルを身に付ける

 

VBAスキルを身に着ける前は、「マクロ開発の外注」で対応していましたが、

今では自分で効率化マクロをサクッと導入しちゃいます。

 

完成されたマクロを使ってエクセル業務を処理する

作業効率が2倍以上アップ!!

便利すぎて自分でもマクロを設定したいと考え始める

参考書やネットの情報でVBAスキルを身に付ける

マクロ開発を代行できる程のスキルを習得

 

 

VBAは

他のプログラミングに比べて参考書やネットで紹介されている情報量が多いので初心者でも導入しやすい

という特徴があります。

 

外注した方が楽だけど、費用がかかる。自分で導入すれば費用は0円だけど時間がかかる。。

いずれにせよ、効率化マクロを導入できれば作業効率が飛躍的にアップするのは間違いありません。

 

あなたに合った方法で導入しちゃいましょう。

 

マクロ開発を外注に依頼する

マクロ開発を外注に依頼する方法は

VBAを全く扱えない方でもエクセル作業を自動化できる最も簡単な方法

です。

 

「変数の引き渡しが必要なくらい複雑な効率化マクロの導入を検討している」「作った資料を自動的にPDFで保存したい」「決まった様式に写真を自動で貼り付けたい」

こんな感じで実現したい内容を依頼するだけで業務内容に合ったマクロを開発してくれます。

 

Left Caption

ガッツポーズの人

完成まで本業に集中できるので効率的

 

 

デメリットは、費用がかかることだけ。

開発内容、依頼先によってかかる費用は大きく異なります。

私が会社員の頃利用していた業者さんは1マクロあたり2万円~3万円の費用がかかりました。

 

Left Caption

疑問がある人

ちょっと高くない。。。

 

ちなみに、マメBlogでもエクセルマクロ開発代行サービスを承っています。

開発内容の確認、VBAコードの設定、動作確認後の調整、など全ての工程を私(マメ父ちゃん)が行っているので、

費用が安い!スピード納期!!

でやらせてもらっています。

 

ほとんど独学で身に付けたVBAスキルなので、内容によっては開発できないこともあるのでご了承ください。

 

ご相談、見積もり依頼は完全無料ですので気になる方は下記のリンクよりお問合せ下さい。

 

 

マクロが設定されたエクセルファイルをダウンロードする

VBA初心者でも『マクロが設定されたエクセルファイルをダウンロード』することで、

すぐに使っているエクセルにマクロを導入することができます。

 

VBA初心者でも形になっているマクロをゲットできる、費用が安い、

というメリットがあります。

しかし、

想定するマクロを見つけることが難しい、業務内容に合わせるためのアレンジが必要

というデメリットもあります。

 

Left Caption

ガッツポーズの人

お目当てのマクロが見つかればラッキー

 

個人ブログやファイルを販売できるサイト「note」や「Tips」ではいろんなマクロの情報が掲載されているので是非参考にしてみてください。

 

今までマメBlogで受注した効率化マクロを下記のnoteで掲載していますので併せてチェックしてみてください。

 

 

 

参考書やネットでVBAスキルを身に付ける

先程も紹介しましたが、

VBAは他のプログラミングに比べて参考書やネットで紹介されている情報量が多いので初心者でも導入しやすい

プログラミングです。

 

言い換えると、

情報量が豊富なので自分で勉強できちゃう

ということです。

 

私のVBAスキルはほとんど独学で身に付けたもので、

考えた処理のほとんどをVBAで表現できるレベルにまで到達した!

と思っています。

 

独学であっても『写真を貼り付けるマクロ』『全てのシートをPDF出力するマクロ』『連番を振るマクロ』など、

業務内容に合ったマクロを開発できるようになれます。

 

独学でVBAスキルを身に付けるコツは、

エラーが発生してもいいからひたすらコードを書く、なんでもいいからエクセル作業をマクロ化してみる

です。

 

とは言っても、全くの知識0の方は何をすればいいかわからないですよね。

 

VBA知識0の初心者の方は、参考書『たった1秒で仕事が片づくExcel自動化の教科書【増強完全版】』を読んでみてください。

 

VBAの知識0の方でもすいすい読み進められる内容になっています。

やさしい内容にも関わらず「え!!VBAを使えばこんなことできるの!?」と感動すると思います。

 

実際に私はこの参考書を読んでからVBAの勉強を始めました。

 

Left Caption

ひらめく人

VBA学習スタートのきっかけをくれた参考書


 

 

VBAの魅力を発見した後は、

ひたすら自動化したい内容のコードを書くだけ

です。

 

【VBA 変数引き渡し】【VBA 参照渡し】【VBA 値渡し】でネット検索すれば知りたいコードをすぐにゲットできます。

 

実現したい処理に向かって、「調べる→書いてみる→エラーを改善する→調べる」を繰り返していると

自然といろんなマクロが作れるようになっているはずです。

 

VBAに興味が湧いてきたという方は今からVBA学習をスタートさせちゃいましょう。