Excel VBA質問箱 IV

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

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


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

【28571】引数の使い方 さくらんぼ 05/9/9(金) 13:02 質問[未読]
【28572】Re:引数の使い方 ちくたく 05/9/9(金) 13:08 回答[未読]
【28573】Re:引数の使い方 さくらんぼ 05/9/9(金) 13:32 質問[未読]
【28591】Re:引数の使い方 ちくたく 05/9/9(金) 16:25 発言[未読]
【28574】Re:引数の使い方 Jaka 05/9/9(金) 13:38 回答[未読]
【28590】Re:引数の使い方 さくらんぼ 05/9/9(金) 16:11 質問[未読]
【28596】Re:引数の使い方 Jaka 05/9/9(金) 17:09 発言[未読]
【28667】Re:引数の使い方 さくらんぼ 05/9/12(月) 16:07 質問[未読]
【28673】Re:引数の使い方 Jaka 05/9/12(月) 16:50 発言[未読]
【28674】Re:引数の使い方 小僧 05/9/12(月) 16:52 発言[未読]
【28680】Re:引数の使い方 でれすけ 05/9/12(月) 20:43 発言[未読]
【28764】Re:引数の使い方 さくらんぼ 05/9/14(水) 10:07 お礼[未読]
【28808】Re:引数の使い方 ichinose 05/9/15(木) 9:03 発言[未読]
【28809】Re:引数の使い方 さくらんぼ 05/9/15(木) 9:18 お礼[未読]
【28670】Re:引数の使い方 小僧 05/9/12(月) 16:41 発言[未読]
【28594】Re:引数の使い方 でれすけ 05/9/9(金) 17:04 回答[未読]
【28665】Re:引数の使い方 さくらんぼ 05/9/12(月) 15:46 お礼[未読]

【28571】引数の使い方
質問  さくらんぼ  - 05/9/9(金) 13:02 -

引用なし
パスワード
   またお邪魔します。
引数の使い方について教えて下さい。

ユーザーフォームにあるPrivate Subの中で使った引数の値を、標準モジュールで使いたいのですが、うまくいきません。


Dim i1, i2 As Integer

Private Sub CommandButton2_Click()
 処理
  i1= ある値X
  i2= ある値Y
  
  call 処理2

という感じで、標準モジュールの中にある処理2の中でi1やi2を使いたいのですが、エラーになります。
i1もi2もemptyの状態です。
どうすればよいのでしょう?教えて下さい。

【28572】Re:引数の使い方
回答  ちくたく  - 05/9/9(金) 13:08 -

引用なし
パスワード
   さくらんぼ さん
こんにちは。

>ユーザーフォームにあるPrivate Subの中で使った引数の値を、標準モジュールで使いたいのですが、うまくいきません。

基本的にはsub~end subで変数はクリアされます。

>  i1= ある値X
>  i2= ある値Y

考えるのが面倒なので、私はいつも、
新しいシートを作ったりして(Set dbWs = Worksheets.Add)、
そこに、変数の値を保持します。
dbWs.Range("A1").Value = "i1の値"
dbWs.Range("B1").Value = i1

【28573】Re:引数の使い方
質問  さくらんぼ  - 05/9/9(金) 13:32 -

引用なし
パスワード
   ありがとうございます。
ただ、sub~end subでクリアされない変数の宣言があったと思うのですが…。
sub~end subの外で宣言すれば、全処理が終了するまで、その値を保つというようなのを、どこかで読んだと思うのです。
処理を簡潔にしたいので、できればそのままの変数を使いたいのですが…。

【28574】Re:引数の使い方
回答  Jaka  - 05/9/9(金) 13:38 -

引用なし
パスワード
   こんにちは。

Private Sub CommandButton2_Click()
Dim i1 As Long, i2 As Long 'Callの場合は、引渡し先と同じ型の宣言
 '処理
  i1 = 1 'ある値X
  i2 = 2 'ある値Y
 
  Call 処理2(i1, i2)
  MsgBox i1 & "-" & i2
End Sub

