Excel (VBA)

Excel VBAに関するフォーラムです。
  • 解決済みのトピックにはコメントできません。
このトピックは解決済みです。
質問

 
(指定なし : 指定なし)
Functionプロシージャの書き方
投稿日時: 24/10/22 00:51:08
投稿者: けけちゃま

ここ最近、質問立て続けで申し訳ございません。。。
 
VBAフォームモジュールの質問です。
 
  
 
【フォームの説明】
・OptionButton1→隣に TextBox1 & ComboBox1
・OptionButton2→隣に TextBox2
  
 
【プロパティ設定】
TextBox1 & TextBox2 & ComboBox1
Enabled = False
BackColor = &H80000000(灰色)
 
  
【やりたいこと】
OptionButton1をクリックしたら、TextBox1とComboBox1は編集可能にしバックカラーを白(&H80000005)にする。TextBox2は編集不可にしバックカラーを灰色にする。
OptionButton2をクリックしたら、TextBox2は編集可能にしバックカラーを白にする。TextBox1とComboBox1は編集不可にしバックカラーを灰色(&H80000000)にする。
  
 
【今まで私のコード】

Option Explicit
Private Sub OptionButton1_Click()
            ComboBox1.Enabled = True
            ComboBox1.BackColor = &H80000005
            TextBox1.Enabled = True
            TextBox1.BackColor = &H80000005
            TextBox2.Enabled = False
            TextBox2.BackColor = &H80000000
End Sub

Private Sub OptionButton2_Click()
            ComboBox1.Enabled = False
            ComboBox1.BackColor = &H80000000
            TextBox1.Enabled = False
            TextBox1.BackColor = &H80000000
            TextBox2.Enabled = True
            TextBox2.BackColor = &H80000005
End Sub

  
これを、Functionプロシージャーをつかって簡素化できないものかと考えております。
本当にFunctionプロシージャーが意味不明すぎて参考書みながら書いてみたのですが、、、
 
【実験1】
 
'funk(arg)の値がTrueであれば、argは、「Enabled = True(編集可)」「BackColor = &H80000005(白色)」になる。
'funk(arg)の値がFalseであれば、argは、「Enabled = False(編集不可)」「BackColor = &H80000000(灰色)」になる。


 Public Function funk(arg As String) As Boolean
        If funk(arg) = True Then
            arg.Enabled = True
            arg.BackColor = &H80000005
        Else
            arg.Enabled = False
            arg.BackColor = &H80000000
        End If
End Function

Private Sub OptionButton1_Click()
        funk(TextBox1) = True
        funk(ComboBox1) = True
        funk(TextBox2) = False
End Sub
 

Private Sub OptionButton2_Click()
        funk(TextBox1) = False
        funk(ComboBox1) = False
        funk(TextBox) = False
End Sub

 
結果:
コンパイルエラー:代入式の左辺の関数呼び出しは、バリアント型またはオブジェクト型の値を返さなければなりません。
  
 
【実験2】ifとか書くからだめなのか?2つのわけるか?
 
 
'funk(arg)の値がTrueであれば、argは、「Enabled = True(編集可)」「BackColor = &H80000005(白色)」になる。
'funk(arg)の値がFalseであれば、argは、「Enabled = False(編集不可)」「BackColor = &H80000000(灰色)」になる。

Public Function funk(arg As String) As Boolean
            arg.Enabled = True
            arg.BackColor = &H80000005
End Function
 
Public Function funk2(arg As String) As Boolean
            arg.Enabled = False
            arg.BackColor = &H80000000
End Function

 
Private Sub OptionButton1_Click()
        funk(TextBox1) = True
        funk(ComboBox1) = True
        funk2(TextBox2) = False
End Sub
 
Private Sub OptionButton2_Click()
        funk(TextBox2) = True
        funk2(TextBox1) = False
        funk2(ComboBox1) = False
End Sub

 
  
結果:
コンパイルエラー:代入式の左辺の関数呼び出しは、バリアント型またはオブジェクト型の値を返さなければなりません。
  
 
Functionプロシージャーって要は自分のオリジナル関数を作るってことだと理解しているのですが、
だったら、「funk()」って関数を作って、()に指定した引き数のEnabledやBackColor を操作したいのですが・・・。
  
 
本当にFunctionプロシージャーが苦手すぎて、【今まで私のコード】みたいに書いていたのですが、OptionButtonなどのコントロール?が多くなってきていよいよしんどくなってきたので、もしかしてFunctionが使えるのでは?!と思ったのですが・・・それはやはり無理なのか、
精一杯考えて上記のコードで、私の頭がバグってきました。
 
