misc.log

日常茶飯事とお仕事と

VBAやVB6のSub/Function呼出し時の括弧と、強制的に値渡しにする方法(しらんかったわ……)

何をいまさら……な話ですが某所で質問が出ていたのに対してストンと答えられなかったので少し調べました。

ExcelなどのVBAや、旧VBであるVisual Basic 6.0などでは、Subで宣言したプロシージャやFunctionで宣言した関数を呼ぶ際には、

  • プロシージャ/関数名のあとに空白をあけて引数を指定する
  • プロシージャ/関数名の前にCallを付けて、関数名等の後ろに括弧で囲った引数を指定する

の2方式があります。これ、プロシージャや関数の動作上はどちらも同じで、たぶん記法が変遷した過程で互換性のためにどちらも使えるようになったのだろうと推測しますが、1点だけ。関数で戻り値が有る場合は括弧を付けないとダメというルールがあります。

で、この話の中で「括弧を付けると強制的に値渡しができる」という話をStackOverflowで見つけました。てっきり「Call」がつくかどうかの括弧かとおもったら違って、Call無しの場合でも引数をそれぞれ1個ずつ囲むとByValで渡されるというものです。

stackoverflow.com

というわけで、呼出し先のプロシージャや関数の引数が「ByRef」で指定されていても、呼ぶ側の引数を括弧で囲えばByValになるというもの。実際にやってみるとこんな感じの呼び出しパターンと動きになります。

f:id:frontline:20171023124912p:plain

あぁ、Callで呼ぶ場合も括弧で値を囲む、すなわち二重括弧にすればByValになるんですね……しらんかったです。というかもう98年ごろから「ByRefは原則使わない」というルールで組んでいたので、ByValを強制する必要がそもそもなかったのですね。てっきり

  • changeValue i
  • changeValue (i)

は同じ動きだと思っていたのですが、違ったとは……。

というわけでいまさらですが自分用メモでした。

ちなみにマイクロソフトのサイトにも情報あります。試してませんがVB.NETも同じなのでしょうね。

How to: Force an Argument to Be Passed by Value (Visual Basic) | Microsoft Docs


ExcelVBAを実務で使い倒す技術

ExcelVBAを実務で使い倒す技術