Sub 処理2(a1 As Long, a2 As Long)
       ' ↑     ↑ 同じ型の宣言
  a1 = a1 + 1
  a2 = a2 + 1
End Sub

また、標準モジュールで、グローバル変数として宣言すれば、どこのモジュールからでも共通変数として使えます。
因みにモジュール天辺に書きます。

Public i1 As Long, i2 As Long

【28590】Re:引数の使い方
質問  さくらんぼ  - 05/9/9(金) 16:11 -

引用なし
パスワード
   Jaka さん:
ありがとうございます。

>  Call 処理2(i1, i2)

このパターンではできるようになりました。
でも、グローバル変数でやろうとすると、うまくいきません。
今後のために教えて下さい。

標準モジュールの最初に

Public i1 As Long, i2 As Long

等のようにPublicで宣言するだけで、他のモジュールやPrivate subではどうすればよいのでしょうか。
何も書かないとPrivate Sub内で「型が違う」等のエラーが出ます。
また、標準モジュールも数個あり、どこの天辺に書くのか、わかりません。
試しにいろいろやってみたのですが、うまく引き渡しできていません。

【28591】Re:引数の使い方
発言  ちくたく  - 05/9/9(金) 16:25 -

引用なし
パスワード
   横から失礼致します。

http://www.accessclub.jp/vba/vba_014.htm

ここらへんも参考になるかと。

【28594】Re:引数の使い方
回答  でれすけ  - 05/9/9(金) 17:04 -

引用なし
パスワード
   こんにちは。

>Dim i1, i2 As Integer
まず、VB/VBAでは1つの変数毎に型を記述しないといけません。
上の書き方では、i1に対する型が省略されているとみなされ、
i1の型はVariantになります。


Dim i1 as Integer, i2 As Integer

Private Sub CommandButton2_Click()
 処理
  i1= ある値X
  i2= ある値Y
  
 call 処理2(i1,i2)

Callするときには引数を渡してあげましょう。

標準モジュールでは、
Public Sub 処理2(i1 as Integer,i2 as Integer)
のように、処理2を定義します。
(処理2側では、変数名をi1,i2としなくてもよいです。)

【28596】Re:引数の使い方
発言  Jaka  - 05/9/9(金) 17:09 -

引用なし
パスワード
   Public P1 As Long, P2 As Long
'どの標準モジュールに書いてもかまいませんが、全モジュール通して1個だけ。

Private Sub main()
aaaaa
bbbbb
ccccc
End Sub

'下の Private Sub は、上と同モジュールに書いてください。
'他モジュールに書きたいのなら、Private を取ってください。
Private Sub aaaaa()
  P1 = 1
  P2 = 10
End Sub

Private Sub bbbbb()
  P1 = P1 + P1
  P2 = P2 + P2
End Sub

Private Sub ccccc()
  MsgBox P1
  MsgBox P2
End Sub

'--------------------------
Sub 最後に単体で実行してみる() '他モジュールでもかまいません。
  MsgBox P1        'しつこく保持しているのが解る?
  MsgBox P2
End Sub

グローバル変数は、意外としつこく保持しているみたいですが、
いつ何時、内容が失われるか解りません。
前にテストした時に5時間後ぐらいに「最後に単体で実行してみる」を実行してみたら、まだ保持していた。
その間、エクセルやそのブックは閉じませんでしたが、インターネット、同エクセル内の他ブックにてVBA回答用のテストなどをしていたにもかかわらず。
エクセルVarによっても違うでしょうが、過信は出来ません。by97
変数が内容を保持しているとおもって、時間がたってから変数の内容を当てにして、単体で実行するコードを書くのは、止めた方が良いです。(意味が通じるかなぁ?)

1度覗いてみてください。
http://www.vbalab.net/vbaqa/c-board.cgi?cmd=ntr;tree=7011;id=excel

【28665】Re:引数の使い方
お礼  さくらんぼ  - 05/9/12(月) 15:46 -

引用なし
パスワード
   ▼でれすけ さん:

ありがとうございます。

