• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:指定の動作中ユーザーフォーム終了方法)

指定の動作中ユーザーフォーム終了方法

cj_moverの回答

  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.1

(1/全2葉) こんにちは。 まずは、基本的事項のお浚いから、、、。 「UserFormの表示/非表示」について、   UserForm1.Show と書いた場合、 既に読込み済の(インスタンスが確立されている)ユーザーフォームだった場合は、 文字通り、ユーザーフォームを表示するだけで、書いたこと、と、実行されること、が一致します。 が、読込みが済んでいない(インスタンスが確立されていない)ユーザーフォームだった場合は、 まず、ユーザーフォームを読み込んで、続けて、ユーザーフォームを表示するようになっていて、   Load UserForm1   UserForm1.Show と、本来的には2行で書くべき2つの処理を1行に省略している、という風に考えてください。 ユーザーフォームの場合は、<ブックやシート等とは大きく違い>、 読込むまではインスタンス(実態)を持っていない<ただの設計図である>ことに留意してください。 イベントに関連付けて全体の流れを説明すると、   Load UserForm1 = 読込む → UserForm_Initialize   UserForm1.Show = 表示する → UserForm_Activate   UserForm1.Hide = 非表示にする → 該当なし   Unload UserForm1 = インスタンスを消す → UserForm_Terminate 別のユーザーフォームが、アクティベートされたりモーダル表示になった場合、   anotheRuseRforM.Show = 自分以外のユーザーフォームを前面表示すると → UserForm_Deactivate                表示されたユーザーフォーム側で → UserForm_Activate これらの事項への理解を一層深めていければ、今回の課題は自ずと解決できるのではないでしょうか。 実践的な話として、 最初に読込む時の処理=Load(UserForm_Initialize)時点での処理、というのは、 大抵の場合、すべての処理が済んで、ブックを閉じるまでは、 そのままにしておいて構わない内容である筈ですから、 通常はUnload(UserForm_Terminate)せずに (可変のパラメータに連動するにはUserForm_Activate等各種イベントで処理可能) 用が無い時は、一旦.Hideで非表示にしておいて、 つまり、読込まれた状態を保持しておいて、 また使う時に.Show(UserForm_Activate)再表示、 非表示→再表示→非表示→再表示→非表示→再表示...を繰り返し、 いよいよ使うことがない、というタイミング(通常はWorkbookを閉じる時)が来たら Unload(UserForm_Terminate)するか、 プロジェクトの終了(リセット)を待って、勝手にインスタンスが消えるのに任せるか、 というように運用します。 なので、ユーザー操作で勝手に <Unload(UserForm_Terminate)即ちユーザーフォームのインスタンス(実態)を消されてしまう> ことを避ける意味で、   Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)     If CloseMode = vbFormControlMenu Then       Cancel = True       Me.Hide     End If   End Sub のような仕組みが用意されていることで、開発者の意図の沿った自由な設計が可能になっています。 End ステートメント、って、ユーザーフォームや、VBAProjectを終了(リセット)させる意味ですから、 というか、よっぽどのことでもない限り使うものではありません。 私は全く使わないです。 #少なくとも近現代のVBAでは、必要なものではない筈です。 #4つのユーザーフォーム、といっても、モーダル表示でお使いのようですから、 #常にひとつずつを排他的に使っているのだとすると、4つというのは少し多いような気もしますが、さておき。   UserForm.Show   UserFormA.Show   UserFormB.Show   UserFormC.Show という記述があるなら、それらと対をなすように、   UserForm.Hide   UserFormA.Hide   UserFormB.Hide   UserFormC.Hide という記述をを適宜用いるように考えてみて下さい。 > If UserForm.Visible = False Then > UserForm.Show > End If 見た目上、正しい結果を得られているのでしょうけれど、これは、ちょっと拙いです。 UserFormが既に読込まれている場合は問題ないのですが、 読込みが済んでいない(インスタンスが確立されていない)場合は、 UserForm.Visibleを取得するタイミングで Load(UserForm_Initialize)することになってしまいます。 UserFormが既に読込まれていることが明らかな場合にしか本来はあってはならない記述です。 (.Hideされているかどうか確認する為の.Visibleプロパティです。) 処理の内容によっては問題が顕在化しないことも多いと思いますが、 期待しないタイミングで勝手に読込み処理されてしまう、ということであれば、 これは一種のバグとも言えます。 Load(UserForm_Initialize)と.Show(UserForm_Activate)の違いを理解し正しい使い分けが出来、 UserForm_Initializeイベント内でUserForm自身(または配下のコントロール)以外のオブジェクト操作は一切しないとか、 現存の記述が最終版で絶対に誰も書き換えることがないとか、条件付きで、 「まぁ差し当たり望んだ結果が得られるのだからオッケーにしよう」という割り切りの元で使うのなら構いません。 #"オッケー"という方が以外に多いので、説得力ないかも知れません?が。 > 上記で、UserFormが表示されているか確認はできますが、 > Endの前に入れようと、後に入れようと > UserForm.showが実行されることはありません。 > だからといって、Exit Subを使うと > UserFormB,UserFormCの動作を継続して行ってしまいます。   UserForm.Show   End の順に処理した場合は、UserForm.Showを実行しますが、 直後に、VBAProjectを終了(リセット)させていますから、 <Unload(UserForm_Terminate)即ちユーザーフォームのインスタンス(実態)を消す> ように指示しているということです。   End   UserForm.Show の順に処理しようとした場合は、 End ステートメントによってVBAProjectを終了(リセット)させたからには、 それ以降の記述(UserForm.Show)が実行されることはない、 どころか、UserFormクラス自体が解放されてしまっています。 VBAでの処理中に現在表示されているユーザーフォームの数、の変動、をトレースすることは、   MsgBox DoEvents() などの方法で可能ですし、(※ユーザーフォーム以外にもカウントするオブジェクトがあるようですから相対値になります) 読込み済の(インスタンスを持つ)ユーザーフォームの数は、   MsgBox UserForms.Count とか、数の把握だけでも意図したことを実現できるようにも思いますが、 ユーザーフォームのインスタンスを勝手に作成することなく、特定のユーザーフォームが読込まれているかを調べるには、   Function FnUserFormIsLoaded(ByVal sUfName As String) As Boolean   Dim o As Object     For Each o In UserForms       If o.Name = sUfName Then         FnUserFormIsLoaded = True         Exit For       End If     Next   End Function などの方法も一応あります。 ただ、.Show→.Hide→.Show→.Hide ... のように運用して、 UserForm_QueryCloseの本来の使い方と組み合わせれば、 基本的には設計者の意図したように表示・非表示をハンドル出来ますから、 表示中かどうか(読込み済かどうか)調べることの必要性、というと、 私には必要とは思えません。 どうにもうまくいかないって場合でも、例えば一時的な演習とでも考えて、 各ユーザーフォームの読込み・表示をPublicな変数でフラグにしてみるというのはアリかも知れません。 そうやってデバッグを容易にしておいて慣れてくれば、 理解が深まり、やっぱり必要なかった、ってことになるように思いますので。 (次の投稿へ続く)

