Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


922 / 13644 ツリー ←次へ | 前へ→

【77479】参照渡しと値渡し Nobu10 15/10/16(金) 2:05 質問[未読]
【77480】Re:参照渡しと値渡し β 15/10/16(金) 2:22 発言[未読]
【77481】Re:参照渡しと値渡し β 15/10/16(金) 2:47 発言[未読]
【77482】Re:参照渡しと値渡し Nobu10 15/10/16(金) 5:33 発言[未読]
【77484】Re:参照渡しと値渡し β 15/10/16(金) 8:08 発言[未読]
【77497】Re:参照渡しと値渡し Nobu10 15/10/16(金) 17:10 お礼[未読]
【77502】Re:参照渡しと値渡し ichinose 15/10/16(金) 18:42 発言[未読]
【77509】呼び出し側で引数の渡し方を決めたい理由 ichinose 15/10/17(土) 19:42 発言[未読]
【77510】Re:呼び出し側で引数の渡し方を決めたい理由 β 15/10/17(土) 19:55 発言[未読]
【77511】Re:呼び出し側で引数の渡し方を決めたい理由 ichinose 15/10/17(土) 21:41 発言[未読]
【77503】Re:参照渡しと値渡し cai 15/10/16(金) 22:44 発言[未読]
【77483】Re:参照渡しと値渡し ichinose 15/10/16(金) 5:33 発言[未読]
【77501】Re:参照渡しと値渡し Nobu10 15/10/16(金) 18:27 お礼[未読]
【77505】Re:参照渡しと値渡し γ 15/10/17(土) 12:50 発言[未読]
【77512】Re:参照渡しと値渡し Nobu10 15/10/18(日) 0:01 お礼[未読]
【77515】Re:参照渡しと値渡し β 15/10/18(日) 6:27 発言[未読]
【77516】Re:参照渡しと値渡し Nobu10 15/10/18(日) 7:19 お礼[未読]
【77517】Re:参照渡しと値渡し γ 15/10/18(日) 8:59 発言[未読]

【77479】参照渡しと値渡し
質問  Nobu10 E-MAIL  - 15/10/16(金) 2:05 -

引用なし
パスワード
   (〜渡し)と言えば渡すほうに主導権があると思います。他のプロシージャへ変数を受け渡しするとき呼出元でのステートメントの書き方は Call mySub (a)などの様に、どの渡しでも同じです。しかし呼出先プロシージャでは受ける変数の前にByRef又はByValと区別しています。つまり(〜渡し)は呼出元ではなく呼出先プロシージャの主導権によって決定されると言っていいのではないでしょうか。すれば(〜渡し)と言うより(〜受け)と言ったほうがよいのではないかと思います。しかし下記のプロシージャでは呼出先でByRefと参照渡しを指定しているのにかかわらず、値渡しになるようです。ここでは、Callステートメントを使用しないでmySub(a)と変数を()で括ると値渡しになり呼出元が主導権を握っています。言いたいことは、(〜渡し)は呼出元プロシージャによって決まるか呼出先プロシージャなのかと言うことです。
Sub Test()             Sub mySub(ByRef aa As String)
Dim a As String            aa="エクセル"
a="Excel"             End Sub
mySub(a)
MsgBox a
End Sub
どなたか説明できる方はよろしくお願いいたします。

【77480】Re:参照渡しと値渡し
発言  β  - 15/10/16(金) 2:22 -

引用なし
パスワード
   ▼Nobu10 さん:

まぁ、〜渡し なのか、〜受け なのか これは 言葉のあや と考えればいいとおもいます。
厳密にいうと、指摘の通り、規定しているのは 受け側ですから、〜受け がいいのかもしれません。
おそらくそうだと思いますが、もしかしたら、受け側の規定に基づいて、渡すほうでなにかしている?
そうでないということは、私のレベルでは検証できないので。