私のコードが間違っているのか・・・本当こんなレベルで申し訳ございませんが、どなたかご教示いただけないでしょうか。(全然ヒントレベルでも大丈夫です)
 
 

回答
投稿日時: 24/10/22 06:12:44
投稿者: simple

コード簡素化の一例を挙げてみます。参考にしてください。
 

Private Sub OptionButton1_Click()
    setEnableTrue ComboBox1, TextBox1
    setEnableFalse TextBox2
End Sub

Private Sub OptionButton2_Click()
    setEnableTrue TextBox2
    setEnableFalse ComboBox1, TextBox1
End Sub

'ヘルパー用プロシージャ
Private Sub setEnableTrue(ParamArray objs() As Variant)
    Dim k&
    For k = LBound(objs) To UBound(objs)
        objs(k).Enabled = True
        objs(k).BackColor = &H80000005
    Next
End Sub
Private Sub setEnableFalse(ParamArray objs() As Variant)
    Dim k&
    For k = LBound(objs) To UBound(objs)
        objs(k).Enabled = False
        objs(k).BackColor = &H80000000
    Next
End Sub
# (さらに一つに纏めて、True,Falseを引数にする手もあるかもしれません。)
 
【以下余談です。】(お急ぎのかたはスキップください。)
6行もある空白改行を間に挟むという、私の長い質問掲示板閲覧歴のなかで初めてみるスタイルに驚愕しました。
迷妄から覚められたようで結構なことです。
 
コードと言うのは意味の纏まりごとに、ある程度固めて書くのが読みやすいと思います。
これから書くかも知れないコメントのために6行空行挿入をされたようですけど、
将来に備えて無駄な空行を入れる必要はありません。必要な時に入れればよいでしょう。
こうした場面でそういうスタイルを使ったとしても、読んでもらえないだけなので、大したロスは
ありませんが、ご自分にとって読みにくく、能率低下を来すことを懸念しておりました。
(なお、"過剰なコメント"は却ってコードの流れを断ち切ってしまうので、真に必要なコメントに限定するのが要諦です。
  このあたり、「リーダブルコード」などという本を立ち読みされるとよいでしょう。)

回答
投稿日時: 24/10/22 10:26:35
投稿者: WinArrow

 
↓のようなことをしたいのではないですか?
 

Option Explicit
'
'Public Function funk(arg As String) As Boolean
'        If funk(arg) = True Then
'            arg.Enabled = True
'            arg.BackColor = &H80000005
'        Else
'            arg.Enabled = False
'            arg.BackColor = &H80000000
'        End If
'End Function
  ↓
Private Sub funk(ByRef arg1 As MSForms.Control, ByVal arg2 As Boolean)
    With arg1
        If arg2 Then
            .Enabled = True
            .BackColor = &H80000005
        Else
            .Enabled = False
            .BackColor = &H80000000
        End If
    End With
End Sub

'Private Sub OptionButton1_Click()
'        funk(TextBox1) = True
'        funk(ComboBox1) = True
'        funk(TextBox2) = False
'End Sub
  ↓
Private Sub OptionButton1_Click()
        Call funk(arg1:=TextBox1, arg2:=True)
        Call funk(arg1:=ComboBox1, arg2:=True)
        Call funk(arg1:=TextBox2, arg2:=False)
End Sub

'Private Sub OptionButton2_Click()
'        funk(TextBox1) = False
'        funk(ComboBox1) = False
'        funk(TextBox) = False
'End Sub
  ↓
Private Sub OptionButton2_Click()
        Call funk(arg1:=TextBox1, arg2:=False)
        Call funk(arg1:=ComboBox1, arg2:=False)
        Call funk(arg1:=TextBox2, arg2:=True)
End Sub

回答
投稿日時: 24/10/22 10:53:49
投稿者: sk

複数ある「オプションボタン/テキストボックス/コンボボックスの組み合わせ」に対して
共通のイベント処理を実装したい、という意味でおっしゃっているのであれば、
とりあえずクラスモジュールの使用を検討されることをお奨めします。

回答
投稿日時: 24/10/22 11:22:21
投稿者: mattuwan44

>結果:
>コンパイルエラー:代入式の左辺の関数呼び出しは、バリアント型またはオブジェクト型の値を返さなければなりません。

 
> Public Function funk(arg As String) As Boolean
 
>funk(TextBox1) = True
 
関数は、何かを与えると何かの答えを返すものです。
 
文法的には、
括弧の中に受け取るもの、括弧の外に返すものを書いてください。
 
