Excel (VBA) |
|
(指定なし : 指定なし)
Functionプロシージャの書き方
投稿日時: 24/10/22 00:51:08
投稿者: けけちゃま
|
---|---|
ここ最近、質問立て続けで申し訳ございません。。。
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
|
|
---|---|
>結果:
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様
|
投稿日時: 24/10/22 20:19:39
投稿者: WinArrow
|
|
---|---|
引用: の注意事項(落とし穴) 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でもイベントが発生するので、
|
投稿日時: 24/10/22 23:22:42
投稿者: けけちゃま
|
|
---|---|
simple様
|
投稿日時: 24/10/23 02:28:37
投稿者: hatena
|
|
---|---|
VBAにはいろいろな機能がありますが、その機能を理解して適切な場所で適切な方法で使う必要があります。
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様
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
|
|
---|---|
質問者さんへ
|
投稿日時: 24/10/24 23:32:23
投稿者: MMYS
|
|
---|---|
けけちゃま さんの引用: けけちゃま さんの引用: クラスモジュールは上級者向けですので、今は覚える必要はありません。そしてクラスモジュールが必要なケースは稀です。今は、そのような機能がある。という認識でよいです。 ※アプリケーションイベントでは必須ですが、アプリケーションイベントが必要なケースも稀です。 ※クラスを理解するにはインスタンスの理解が必要。 けけちゃま さんの引用: SubプロシージャとFunctionプロシージャの違いは値を「返す/返さない」の違いです。 Functionプロシージャは処理結果の値を呼び出し元に返すために使用します。 今回は値を返す必要がないので、Subプロシージャで記述が一般的です。(Functionは使わない) ※プログラマは第三者た作成したコードを読む場合、Functionを使用している箇所では、戻り値は何だろう。と考えます。つまり意味なくFunctionプロシージャを使用すると、可読性が下がり、解読・バク発生の要因になるため、単なる処理、つまり値を返さない場合、Subプロシージャで記述です。 また、意味もなく、戻り値の形を指定し、戻り値も設定しない。となると、なぜだろう。と不要な思考か発生するため止めたほうが良いです。 けけちゃま さんの引用: こちらも、今の時点では、覚える必要はありません。まず変数の標準型を習得しましょう。 ・数値型 ・文字列型 ・日付型 ・ブール型 ・オブジェクト型 ・バリアント型 ちなみに、MSForms.Controlの意味は、「フォームコントロールのインスタンスを渡す」です。 けけちゃま さんの引用: 「参照渡し・値渡し」は、原本を渡すか、コピーを渡すか。です。 参照渡しは、原本をそのまま渡す。つまり、呼び出し先で書き換えると、呼び出し元の変数も書き換わってしまう。 値渡しは、原本のコピーを渡します。つまり、呼び出し先で書き換えても、呼び出し元の変数には影響しません。 なお値渡しはコピーを行うため(理論上)実行スピードが落ちます。そのため指定しない場合、実行スピード重視で、原本をそのまま渡す参照渡しです。 ※わかりやすく例えるなら「住民票」の写しです。役所でもらえるのは「写し」です。「写し」をいくら汚しても「住民票」原本はまったく変化しません。 |
投稿日時: 24/10/25 11:24:39
投稿者: WinArrow
|
|
---|---|
引用: ご想像の通りです。 簡単な確認方法 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の意味がわかりそうです
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様
|
投稿日時: 24/10/29 13:20:28
投稿者: けけちゃま
|
|
---|---|
皆様、この度は私の質問に対して色々ご意見をいただきありがとうございます。
|
投稿日時: 24/10/29 13:32:28
投稿者: mattuwan44
|
|
---|---|
>ファンクションプロシージャで得た値つかって、別の値をだすときに使うんだなと。
|
投稿日時: 24/10/29 15:06:57
投稿者: mattuwan44
|
|
---|---|
本はもう卒業でいいのではないでしょうか?
|
投稿日時: 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様
|