>>Dim i1, i2 As Integer
>まず、VB/VBAでは1つの変数毎に型を記述しないといけません。
>上の書き方では、i1に対する型が省略されているとみなされ、
>i1の型はVariantになります。

そうでしたか。まとめて記述できると思ってました。ありがとうございます。


>Callするときには引数を渡してあげましょう。

Callを使っての処理はできるようになりました。

【28667】Re:引数の使い方
質問  さくらんぼ  - 05/9/12(月) 16:07 -

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

ありがとございます。

>Public P1 As Long, P2 As Long
>'どの標準モジュールに書いてもかまいませんが、全モジュール通して1個だけ。


この方法でやろうとすると、どうしてもうまく引き渡せません。

-------------
*** UserForm1の中 ***

Private Sub CommandButton2_Click() 
 (ここでのi1,i2の宣言無し)

  i1=ある値X
  i2=ある値Y
  Call 処理2 (標準モジュール)(i1,i2の値使用)

End Sub

--------------

*** 標準モジュールのうちの1つ ***

Public i1 As Integer, i2 As Integer

Sub 処理2

 i1,i2を使った処理

End Sub

---------------

簡単にまとめるとこんな感じになっているのですが、'Private Sub' ではi1,i2に値が入っているのに、'Sub 処理2'に移ったときには'0'となっています。
この間、時間もたっていません。
教えていただいたhpも見てみましたが、よくわかりませんでした。
Callを使う方法を教えてもらって、処理としてはできるようになったのですが、やはり今後のためにグローバル変数についても知っておきたいし、このままではどうしてもすっきりしないので、どこが間違っているのか教えてください。

【28670】Re:引数の使い方
発言  小僧  - 05/9/12(月) 16:41 -

引用なし
パスワード
   ▼さくらんぼさん、みなさま:
こんにちは。

リンク先を色々と眺めていたのですが、載っていなかったようなので
ここも参照してあげて下さい。

(当方の見落としでしたらすみません。)

http://support.microsoft.com/default.aspx?scid=kb;ja;408871

【28673】Re:引数の使い方
発言  Jaka  - 05/9/12(月) 16:50 -

引用なし
パスワード
   >この方法でやろうとすると、どうしてもうまく引き渡せません。
え〜と、引き渡すんじゃなくてグローバル変数に入れておくだけです。
今一状況がつかめないので、新規ブックにて試してみてください。


標準モジュール

Public p1 As Integer, p2 As Integer

Sub aaa()
  UserForm1.Show
  MsgBox p1
  MsgBox p2
End Sub

Sub bbbb()
  p1 = p1 * 2
  p2 = p2 * 2
End Sub

----------------
フォームモジュール

Private Sub CommandButton1_Click()
  p1 = 10
  p2 = 1000
  bbbb
  Unload Me
End Sub

【28674】Re:引数の使い方
発言  小僧  - 05/9/12(月) 16:52 -

引用なし
パスワード
   ▼さくらんぼ さん、みなさま:
こんにちは。

>簡単にまとめるとこんな感じ

'ユーザフォームに
Private Sub CommandButton1_Click()
  i1 = 1
  i2 = 3
  Call 処理2  '(標準モジュール)(i1,i2の値使用)
End Sub

'モジュールに
Sub 処理2()
  MsgBox i1 & "  " & i2
End Sub

思いっきり簡単にしましたが、メッセージボックスに「1 3」と表示されました。
(当方の環境 WinXP Excel2002 SP3)


まとめてしまった所に何かワナが隠れている(かも)しれません。

【28680】Re:引数の使い方
発言  でれすけ  - 05/9/12(月) 20:43 -

引用なし
パスワード
   こんばんわ

標準モジュールとユーザフォームのモジュールの先頭に
Option Explicit
を書いて実行してみてください。
変数が定義されていませんというエラーが出たら、
変数のスコープがあっていません。

CommandButton2_Clickプロシジャーの
>  i1=ある値X
>  i2=ある値Y
のところで、変数名を選択して、右クリックして、
[定義]を選んでください。
それで、標準モジュールのi1,i2の定義部分にジャンプすればOKなんですが。