受け取るものを文字列型にしているけど、与える方はオブジェクトになっているよというエラーです。
 

Option Explicit

'コントロールを「名前(文字列)]で受け取る
Public Function funk(ByVal arg As String, ByVal flg As Boolean) As Boolean
    With Controls(arg)
        If flg = True Then
            .Enabled = True
            .BackColor = &H80000005
        Else
            .Enabled = False
            .BackColor = &H80000000
        End If
    End With
End Function

'コントロールを「オブジェクト」で受け取る
Public Function funk2(ByRef arg As MSForms.Control, ByVal flg As Boolean) As Boolean
    If flg = True Then
        arg.Enabled = True
        arg.BackColor = &H80000005
    Else
        arg.Enabled = False
        arg.BackColor = &H80000000
    End If
End Function

Private Sub OptionButton1_Click()
    Stop
    funk TextBox1.Name, True
    funk ComboBox1.Name, True
    funk TextBox2.Name, False
End Sub

Private Sub OptionButton2_Click()
    funk2 TextBox1, False
    funk2 ComboBox1, False
    funk2 TextBox2, True
End Sub

 
こんな感じでエラーがなくなると思います。
まとめる案は時間ができたらなんか考えようと思います。

回答
投稿日時: 24/10/22 11:42:06
投稿者: gombohori

 OptionButtonのChangeイベントを使うべきだと思いますよ
 

 Private Sub OptionButton1_Change()
   SetEnable Me.TextBox1, Me.OptionButton1.value
   SetEnable Me.ComboBox1, Me.OptionButton1.value
 End Sub

 Private Sub OptionButton2_Change()
   SetEnable Me.TextBox2, Me.OptionButton2.value
 End Sub

 Function SetEnable(ByRef c As MSForms.Control, value As Boolean)
   c.Enabled = value
   c.BackColor = IIf(value, &H80000005, &H80000000)
 End Function

回答
投稿日時: 24/10/22 11:48:44
投稿者: mattuwan44

>受け取るものを文字列型にしているけど、与える方はオブジェクトになっているよというエラーです。
 
あ、説明を間違ってます^^;無視してください。

回答
投稿日時: 24/10/22 11:57:21
投稿者: gombohori

 こんな書き方をしたいのかな?


 Private Sub OptionButton1_Change()
    SetEnable(Me.TextBox1) = Me.OptionButton1.Value
    SetEnable(Me.ComboBox1) = Me.OptionButton1.Value
 End Sub
 Private Sub OptionButton2_Change()
    SetEnable(Me.TextBox2) = Me.OptionButton2.Value
 End Sub
 Private Property Let SetEnable(ByRef c As MSForms.Control, newValue As Boolean)
    c.Enabled = newValue
    c.BackColor = IIf(newValue, &H80000005, &H80000000)
 End Property

回答
投稿日時: 24/10/22 13:52:26
投稿者: mattuwan44

Option Explicit

Private Sub OptionButton1_Click()
    SetEnabled 1
End Sub

Private Sub OptionButton2_Click()
    SetEnabled 2
End Sub

Private Sub SetEnabled(ByVal i As Long)
    Dim c As MSForms.Control
    Dim j As Long
    
    For Each c In Controls
        Select Case TypeName(c)
            Case "TextBox", "ComboBox"
                j = StrReverse(Val(StrReverse(c.Name)))
                c.Enabled = IIf(i = j, True, False)
                c.BackColor = IIf(i = j, &H80000005, &H80000000)
            Case Else
        End Select
    Next
End Sub

 
今回の例だと、Functionプロシージャの練習には向かないかもです。
やるなら、IIF関数とかStrReverse関数とかを自作してみてはいかがでしょうか?
それらも、中身は見れないですが、誰かが作ったプログラムなので、
自分で作ってみてもOKです。(新たに作る意味はないですが^^;)
 
>ここ最近、質問立て続けで申し訳ございません。。。
全然大丈夫かと^^
自分も掲示板で質問しまくって覚えたので^^

投稿日時: 24/10/22 15:31:23
投稿者: けけちゃま

simple様
WinArrow様
sk様
mattuwan44様
gombohori様
 
ひぃーー、皆様ありがとうございます泣
一旦内容を確認させていただくのでしばしお返事にお時間をいただけますでしょうか・・。
 