satoron666
質問者

お礼

回答いただきありがとうございます。

satoron666
質問者

補足

んー、むずかしいですね。 .Show .Hide の意味はなんとなく理解しておりました。 Loadは見えないけど、メモリ上では動作。 Unloadはメモリから削除し、画面表示も見えない。 Showはメモリ上もあるし、見える。 Hideはメモリ上あるけど、隠す。 こういった認識です。 中々むずかしくて混乱しております。

関連するQ&A

  • ユーザーフォームの切り替えについて・・・

    UserForm1とUserForm2の2つのユーザーフォームがあります。 UserForm1の中にあるcommandButton1をクリックすると、UserForm2が表示される仕組みになっています。 (ちなみに、UserForm2にもコマンドボタンがあり、クリックするとUserForm1に戻るようになっています) UserForm1の方に、 Private Sub CommandButton1_Click() UserForm2.Show 0 Unload UserForm1 End Sub UserForm2の方に、 Private Sub CommandButton1_Click() UserForm1.Show 0 Unload UserForm2 End Sub と記述してあります。 ところが、それぞれのユーザーフォームには、閉じると同時にブックが閉じるように Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) ActiveWorkbook.Save 'ブックを保存 ActiveWorkbook.Close 'ブックを閉じる Application.Quit 'excelを終了 End If End Sub というコードを記述しているため、UserForm1からUserForm2へ移るときにブックが閉じてしまいます。 右上の「×」を押したときだけブックを閉じるようにしたいのですが、どういうコードを書いたらいいのですか? 宜しくお願いします。(*´Д`人)

  • ExcelVBA:フォームの閉じるボタン「×」を消す方法

    ExcelVBAで、ユーザーフォームの閉じるボタン「×」を使用できなくなる方法は以下のコードで教わったのですが「×」自体消す方法ってあるでしょうか? Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) If CloseMode = 0 Then Cancel = 1 End Sub 回答よろしくお願いします。

  • エクセル ユーザーフォームの位置

    ブックを閉じた時のユーザーフォームの位置を、次回ブックを開いた時に同じ位置で表示したいです。 以下のコードでユーザーフォームは閉じれないようになっています。 Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer) If CloseMode = vbFormControlMenu Then Cancel = True End If End Sub この場合でも、前回と同じ位置でのユーザーフォームの表示は可能でしょうか? 可能な場合はどのようにしたらいいでしょうか?

  • VBA ユーザーフォームのコードについて

    下記の2つのコードの意味について教えて下さい。 Private Sub CommandButton1_Click() If ComboBox1 = "" Then ComboBox1.SetFocus・・・・・1 Exit Sub End If Application.Run (ComboBox1.List(ComboBox1.ListIndex))・・・2 End Sub 1と2がわかりません。 Private Sub UserForm_Initialize() TB = Array("マクロ1", "マクロ2", "マクロ3") Me.ComboBox1.List = TB End Sub 「Private Sub UserForm_Initialize()」と「Array」がわかりません。 よろしくお願いします。

  • フォームのボタンからのみexcelを終了したい

    おねがいします。 都合上、フォームのボタンからだけexcelを終了したのです。 Private Sub CommandButton1_Click() Application.DisplayAlerts=False Application.Quit End Sub それに伴い、 右上のexcelのxボタン、シートのxボタンを無効化または非表示にしたいです。 Private Sub Workbook_BeforeClose(Cancel As Boolean)      If CloseMode = 0 Then     Cancel = 1   End If End Sub これで、エクセルxボタンは無効になりましたが、 フォームからの終了も出来なくなってしまいました。 フォームからのみ終了する方法を教えてください。

  • Excel ユーザーフォーム呼び出し時エラー

    WindowsVista HomePremium Excel 2007 Microsoft Visual Basic 6.5 です。 Excelでユーザーフォーム(UserForm1)を作り、   Sub Auto_Open()     UserForm1.Show   End Sub で起動時に呼び出すようにしました。 確認のため、一度Excelを閉じ起動し直したところ正常に動作しました。 もう一度確認のため同じように再起動をすると、  実行時エラー '2110': コントロールが表示されていない、利用できない、またはフォーカスを持てないため、そのコントロールにフォーカスを移すことはできません。 と出て、それ以降何度やっても動作しなくなってしまいました。 解決法か原因がわかる方いらっしゃいましたら、ぜひご教授ください。よろしくおねがいします。 ユーザーフォーム関係のコードを以下に書いておきます。(内容は小遣い帳のようなものです。) ―――――――――――――――――――― Private Sub CommandButton1_Click() Dim NUM As Integer If TextBox1.Text = "" Then MsgBox "概要が記入されていません。" TextBox1.SetFocus GoTo 100 ElseIf TextBox2.Text = "" Then MsgBox "収支が記入されていません。" TextBox2.SetFocus GoTo 100 ElseIf ComboBox1.ListIndex = -1 Then MsgBox "収支の種類が選択されていません。" ComboBox1.SetFocus GoTo 100 End If Range("F6").Select NUM = 0 Do While ActiveCell.Offset(NUM, 0) <> "" NUM = NUM + 1 Loop ActiveCell.Offset(NUM, 0).Select ActiveCell = TextBox1.Value If CheckBox1 = True Then TextBox2 = -TextBox2 End If If ComboBox1.ListIndex = 0 Or ComboBox1.ListIndex = 1 Then ActiveCell.Offset(0, ComboBox1.ListIndex + 1) = TextBox2.Value Else ActiveCell.Offset(0, ComboBox1.ListIndex + 2) = TextBox2.Value End If TextBox1 = "" TextBox2 = "" CheckBox = Falses ComboBox1.ListIndex = -1 100 End Sub ―――――――――――――――――――― Private Sub CommandButton2_Click() Dim NUM As Integer If TextBox3.Text = "" Then MsgBox "移動金額が記入されていません。" TextBox3.SetFocus GoTo 100 ElseIf ComboBox2.Text = "" Then MsgBox "移動元が選択されていません。" ComboBox2.SetFocus GoTo 100 ElseIf ComboBox3.ListIndex = -1 Then MsgBox "移動先が選択されていません。" ComboBox3.SetFocus GoTo 100 End If Range("F6").Select NUM = 0 Do While ActiveCell.Offset(NUM, 0) <> "" NUM = NUM + 1 Loop ActiveCell.Offset(NUM, 0).Select ActiveCell = "移動" If ComboBox2.ListIndex = 0 Or ComboBox2.ListIndex = 1 Then ActiveCell.Offset(0, ComboBox2.ListIndex + 1) = -TextBox3.Value Else ActiveCell.Offset(0, ComboBox2.ListIndex + 2) = -TextBox3.Value End If If ComboBox3.ListIndex = 0 Or ComboBox3.ListIndex = 1 Then ActiveCell.Offset(0, ComboBox3.ListIndex + 1) = TextBox3.Value Else ActiveCell.Offset(0, ComboBox3.ListIndex + 2) = TextBox3.Value End If TextBox3 = "" ComboBox2.ListIndex = -1 ComboBox3.ListIndex = -1 100 End Sub ―――――――――――――――――――― Private Sub CommandButton3_Click() Unload Me End Sub ―――――――――――――――――――― Private Sub CommandButton4_Click() Unload Me End Sub ―――――――――――――――――――― Private Sub UserForm_Initialize() myarray1 = Array("収支", "クレジット", "郵便局", "机", "500", "1") For i = 0 To 5 ComboBox1.AddItem myarray1(i) ComboBox2.AddItem myarray1(i) ComboBox3.AddItem myarray1(i) Next i TextBox1.SetFocus End Sub

  • EXCEL VBAのユーザーフォームに引数を渡す方法について

    すいません、EXCEL VBAのユーザーフォームに引数を渡す方法についてご質問があります。 シート上にコマンドボタンを2つ用意する。 コマンドボタン1を押すと変数mは1 コマンドボタン2を押すと変数mは2 としてユーザーフォームを呼び出す。 Public m As Integer Private Sub CommandButton1_Click()  m = 1  Call フォーム呼び出し(m) End Sub Private Sub CommandButton2_Click()  m = 2  Call フォーム呼び出し(m) End Sub Sub フォーム呼び出し(m As Integer)  UserForm1.Show End Sub 次にユーザフォームにコマンドボタンを1個置き、 ボタンを押したとき、mが1であれば「ボタン1」 mが2であれば「ボタン2」 とメッセージボックスを出し、ユーザーフォームを閉じる。 Private Sub CommandButton1_Click()   If m = 1 Then    MsgBox "ボタン2"   ElseIf m = 2 Then    MsgBox "ボタン2"   End If  Unload UserForm1 End Sub プロシージャ間の引数渡しは色々なテキストに載っているのですが ユーザーフォームに引数を渡す方法はどうも見つからず、 Private Sub CommandButton1_Click(m) としても、コンパイルエラーとなってしまいます。 よろしくご教示をお願いいたします。

  • ExcelVBAでのユーザーフォームについて

    ご回答ありがとうございました。 これといった資料がなく(探し方が悪いのかもしれませんが)、少ない経験値で複雑なというか面倒な処理のマクロ(VBA)を組まされることになり、困っているところです。当初の話だと「勉強しながらでよい」ということだったのですが、いろいろと仕事が次々と舞い込んできて、そんな余裕もなくせっぱ詰まり少ない知識で必死にやっています。 先にご回答いただいた内容で是非アドバイスをいただきたいと思い、新たに質問させていただきました。 ユーザーフォームでマルチページを作っています。そこでもコンボボックスを使うのですがそこの記述方法をアドバイス下さい。やっぱり記述場所がおかしいのか、クリックするとリストの内容がコンボボックスをクリックした分だけ繰り返してしまうことがあります。 ////////////////////////////////////////////////////// Private Sub UserForm_Initialize() Dim sh As Worksheet Set sh = Worksheets("対象年") Dim i As Integer Dim lastRow As Integer lastRow = sh.Cells(Rows.Count, 1).End(xlUp).Row With ComboBox1 For i = 2 To lastRow If ComboBox1 = "" Then .AddItem sh.Cells(i, 1).Value End If Next i End With End Sub ////////////////////////////////////////////////////// Private Sub ComboBox1_DropButtonClick() Dim sh As Worksheet Set sh = Worksheets("対象年") Dim i As Integer Dim lastRow As Integer lastRow = sh.Cells(Rows.Count, 1).End(xlUp).Row With ComboBox1 For i = 2 To lastRow If ComboBox1 = "" Then .AddItem sh.Cells(i, 1).Value End If Next i End With End Sub ////////////////////////////////////////////////////// とまぁ、結局コードは同じなのですが。 それと、結果をラベルに出させる場合には回答で記述いただいた ////////////////////////////////////////////////////// Private Sub ComboBox1_Change()   Dim vTgYear As Variant   vTgYear = ComboBox1.Value   Label1.Caption = vTgYear - 1 & "~" & vTgYear + 1 & "年" End Sub ////////////////////////////////////////////////////// で、よいでしょうか? よろしくお願いいたします。

  • ExcelVBA ユーザーフォーム間の変数について

    UserForm1のコントロールボタンbtn1又はbtn2をクリックするとUserForm2を開く。 UserForm1にはテキストボックスtxtN1、txtN2がある。 UserForm2のテキストボックスtxtN3に入力された値をbtnDecideをクリックすると、 UserForm1に自動入力するようにする。 その際btn1をクリックしてUserForm2を開いた場合はtxtN1に、btn2をクリックして開いた場合は txtN2に自動入力されるようにする。 以下のようにコードを組んでみました。 UserForm1のコード Public Number as integer Private Sub btn1_Click() Number = 1 UserForm2.Show End Sub Private Sub btn2_Click() Number = 2 UserForm2.Show End Sub UserForm2のコード Public Number as integer Private Sub btnDecide_Click() If Number = 1 Then UserForm1.txtN1 = txtN3.Text else:Number=2 UserForm1.txtN2= txtN3.Text End If Unload Me End Sub 以上になります。 どうもpublic 変数NumberがUserForm2を開いた段階でリセットされているようなのです。 何かいい方法はありますでしょうか。 教えていただける方がいましたらよろしくお願い致します。

  • ユーザーフォームに入力したデーターが転記できない

    いつもお世話になります。 Windows7 excell2010 です。 いろんなものに勉強してここまでに作成したユーザーフォームですが、データーは入力できるのですがコマンドボタンをクリックしても各セルに反映されません。 色々と試行錯誤していますがうまくゆきません。 どこに不具合があるかわからず恐れ入りますがどなたかご指導いただけませんか。 参考にコードは参考に下記にします。 ユーザフォームのVBAは下記です コード ※Module1 Sub 売上() Do UserForm1.Show Loop End Sub Sub 入金() Do UserForm2.Show Loop End Sub ※UserForm1 Private Sub UserForm_Initialize() With ComboBox1 .AddItem "1" .AddItem "2" .AddItem "3" End With End Sub Private Sub CommandButton1_Click() n = Cells(Rows.Count, 1).End(xlUp).Row + 1 Cells(n, 2) = UserForm1.TextBox1.Text Cells(n, 3) = UserForm1.TextBox2.Text Cells(n, 4) = UserForm1.TextBox3.Text Cells(n, 11) = UserForm1.ComboBox1.Text Unload Me End Sub Private Sub CommandButton2_Click() Unload Me End End Sub ※UserForm2 Private Sub CommandButton1_Click() n = Cells(Rows.Count, 1).End(xlUp).Row + 1 Cells(n, 2) = UserForm2.TextBox1.Text Cells(n, 3) = UserForm2.TextBox2.Text Cells(n, 4) = UserForm2.TextBox3.Text Unload Me End Sub Private Sub CommandButton2_Click() Unload Me End End Sub