「みんな教えて! 選手権!!」開催のお知らせ

親プロシージャに数値を渡すときに、引数付のFuncitonプロシージャと引数付のSUBプロシージャは、結果を見ると同じ動きをするように思います。
このような場合、両者には、どのような違いがあるのでしょうか?

Sub 親プロシージャ()
Cells(1,MyNOend)=123
end Sub

・子プロシージャ
Function FMyRowCnt(MyNOend As Integer)
MyNOend = TMYKanriBkWs1.Range("D1").CurrentRegion.Rows.Count
End Function
Sub FMyRowCnt(MyNOend As Integer)
MyNOend = TMYKanriBkWs1.Range("D1").CurrentRegion.Rows.Count
End Sub

以上 よろしくお願い致します。

A 回答 (6件)

こんにちは。

#2,#4 を書いたものです。

#5 さんの回答について、数点書かせていいだきます。
専門家さんとしていますが、ちょっと内容には疑問を感じました。

Excel VBAとAccess VBAとは赴きは違っていても、Sub プロシージャも、Function ユーザー定義も、サブルーチンで使用する分には、基本的には変わりません。ただ、Access VBAでは、呼び出しの必要があって、関数にするかもしれませんが、Excelでは、関数の呼び出しは、Access のようにはしません。それは、ワークシートが一つのコントロール・オブジェクトになっているからです。

> 『Sub』プロシージャは引数の変数を書き換えると呼び出し元『親』で書き換えた値が反映します。→処理部分を『サブルーチン』として分離しただけです。

 Subプロシージャは、戻り値自身はありませんが、デフォルトで、参照渡しになっていますが、値渡しも可能です。

例題1

>・『Function』プロシージャは引数の変数を書き換えても呼び出し元『親』の値は変化しません。

 参照渡し(byRef)にすれば、親の変数は変わります。
 例題2

 
以下は、初歩的なサンプルです。
--------------------------------------------------
例題1:

'値渡し、参照渡しの例
Sub Test1()
Dim a
Dim b
 a = 1
 b = 1
 subTest1 a, b
 MsgBox "a: " & a & ",b: " & b
End Sub

Sub subTest1(ByVal a, ByRef b)
 a = a + 1
 b = a
End Sub


例題2:
'参照渡しの例
Sub Test2()
Dim a
Dim b
 a = 1
 b = 0
 subTest2 a, b
 MsgBox "a: " & a & ",b:" & b
End Sub

Function subTest2(ByVal a, ByRef b)
 a = a + 1
 b = a
End Function
    • good
    • 0

★簡単に説明すると『引数』と『戻り値』の扱いです。


・両方とも『親』プロシージャから呼ばれますが、
 『Sub』プロシージャは引数の変数を書き換えると呼び出し元『親』で書き換えた値が
 反映します。→処理部分を『サブルーチン』として分離しただけです。
・それで『Function』プロシージャは引数の変数を書き換えても呼び出し元『親』の値は
 変化しません。また、他の言語と同じように『関数』としての仕組みとして『戻り値』
 が『親』へ戻せます。→ここの部分が『Sub』プロシージャと大きく違います。『Sub』
 プロシージャは『戻り値』を返せません。

●使い分け
・変数(引数)の操作を『親』プロシージャと共有したい場合は『Sub』プロシージャを使う。
 または、複数の処理結果を返したい場合に使う。
・変数(引数)の操作を『親』プロシージャと別に扱いたい場合は『Function』プロシージャを使う。
 または、『関数』という意味で『戻り値』で処理結果を返したい場合に使います。

最後に:
・昔、Basic 言語には『Sub』プロシージャしか記述できませんでした。
 その後、他の言語のような『関数』機能を自分で定義できる『Function』プロシージャが
 登場しました。この登場により、呼び出し元『親』の処理で『戻り値』として処理結果を
 受け取れるように便利になりました。
・以上。おわり。
    • good
    • 0
この回答へのお礼

すばらしい文章能力に感激です。
いままで回答してくださった皆様のアドバイスを読み、さらにOh-Orangeさんの回答を読む。これで、完璧に頭に入りかつ、仕える知識になりました。

ありがとうございました。

お礼日時:2007/02/23 18:52

#2です。



補足:
Excel VBAの場合は、動的な作業に対しては、サブルーチン・プロシージャがよいです。静的なものは、サブルーチン関数でもよいかと思います。Access VBAとは、この点で違ってくると思います。その関数は、必ずしも呼び出しに使うわけではありません。

ただ、本質的に何のためにするか、ということです。