当方のレベル
クラスモジュールまったく不明(ここ最近になって興味をしめしネットで検索するとまずファンクションプロシージャを使いこなせるようになるべきとかかれていたので、いまこちらにフォーカスを置いている感じです)
call を使ってSubプロシージャを呼び出すことはできるんですが、ファンクションってなんか全然Subプロシージャとレベルが段違いと悟り今まで回避していた感じです。。
(一応、VBAエキスパートは数年前に受かってはいるのですが・・・まぁ実際かかないとなかなか実務に生かせないですよね・・)
 
あとは、仕事は、全然7でSE系でもなんでもないです(質問のレベルから察して頂いているかと思いますが爆)

回答
投稿日時: 24/10/22 20:19:39
投稿者: WinArrow

引用:
OptionButtonのChangeイベントを使うべきだと思いますよ

の注意事項(落とし穴)
 
1回目
OptionButton1 クリック時、
    OptionButton1.Value は「TRUE」になる・・・Changeイベント発生
    OptionButton2.Value は「Flse」変化しない Changeイベント発生しない
2回目
OptionButton2 クリック時、
    OptionButton1.Value は「False」になる・・・Changeイベント発生する
    OptionButton2.Value は「True」変化する Changeイベント発生する
 
というわけで、TrueでもFalseでもイベントが発生するので、
If OptionButton1.Value = lrue Then
が必要です。

回答
投稿日時: 24/10/22 21:14:30
投稿者: gombohori

 >というわけで、TrueでもFalseでもイベントが発生するので、
 デザイン時のプロパティの設定次第です
 TextBox2のEnabledがTrueなら当然 OptionButton2のValueもTrueにしておくべきです
 TrueでもFalseでもイベントが発生するのが、いいところでしょう
 
 >If OptionButton1.Value = lrue Then
 >が必要です。
 不要でしょう
 
  

投稿日時: 24/10/22 23:22:42
投稿者: けけちゃま

simple様
 
確認できました!
コードだけでみると、ParamArrayってなんだ?から入り、心折れけましたが、
調べてF8でみたらイメージわきました!(複数を引数にするって感じ?のやつなんですね)
 
 
ファンクションがなくても、サブプロシージャーに引数つければこんなことができるんですね。(自分で作るサブプロシージャーは毎度引数なしでした。)
 
これなら私でも時間をかければ頑張って今後も応用編ができるかも?と思いました。(いや多分相当頑張らないとだめですが)
 
 
そして、プロシージャーの命名が超わかりやすかったです。
「リーダブルコード」ですね!
書籍のおすすめ、めちゃくちゃありがたいです!
ネットでいまチラってみましたが、私もプロシージャや変数のネーミングに毎回悩んでは、利用するときに「なんだっけこのプロシージャ」ってなっていた気がします(汗)。
 
よんでみます。(そもそも私がもっている参考書って、KENスクールでつかっていたスクール専用教科書なので、もっとコード実務的な本を読むべきかもしれませんね‥なんかいい本あれば‥)
 
毎度心得的なものも教えていただきハッとさせられます、ありがとうございます><。
 
 
【他の皆様、コメント返信もう少しお時間ください・・泣 ※自分の知らない(多分聞いたことがあるけど、理解できてない)単語がありすぎて、愕然中ですが、調べまくってます】

回答
投稿日時: 24/10/23 02:28:37
投稿者: hatena
投稿者のウェブサイトに移動

VBAにはいろいろな機能がありますが、その機能を理解して適切な場所で適切な方法で使う必要があります。
 
プロシージャにはSubプロシージャとFunctionプロシージャがありますが、下記の違いがあります。
Subは特定の処理を実行する。
Functionは特定の処理を実行した後、結果を値として返す。
 
今回の質問の要件は、オプションボタンの値によって、テキストボックスとコンボボックスのEnabledとBackColorを変化させる、という処理です。
結果を値として返す必要がないのでFunctionである必要はありません。
 
複雑な処理で場合によっては失敗することがあり、処理が成功したか失敗したかによって以降の処理が変わるというような場合ではFunctionにしますが、今回はそのような必要もないでしょう。
 
----
オプションボタンですが、複数のオプションから一つを選択するという機能を持つものです。
 
質問のコードでは、オプションボタンのクリック時にすべてのテキストボックス、コンボボックスのプロパティを変更するというコードを書いてますが、この書き方だとオプションや関連付けられるコントロールが多くなると、それにつれてコードが複雑化します。
 
一つのオプションをクリックすると選択されてChangeイベントが発生し、選択が解除されたオプションでもChangeイベントが発生します。
Changeイベントを利用すると関連付けられたコントロールのプロパティを変更するだけで済みます。
 
---
オプションボタンに複数のコントロールを関連付ける場合、可変数の引数をとることができるParamArrayステートメントをうまく使うとコードを簡素化できます。
 