mySub(a) と書いておられますが、ほんとは、ちょっと違っていますよね。
mySub (a) 、mySub と ( の間にスペースがありますね。 たとえ、コードペインで mySub( と、くっつけて
タイプしてもエンターをすれば自動的にスペースが挟まれますね。
これをCallステートメントで記述すると Call mySub((a)) と、スペースは挟まれません。

まぁ、それはさておき、Call mySub(a) と Call mySub((a)) 、ないしは mySub a と mySub (a) の違いですけど
変数を ( ) で囲むと、その変数の「クローン」がメモリー領域にテンポラリーに生成され、それを渡すことになります。
つまり、(a) の場合、 a そのものを渡してはいないんです。a の影武者です。
ですから、byRefの受け側のプロシジャで、たとえ焼かれようと煮られようと、殺されようと、
本物の a はぴんぴんしているわけです。

ご理解いただけましたでしょうか?

【77481】Re:参照渡しと値渡し
発言  β  - 15/10/16(金) 2:47 -

引用なし
パスワード
   ▼Nobu10 さん:

ついでに老婆心ながら。

メソッドあるいは関数 (引数) と記述する人がいます。
↑で申し上げたことを理解して、あえてそうしているならいいのですが
ほとんどは、理解せずに使っている。

たとえば MsgBox ("こんにちは")

たまたまエラーにはなりませんが、これは【間違った】記述です。

MsgBox にはメッセージの他に、ボタンの種類なんかも指定できますよね。

MsgBox ("こんにちは",vbInformation)

このようにコードペインに打ち込んでエンターしてみてください。
コンパイラーに叱られますねぇ。

MsgBox "こんにちは",vbInformation

これが正しい書き方です。

MsgBox ("こんにちは") は、なぜOKなのか?

それは この ( ) が 引数に対してつけられたものではなく、その中の1つの変数に対して
つけられたものだからです。

つまり、

MsgBox ("こんにちは"),vbInformation

といったように、第1引数を ( ) で囲んでいるということなんです。

で、この( ) で囲まれた変数は、前レスで説明したクローンになります。

【77482】Re:参照渡しと値渡し
発言  Nobu10 E-MAIL  - 15/10/16(金) 5:33 -

引用なし
パスワード
   結果を見ればクーロンを渡していることになります。
呼出元が呼出先の要求を無視するのであれば、呼出先で(〜渡し)を指定する必要が無いと思います(指定しても無視される時があるから)。呼出元に一任すれば何のことはありません。つまり、ByRef、ByVarを書くべきところは呼出元であると思います。そうすれば何の問題も起こりません。回答の中で、”受け側の規定に基づいて、渡すほうで何かしている?“という記述は渡すほうが受け側に行って、一度お伺いを立ててから戻って、もう一度受け側に行って情報を与えると言うことなのでしょうか?もしそうだとしたらこのような事も渡す側でByRef、ByVarを指定すると必要が無くなり全てすっきりすると思います。

【77483】Re:参照渡しと値渡し
発言  ichinose  - 15/10/16(金) 5:33 -

引用なし
パスワード
   ▼Nobu10 さん:

>(〜受け)と言ったほうがよいのではないかと思います。
言葉の問題は、歴史を紐解かないと理解できないことがあると思いますよ!!
パラメータ渡し、私が30年前に使っていた低級言語では、値渡しという概念がない言語でした。参照渡しだけです。方式が一つしかないのですから、言葉として参照渡しで
問題がないですね!! こんな時代が長く続いた後に 値渡し方式がでてくると、
言葉使い方で  参照渡しと値渡し というワードが自然に定着しても 違和感がなくなってしまいます。


因みに変数宣言だって

Dim A As Long

このDimって dimensionの略です。私のイメージですとこれは次元という意味なので、
言葉的には、違和感がありますよね!!

私の以前使っていた言語では 

Dcl A As Integer

declare 宣言する  の方がしっくりきます。

歴史的にみると、

昔のBasicには、変数宣言がありませんでした(N88Basicの時代)。

ですから、いきなり a,b,cなどの変数がとびでてくることになります。

配列だけは、

Dim Ary(15)

Dim ary(10,20)

と規定が必要でした(10未満は要らなかった)

Basicで変数宣言が可能になったとき、このなごりで
dim a as integer

になったのでしょう。


パラメータ渡しの話に戻ると、オブジェクトのプロパティをパラメータに使っても
値渡し扱いになりますね!!


Sub test()
  Call test2(Range("a1").Value)
End Sub
Sub test2(ByRef myval As Variant)
  myval = 123
End Sub


test実行でセルA1に変化ないですよね

【77484】Re:参照渡しと値渡し
発言  β  - 15/10/16(金) 8:08 -

引用なし
パスワード
   ▼Nobu10 さん:

(アップ後、一部、加筆訂正)

思い出しました。
別の板で、オブジェクトのキーワード や ローカル変数について で
トピを立てられたかたでしたか。

ちなみに、別板で、【私ならこう表現する】と書いて締められた、その【模範説明文】にも
おかしなところはたくさんありましたよ。

様々なことに疑問をもたれるのは結構なことだとは思いますが、
まぁ、法律の文章にも、あやふやな、矛盾のあるところもおおいですし。

>結果を見ればクーロンを渡していることになります。

結果ではなく、これは(ご存じだったかどうかは別にして)そういう仕様です。

むしろ気になるのは(Nob10さんは、そうではないと思いますが)
Call mySub(a) と mySub (a) が 【同じもの】だと思いこんでいる人が多いということです。
いいかえると mySub (a) を Call文でかくと Call mySUb((a)) ということだいうことが
わかっていない人が多いということです。

>つまり、ByRef、ByVarを書くべきところは呼出元であると思います。そうすれば何の問題も起こりません。

特段、異論はありませんが、そうでなくても何の問題もないと思いますが?

>”受け側の規定に基づいて、渡すほうで何かしている?“という記述は渡すほうが受け側に行って、一度お伺いを立ててから戻って、もう一度受け側に行って情報を与えると言うことなのでしょうか?

コンパイラーの機能はご存じですよね。
実行の開始前に呼び出し先があるかどうかを、コンパイラーがチェックしていますよね。
なので、呼び出し先指定がどうなっているかは、実行前にわかっていますね。
ですから、【もしかしたら】と書きました。ただし検証はできません。
少なくとも、【一度お伺いを立ててから戻って、もう一度受け側に行って情報を与える】という
ばかなことは、するはずがないですね。

まぁ、別板でもありましたように、疑問を共有して、ディスカッションするというより
【君たちの理解は間違っている】と主張されるかたのようですから、βは、これで撤収します。

別板でも感じましたが、ご意見は、このような掲示板で声高に唱えられるより、正式にMSに
提言されてはいかがですか?

【77497】Re:参照渡しと値渡し
お礼  Nobu10 E-MAIL  - 15/10/16(金) 17:10 -

引用なし
パスワード
   mySub (a)をCall文で書くとCall mySub((a))になるとは知りませんでした。疑問をこの掲示板で立てたことで、私自身のVBAに対する理解が少し深まりました。誠にありがとうございます。私は沖縄在住の69歳のリタイア組です、ボケ防止のためにVBAの本を読んでプロシージャを組み、頭の体操をしています。何かを作る目的があるわけではなく、リタイアしていますので仕事で使おうとしているわけでもありません。ただ単に、本を読んで疑問に感じたことやもっと異なった視点から説明がほしい時に掲示板に立てているだけです。プログラム言語はVBAが初めてで、始めて3年ぐらいなります。そんな私が「君たちの理解は間違っている」なんて言える訳がありません。むしろ逆で私の主張のここがおかしいとか、間違っていると皆さんに指摘してもらいたいのです。そうする事で私のVBAの理解度を高めていきたいのです。しかし誤解が生じたと言うことは、私の文章が誤解を与える文章だったと言うことでしょう。以後気をつけてレスしたいと思います。私の疑問は今のところプロシージャを作成する技術的なものではなく、概念的なものです。知らなくてもプロシージャ作成にはあまり関係のないことだと思っています。つぎはキーワードについて疑問を主張したいと思います。皆さんよろしくお願いいたします。

【77501】Re:参照渡しと値渡し
お礼  Nobu10 E-MAIL  - 15/10/16(金) 18:27 -

引用なし
パスワード
   いろいろと教えていただいて、ありがとうございます。自分でもつまらない質問だと思いますが、自分を納得させながら一歩一歩、歩んで行きたいと思います。これからもつまらない質問をすると思いますがよろしくお願いいたします。

【77502】Re:参照渡しと値渡し
発言  ichinose  - 15/10/16(金) 18:42 -

引用なし
パスワード
   質問の意図を誤解していたようです。

>プロシージャを作成する技術的なものではなく、概念的なものです。知らなくてもプロシージャ作成にはあまり関係のないことだと思っています。
いいえ、そんなことはありません。プロシジャーやパラメータの意味を深めるには
大切だと思いますよ!!

>ByRef、ByVarを書くべきところは呼出元であると思います。

これは 違います。あくまでも呼出先です。




Sub 足し算2を足す(ByVal 数 As Long, ByRef 答え As Long)
  答え = 数 + 2
End Sub


上記のコードは、指定された数字に2を足した数を 返す という機能を持ちます よね?

入力データ 数  長整数型 値渡し
出力データ 答え 長整数型 参照渡し

足し算2を足す というプロシジャーが機能を遂行できるように
パラメータの性質を決めるのが 理屈だと思いませんか?


「数」という変数は、「足し算2を足す」というプロシジャーでは、参照さえできれば
良いので 値渡しであり、 「答え」という変数は、結果を格納するので
参照渡しのパラメータにする。

「足し算2を足す」というプロシジャーの機能に沿って パラメータを決めるのですよ!!


だから、現状の文法で良いのです。


Sub test1()
  Dim a As Long
  Dim b As Long
  a = 5
  b = 1
  Call 足し算2を足す(a, b)
  MsgBox b
End Sub


Sub test2()
  Dim a As Long
  Dim b As Long
  a = 5
  b = 1
  Call 足し算2を足す(a, (b))
  MsgBox b
End Sub


因みに test2では、参照渡し が 値渡しになっているように見えますし、
結果はおなじですが、メカニズムは、若干違いますよ!!


追伸

私は、Nobu10さんの質問や投稿内容 良いと思いますよ!!
少なくとも作成依頼の投稿に比べたら断然です。
比較することすら 失礼だと思うくらいです。

【77503】Re:参照渡しと値渡し
発言  cai  - 15/10/16(金) 22:44 -

引用なし
パスワード
   >結果を見ればクーロンを渡していることになります。
クローンを参照渡ししていると考えたらどうでしょうか。

【77505】Re:参照渡しと値渡し
発言  γ  - 15/10/17(土) 12:50 -

引用なし
パスワード
   こんにちは。
横合いから失礼します。
既に適切な指摘がございましたが、念のため追記します。

プロシージャを定義した段階で、参照渡し、値渡しのどちらにするかは
決める仕組みになっています。指定を書略したらByRefです。
呼び出す際に、それを承知して使うわけです。

貴兄の指摘のように、
> つまり(〜渡し)は呼出元ではなく呼出先プロシージャの主導権によって
> 決定されると言っていいのではないでしょうか。
どちらが主導権を持っているかというようなことではないと思います。

>つまり、ByRef、ByVarを書くべきところは呼出元であると思います。

VBAは、そういう設計の言語ではありません。(該当する言語例を知りません)
型の指定や、引数の引き渡しなどすべて、
呼び出されるプロシージャ側で一意的に定義するのが決まりです。

・呼び出す側で動的に変更することもできませんし、
・受ける側が、呼び出す側の指定に応じて、どんな呼び出し方にも対応できるとか、
そういう仕組みにはなっておりません。

プロシージャは複数箇所で何度でも呼び出すことが想定されますから、
呼び出す側で逐一指定しなければならないとしたら、
少なくとも、相当に記述効率が悪くなるでしょう。

いずれにしても、あなたがこれから言語を設計でもしようとしているなら、
そうした議論が有益かもしれませんが、
既にある言語のことを議論しているのでしょうから、
まずは、その言語のきまりを正確に理解することが大切だと思います。

もし言語設計をこう変えるべきだという議論をしたいのなら、
こうした場所は適切ではありません。(適切な場所も知りませんが)

------------------------
呼称の件にもふれましょう。

下世話な譬え話で恐縮ですが、
賄賂を渡す、受取るといった行為が世間には見られますね。

賄賂というものは、その効果、期待に関して、
両者にほぼ共通した認識があると言ってよいでしょう。
受け取る側がその性格を決めているわけでもなく、
渡す方もその効果を信じているからこそ、阿吽の呼吸で渡すのです。

そうした行為に対して、
賄賂を「受け取る」と呼ぶべきで、賄賂を「渡す」と呼ぶべきではない、
と主張されているようなもので、余り生産的な話でもなかろうと思います。
(いやあ、極端なたとえ話だったかも)

---------
ちなみに、別掲示板の件、拝見していた私も、βさんと同じ印象を持ちました。
ローカル変数というタイトルの別掲示板のご発言で、捨て台詞的に、
あなた方は間違っている? 私ならこう書く、と主張された件です。

もともと、適用するスコープを「広くする」にはどうするか、
というのが元記事なんですよ。
プロシージャレベル変数の説明が仮に不足してとしても、
それが致命的だとも思いません。
そこに重点があるわけではないからです。
プロシージャレベルの話はあくまで前段なのです。

にもかかわらず、あなたは、スコープを一番狭くしたときについての説明記述は、
こうあらねばならない、おかしい、と主張されたわけです。

主張された内容自体を単独で拝見すれば、誤字を除き概ねよいと思いますが、
記事を記載した側の気持ちを忖度すれば、
それはテーマが違うといったところかもしれません。
いずれにせよ、鬼の首でも取ったように主張することでもないと思います。

【77509】呼び出し側で引数の渡し方を決めたい理由
発言  ichinose  - 15/10/17(土) 19:42 -

引用なし
パスワード
   もう何年もやっていないので はっきりした記憶ではないですが、
Fortranは、このパラメータ渡しが参照渡しでした。

つまり、値渡しという概念がありませんでした。



call aaa(val(b))

と変数bをVal関数(ここがうろ覚え)で囲むことで値渡しで渡すことができました。


つまり、呼び出す側がパラメータの渡し方を指定していたのです。

参照渡しだけの仕様ですから、呼び出し先でパラメータがどのように使われるのか
心配だったのでしょうかねえ?

値を壊されたては、堪らない ということで値渡しの選択が出来たのでしょうか?


こんなことを考えていたら、VBAだって、一部の例外はありますが、

Option Explicit
Sub test()
  Dim a As Long
  Dim ans As Long
  a = 5
  足し算2を足す a, ans
  MsgBox ans
  a = 7
  足し算2を足す a, (ans)
  MsgBox ans
End Sub
'===========================================================
Sub 足し算2を足す(ByRef 数 As Long, ByRef 答え As Long)
  答え = 数 + 2
End Sub


このように呼び出されるプロシジャーでは、引数を参照渡しにして、

呼び出す側で (a) や a  という記述で

値渡しと 参照渡しを使い分けることができます。


これでいくつも実験してみて、

パラメータ渡しがどちらがよいか試してみては いかがですか?

【77510】Re:呼び出し側で引数の渡し方を決めたい...
発言  β  - 15/10/17(土) 19:55 -

引用なし
パスワード
   ▼ichinose さん:

Fortran の知識は全くないのですが、Val(b) というのが、もしかしたら
b の値 ということで、テンポラリーに、メモリー域のどこかにセットされて、
そのテンポラリー域を参照渡ししていたのではないでしょうか?

VBAでも (a) とやると、a のクローンを(うけがわが byRef なら)参照渡ししているわけですので。

【77511】Re:呼び出し側で引数の渡し方を決めたい...
発言  ichinose  - 15/10/17(土) 21:41 -

引用なし
パスワード
   >Fortran の知識は全くないのですが、Val(b) というのが、もしかしたら
>b の値 ということで、テンポラリーに、メモリー域のどこかにセットされて、
>そのテンポラリー域を参照渡ししていたのではないでしょうか?
>VBAでも (a) とやると、a のクローンを(うけがわが byRef なら)参照渡ししているわけですので。

当時の私には、C言語プロジェクトの同僚から、Cは原則、値渡し と聞いていただけなので、内部の事など想像すらしませんでしたが、今 考えれば、そういうことなんでしょうねえ。


VBAで同じような環境でコードを書いてみれば、どちらがよいか結論がでそうなので
このような投稿をしましたが、
私の意見は、あくまでも 機能をもっている呼び出されるプロシジャーが
必要な引数の渡し方も決定するのがよい という意見です。
VBEは、便利なので
呼び出しを記述するときに 引数が 参照渡しか値渡しかわかるようになっていますしね!!

参照設定なしで 外部オブジェクトを使用するときに
安全のために値渡しでというなら 呼び出し時に (a) という使用方法は
分かる気がしますね!!

マニュアル調べろ と言われればそのとおりですが・・・・。

【77512】Re:参照渡しと値渡し
お礼  Nobu10 E-MAIL  - 15/10/18(日) 0:01 -

引用なし
パスワード
   回答者の皆様、誠にありがとうございます。本を読むよりずっと理解が深まりました。
皆さんの回答を読み、私なりに理解した事はサブルーチンの方で渡し方を決めるのが一般的であると言っている、と思っていますが、私もそのことには異存は無く納得しています。しかし、そうでは無くメインルーチンが渡しを決めてサブルーチンを呼ぶことができることを知ったので、引数の渡し方はどのルーチンが決めるのかと疑問を持ったわけです。ちなみに、サブのほうで渡しを決めるのが基本的ということですよね。この点で(渡し)と言うより(受け)のほうが適しているのではないかと考えたわけです。
(渡し)については歴史的な用語としての使い方に名残があるようですので、特にこれ以上論議する必要がないと考え、この掲示板の項を解決済みで終了したいのですが、終了の仕方が分かりません。以前はやったのですが、すみません教えてください。

【77515】Re:参照渡しと値渡し
発言  β  - 15/10/18(日) 6:27 -

引用なし
パスワード
   ▼Nobu10 さん:

こちらの掲示板では、↑の Nobu10 さんの【礼】マーク付の解決コメントで終了となります。
(別掲示板とは異なり、そのあとも、Nobu10さん含めて書きこみはできるのですが)

【77516】Re:参照渡しと値渡し
お礼  Nobu10 E-MAIL  - 15/10/18(日) 7:19 -

引用なし
パスワード
   ありがとうございました。

【77517】Re:参照渡しと値渡し
発言  γ  - 15/10/18(日) 8:59 -

引用なし
パスワード
   間に合いませんでした。

コメントはしますが、返事を求めるものではありません。

>そうでは無くメインルーチンが渡しを決めてサブルーチンを呼ぶことができることを知った
それは事実ではありません。

既に何度も説明がありましたが、
引数に余計なカッコをつけることで、
元の変数とは別の領域にクローンが作成され、
その参照が渡されているだけで、
元の引数の値が変化していないために、ByBalのように見えているだけです。
依然としてByRefであることに変わりはありません。

一方、ByValで定義されているプロシージャを、
呼び出し側でByRefと変更することもできません。
メインルーチン側で渡し方法を決めるなどということはできません。

>サブのほうで渡しを決めるのが基本的
"基本的"ではありません。
例外なく、プロシージャにおける定義に従っています。

呼出元が主導権を握ることができる、ないしコントロールができる、
という認識をお持ちのようですが、それでは、
ByValで定義されているプロシージャを、
ByRefとして機能するメイン側の呼び出し方があるのか、
考えてごらんになると良いでしょう。

---------------------
賄賂云々の譬えを申し上げたが、適切さを欠きました。
というのは、渡す側、受ける側に独立の人格があるような譬えだったからです。

メインプロシージャ、subプロシージャ、functionプロシージャ側に
独立の人格?など無く、各プロシージャーを厳格に定義し、それらを認識した上で、
プロシージャに実行の一部を委ねるのは、同一の主体でしかありません。
各プロシージャの定義を承知したうえで使っているのです。

あたかもそれぞれに意志があるかのような擬人化したモデルで、
コードの理解を図ろうとすると無理が生ずるのではないでしょうか。

922 / 13644 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free