• ベストアンサー

ExcelVBAにて関数の参照渡し

XPにてExcel2002を使用しています。 Cですと、 void aaa(double *x ,double (*func)(double)){ } のように関数のポインタを渡すことができると 思うのですが、これと同じことがVBAで できるのでしょうか?

質問者が選んだベストアンサー

  • ベストアンサー
  • sakenomo
  • ベストアンサー率52% (35/67)
回答No.5

No.4です。ご希望のようなことは、できないように思います。もっとも、私も勉強不足なのですが…。 前記の例では二つの関数をまとめましたが再利用をお考えなら、たとえば下記のようにmainの中でmainとmyFunc等間の仲立ちをするanyFuncを使い、常に二つをセットで用いるなどの工夫をするしかないような気がします。 Function anyFunc(ByRef b As Double, Optional Dore As String)  Select Case Dore  Case "myFunc1", ""   anyFunc = myFunc1(b)  Case "myFunc2"   anyFunc = myFunc2(b)  Case "ourFunc"   anyFunc = ourFunc(b)  End Select End Function

0shiete
質問者

お礼

ご回答頂いたとおり、仲立ちの関数を 用意することで解決しました。 どうも有難うございました。 (お礼が遅くなって申し訳ありません)

その他の回答 (5)

noname#4564
noname#4564
回答No.6

  CallByName関数を使用すれば希望の形に近くなるかもしれません。 # どの程度実用に耐えられるかは不明。 ※ Eval関数はExcel(2000)には実装されていません。 VB(A)で関数のアドレスを扱う場合、AddressOf演算子を使いますが、これは通常、コールバックやサブクラス化(メッセージフック)に使用するので、仕様の拡張(アルゴリズムの分岐)を柔軟に行うために使用するC言語の関数ポインタとは趣旨がちょっと違うような気がします。  

0shiete
質問者

お礼

ご回答いただき、有難うございました。 (お礼が遅くなって申し訳ありません)

  • sakenomo
  • ベストアンサー率52% (35/67)
回答No.4

はずしているかもしれませんが、こんな感じでしょうか。 Function anyFunc(ByRef b As Double, Dotti As Boolean)  If Dotti = True Then    anyFunc = b * 1  'myFunc1の処理  Else    anyFunc = b * 100 'myFunc2の処理  End If End Function Sub main(Dotti As Boolean)  Dim x As Double  x = 5  MsgBox anyFunc(x, Dotti) End Sub Sub test()  main (True)  main (False) End Sub

0shiete
質問者

お礼

ご回答有難うございます。 私のしたい処理はご回答にある記述で可能です。 (任意の関数をanyFuncという名前にしてしまう方法) ですが、たとえば、ご回答にあるmain関数を別のVBAで再利用したいときに、渡したい関数(myFunc1など)を Function anyFunc(ByRef b As Double, Dotti As Boolean)  If Dotti = True Then ...  Else ...  End If End Function の形式に書き換えないといけないというわずらわしさがあります。(コードが小さければ、たいした手間ではないのですが) 質問の中に書いたような、関数を参照渡しする方法が あれば、もっとスマートに書けると思うのです。 他の回答をもう少し、待ってみようと思います。 有難うございました。

  • todo36
  • ベストアンサー率58% (728/1234)
回答No.3

試していませんが 関数名をStringで受け取って、Evaluateとか

  • Silent-G
  • ベストアンサー率15% (2/13)
回答No.2

すみません、はずしていましたね。 >>Function(ByRef x As Double) >におけるxとして関数を指定したいのです。 という事であれば、無理です。 クラスを使えば似たような事ができるかもしれませんが・・・ こちらは、私も勉強不足なので参考URLあげときます。

参考URL:
http://www.moug.net/skillup/opm/opm08-01.htm
0shiete
質問者

お礼

mougは私もお世話になっています。 仲立ちの関数を用意することで解決しました。 どうも有難うございました。 (お礼が遅くなって申し訳ありません)

  • Silent-G
  • ベストアンサー率15% (2/13)
回答No.1

VBAでポインタは使えませんが、 引数の参照渡しということであれば、 デフォルトが参照渡しなのでそのままでOKです。 明示的に記述するには"ByRef"をつけます。 Function(ByRef x As Double) ちなみに、値渡しは"ByVal"です。こちらは必ず指定しないといけません。 詳細はヘルプのFunctionステートメントの項に詳しく記述されていますよ。 では。

0shiete
質問者

補足

ご回答有難うございます。 VBAではデフォルトが参照渡しということは 知っているのですが、 >Function(ByRef x As Double) におけるxとして関数を指定したいのです。 つまり、 Function myFunc1(ByRef a As Double) myFunc1=(処理) end Function Function myFunc2(ByRef b As Double) myFunc2=(処理) end Function Sub main(ByRef anyFunc As Double) Dim x As Double Dim y As Double x=5 y=anyFunc(x) end Sub というニュアンスにしてmainにmyFunc1を渡したり myFunc2を渡したりして、mainの中でどちらかの 関数を使いたいのです。 そして、mainの中では、どちらが渡されたのかということを気にせずanyFuncという名前で使いたいのですが、これを解決する方法はあるのでしょうか?