すでにいろいろなコード例が出ていておなかいっぱいだと思いますが、一例を置いておきます。
 

Private Sub OptionButton1_Change()
    SetEnabled Me.OptionButton1, Me.TextBox1, Me.ComboBox1
End Sub

Private Sub OptionButton2_Change()
    SetEnabled Me.OptionButton2, Me.TextBox2
End Sub

Private Sub SetEnabled(OptBtn As MSForms.OptionButton, ParamArray LinkCtls() As Variant)
    Dim ctl As Variant
    For Each ctl In LinkCtls
        ctl.Enabled = OptBtn.Value
        ctl.BackColor = IIf(OptBtn.Value, &H80000005, &H80000000)
    Next
End 

投稿日時: 24/10/24 20:47:08
投稿者: けけちゃま

WinArrow様
ありがとうございます泣
確認しました!。
文法的にいうと、
 
arg1のコントロールにおいて…
arg2がTrueであれば (If arg2 Thenって、If arg2=True Then と同じですよね うんきっとそうだ‥)
arg1.Enabled = True
arg1.BackColor = &H80000005
 
arg2がTrue以外であれば(つまりFalse)
arg2.Enabled = True
arg2.BackColor = &H80000005
ってことですね・・!
 
(simple様がいっていた、# (さらに一つに纏めて、rue,Falseを引数にする手もあるかもしれません。ってやつがこやつですね!)
  
(ByRef arg1 As MSForms.Control, ByVal arg2 As Boolean)
ByRefとか ByVal(参照渡し、値渡し?)の理解は時間をかけて解読します。
 
AS  MSForms.Control がよくわからなくて(よく見てみると、自動作成のBeforeUpdateイベントプロシージャにも似たようなものありますね)まずはこれを勉強しないと今後も壁にぶちあたりそうなので精進します。
 
(ネットでしらべるとクラスモジュール前提のものばかりで、どこの理解から進めればいいか迷走しておりますがなんとかやってみます T_T)
 
  
 
sk様
ありがとうございます泣
クラスモジュールは全く知識ないのですが、色々調べているうちに、噂ではだいぶ便利な機能な気がしてなりませぬ・・。
クラスモジュールぜひ理解を深めていきたいと思います(引数付きのプロシージャー作成に慣れてからの方がいいのかなと自分で思ってます)
 
  
 
mattuwan44様
前回に引き続き、ありがとうございます泣泣
なんとなく、上から皆様のコメント見ているうちにAs MSForms.Controlの意味がわかりそうです(←理屈はわからないけど感覚的に!
 
Public Function funk(ByVal arg As String, ByVal flg As Boolean) As Boolean
 
の最後のAs Booleanがやはり何を返しているのかがわからず、まさかと思い、下記Subに改造して下記でもやってみたら同じく起動しました!
 
24/10/22 13:52:26のコメントも確認しました。
本件の例はやはり、ファンクションプロシージャーには向かなさそうな感じは私も皆様のコメントをみているうちに察しました爆。
 
でも文法的を入れていただけることで理解力増しました!ありがとうございます!
'コントロールを「名前(文字列)]で受け取る
 

Public Sub funk(ByVal arg As String, ByVal flg As Boolean)
    With Controls(arg)
        If flg = True Then
            .Enabled = True
            .BackColor = &H80000005
        Else
            .Enabled = False
            .BackColor = &H80000000
        End If
    End With
End Sub
 
'コントロールを「オブジェクト」で受け取る
Public Sub funk2(ByRef arg As MSForms.Control, ByVal flg As Boolean)
    If flg = True Then
        arg.Enabled = True
        arg.BackColor = &H80000005
    Else
        arg.Enabled = False
        arg.BackColor = &H80000000
    End If
End Sub

 Private Sub OptionButton1_Click()
'    Stop
    funk TextBox1.Name, True
    funk ComboBox1.Name, True
    funk TextBox2.Name, False
End Sub
 
Private Sub OptionButton2_Click()
    funk2 TextBox1, False
    funk2 ComboBox1, False
    funk2 TextBox2, True
End Sub

  
 
2つめのコード
For Each c In Controls
ってフォームにあるすべてコントロールの数分繰り返すってことだと、コントロールが多くなると負担かかるものですかね。
(いや、まさかフレームで囲った範囲だけ?そうだったらいいな・・)
参考書みてもファンクションプロシージャーじゃないとできない!っていうコードがよくわからなったのですが、IIF関数・StrReverse関数について調べてみますね!ありがとうございます泣
 
(お優しいことばも添えていただき感涙にむせびます)
 
 
【gombohori様 WinArrow様 hatena様】
OptionButtonのChangeイベントとはまたざっと読むと今後のためになりそうな気がしてなりません。
せっかく頂いた貴重な情報なので確認させてください。またしばしお時間ください><
(1日目より3日目のほうがなぜか理解が深まる・・)

回答
投稿日時: 24/10/24 23:13:11
投稿者: simple

質問者さんへ
私のは前座ですので余り参考になりません。
gombohoriさんはじめchangeイベントプロシージャを使ったものがよいと思いました。
また、hatenaさんの投稿はよくまとまっていますし、大いに参考にしていただきたいです。

回答
投稿日時: 24/10/24 23:32:23
投稿者: MMYS

けけちゃま さんの引用:
当方のレベル
クラスモジュールまったく不明

けけちゃま さんの引用:
(ネットでしらべるとクラスモジュール前提のものばかりで、どこの理解から進めればいいか迷走しておりますがなんとかやってみます T_T)

クラスモジュールは上級者向けですので、今は覚える必要はありません。そしてクラスモジュールが必要なケースは稀です。今は、そのような機能がある。という認識でよいです。
 
※アプリケーションイベントでは必須ですが、アプリケーションイベントが必要なケースも稀です。
※クラスを理解するにはインスタンスの理解が必要。
 
 
けけちゃま さんの引用:
Public Function funk(ByVal arg As String, ByVal flg As Boolean) As Boolean
 
の最後のAs Booleanがやはり何を返しているのかがわからず、まさかと思い、下記Subに改造して下記でもやってみたら同じく起動しました!

SubプロシージャとFunctionプロシージャの違いは値を「返す/返さない」の違いです。
Functionプロシージャは処理結果の値を呼び出し元に返すために使用します。
今回は値を返す必要がないので、Subプロシージャで記述が一般的です。(Functionは使わない)
 
※プログラマは第三者た作成したコードを読む場合、Functionを使用している箇所では、戻り値は何だろう。と考えます。つまり意味なくFunctionプロシージャを使用すると、可読性が下がり、解読・バク発生の要因になるため、単なる処理、つまり値を返さない場合、Subプロシージャで記述です。
また、意味もなく、戻り値の形を指定し、戻り値も設定しない。となると、なぜだろう。と不要な思考か発生するため止めたほうが良いです。
 
 
けけちゃま さんの引用:
AS  MSForms.Control がよくわからなくて

こちらも、今の時点では、覚える必要はありません。まず変数の標準型を習得しましょう。
・数値型
・文字列型
・日付型
・ブール型
・オブジェクト型
・バリアント型
 
ちなみに、MSForms.Controlの意味は、「フォームコントロールのインスタンスを渡す」です。
 
 
けけちゃま さんの引用:

ByRefとか ByVal(参照渡し、値渡し?)の理解は時間をかけて解読します。

「参照渡し・値渡し」は、原本を渡すか、コピーを渡すか。です。
参照渡しは、原本をそのまま渡す。つまり、呼び出し先で書き換えると、呼び出し元の変数も書き換わってしまう。
値渡しは、原本のコピーを渡します。つまり、呼び出し先で書き換えても、呼び出し元の変数には影響しません。
なお値渡しはコピーを行うため(理論上)実行スピードが落ちます。そのため指定しない場合、実行スピード重視で、原本をそのまま渡す参照渡しです。
 
※わかりやすく例えるなら「住民票」の写しです。役所でもらえるのは「写し」です。「写し」をいくら汚しても「住民票」原本はまったく変化しません。
 

回答
投稿日時: 24/10/25 11:24:39
投稿者: WinArrow

引用:

(If arg2 Thenって、If arg2=True Then と同じですよね うんきっとそうだ‥)

 
ご想像の通りです。
 
簡単な確認方法
 
Sub test()
Dim arg2 As Boolean

    arg2 = True
    
    If arg2 Then
        Debug.Print True
    End If
End Sub

[/quote]

回答
投稿日時: 24/10/25 11:49:05
投稿者: mattuwan44

>なんとなく、上から皆様のコメント見ているうちにAs MSForms.Controlの意味がわかりそうです
 
Microsoft Forms オブジェクト の中の様々なコントロー群
みたいなイメージです。
https://learn.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/objects-microsoft-forms
 
>For Each c In Controls
>ってフォームにあるすべてコントロールの数分繰り返すってことだと、コントロールが多くなると負担かかるも>のですかね。

 
数10個ぐらいではそんなに負荷はかからないんじゃないですかねぇ。。。
やってみて重いなら別案考えればいいかなぁ。。。
とりあえず、クリックイベントにこだわったら、
対象のものを探し回る必要があるかなぁとは思います。
(数が限られて、探さなくてもわかるなら直にコードに書きこんでも良いでしょう。)
 
>参考書みてもファンクションプロシージャーじゃないとできない!っていうコードがよくわからなった
 
「ファンクションプロシージャーじゃないと」と考えずに、
「こんな関数があると便利だな」とか、
「本筋の話からそれるので、他のプロシージャに追い出したいな」
と思ったときにFunctionプロシージャを使うといいかと思います。
 
例えば、
hatenaさんのコードが、一番洗練されているかと思いますが、
 

 Function SetEnable(ByRef c As MSForms.Control, value As Boolean)
   c.Enabled = value
   c.BackColor = IIf(value, &H80000005, &H80000000)
 End Function

 
ここのプロシージャでは、
与えられたコントロールの、
操作の可/不可を切り替えるのが仕事なので、
極端な話、TrueかFalseかをプロパティに設定できればよく、
表示の色とかは別のはなしとして考えてもいいのかなと思ったら、
Functionプロシージャを使うことになります。
 
Function SetEnable(ByRef c As MSForms.Control, value As Boolean)
   c.Enabled = value
   c.BackColor = EnabledColor(value)
End

function EnabledColor(byref flg as boolean)as long
    enavledcolor = IIf(flg, &H80000005, &H80000000)
end function

 
もっというと、
&H80000005
こういうのも、
const clrTrue as long = &H80000005
const clrFalse as long = &H80000000
というような形で定数として事前に宣言してもいいかもしれません。

投稿日時: 24/10/29 13:15:43
投稿者: けけちゃま

gombohori様
WinArrow様
hatena様
  
 
Changeイベントようやく理解できました!
OptionButton1の値=Trueの時は、
TextBox1の値=True
ComboBox1の値=True
の規則を利用するってことですね!(考え方あってますかね・・)
なんでそのような発想が・・・これは経験の差なのか、地頭の差なのか・・それともこれは王道コードでどこかの参考書に載っているものなのか…
いずれにしてもすごいと思いました。
 
gombohori様のPropertyプロシージャについては、これも全く無知なので、また一つ課題にさせてください、ありがとうございます・・!
(課題だらけ・・T_T)
  
hatena様
すごく分かりやすい説明を頂きありがとうございます。
そして、ParamArrayについては最近ようやく理解したので、すごく洗練されたコードになり感動しました。(そしてそれがようやく読めるようになった自分に感動T_T)
 
このコードを使ってみたいと思います。(ほかの皆様からも頂いたコードとても勉強になりました、ありがとうございます・・!)
  
 
WinArrow様
確認方法ご教示ありがとうございます。
まだ完全に理解できていないですが、多分Boolean型をちゃんと理解する必要があると思いましたのでこちら持ち帰ります泣!
  
mattuwan44様
enavledcolorの値をSetEnableに返す…まだ解読ができておりませんが、
きっとファンクションプロシージャーを勉強するにあたりきっと読めるようになると思うので参考にいたします、ありがとうございます!
というもの、一昨日からまた別件のバグ(OneドライブにいれたThisWorkbookのパスがおかしい)が生じて調べまくったら、
https://it-yobi.com/excel-b-noex24/
のサイトにたどり着き、なんとなくファンクションプロシージャーの値を返す意味がわかりかけました。
ファンクションプロシージャで得た値つかって、別の値をだすときに使うんだなと。(語彙力・・すみません)
  
MMYS様
ありがとうございます(´;ω;`)
周りから「コードかけるんだすごね」と言われちょっとうれしくなったものの、
ここでの皆様のレベルに圧倒され、自分の非力さに穴があったら入りたいレベルでした…苦笑。
 
ブール型はなんとなくTrueとFalseなのはわかるんですが、
バリアント型がよくわからなくて(それ以外はバリアントって思っておけばいいのかなくらい)、
なんなら全部バリアント型のほうがいいのでは?と思うのですが、無駄に要領を使いすぎる感じなのかなと思ってます。
これは基礎知識になると思うので自分で調べてみます!
そして、「参照渡し・値渡し」の違いとデメリット(値渡しはコピー分速度が落ちる、なるほど!!)もありがとうございます。
すごくわかりやすかったです!。
 
 

投稿日時: 24/10/29 13:20:28
投稿者: けけちゃま

皆様、この度は私の質問に対して色々ご意見をいただきありがとうございます。
精進いたします。
 
私にとって皆様は、プログラマーレベルとかってに思っているのですが、
皆様がここまでの知識になるまでに、ご愛用された参考書などがあれば教えていただきますでしょうか・・・><。
(あまりに上級レベルはさすがにまだ敬遠したいと思っておりますが

回答
投稿日時: 24/10/29 13:32:28
投稿者: mattuwan44

 >ファンクションプロシージャで得た値つかって、別の値をだすときに使うんだなと。
 
ちょっと違うかもです。
ブラックボックスという言葉をご存じないでしょうか?
その仕組みを自分で作るのが、functionプロシージャです。
 
自分で作って自分で使うのでわかり難いかも知れませんが。。。。
TrueかFalseかが分かっているときに、
Trueの色の値が欲しいときは、ブラックボックスにTrueを入れれば、期待した答えが返ってくる
反対も同様です。
それ以外を考えなくてもいいようにしたらどうかなという例でした。
例が無理やりなのでわかりずらいですよね^^;

回答
投稿日時: 24/10/29 15:06:57
投稿者: mattuwan44

本はもう卒業でいいのではないでしょうか?
ExcelVBAの情報は大体ネットで賄えるかと。
よく見るのはこの辺。。。
 
オフィス田中
http://officetanaka.net/index.stm
 
インストラクターのネタ帳
https://xn--relief-2o4e6c3dvc7eqthevf.jp/
 
Excelの神髄
https://excel-ubara.com/
 
Excel大事典
http://www4.plala.or.jp/gen2/excel/
 
Excelでお仕事!
https://www.asahi-net.or.jp/~ef2o-inue/top01.html
 
Addin Box
https://addinbox.sakura.ne.jp/
 
Functionプロシージャとかの話なら、
Excel大事典の「構造化プログラミングに挑戦」の項を読むといいかも知れません。

回答
投稿日時: 24/10/31 22:16:59
投稿者: MMYS

けけちゃま さんの引用:

皆様がここまでの知識になるまでに、ご愛用された参考書などがあれば教えていただきますでしょうか・・・><。

ここに回答されている方は、10年20年前に習得された方が多いでしょうから当時の書籍を紹介されても参考にはならないかと。それに、すでに絶版かつ、発行当時はExcel2003とかですから。
 
まず、質問者さんは、基礎が不足しているように思います。それには初心者向け書籍を読み、そこに書かれた内容のみ習得することをお勧めします。初心者向け書籍は、習得が必須の内容のみが書かれているからです。今は必要のない事は書かれていません。より高度な事は、必要になってからで十分です。
 
おすすめの書籍は分かりませんが、図書館でVBA書籍を借りてくることをおすすめします。何冊か借りて、自分にあったものを読むことをお勧めします。
 
私自身は「大村あつし」さんの書籍か参考になりました。今でも執筆されているので、大村あつし著者の書籍を手にとってみるのも良いでしょう。
なお、大村あつしさんは、ここのサイト、Mougを立ち上げた人物です。(現在は運営会社も代わってMougには関わってないみたいですが)
https://ascii.jp/elem/000/000/322/322945/
 
 
ある程度、コードが書けるようになったら次のような書籍が参考になるかもしれません。また自信が付いたら、コーディング全般・コンピュータ全般が書かれた書籍を読むことをお勧めします。
 
Excel VBAでちゃんとしたアプリを作る本
https://gihyo.jp/book/2024/978-4-297-14325-1
 
実務で使える Excel VBA プログラミング作法〜「動けばOK」から卒業しよう!生産性が上がるコードの書き方
https://gihyo.jp/book/2019/978-4-297-10871-7
 
良いコード/悪いコードで学ぶ設計入門―保守しやすい 成長し続けるコードの書き方
https://gihyo.jp/book/2022/978-4-297-12783-1
 
[増補改訂]良いコードを書く技術──読みやすく保守しやすいプログラミング作法
https://gihyo.jp/book/2021/978-4-297-12048-1
 
プロになるなら身につけたい プログラマのコーディング基礎力
https://gihyo.jp/dp/ebook/2017/978-4-7741-8828-7
 
なお、書籍の内容はご自身で判断願います。
 

投稿日時: 24/11/01 14:31:34
投稿者: けけちゃま

mattuwan44様
MMYS様
 
ありがとうございます!
やはりまだまだ基礎がなっていないですよね・・(自分がどのレベルかもよくわからず)
今回、教えていただいた情報をもとにさらなる勉強を進めていきたいと思います!!
 
皆様
これにて解決済みにさせてはいただきます。
本当にありがとうございます!!