[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]
『ユーザーフォームについて』(あいり)
ユーザーフォームでどこまで出来るか教えて下さい。゚(゚´Д`゚)゚。
例えばユーザーフォームで”有”と”無”というオプションボタン
(チェックボックスでもいいのですが、選択はどちらか1つのみ)、を
選ぶボタンがあるとします。
その下にA,B,Cというコマンドボタンがあるとします。
有を選択すれば、A,B,Cどれかを選べるようにし、
無を選択すれば、ボタン選択出来なくなるようにします。
その下に表示というコマンドボタンを作り、
有無の選択と有の場合のA〜Cの選択が無ければ、
「選択されてません」などの表示がでるようにします。
最初の無の場合は、無と同じシート名のシートのみが表示され、
有の場合は、有と同じシート名のシートと、選択したA〜Cの
シート2種類が表示されるようにしたいのですが、
可能でしょうか??
もし可能でしたら、どなたかユーザーフォームのVBAの書き方か、
ヒントを教えて下さい。゚(゚´Д`゚)゚。
< 使用 Excel:Excel2013、使用 OS:Windows7 >
>あいり さん http://www.eurus.dti.ne.jp/~yoneyama/Excel/vba/index.html ヒント(22のユーザーフォームを利用するの項目に、 ◦オプションボタンの使い方 などがありますので、参考にしてください。)
>最初の無の場合は、無と同じシート名のシートのみが表示され、 >有の場合は、有と同じシート名のシートと、選択したA〜Cの >シート2種類が表示されるようにしたいのですが、
無と同じシート名? 有と同じシート名のシート? 選択したA〜Cのシート? 例えば、A〜Cは、Sheet3〜Sheet5の文字列ですか? 無と書いてますが、Sheet1の文字列ですか? 有と書いてますが、Sheet2の文字列ですか?例えばですが。
******************************************** 無のときは、リストを表示せず、 有のときは、A〜Cのリストを表示するの部分だけ、 マクロを使用せずに、リストを使用するのが、簡単でいいと思いますが http://note.chiebukuro.yahoo.co.jp/detail/n149222
他の部分は、マクロですが。 (マリオ) 2017/02/17(金) 09:41
直接の質問テーマからは、ちょっとはずれますけど、
>その下にA,B,Cというコマンドボタンがあるとします。
通常、コマンドボタンは、それをクリックしたら、何らかの処理を実行します。 (もちろん、実行しなくてもいいのですが、普通は 実行します)
でも、このユーザーフォームで、実際の動作というか、実行は あくまで
>その下に表示というコマンドボタンを作り、
この 表示 というコマンドボタンが押され時で、A,B,C は、有、無 とともに、どのように 実行させるかという 単なる条件ですよね?
なので、これらはコマンドボタンにはせず、有、無 とは 別にグループ化されたオプションボタンにしておくのが 素直なデザインだと思いますね。
(β) 2017/02/17(金) 13:53
質問です。(マリオさんとカブるところがありますが)
>>無と同じシート名のシート >>有と同じシート名のシート >>選択したA〜Cのシート
これらのシート名って具体的には? また、実行結果は ブックの指定されたシートのみが表示状態、あとのシートは非表示状態 になる ということですね?
それと、有 というオプションボタンとか A,B,C というコマンドボタンとか 表示 というコマンドボタン といった表現をしておれれます。
これは、本当に、そのコントロールのオブジェクト名が 有 とか A とか 表示 ということですか? それとも、オブジェクト名は別途あり、単に、キャプションとして表示されている文字列が 有 とか A とか 表示 ということですか?
(β) 2017/02/17(金) 14:11
なかなか仕事が終わらず、お返事遅くなり申し訳ございません。゚(゚´Д`゚)゚。
拙い説明ですみません!
有、無、A、B、Cはすべてシート名です。
チェックボタンのチェック内容によって、
必要なシートの表示、非表示をさせたいとおもっています。
リストというのも良いかもしれませんね(*^^*)
リストで選んだ結果によって、どのシートを表示させるか、という
マクロを組めばいいということですよね!
ただ、他の人も使うので、出来ればユーザーフォームのような形が良かったのですが。。。
もっと勉強して出直してまいります。゚(゚´Д`゚)゚。
βさま
グループ化されたオプションボタンってなんでしょう??
ごめんなさい不勉強で。゚(゚´Д`゚)゚。
有と無は実際と同じシート名です。
ABCは地名です。
具体的には、A大阪、B兵庫、C名古屋です。
実行結果は、指定されたシートのみが表示され、他は表示されない、というものです。
仕事で使う資料なのですが、組み合わせをよく間違えやすいので、
選択した結果、必要シートのみ表示されるという
フォーマットがあれば、便利かと思い質問しました(>人<;)
(あいり) 2017/02/17(金) 21:34
>グループ化されたオプションボタンってなんでしょう??
オプションボタンは、何もしなければ、たとえば 5つあったとして、どれかが選択されて ポッチ(?)がついたら 他のオプションボタンのポッチは消えますね。 常に 1つだけが選ばれた形になりますね。
仮に オプションボタンで選びたいグループが 2つあったとします。
1つのグループは 有 と 無。 2つめのグループは A と B と C。
つまり 有 と 無 のいずれかを選びたい。 また AかBかCのいずれかを選びたい。 ところが何もしないで 有 を選んで 次に B を選ぶと 有 のポッチ が消えますね。 せっかく選んだのに。
こういう場合、オプションボタンのプロパティに GroupName というものがあるんですが(初期値は空白になっています) このGroupName を 有 と 無 のオプションボタンには、たとえば umu というグループ名をセット。 A と B と C のオプションボタンのGroupName には、たとえば abc とセットしておく。
そうすると、有、無 と A、B、Cが 別グループになって、それぞれのグループで1つ選ぶことができるようになります。
もう1つ方法があります。
ユーザーフォーム上に Frame を配置します。 で、その上に オプションボタンを配置します。 それとは別のFrame を配置します。 で、その上にもオプションボタンを配置します。
こうしておくと、それぞれのFrame上のオプションボタンだけが 1つのグループだと認識され それぞれで、1つ選ぶことができます。 この場合、GroupName の設定は不要です。
こちらで A,B,C もオプションボタンにして書いたコードサンプルが2つほどあります。 もしよかったらアップします。
ただ、質問した事項、コントロールの名前について、回答をもらっていないので、コードが完成していません。 たとえば 「有 というオプションボタン」、このオプションボタンのオブジェクト名は OptionButton1 といったもので そのキャプションとして 有 という文字が表示されているのですか?
それとも、オブジェクト名も 有 に変更してあるのですか?
( β) 2017/02/17(金) 22:01
オプションボタンはグループで分けると、同じエクセル内でも各グループで1つづつ選べるんですね( ゚д゚)
ごめんなさい、まだ、どのボタンでいくか決めてなかったので、
配置してません(>人<;)なので、各ボタンの
オブェクト名もまだです。゚(゚´Д`゚)゚。
(あいり) 2017/02/17(金) 22:18
少しわかりにくいかもしれませんがサンプルです。
まず、OptionButton1 〜 OptionButton5 を配置してください。 (コントロール名は、配置後任意の名前にしてもいいのですが、とりあえず デフォルトでつけられる名前で)
OptionButton1 と OptionButton2 を マウスで選んで GroupName に umu とセット。 (2つのオプションボタンに一括でセットできます)
OptionButton3,OptionButton4,OptionButton5 をマウスで選んで GroupName に abc とセット。
これら GroupName の文字列は任意です。お好きなものでOK。 コードでは、一切参照していません。 単に、オプションボタンのグループ分けのためです。
それぞれのキャプションには "有" とか "無" とか "A" とか "兵庫" といった、わかりやすいものを セットしておきましょう。(なんでもOKです。コードでは、このキャプションは参照していませんので)
CommandButton1 も配置してください。キャプションを "シート切替" とか "表示" といったものにしておきましょう。
で、ユーザーフォームモジュールに以下。
Private Sub CommandButton1_Click() '表示 Dim valABC As String If OptionButton1.Value Then '有 If OptionButton3.Value Then valABC = "A" If OptionButton4.Value Then valABC = "B" If OptionButton5.Value Then valABC = "C" Select Case valABC Case "A" SheetShow "有", "大阪" Case "B" SheetShow "有", "兵庫" Case "C" SheetShow "有", "名古屋" Case Else MsgBox "A,B,C が未選択です" End Select ElseIf OptionButton2.Value Then SheetShow "無" Else MsgBox "有、無 が未選択です" Exit Sub End If End Sub
Private Sub OptionButton1_Click() '有 setABC End Sub
Private Sub OptionButton2_Click() '無 setABC End Sub
Private Sub setABC() OptionButton3.Enabled = OptionButton1.Value 'A OptionButton4.Enabled = OptionButton1.Value 'B OptionButton5.Enabled = OptionButton1.Value 'C End Sub
Private Sub SheetShow(ParamArray v()) Dim sh As Worksheet Dim z As Variant z = v Sheets("有").Visible = True Sheets("無").Visible = True For Each sh In Worksheets If IsNumeric(Application.Match(sh.Name, z, 0)) Then sh.Visible = True Else sh.Visible = False End If Next End Sub
なお、setABC を以下にすると、また違った表示効果になります。 お好きなほうで。
Private Sub setABC() OptionButton3.Visible = OptionButton1.Value OptionButton4.Visible = OptionButton1.Value OptionButton5.Visible = OptionButton1.Value End Sub
( β) 2017/02/18(土) 11:47
お返事遅くなりごめんなさい(>人<;)
希望していた通りの結果になり、いまパソコンの前で嬉し泣きしてます。゚(゚´Д`゚)゚。
すごいですね!!ありがとうございます!
少しコードで教えて欲しいのですが、
> OptionButton3.Enabled = OptionButton1.Value 'A > OptionButton4.Enabled = OptionButton1.Value 'B > OptionButton5.Enabled = OptionButton1.Value
enabledって、trueかfalseで繋ぐのしか知らなかったのですが、
この場合は、オプションボタン1を選択するとABCの
ボタンを無効にしない、ということですか??
あと、
ParamArray と
> If IsNumeric(Application.Match(sh.Name, z, 0)) Then
の部分の意味を教えていただけますでしょうか??
ParamArray は調べたのですが、あまりよく分からず、、、(>人<;)
お忙しいところごめんなさい!
本当に暇な時でいいので、教えて欲しいです。゚(゚´Д`゚)゚。
(あいり) 2017/02/19(日) 02:02
***************************************************************** >β先生 間違ってましたら訂正お願いします。
***************************************************************** >あいり さん うまく説明できてないかもしれませんが…。
>この場合は、オプションボタン1を選択するとABCの >ボタンを無効にしない、ということですか??
そうだと思います。オプションボタン1を選択すると OptionButton1=Trueになる。一方、グループ化した他方の オプションボタン2は、OptionButton2=Falseになる。 逆に、オプションボタン2を選択すると グループ化したオプションボタン1は、OptionButton1=Falseになり、 オプションボタン2は、OptionButton2=Trueになる。 (※OptionButton1 と OptionButton2 は、GroupName に umu とセットしました)
もし、★仮に、グループ化をしない場合、コード内で、 次のように記述することになるんじゃないでしょうか? Private Sub OptionButton1_Click() '有 OptionButton1.Value=True'★ OptionButton2.Value=False'★ setABC End Sub Private Sub OptionButton2_Click() '無 OptionButton1.Value=False'★ OptionButton2.Value=True'★ setABC End Sub
余談ですが、「setABC」の箇所は、「Call setABC」と書いた方が、 分かりやすいかも(※他のプロシージャを読み込んでいる)。 同様に、「SheetShow "有", "大阪"」 →「Call SheetShow ("有", "大阪")」と書いた方が、 分かりやすいかも。 「SheetShow "有", "兵庫"」、「SheetShow "有", "名古屋"」も同様。 _ _ _ _ >ParamArray と > If IsNumeric(Application.Match(sh.Name, z, 0)) Then >の部分の意味を教えていただけますでしょうか??
シートが、左から「有」「無」「大阪」「兵庫」「名古屋」の順番で 5枚あるとすると、For Each sh In Worksheets〜Next内での処理なので、 sh.Nameには、順番に、「有」「無」「大阪」「兵庫」「名古屋」の文字列が入る。
「SheetShow "有", "大阪"」としているケースでは、 Private Sub SheetShow(ParamArray v())で、受け取っている v配列は、「v(0)=有」、「v(1)=大阪」の2つの文字列を格納した配列になる(下記の★Debug処理参照)。 (v(0)とあるように、番号は、0からはじまります。) v()配列を、なぜz配列に格納し直さないといけないのかについては、 …?なぜだろう? 下記のコード★で、TypeNameを使って型を確認したら、 v()配列もvariant型ですね。
Application.Match(sh.Name, z, 0)で、sh.Nameは1つの文字列、 zは、variant型のArray配列で、この場合、計2回、一致しているかどうかの確認をしている。一致していると、返り値として番号が返る。 Debug(★下記参照)してみましたら、For Each sh In Worksheets〜Nextしているので、「2」,「1」の順番で番号が返りました。 3回やって、3回とも「2」,「1」の順番だったが、「1」,「2」の順番になることもあるような…? IsNumericは、数字かどうかの判定です。 ************************************************************** Private Sub SheetShow(ParamArray v()) Dim sh As Worksheet Dim z As Variant
Debug.Print "v開始番号: " & LBound(v) '★ Debug.Print "v終了番号: " & UBound(v) '★ Debug.Print "v開始: " & v(LBound(v)) '★ Debug.Print "v終了: " & v(UBound(v)) '★ Debug.Print "vの型: " & TypeName(v) '★ z = v Debug.Print "zの型: " & TypeName(z) '★
Sheets("有").Visible = True Sheets("無").Visible = True For Each sh In Worksheets If IsNumeric(Application.Match(sh.Name, z, 0)) Then Debug.Print Application.Match(sh.Name, z, 0) '★ ************************************************************** (マリオ) 2017/02/19(日) 08:47
マリオさんから説明がアップされましたけど、メモしましたので。
まず、
>>OptionButton3.Enabled = OptionButton1.Value
これについてのみ。ParamArray については、レスを分けます。
左辺の OptionButton3.Enabled は OptionButton1 というオブジェクトが持っている Enabled という名前のプロパティを示します。 ふつうの変数 と考えてください。与えることができる値は TrueかFalseのいずれかですね。
こんなコードがわかりやすいでしょうか。
変数1 = True 変数2 = 変数1
変数2 には True が格納されますね。
やりたかったことは。OptionButton1(有)が選ばれていたら OptionButton3.Enable の値を True にしたい、 選ばれていなかったら OptionButton3.Enabled の値を False にしたい。こういうことですね。
で、『たまたま』ですけど、OptionButton1 が選ばれていれば、OptionButton1.Value は True です。 選ばれていなければ False です。 そういった値が OptionButton1.Value というプロパティに入っています。 これは、まさしく、条件によってOptionButton3.Enabled にセットしたい値と一致してますね。
なので、変数2 = 変数1 の記述で、セットすべきものがセットされるということです。
わかりにくいですかね?
あぁ、レスするためにコードを眺めていましたら、おバカだなぁというところに気が付きました。
OptionButton3.Enabled = OptionButton1.Value 'A OptionButton4.Enabled = OptionButton1.Value 'B OptionButton5.Enabled = OptionButton1.Value 'C
もちろん、これでもいいのですが、仮に右辺 OptionButton1.Value の参照を 別のものに変えたとします。 (別のオプションボタンを判定、あるいは 初期値としての OptionButton1 という名前を opt有 という名前に変えた)
そうすると、3行の右辺を変更しなければいけません。
OptionButton3〜5 の Enabled は、一蓮托生、同じ値ですから
OptionButton3.Enabled = OptionButton1.Value 'A OptionButton4.Enabled = OptionButton3.Enabled 'B OptionButton5.Enabled = OptionButton3.Enabled 'C
このように書いておくと、コード変更は最初の1行だけで済みますね。
同様に
OptionButton3.Visible = OptionButton1.Value OptionButton4.Visible = OptionButton1.Value OptionButton5.Visible = OptionButton1.Value
これも
OptionButton3.Visible = OptionButton1.Value OptionButton4.Visible = OptionButton3.Visible OptionButton5.Visible = OptionButton3.Visible
と書いたほうがよかったです。
( β) 2017/02/19(日) 08:58
ParamArray の説明の前に。
>「setABC」の箇所は、「Call setABC」と書いた方が、 分かりやすいかも
たしかに わかりやすいかもしれませんね。 あぁ、これは別のサブプロシジャを実行してるんだなと 視覚的にわかりますからね。
MsgBox "Hello" と書きますね。Call MsgBox("Hello") とは、あまり書きませんね。 まぁ、 MsgBox という超有名な関数名と setABC という、なんじゃこれ? という名前の 認知度の違いもありますから setABC の場合は Call 文 で記述したほうがわかりやすいでしょうね。
> v()配列を、なぜzに格納し直さないといけないのか
私もそう思いますね。でも、エラーになるからしょうがない。 ほかにもありますね。たとえば Typeステートメントを シートモジュール等のプライベートモジュールに記述すると コンパイラーから叱られますね。Private Type として記述しなければいけない。 変数なんかは プライベートモジュールであっても Public 記述をして、別モジュールのコードから 記述されたモジュール名.その変数 で参照できるのに。
まぁ、コンパイラーにはコンパイラーの事情があるんでしょうから、仕様として受け入れるしかないでしょうけど。
で、本題です。
Application.Match(sh.Name, z, 0) については マリオさんの説明通り、そのシートが表示対象かどうかを 判定しているところですので、もうおわかりですね。
●ParamArray
たとえば 行番号と列番号を与えて処理するサブプロシジャを書こうとすると
Sub abc(i As Long, j As Long) MsgBox Cells(i, j).Address End Sub
こんな、引数2つのサブプロシジャにしますね。
で、使う場合は Call sbc(10,20) こんなように記述しますね。
この場合引数が2つと決まっていますから、サブプロシジャ側の引数規定も2つ書くわけです。
今回、書きたいなと思ったサブプロシジャは、いくつかわからないけど、必要なシートを、必要なだけ記述して それを表示させる。1シートかもしれないし、100シートかもしれない。
こういった場合、サブプロシジャ側の引数規定に Optional を付けておくことで、指定してもいいし、省略してもいい という記述にすることができます。(この場合 データ型は VAriantにしておく必要があります)
Sub abc(Optional s1 As Variant, Optional s2 As Variant, ・・・・・,Optional s100 As Variant)
こうしておけば サブプロシジャ内で
If Not IsMissing(s1) Then
s1 処理 End If
If Not IsMissing(s2) Then
s2 処理 End If
・ ・ ・
If Not IsMissing(s100) Then
s100 処理 End If
こんな処理ができますし、使うほうは Call abc("Sheet1","Sheet3") とか Call abc("Sheet5") とか Call abc("Sheet2","Sheet4","Sheet80") と書くことで利用可能です。
でも、もし、101個の指定をしたかった場合、サブプロシジャの引数規定を変更しなければいけませんね。 なにより、サブプロシジャ側のコード記述が煩雑というか、もう大変。非現実的なものになりますね。
こんなとき便利なのが、サブプロシジャ側で 引数を ParamArray として宣言しておくこと。 こうしておけば、使う側が Call abc(●,□,▼,○,・・・・・) といくつ指定しようが、それを 1次元配列に格納して サブプロシジャに渡してくれます。サブプロシジャ側では、この渡された配列を、ごくごく普通の配列として参照できますから 使う側で与えた引数をすべて取得できるわけで、コードとしてもすっきりします。
(もっとも、マリオさんがふれたように、別関数の引数として、その配列を与えるとコンパイラーエラーになる、それだけが例外です)
( β) 2017/02/19(日) 09:48
>あいり さん
余談ですが、■*****以降のコードを追加すると、次のようになります。
・エクセルファイルを最大化表示で起動した後に自動で、 フォームがA1セルの左上に合わせた位置で立ち上がります。 シートは「無」だけになる。 (フォームが立ち上がったとき、「無」ラジオボタンが選択された状態にしている)
・「有」または「無」シートのA1セルを左ダブルクリックすると、 フォームが立ち上がります。
・フォームで「表示ボタン」を押した後に、フォームを閉じます。
■UserForm1に記述するコード ***************************************************************** ◆(1)既存のプロシージャ【Private Sub SheetShow(ParamArray v())】 の最後のEnd Subの前の行に、次の1行を追加。 Unload UserForm1
◆(2)次のプロシージャを新規に記述 Private Sub UserForm_Initialize() With UserForm1 .Caption = "Excel シート選択" '------- 画面中央に表示 ------- '.StartUpPosition = 2 '------- A1セルの左上に合わせて表示 ------------------ .StartUpPosition = 0 .Left = ActiveWindow.PointsToScreenPixelsX( _ Range("A1").Left) * (72 / 96) - 2 '-2は微調整 .Top = ActiveWindow.PointsToScreenPixelsY( _ Range("A1").Top) * (72 / 96) '----------------------------------------------------- End With
OptionButton2.Value = True '「無」を選択 End Sub ***************************************************************** '_ '_ ■ThisWorkbookに記述するコード ***************************************************************** Option Explicit
Private Sub Workbook_Open() Application.WindowState = xlMaximized 'Excelを最大化表示
ThisWorkbook.Sheets("無").Visible = True Dim sh As Worksheet For Each sh In Worksheets If Not (sh.Name = "無") Then sh.Visible = False '特定のシート以外を非表示 Next
Call UserForm1表示 End Sub ***************************************************************** '_ '_ ■Module1に記述するコード ***************************************************************** Option Explicit
Sub UserForm1表示() UserForm1.Show vbModeless End Sub
'---- おまけ --------------- Sub 全てのシートを表示() Dim sh As Worksheet For Each sh In Worksheets sh.Visible = True Next MsgBox "全シート表示!" End Sub ***************************************************************** '_ '_ ■シート(「シート名:有」「シート名:無」)に記述するコード ***************************************************************** Option Explicit
Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean) If Target.Count > 1 Then Exit Sub If Target.Address <> "$A$1" Then Exit Sub Cancel = True Call UserForm1表示 End Sub *****************************************************************
(マリオ) 2017/02/19(日) 18:07
お二人とも、このたびは誠にありがとうございました(>_<)
コードを提示して頂いたうえ、そのご説明まで丁寧にして
くださり、本当に感謝です(;_;)
実は配列がめっちゃ苦手で、変数も多くなるととたんに分からなくなるの
ですが、お二人の説明がとても分かりやすかったので、
読んでいて本当にためになり、
ワクワクして読み進めました!
とはいえ、まだまだ未熟なので、
100%の理解に達していないので、もう少し
じっくり読み進めたいと思いますが、
取り急ぎ、お礼を言わせてください☆彡
本当にありがとうございました!
(あいり) 2017/02/19(日) 22:43
[ 一覧(最新更新順) ]
YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki.
Modified by kazu.