関連するQ&A

  • C++:ある関数を定義するときに別の関数を用いて定義はできないのですか。

     Visual C++を使っています。  以下のように関数func2において関数func1を使いたいのですがコンパイルするとポインタがどうのこうのと言ってきます。  書き方が間違っているのでしょうか、別にいい方法がありましたら教えてください。参考書はありますので、どの項目を見ればよいと言うアドバイスでも結構です。 const double a=100.0; //グローバル変数aを定義 //関数func1を定義 double func1(double x){ return exp(x); } //関数func2を定義 double func2(double y){ return func1(a)*exp(y);//func(a)は係数。 } 実際はfunc1とfunc2はもっと複雑な形なのでどうしても別々に定義したいです。

  • 関数の掛け算を返す関数

    いま関数の積分を行おうとしています. この積分を行う関数が double integral(double (*func)(double), double a, double b ) {    double ans;    .....    return ans; } となっていて,aからbまでfuncが指す関数を積分して結果を返します. 積分をさせる関数は double f1(double x) { return 3.0*x; } double f2(double x) { return x*x; } となっていて,同じようにg1, g2も用意します.(本当は関数が3つ4つあります.) 例えばf1を積分したいとき, int main() {    double ans = integral(f1, a, b);    printf("%f\n", ans); } ですよね. 自分で積分する関数を選ぶときは,ここに配列で場合分けをして double (*func_f[])(double)={f1, f2}; scanf("%d", &flag); /* flagに0~1を代入 */ ans = integral(func_f[flag], a, b); でいいと思います. さて,そこで本題なのですが, double (*func_f[])(double)={f1, f2}; double (*func_g[])(double)={g1, g2}; としておいて, scanf("%d", flag1); scanf("%d", flag2); func_f[flag1], func_g[flag2]; として関数を入力側から決定して, (例えばflag1=1, flag2=1,であったとして *func_f[1]=x*x *func_g[1]=5.0*x ならば) h(x)=(x*x)*(5.0*x)=5.0*x*x*x という関数を作って, h(x)を指すポインタを double (*h_ptr)(double) とすれば ans = integral(h_ptr, a, b); としたいのです. (f1*g2)を一つの関数としてh(x)=(f1*g2)(x)というように扱うことができればいいと思うのですが. integralの引数で,関数のポインタを2個にすると,汎用性が失われてしまうと思うので,できればそこは変えたくないです. どのようにすればよいのでしょうか? また,「考え方を変えればよい」などの意見も頂きたいです. 皆様,どうぞよろしくお願いします.

  • 【C言語】別関数でポインタの値を変えたのに変わらない。

    【C言語】別関数でポインタの値を変えたのに変わらない。 メイン関数のポインタの値を、別関数で書き換えるプログラムを作りました。 以下がそのプログラムになります。 そのままだと、ダブルポインタを操作する必要があるので分かり辛いです。なので、ダブルポインタをシングルポインタにしてからポインタの書き換えを行うようにしました。その結果、きちんとポインタの書き換えが出来なくなってしまいました。 なぜ出来なくなってしまったのでしょうか。 2つのプログラムの違いは、 >  *pp = &dummy; が >  p = *pp;      // ダブルポインタをシングルポインタにした >  p = &dummy; に変わっただけです。 【参考】http://www.kouno.jp/home/c_faq/c4.html#8 -----------------正しいプログラム---------------- // 以下プログラムは、正しく動作する // 実行結果は、 //   p = 5 // と表示される void func( int **pp ); int main (void){   int *p;   int a = 0;   p = &a;   func( &p );   printf("p = %d\n", *p);   return 0; } void func( int **pp ){   static int dummy = 5;   *pp = &dummy; } ---------------------------------------------- -----------------間違いプログラム---------------- // 以下プログラムは、正しく動作しない // 実行結果は、 //   p = 0 // と表示される void func( int **pp ); int main (void){   int *p;   int a = 0;   p = &a;   func( &p );   printf("p = %d\n", *p);   return 0; } void func( int **pp ){   static int dummy = 5;   int *p;   p = *pp;      // ダブルポインタをシングルポインタにした   p = &dummy; } ----------------------------------------

  • 使い回しの効く関数の作り方

    ある関数をaからbまで積分する関数integralがあります. integral(double (*func)(double, void*), void* t, double a, double b) 例えば次の関数 fx=5x double fx(double x, void* y0) { double y =*(double*)y0; return y*x; } を積分するときには double y=5.0; integral(fx, &y, 1.0, 5.0); としています. さらに gx=5x+5 のようなときは, 構造体を宣言して double gx(double x, void* y0) { parameter p =*(parameter*)y0; return p.y*x + p.z; } としています. これはいい方法なのでしょうか? 関数funcの引数の数を変えてしまうと, integralの使い回しができなくなると思い, このような方法にしていますが, これも被積分関数ごとに構造体を用意しなければならず, あまり良くないんじゃないかな~って思っています. もっといい方法があれば教えていただきたいです. よろしくお願いします.

  • C言語での関数の引数の受け渡しについて

    C言語での関数の引数の受け渡しについて教えてもらいたいのです。 char *p=Goo;  というポインタpがmain関数で定義され、このポインタpをある関数 void func(・・・) に渡すことは出来ますか? つまりポインタを実引数として扱うことはできるのかという事ですが・・・ int p=10; とかだったら、 void func(int test) の関数には、main関数で func(p) で仮引数testにわたせると思うんですが・・・ もし出来るようでしたら、関数の渡し方と定義の記述を教えてください。 どうか宜しくお願いします。

  • 【C++】関数ポインタの代入

    C++の関数ポインタについて質問です。 下記のように関数ポインタを宣言し、3通りの代入を行ってみました。 (3)のように関数名の頭に&を付けた場合と(2)のように&を付けなかった場合で 全く動きが同じになってしまうのですが、何故なのでしょうか? ------------------------------------------ #include "stdafx.h" #include <iostream> using namespace std; void Func1(){ cout<<"Func1が呼ばれました。"<<endl; return; } int main() { //(1) void (*fp1_1)(); fp1_1 = Func1; fp1_1(); //(2) void (*fp1_2)()=Func1; fp1_2(); //(3) void (*fp1_3)()=&Func1; fp1_3(); getchar(); return 0; }

  • c言語 配列

    関数の中で複数の値を配列で返したいのですが,どうすればいいでしょう? 配列を関数に渡す時にはアドレスが渡されるので,ポインタと同様関数内で値を変えればmain関数の値も変わるのではないかと思ったのですが,上手くいきません. 知りたいのは,main関数の中の配列(できれば2次元配列)の値を他の関数から値を変更する方法です.下のプログラムはためしに書いてみたものです.質問を理解するうえで役立てば幸いです. #include<stdio.h> void func(double aaa[][3] ,double bbb[]); void main(void){ double array_a[3][3]={{1,2,3},{4,5,6},{7,8,9}}; double array_b[3]={0}; func(array_a,array_b); } void func(double aaa[][3] ,double bbb[]) { int i,j; for (i=0;i<3;i++) { for (j=0;j<3;j++) { bbb[i]=bbb[i]+aaa[i][j]; } } }

  • 参照渡しにならないのは何故?

    参照渡しにならないのは何故? 基本的な質問で大変恐縮なのですが、C言語で以下のコードを書いてみました。 メインの関数ではchar型のポインタのみ用意し、呼び出し先のtest関数内で当該ポインタ用に 領域を割り当て文字列をコピーしています。 ここまでは良いのですが、呼び出し元のメイン関数に戻るとtest関数にて設定したはずの値 が消えてしまいます。 結局のところ、メインの関数で用意したchar型のポインタがうまくtest関数にわたっていない (?)ような動作なのですが、どうしてこうなってしまうのか理解できず苦しんでいます。 ご教授いただければ幸いです。 #include <stdio.h> #include <stdlib.h> #include <string.h> void test(char *pc_buf){ pc_buf = (char *)malloc(10); memset(pc_buf,(int)NULL,10); strcpy(pc_buf,"12345"); return; } void main(){ char *pc_buf; pc_buf = NULL; test(pc_buf); printf("[%s]\n",pc_buf);getchar(); }

  • signal関数の使い方

    標準関数のsignal()関数についてですが void (*signal(int sig, void (*func)(int)))(int); 関数の形式からしてよくわかりません。 僕のイメージでは関数のポインタというと void (*func)(int,int) という感じですが上の場合 void (*func(int,int))(int) /*引数は仮にint型*/ という形式になってますよね。末尾の(int)は引数のはずですがどこの引数になっているのかよくわかりません。 しかも関数の使用例などをみると signal(SIGINT, func); という形で使っており末尾の(int)がどこにいったのかさっぱりわかりません。 よろしくお願いします。

  • 関数へのポインタで

    関数を場合によって使い分けたくて, 次のようにしています. double f1(double x) { return 3*x; } double f2(double x) { return 5*x; } double f3(double x) { return 10*x } /* 同じようにg1, g2, g3があります. */ 次のようなルーチンを使って, void sub(double (*F)(double), ...) { F(a); F(b); } int main() { double (*func_f[])(double)={f1, f2, f3}; double (*func_g[])(double)={g1, g2, g3}; sub(func_f[i], ...) } といった感じにしています. いま,f1*g2のような関数に対してsubを使いたいのですが,この場合はどのようにすればいいのでしょうか? (f1*g2)を一つの関数として扱えることができればいいと思うのですが,方法がわかりません. 教えて下さい. よろしくお願いします.

専門家に質問してみよう