ちなみに、Callで呼び出す場合において、グローバル変数で値を渡す方法は
私はあまり推奨しません。

【28764】Re:引数の使い方
お礼  さくらんぼ  - 05/9/14(水) 10:07 -

引用なし
パスワード
   みなさま、本当にどうもありがとうございました。
おかげさまで、できるようになりました。


>ちなみに、Callで呼び出す場合において、グローバル変数で値を渡す方法は
>私はあまり推奨しません。
 ↑
最後に、なぜ推奨できないのか教えていただければ嬉しいです。

【28808】Re:引数の使い方
発言  ichinose  - 05/9/15(木) 9:03 -

引用なし
パスワード
   ▼さくらんぼ さん:
おはようございます。

>みなさま、本当にどうもありがとうございました。
>おかげさまで、できるようになりました。
>
>
>>ちなみに、Callで呼び出す場合において、グローバル変数で値を渡す方法は
>>私はあまり推奨しません。
> ↑
>最後に、なぜ推奨できないのか教えていただければ嬉しいです。

私も「グローバル変数で値を渡す方法」は推奨しません。


それは、コードをトレース(特に他人の書いたコードを読むと実感します)する場合、
「パラメータ渡しの方法」がわかりやすい手続きですし
(どの変数が引数として使われているかということがわかりやすい)、
又、何らかの原因でコードの修正を求められた時に「グローバル変数で値を渡す方法」よりも「パラメータ渡しの方法」がよりミスの少ない修正が可能だと思うからです。

VBAでは、プロシジャー間のパラメータ渡しが可能になっていますが、
他言語で、これが出来ない仕様の言語を経験したことがあります。
泣く泣くグローバル変数渡しを使うのですが、この場合は、コメントも詳細に記述しなければなりませんでした。

Sub main()
  A=3
  B=5
  Call tashizan()
  Msgbox C
End sub

別の標準モジュール


Public A as long
  Public B as long
  Public C as long
‘====================================================
Sub tashizan()
  C=A+B
End sub

この例でもtashizanというプロシジャーに対して、
A,B,Cが引数であるというコメントがないと
時間が経てばわからなくなってしまうと思いませんか?
また、この場合、引数としての変数名はA,B,Cと固定の手続きになってしまい、
コードの柔軟性という観点からも「パラメータ渡しの方法」が望ましいと思います。

Sub main()
  Dim myvalue1 as long
  Dim myvalue2 as long
  Dim ans as long
  Myvalue1=3
  Myvalue2=5
  Call tashizan(Myvalue1,Myvalue2,ans)
  Msgbox ans
End sub

別の標準モジュール

‘====================================================
Sub tashizan(Hensu1 as long ,Hensu2 as long,Kotae as long)
  Kotae = Hensu1+ Hensu2
End sub

というようにパラメータ渡しの方が「引数の行方が明確になっている手続き」だと思います。
コードが複雑になったものであれば、
この違いがメンテナンスを行うにあたって大きいと思いますよ。

一昔前のプログラマだった(今は違いますが)私の世代では、
「マイヤーズの複合設計法」という手法をとおしてこういう事は
学んだ記憶があります(当時は結構有名だったと思います)。

まっ、買うことはないと思いますが、図書館などで見つけたなら一読してみては?

【28809】Re:引数の使い方
お礼  さくらんぼ  - 05/9/15(木) 9:18 -

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

ありがとうございます。
納得です。すごくよくわかりました。
確かに他の人が書いたコードを読むのは苦労しますよね。
自分の書いたものでも、時間が経てばよくわからなくなってくる…。
現在、たまーにしかVBAを使わない私にとって、久しぶりに見ると???となってしまいます。
グローバル変数もなんとか解決した上で、「パラメータ渡しの方法」でコードは残そうと思います。
どうもありがとうございました。

私も一昔前(二昔前?)にSEの経験があるのですが、「マイヤーズの複合設計法」は聞いたことがないです。勉強不足ですみません。

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