参照渡しと値渡しの処理スピードの違いというものはあります。しかし、それ以上に、分散処理のため(たぶん、使用メモリも減る)と、デバッグのしやすさ、つまりコードの読みやすさがあると思います。そういうことを心がければ、自ずと選択は決まってくるのではないか、と私は思います。

>このような場合、両者には、どのような違いがあるのでしょうか?
違いはないれど、不自然です。

以下のように、戻り値を与えたほうがよいです。

引数の方は、Long 型です。

Function FMyRowCnt(MyNOend As Long)
 FMyRowCnt = TMYKanriBkWs1.Range("D1").CurrentRegion.Rows.Count
End Function
    • good
    • 0
この回答へのお礼

質問の仕方から、内容への回答まで、どうもありがとうございました。
素人のため、盛り沢山で有用な回答のすべてを、うちに取り入れることができませんでしたが、ご丁重な回答どうもありがとうございました。

また、「違いはないけれど、不自然です」のようなニュアンスも教えていただけたことが、大変ありがたく思います。

お礼日時:2007/02/23 18:45

小生も、その昔、疑問に思ったことです。


小生なりに理解したことを書いて見ます。
functionは、返す答えが1つの場合。
従って、 functionの場合は、
a=FMyRowCnt(xxxx)、であったり、
或いは、 if FMyRowCnt<>"" thenであったりします。

functionでありがたいのは、下記のような場合です。
if mysheetExsits("xxxxxxx")=true then xxxxxxxx
(勿論、mysheetExsitsはfunctionです)

subroutineでも、1つ(以上)の値を返すことが可能です。
sub test(byval aaa as integer, byref bbb as interger, byref ccc as interger)
byvalは、親から、子への一方向のみ、
byrefは、双方向です。従って、子で、値を書き換えると親はそれを参照することができます。
小生は、サブルーチンで、処理をして、結果がfailとなった時に
byrefにて、親に返してやります。
先ほど書きました、
if mysheetExsits("xxxxxxx")=true then xxxxxxxx
と変わらないです。
結局、サブルーチンは、何となく、使いやすいので、使ってしまいます。
if mysheetExsits("xxxxxxx")=true then xxxxxxxx
このような、使い方は、絶対に、functionでなければやれないと思います。
    • good
    • 0
この回答へのお礼

とても平易にかつ有用に、そして、例題たっぷりに教えてくださり、どうもありがとうございました。

大変よくわかりました。なるほどってかんじでした。

お礼日時:2007/02/23 18:47

こんばんは。



たぶん、サンプルのために書いただけのコードで、そのコードの完成型をご存知の上で書いているとは思います。簡単なサンプルでも、出来れば、きちんとした完成型で書いていただいたほうがよいかと思います。この質問は、わずかな差でしかありませんが、あえて、そのような質問をする場合は、それなりの力も問われることになるかと思います。

Excel VBAでは、そのような内容のコードは、あえて、サブルーチンにする必要はありませんが、いわゆる戻り値を明示的に持つようにすべきものなので、関数タイプだと思います。しかし、関数は、共有性を重視しますので、Excel VBAでは、いくら参照渡しでも、関数にキメウチ的なコードは、書きません。

MyNOend = TMYKanriBkWs1.Range("D1").CurrentRegion.Rows.Count

こういう細かい部分を抜きにして言うなら、その大きな違いは、そのメイン・プロシージャの読みやすさだと思います。参照渡しにする場合、いきなり、サブルーチン側の引数で現れるような変数は存在しません。その分だけ、手数が多くなり複雑になっていきます。メイン側で、意味が分かりにくい変数が出てきます。

Excel VBAでは、あくまでも、関数は、プロジェクト全体の共有性を持たせて、独立性は高くなる、と思います。そして、通常、1つの値を返すことを目的として作ります。また、サブルーチン・プロシージャは、同じモジュール内で操作するのが一般的です。そして、より独立性を高くするなら、クラス側で設定させます。
    • good
    • 0
この回答へのお礼

お礼を#4にまとめさせていただきました。

お礼日時:2007/02/23 18:48

普通、Functionで定義したものはその定義名に結果を代入して値を返すように使います。

この例だと
FMyRowCnt=TMYKanriBkWs1.Range("D1").CurrentRegion.Rows.Count
として、親の方は
Cells(1,FMyRowCnt)=123
と書けます。
このあたりはVBAだとあまりありがたみがないかも知れません。他のプログラミング言語だと引数に値をいれてもその値が変わらないという風になっているものもあります。
    • good
    • 0
この回答へのお礼

どうもありがとうございました。
関数としてそのままの利用ができることが違いのうちの1つなのですね。

お礼日時:2007/02/23 18:43

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!


おすすめ情報