• 締切済み

ExcelVBAで指定時間に自動で終了ボタンを押す

Excel2003を使用しております。 とあるExcelファイルを開くと、フォームを開く設定にして有ります。 朝の8時にフォームの終了ボタンの処理を自動で行いたいので、コードを追加しました Private Sub Workbook_Open() Worksheets("シート1").Activate Range("A1").Select frmテスト.Show vbModeless Application.OnTime TimeValue("08:00:00"), "cmd終了" '←追加したコード End Sub frmテストのフォームにあるコードはこんな感じです Private Sub cmd終了_Click() コードたくさん~ End Sub 朝の8時にfrmテストのフォームにある、終了ボタンのコードを実行させたいのですが、8時になるとエラーが出ます。 マクロ "C\Documents and Setting\ユーザー名\デスクトップ\ファイル名.xls'!cmd終了'が見付かりません。 と、表示されます。 宣言の仕方が悪いのでしょうか?

みんなの回答

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

#1、cjです。思い出したことがあったので追加レスします。 現在の記述をそのままに近い形で活かして、短手数で実現する方法です。 裏ワザとして、CommandButton コントロールの隠しプロパティを使います。   frmテスト.CommandButton1.Value = True という記述で   Private Sub cmd終了_Click() を呼び出します。 手順としては、標準モジュールにプロシージャ(1行コード)を追加し、 OnTime メソッドに指定するプロシージャ名を変更するだけです。 一般にあまり知られていない手法ですし、 誰も動作を保証してくれないでしょうから、 以後のメンテは自分ひとりでやる決意が必要ですが、 それでも宜しければ、当座、簡単に済ませられます。 ' ' ===== ThisWorkbook モジュール ====== Private Sub Workbook_Open()   Worksheets("シート1").Activate   Range("A1").Select   frmテスト.Show vbModeless   Application.OnTime TimeValue("08:00:00"), "Module1.ClickFrmBtn"  End Sub ' ' ===== frmテスト (UserForm モジュール) ====== Private Sub cmd終了_Click()   コードたくさん~(そのまま変更なし) End Sub ' ' ===== Module1 (標準 モジュール) ====== Private Sub ClickFrmBtn()   frmテスト.CommandButton1.Value = True End Sub ' ' ===== ====== ====== ====== ====== ======

すると、全ての回答が全文表示されます。
  • cj_mover
  • ベストアンサー率76% (292/381)
回答No.1

こんにちは。 UserFormモジュール(クラス)の(イベント)プロシージャを他のモジュールから呼び出す ということになるのでしょうけれど、 私としてはやったことない考えたことない課題ですし、有意な情報に辿りつくこともなかったので、 参考回答としての私見になりますれど。 UserFormの場合は、他のクラスモジュール(ThisWorkbookやSheet)とは違って、 呼び出されて(読み込まれて)初めてインスタンスを持つ(存在する)ので、 配下のプロシージャを、他のモジュールから呼び出すことは (配下のマクロをアプリケーションのスケジュールに渡すことは) 出来ない、と考えた方がいいんじゃないでしょうか。 対処としては、 「複数の契機から呼び出される共通の処理は、標準モジュールに書く」 というような教科書的な設計が、例として挙げられます。 ' ' ===== ThisWorkbook モジュール ====== Private Sub Workbook_Open()   Worksheets("シート1").Activate   Range("A1").Select   frmテスト.Show vbModeless   Application.OnTime TimeValue("08:00:00"), "Module1.FrmCloseSeq"  End Sub ' ' ===== frmテスト (UserForm モジュール) ====== Private Sub cmd終了_Click()   Application.Run "Module1.FrmCloseSeq" End Sub ' ' ===== Module1 (標準 モジュール) ====== Private Sub FrmCloseSeq()   コードたくさん~ End Sub ' ' ===== ====== ====== ====== ====== ====== 「コードたくさん~」と記された処理群は、  cmd終了_Click イベント と  Workbook_Open イベント(OnTime メソッドを介す) と、 2つの契機(イベント)から共通で呼び出されているという見方ができます。 通常、こういった場合は、共通の処理を 標準モジュールのプロシージャに纏めて記し、 それぞれのイベントから標準モジュールのプロシージャを呼び出すようにします。 注意点は2つ。どちらも標準モジュールの記述について、   1■親オブジェクト(frmテスト)を正しく指定すること。   2■UserForm が読み込まれていない(未Load|既UnLoad)場合のエスケープ。 1■ UserForm モジュールでは、   親オブジェクトを指定しない書き方 例: TextBox1.Value = ""   Me キーワードで親オブジェクトを指定する書き方 例: Me.TextBox1.Value = ""   UserForm オブジェクト(クラス)を指定する書き方 例: frmテスト.TextBox1.Value = " など主に3通りの書き方が可能ですが。 標準モジュールの記述として書き換える時には、   frmテスト.TextBox1.Value = "" のように、親オブジェクト(クラス)を指定する必要があります。 (大抵は   With frmテスト     .TextBox1.Value = ""     コードたくさん~   End With  のようにWith フレーズで纏めて書くことが多いです。) 2■ しかし、UserForm が読み込まれていない(ユーザー操作で既に閉じられている等)時に、 UserForm オブジェクト(クラス)を呼び出してしまうと、 (例えば、 frmテスト.TextBox1.Value = "" を実行するなど) そこで、UserForm があらためて読み込まれてしまい、 Initialize イベントなどに書かれた処理が実行され、 思わぬことになる場合もあるので、注意する必要があります。 これを回避するには、UserForm オブジェクト(クラス)を呼び出す前に、 UserForm が読み込まれているかどうかを 事前にチェックして条件分岐する必要があります。 UserFormがひとつしかない場合ならば、   If UserForms.Count > 0 Then     コードたくさん~   End If とか、   If UserForms.Count = 0 Then Exit Sub     コードたくさん~ とか。 UserFormが複数ある場合は、   For i = 0 To UserForms.Count - 1     If UserForms(0).Name = "frmテスト" Then Exit For   Next i   If i = UserForms.Count Then Exit Sub     コードたくさん~ とか。 (※ここら辺の対応はExcelのバージョンによる違いが大きいです。) ■■ 以上は一例です。 イベントプロシージャを他のプロシージャから呼び出すこと、 についてはネガティブな意見がわりと多いと思います。 厳禁だという人もいるでしょうし、構わないとする人もいるでしょう。 私としては、奨めませんし、自分ではやらない、ですけど、 ダメとは言わないし、特に害が無さそうならばお手伝いすることもあります。 ただ、質問者さんご自身が、どうしようか迷うようでしたら、 標準モジュールを使っていく方が、先々メンテナンスが楽になるという意味で お奨めです。 とりあえず、以上です。何かあれば補足欄にでも書いてみてください。

すると、全ての回答が全文表示されます。