[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『マクロでファンクションへ配列を渡して返す方法』(ろっしい)
マクロでファンクションプロシージャへ配列を渡して返す方法。
配列とファンクションプロシージャを組み合わせて、配列をファンクションプロシージャへ渡して、さらに戻ってきた値を取得するということは可能でしょうか?
やりたいことは、
1.hairetsu(1)〜hairetsu(10) に1〜10の数字が入っている
2.これをファンクションプロシージャへ渡す
3.ファンクションプロシージャの中で各々10倍し、メインに返してくる
というものです。
感じとしては、
Sub親プログラム()
Dim hairetsu(10) as Integer Dim hairetsu_10(10) As Integer
For i= 1 To 10 hairetsu(i)=i Next hairetsu_10 =ファンクションプロシージャ(hairetsu) End Sub
ファンクションプロシージャ(hairetus_f As Integer ) As Integer
For j= 1 to 10 hairetsu_f = hairetsu_f( j ) * 10 next ファンクションプロシージャ = hairetsu_f End Function
適当にあれこれやってみてはみましたが、いずれも「配列には割り当てられません」と警告が出て止まってしまいます(泣)。上手くいく方法があったらご教授願えると幸いです。
または、とにかく「配列を他のプロシージャに渡して配列として戻す」ということをやりたいだけなので、他の方法で簡単な方法があったら教えていただけると助かります。よろしくお願いします m(__)m
Dim i As Integer Dim hairetsu() As Integer, hairetsuA() As Integer, hairetsu_10() As Integer ________________________________________ Sub 親プログラム() With Worksheets("sheet1") For i = 1 To 10 ReDim Preserve hairetsu(i) ReDim Preserve hairetsu_10(i) hairetsu(i) = i hairetsu_10(i) = funkA(hairet_f) .Cells(i, 1) = hairetsu(i) .Cells(i, 2) = hairetsu_10(i) Next End With End Sub ________________________________________ Function funkA(ByVal hairet_f As Integer) As Integer ReDim Preserve hairetsu(i) hairet_f = i * 10 funkA = hairet_f End Function ________________________________________ Function funkB(ByVal hairet_f As Integer) As Integer With Worksheets("sheet1") For f = 1 To 10 Step 2
ReDim Preserve hairetsu(i) ReDim Preserve hairetsuA(f) hairetsuA(f) = f hairet_f = hairetsuA(f) * hairetsu(i) * 10 .Cells(f, 3) = hairetsuA(f) .Cells(f, 3 + i) = hairet_f Next funkB = hairet_f + 10 * i End With End Function 試してみて下さい。(おいぼれ弥太郎)
こんにちは
Sub 親プログラム() Dim i As Integer Dim hairetsu(1 To 10) As Integer For i = 1 To 10 hairetsu(i) = i Test hairetsu(i) Cells(i, 1).Value = hairetsu(i) Next End Sub
Sub Test(hai) hai = hai * 10 End Sub
少し違うので書いときますね (りな)
おいぼれ弥太郎さん、りなさん、ありがとうございます。
質問の趣旨が曖昧でしたね。すみませんでした。やりたいことは、親プログラムからサブプロシージャ(ファンクションプロシージャ)へ、配列を全部一気に送ってしまい、それを加工した配列を一気に返したいということです。
りなさんのケースだと、一つ一つ配列の要素を渡して、それが一つ一つ帰ってきていますよね。(違っていたらすみません)。おいぼれ弥太郎さんのケースは、私の力量不足で私のやりたいことがどうプログラムされているのかよく理解できていません。明日、入門テキストを買ってきて ReDim や Preserve 等々を勉強します。せっかく丁寧にお答えいただいたのにすぐにお返事できなくてごめんなさい m(__)m
なぜ要素を一つ一つ送るのではなくて、配列を一気に送りたいかというと、今やっているのは、
5個の要素数を持つ配列 a(1)〜a(5) をファクションプロシージャに送って、そのファクションプロシージャの中で c(1)=a(1)+a(2), c(2)=a(1)+a(5) ・・・・c(5)=a(4)+a(3) 等々、配列の要素を組み合わせて、同じ数の要素数をもつ、a() を加工した配列 c() を作り、さらにそれを親プログラムに戻して、b(1),b(2),...,b(5) に入れたいのです。このとき、再びa() も必要になるので別名にする必要があるということです。
1次元配列や2次元配列の場合だったら、まず配列を一気に送って加工し、その配列 c(i,j) を一度Book を開いてデータを書き込み、サブプロシージャからそのbook名を返してこればやりたいことはできるのですが、最終的には3次元か4次元配列になりそうなので、それが面倒になりそうだからです。
もう一点、なぜサブプロシージャに送るかというと、今は親プログラム1本で非常に長いコードを書いてます。そのプログラムを友人に見せたところ「構造化プログラミングにしたほうがいいよ」と言われたからです。(私のつたない理解では、構造化プログラミングとは長いプログラムを、処理事にサブプログラムに分割してすっきりとしたプログラムにすることだと考えています。違ってるかもしれませんが・・・)
非常に長くなりましたが、趣旨はご理解いただけたでしょうか? まずはお答えいただいたプログラムを完全に理解するのが筋なのですが、取り急ぎお礼をしたかったため書き込みさせて頂いた次第です。明日ゆっくり勉強してみます。ありがとうございました m(__)m (ろっしい)
Dim n As Integer Dim hairetA(5) As Integer, hairetB(5) As Integer
Sub 親プログラム() Dim i As Integer '便宜上hairetAに入力しときます。 For i = 1 To 5 hairetA(i) = 5 * i Next ’Functionを実行させます。 keisan (hairetBの必要時書き込み) ’ここからは確認のための作業ですから不要 For i = 1 To 5 Cells(i, 1) = hairetB(i) Next i Cells(i - 1, 3) = hairetB(3) End Sub
For n = 1 To 5 Select Case n Case 1 keisan = hairetA(1) + hairetA(2) Case 2 keisan = hairetA(1) + hairetA(4) Case 3 keisan = hairetA(2) + hairetA(3) Case 4 keisan = hairetA(3) + hairetA(4) Case 5 keisan = hairetA(4) + hairetA(5) End Select hairetB(n) = keisan Next n End Function
こんにちは
>最終的には3次元か4次元配列になりそうなので、それが面倒になりそうだからです。
Dim hairetsu(5,5,5,5) As Integer とすれば625個、 Dim hairetsu(10,10,10,10) As Integer では10000個ものInteger型配列が 定義されるとおもいますが、そこまでの多次元配列が必要ですか?
おいぼれ弥太郎さん 私が書こうとおもったらすでに書き込まれていたのですが、せっかく作ったし 少し違うので一応書いておこうとおもったのです 間違いを指摘したつもりではないので、もし気を悪くされたのならすいませんでした。 ちなみに私も初心者ですよ (りな)
Integer型配列 → Integer型変数 の間違い (りな)
りなさんこんちわ
いえいえ、気ぃ悪うするなんてとんでもおまへん。私の文面、気ぃ悪うしたみたいに 見えたんやったらこっちこそごめんやで。 それどころか、あぁそんなあるんやなあと早速コピー取っときましたわ。初心者にと っては何もかも勉強ですさかいな、ええ。 ところで3次元とか4次元とかの配列の話になるとコラもう私の能力の範囲外でして 何やらお門違いの所へ首突っ込んだようで慚愧の至りですわ、ええ。 (気分こわしたんとちゃいまっせえ。念のため) おいぼれ弥太郎
みんな頑張ってますね。 勝手にロムろうと決めていたんですけど、ちょっとだけ参加〜
hairetsuをファンクションプロシージャに参照で渡し、 その戻り値をhairetsu_10に参照で戻すということで、 Variant型で配列のアドレスを受けるのが簡単です。 (ramrun)
Sub macro() Dim hairetsu(1 To 10) As Integer Dim hairetsu_10 As Variant For i = 1 To 10 hairetsu(i) = i Next i hairetsu_10 = fnc(hairetsu) For i = 1 To 10 Cells(i, 1).Value = hairetsu(i) Cells(i, 2).Value = hairetsu_10(i) Next i End Sub
Function fnc(ByRef hairetsu As Variant) As Variant Dim buf As Variant buf = hairetsu For i = 1 To 10 buf(i) = buf(i) * 10 Next i fnc = buf End Function
Sub 親() Dim hairetsu(1 To 5, 1 To 2) As Integer Dim i As Integer, n As Integer For i = 1 To 5 hairetsu(i, 1) = i Next i 子 hairetsu
For n = 1 To 2 For i = 1 To 5 Cells(i, n).Value = hairetsu(i, n) Next i Next n End Sub Sub 子(hairetsu) Dim j As Integer For j = 1 To 5 hairetsu(j, 2) = hairetsu(j, 1) * 10 Next j End Sub
これではダメでしょうか?
>いえいえ、気ぃ悪うするなんてとんでもおまへん。私の文面、気ぃ悪うしたみたいに >見えたんやったらこっちこそごめんやで。 ちょっと安心しました (りな)
<ramrunさん> さすが手練れ者、あっさり極上のコードを作られてしまいましたなぁ。 ByRefなんぞさわったこともおまへんから、早速コピーしてどんな働きをするのか黄色 のマークを何遍廻したやら... まだまだ理解でけてまへんが、見よう見まねで作り替えてみましたん。こんな使い方で どないでっしゃろか? いゃあ、ろっしいさんに適切な解答をつけるどころか、それに便乗してちゃっかり私 の為の教室に変えてしもたみたいで、なんや悪いような儲けたような(間違いなく後者 ,ろっしいさん御免)気がしますわ、ええ。 ところで、つかぬ事をお伺いしますが、皆さんCells(a,b)の後に.Valueと書いてまん なあ。あれって必要なんでっしゃろか?気になりまんねん。 1つの設問でこないに長いこと引っ張っとったらそのうちKazuさんにお小言ちょうだ いしそうでんなぁ。(おいぼれ弥太郎)(^^)
Dim hairetsu(1 To 5, 1 To 2) As Integer
Sub 親プログラム() Dim hairetsu_10 As Variant Dim i As Integer For i = 1 To 5 hairetsu(i, 1) = i * 5 Next x = True ' ここはセル参照するようにすればコードをいじらなくて済む hairetsu_10 = func(x, hairetsu) For n = 1 To 2 For i = 1 To 5 Cells(i, n).Value = hairetsu_10(i, n) Next i Next n
End Sub ---- Function func(ByVal x As Boolean, ByRef hairetsu As Variant) As Variant Dim y As Integer Dim buf As Variant If x = True Then y = 5 Else y = 10 End If buf = hairetsu For n = 1 To 5 Select Case n Case 1 buf(n, 2) = hairetsu(1, 1) + hairetsu(3, 1) * y Case 2 buf(n, 2) = hairetsu(2, 1) + hairetsu(4, 1) * y Case 3 buf(n, 2) = hairetsu(2, 1) + hairetsu(3, 1) + y Case 4 buf(n, 2) = hairetsu(3, 1) + hairetsu(4, 1) + y Case 5 buf(n, 2) = hairetsu(4, 1) + hairetsu(5, 1) + y * 2 End Select Next n func = buf End Function
わたしは .Valueを省略すると読みにくくなると思うんで省略しないんですよね あと、どっかのホームページにVBAでは省略しないほうが効率がいいみたいなこと書いてました。 ByRefは参照渡しを明示するためでしょう (りな)
そうですね、Cells(r,c).Value は入れるのが由緒正しいコードの書き方です。 省略してもきちんと動きます。 どちらにするかは、本人が決めればよいのです。 (kazu)
みなさん、本当にありがとうございました。色々勉強になりました。
まず、2次元配列や3次元配列が必要な背景は、現在仕事で会計上の項目が32個あって、その項目が12ヶ月分あり、さらに、部署ごとにシートになっていて、部署が4つあるデータを扱っていて、それが相互に関係する計算をする必要があって、それを一気に計算したいため、32×12×4 を組んでしまったのです。それが複数年度に渡る場合は4次元になりますが、いまのところは単年度ベースで良いみたいなので、3次元で収まっています(もっとスマートなやり方がありそうですが、なんか一気にやりたかったのです)。
さて、みなさんが書いてくださったコードを、一応自分でも一通りやってみて、最後に疑問が残ったことがあります。このままやっても問題なくプログラムは走るのですが、根本的に理解していないままやっていって、また同じような質問をするのは失礼かと思い、「聞くは一時の恥、聞かぬは一生の恥」と思い、一点だけ教えていただければ幸いです。
私は、以下のようなテストをしてみました。ByRef は今回初めて知ったのですが、ヘルプを参照したところ、ByVal の値渡しの方が、元々のデータを壊さなくて(私にとっては)ベターかなと思い、コードを書いてみました。
Sub macro()
Dim hairetsu(1 To 10) As Integer Dim hairetsu_10 As Variant Dim hairetsu_20 As Variant
For i = 1 To 10 hairetsu(i) = i Next i hairetsu_10 = fnc(hairetsu) hairetsu_20 = fnc_2(hairetsu)
For i = 1 To 10 Cells(i, 1).Value = hairetsu(i) Cells(i, 2).Value = hairetsu_10(i) Next i
For i = 1 To 10 Cells(i, 3).Value = hairetsu_20(i) Next i
End Sub
'Function fnc(ByRef hairetsu As Variant) As Variant 'コメント化してあります Function fnc(ByVal hairetsu As Variant) As Variant
Dim buf As Variant buf = hairetsu For i = 1 To 10 buf(i) = buf(i) * 10 Next i fnc = buf
End Function
'Function fnc_2(ByRef hairetsu As Variant) As Variant 'コメント化してあります
Function fnc_2(ByVal hairetsu As Variant) As Variant
'Dim buf As Variant 'コメント化してあります 'buf = hairetsu 'コメント化してあります For i = 1 To 10 'buf(i) = buf(i) * 10 'コメント化してあります hairetsu(i) = hairetsu(i) * 10 ' 自分なりに変えてみたところです Next i 'fnc = buf 'コメント化してあります func = hairetsu ' 自分なりに変えてみたところです End Function
fnc_2 で上手くいかないところが疑問点です。
私の理解では、fnc_2 に値渡しで送っているので、fnc_2 中の hairetsu は macro() 中の配列とは違ったもので、かつバリアント型なので動くかなぁと思ってやってみたのですが、やっぱり親プログラム macro() の中の hairetsu_20 に行った所で「型が一致しません」とエラーで止まりました。
何故、 buf のような他の配列に入れると上手くいって、そのままやってしまうと上手くいかないかが理解できずにいます。
質問ばっかりしていてお叱りを受けるかもしれませんが、これが解ると配列だけではなく、変数の型等の理解も深まると思い、恥を承知で最後のお願いにあがった次第です。よろしくお願いします m(__)m (ろっしい)
>ろっしいさんこんばんわ コードの書き間違いとちがいまっか?Function fnc_2のコードの最下行func=hairetsu はfnc_2=hairetsuでないとあかんのんちゃいまっか。書き換えたら動きましたでぇ。
>kazuさん、りなさん.Valueの件、早速のご返答おおきに。これからは私も由緒ある書 きかたを身につけるよう心がけますわ。kazuさん怒ってはらへんみたいで良かった良 かった。 りなさん、アンタ初心者を名乗るんは止めてくれしまへんか。でないとほんまの初 心者の立場がなくなりまんがな。(**)←これ怒った顔 おいぼれ弥太郎
間違えてました。お恥ずかしいです。穴があったら入りたいほどに・・・・・
ですが、こんなマヌケな質問にまで最後までお付き合いいただき、まことに感謝しています。
すべて解決してすっきりさわやかです。いろいろとありがとうございました。 m(__)m (ろっしい)
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.