
EXCEL VBA WEBページを参考にして、あれこれ失敗してはなんとか、色々なコードを書いてきました。そんな学び方なので、基本がきちんとわかっていないようで、いつもすんなりいきません。
さて、教えてください。
EXCEL のファイルが開いたあと、ユーザーフォームを表示して、自動的にエクセルが終了するようなマクロを作りたくて、次のようなコードを書きました。
Private Sub Workbook_Open()
Dim Waittime As Date
Worksheets("sheet1").Select
UserForm1.Show vbModeless
Waittime = Now() + TimeValue("00:0:10")
Application.Wait Waittime
Unload UserForm1
Application.DisplayAlerts = False
Application.Quit
End Sub
しかし、
ワークブックを開きにいくと、エクセルが立ち上がりにいきますが、
ワークシートが開かず、ユーザーフォームだけが表示されてエクセルが終わってしまいます。
本当は、ワークシート上に入力してある色々な内容をまず見せて、
それから最後にユーザーフォームを表示してエクセルを閉じさせたいので、ユーザーフォームが表示されるだけでは困るのです。
どのようにコードを直せば、ワークシートが開かれてシート上の内容が表示され、そのあとユーザーフォームが表示されて、エクセルが終了するようになるでしょうか。
アドバイス、どうか、よろしくお願いいたします。
No.16ベストアンサー
- 回答日時:
ということは、エクセルが通常開いたときは、最初に開いているシートがアクティブである(がアクティブに変化しないとプロシージャの内容は働かない)ということなのですね、、、。
ということは、シート2を開いた状態で常に閉じるようにすれば、オープン時の命令はシート1をアクティブにする内容だけで足りるということにりますね。
>シート2を選択した状態であれば、Workbook_Openの中は
Sheets(1).Activate
Sheets(1).Range("A1").Select
だけで十分でしょ? という意味だと思いますが、答えはNOです。
以下、私の仮説になります。
Workbook_Openが実行されたタイミングでは、おそらくワークブック自体がアクティブになっていません。
そして、ワークブックがアクティブになってない状態でシートのアクティブをしても 、ワークブックとシートがアクティブになるだけで
Worksheet_Activateは実行されないようです。
Worksheet_Activateが実行される条件は、ワークブックがアクティブである状態で、シートを非アクティブからアクティブに変更することのようです。
ですので、上記コードだとワークブックとシートがアクティブになるだけでWorksheet_Activateは実行されません。
『ということは、シート2を開いた状態で~~~』を実現したいのであれば、以下のように記述すれば実現できます。
ThisWorkbook.Activate
Sheets(1).Activate
※今更ではありますが、Sheets(1).Range("A1").Select は不要です。
ただ、ブック保存時のシート2を選択し忘れると動きませんので、個人的にはどのシートで保存しても動くシート2→シート1の方が良い気がします。
Worksheet_Activate プロシージャ内の 標準モジュールのプログラムを呼び出す内容を、そのままWorksheet_Activate プロシージャ内に書いたのでは、私の考える動きは実現できないのでしょうか?
>Worksheet_Activate内に書きたいのではなく、Workbook_Open内に書きたいの誤りですかね?
すいません、貴方の言う通りです。
Workbook_Openに書けば、Worksheet_Activateに書く必要はありません。
ただ、標準モジュールのプログラムを呼び出す前に、シート1をアクティブにするコードは入れておいた方が良いと思います。
No.15
- 回答日時:
〇 Sheet1 をActiveにするためには、一旦シート2をActiveにしないとならないのでしょうか?
>Worksheet_Activateはシートが非アクティブからアクティブになったときに実行されますので、
シート1以外のシートをアクティブ(シート1を非アクティブ)にしてあげる必要があります。
シート1がアクティブのときに.Activateをコードしても、Worksheet_Activateは実行されません。
〇 Worksheet Activate プロシージャから 少し時間をおいて 標準モジュールのプログラムを呼び出すという流れは、シート1が開かないうちにユーザーフォームが表示されて終わってしまうことの防止につながっているような想像をしていますが、そういうことなのでしょうか?
>すいません、特に意味はありません。ですので、以下でも要件を満たせます。
変更前:Application.OnTime Now + TimeValue("00:00:01"), "フォーム開く"
変更後:Application.OnTime Now, "フォーム開く"
No.14
- 回答日時:
No.11のママチャリです。
混乱させてしまって、申し訳ありません。
No11に、訂正内容を記載しておりますが、その内容が正しく伝わっていないようです。
もう一度、冷静になって、再確認してみて下さい。
>現況は、ThisWorkbookモジュールのWorkbook_SheetActivateプロシージャ?に
誤)ThisWorkbookモジュールのWorkbook_SheetActivateプロシージャ
正)ThisWorkbookモジュールのWorkbook_Activateプロシージャ
No.13
- 回答日時:
おはようございます。
#5,6です。
私は、#4nekorondaさんの回答で希望されている挙動を得られると思っています。
その上で、#5で他の方法を検証感覚で提案しました。
回答と思われるものがあるにもかかわらず、#6で検証結果を回答したのは、この処理が何のために行いたいかを想像したからです。
(合理的な使用目的は想像できませんでしたが)
ここで、再度書き込みするのは、検証時のアドバイスが目的です。
1つ気になる点があります。
質問者様のコードは、シート名を指定していますが、#4、回答はインデックスです。また、2つ以上のシートがある事が条件になります。
質問者様のシート構成など不明の為、このあたりの不具合で検証に差異が出来ないように指摘させていただきます。
>最初にシート1が開いたときは、Workbook_SheetActivate の状態ではないということみたいです。
Workbook_SheetActivateもWorksheet_Activateも同じですが、アクティブになったら発生するので
開いた時には、変化しないので発生しません。
どちらのイベントに書いても良いと思いますが、Workbook_SheetActivateの場合、ブックにあるすべての
シートで発生するので、シート2をアクティブにした時にもシート1をアクティブにした時にも発生します。
従って、シート1でのイベントを拾うために使用するなら、シートオブジェクト Sh を使用して限定する必要があります。
実は、この処理が何のために行いたいか 興味があります。もちろんそれの補足は、不要です。
シートを表示して、UserFormを vbModeless で表示
ここで、Waittimeを実行しなければ、ブック操作は可能と思いますが、Waittimeを実行してApplication.Quit
UserFormで操作するだけなら、vbModelessである必要が無いと思うので、、、、
実は、この質問をすることになった理由は、
マクロウィルス?(正確にはそういっていいのかどうかわかりませんが)を体験的に学ぶ材料として、エクセルファイルを開いたときに、まずシート1上でメッセージを見てもらったうえ、表示等を変化させ、更には最後にメッセージを表示して、そのままエクセル自体が閉じてしまう というようなワークブックを作ろうとした。このような背景によるものです。
おそらく、皆さんは、開いたあと勝手に閉じてしまうワークブックなど何の意味があるのだろう ???? な気分であったのだろうと思います。
ワークブックは基本設定により、シート3まで用意されているので、シートを切り替えたうえ、特定のセルを選択することにより、当該シートをアクティブにすることによりプロシージャ?の内容が実行されるようにする。
これでいける気がしてきています。
VBmodelessも 確か、指定しなかったら、フォームを閉じないと先に進まなかった? からそうしてみた 程度のことで、ひょっとしたら、そうしなくても動くのかもしれません、、、。
>私は、#4nekorondaさんの回答で希望されている挙動を得られると思っています。
そんな気がしていますので、やってみます。
よくわかっていない私が、途中で、
「Workbook_SheetActivate プロシージャに書けば行けるのでは」というアドバイスをいただいて、シートが開いただけではアクティブにはならないという知識がなかったため、相当皆さんのお手を煩わせた気がします。
今回、ほんとに、いつもそうですが、勉強になりました。
ここに、この話題にお付き合いいただいた、皆さんに改めて感謝いたします。
>シート1でのイベントを拾うために使用するなら、シートオブジェクト Sh を使用して限定する必要があります。
の意味も、よーくもう一度皆さんのコメントを考えあわせて理解できるかなという程度のレベルです。
頑張ります。
No.12
- 回答日時:
いろいろな方が、しろうとにお付き合いいただいて、感謝です。ありがとうございます。
具体的には明日以降、自分でコードを書いてやってみます。
ワークブックオープン時に、一旦シート2のセル選択したあと、シート1のセルを選択、
これによりシート1をアクティブにする。
シート1モジュールには、シート1がアクティブになった時のコードを書き、
実行する細かい内容は標準モジュールに記載
こんなイメージに解釈いたしました。
シート1はワークブックが開いただけではアクティブにならない?んですね、、、。
まだまだわからない世界です、、、。
No.11
- 回答日時:
No.7です。
補足コメント読みました(これは、私への補足で合ってますよね?違っていたら無視してください)
>シート1モジュールのWorkbook_SheetActivateイベントプロシジャにコードを書いてみました。
シートモジュールに、「Workbook_SheetActivate」イベントプロシジャって、ありますか?
私のExcelのシートモジュールには、「Worksheet_Activate」しかないのですが・・・。
「Workbook_SheetActivate」は、「thisWorkbook」モジュールでしょ!!
本題です。
申し訳ございません。私の認識不足でした。実際にやってみたらダメでした。
そこで、回答を次の通り、訂正させてください。
「thisWorkbook」モジュールの「Workbook_Activate」イベントプロシジャに書いてください。
大変、失礼いたしました。
いろいろとありがとうございます。
Workbook_SheetActivateの勘違いは私がしろうとがゆえの思い込み?
ThisWorkbookモジュールにはないと思い込んで、似たようなものをシート1に見つけてそこに書いてしまったものと思います。
さて、いろいろやっているうちに訳がわからなくなってきてしまって、、、
現況は、ThisWorkbookモジュールのWorkbook_SheetActivateプロシージャ?に
Private Sub Workbook_SheetActivate(ByVal Sh As Object)
Dim Waittime As Date
UserForm1.Show vbModeless
Waittime = Now() + TimeValue("00:0:10")
Application.Wait Waittime
Unload UserForm1
Application.DisplayAlerts = False
Application.Quit
End Sub
となっています。
ブックを開くと、シート1が表示されますが、そのままで、シート2を選択すれば、フォームが表示されたのちエクセルが終了します。
目指すのは、シート1が最初に表示され、そこに入力されている内容が確認できるうえにフォームが現れるというもの。
さらにどんな加工を加えれば、それが実現できますでしょうか?
あるいはそんなこと無理でしょうか?
No.10
- 回答日時:
すいません、No.9を訂正させていただきます。
一旦、以下のように
Sheets(2).Activate
Sheets(2).Range("A1").Select
Sheets(1).Activate
Sheets(1).Range("A1").Select
コード上で別シートを選択させた後にシート1を選択すれば実行されます。
No.8
- 回答日時:
他の回答者から指摘ありましたが、
No.4のプログラムではユーザーフォームが開いているタイミングで、
ctrl + Break キーを押せばデバッグモードに入れますので為念補足させて頂きます。
No.7
- 回答日時:
Workbook_Openイベントプロシジャに、コードを書いているようですが、Workbook_SheetActivateイベントプロシジャに書けば、良いような気がします。
ちなみに、このコードだと、二度とブックの編集ができなくなりそうですが、何か対策されてます?
解答ありがとうございます。
編集は、セキュリティセンターの設定をマクロが開かないようにした後しています。
「Workbook_SheetActivateイベントプロシジャ」?
の知識経験がないため、今まで書いたことのあるコードの選択肢しかなく、このような形になったのだと思います。
ちなみに、このWorkbook_SheetActivateイベントプロシジャ
を使えば、最初にシート1が開いた後にシート1に入力した内容が見れて、その後コードに書いた内容が実現されると考えてよろしいでしょうか?
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
エクセルで複数のシートに画像...
-
エクセルシートの見出しの文字...
-
【ExcelVBA】マクロの入ったシ...
-
エクセル、特定のシートにパス...
-
ハイパーリンクでジャンプした...
-
エクセルでブック内の倍率がバ...
-
エクセルを開くとメニューバー...
-
エクセルの複数シートでのリン...
-
EXCELの図形(テキストボックス)...
-
エクセルのファイルサイズが急...
-
特定のシートのみ再計算させな...
-
エクセルで誤ってF11キーを押す...
-
エクセルVBAでエラー!
-
エクセルのシート名のフォント...
-
EXCELで複数のシートを一度に「...
-
Wordで差し込み印刷時に表示す...
-
ワード差込ファイルで複数エク...
-
EXCELの「シートの見出し」のフ...
-
アクセスからエクセルのシート...
-
DATE関数 4月31日などのあ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
EXCELで複数のシートを一度に「...
-
エクセルでブック内の倍率がバ...
-
ハイパーリンクでジャンプした...
-
特定のシートのみ再計算させな...
-
【ExcelVBA】マクロの入ったシ...
-
エクセルシートの見出しの文字...
-
EXCELの図形(テキストボックス)...
-
エクセルのシー名を二段表示に...
-
エクセルのファイルサイズが急...
-
エクセルで複数のシートに画像...
-
エクセル、特定のシートにパス...
-
エクセルの複数シートでのリン...
-
ワークシートそのものの色を変...
-
Wordで差し込み印刷時に表示す...
-
Accessのテーブルを既存のExcel...
-
エクセルの2つのシートを並び...
-
EXCELで存在しないシート...
-
Nintendo Switch 2 キャリング...
-
エクセルを開くとメニューバー...
-
エクセルで、シートの名前を変...
おすすめ情報
シート1モジュールの
Workbook_SheetActivateイベントプロシジャ
にコードを書いてみました。
今度は、シート1は開きますが、一度他のシートを選択して、もう一度シート1を選択し直さないと、コード内容が実行されません。
最初にシート1が開いたときは、Workbook_SheetActivate の状態ではないということみたいです。
これがあと解決されれば、目的達成ということになりそうです。
どなたか、アドバイスいただけると幸いです。
皆さん、本当に色々と考えてくださって、お付き合いくださりありがとうございました。
Qcahan1962さんのおっしゃる通り、nekorondaさんのアドバイス通りにやってみたところ、望む結果を得ることができました。
#4あたりで、nekorondaさんの内容が難しく思えて、そのあと Worksheet activate?プロシージャに書けば全て解決みたいに安易に考えてしまいそれに飛びつき、色々とアドバイスをいただいてふらふらしているうちに、自分でやっていることが混乱、皆さんのお手を相当煩わす結果となり、反省しております。
何人もの方に、この素人の私が投げかけた、実務上意味のない内容にかかわっていただき、皆さん方全員にお礼を形にしたいのですが、ベストアンサーを無駄にはしたくないので、早期から解決策を教えてくださっていた、nekorondaさんをベストアンサーとさせていただきます。
ところで、更にこの素人の私に、もしよろしかったら、教えていただきたいことがあります。
〇 Sheet1 をActiveにするためには、一旦シート2をActiveにしないとならないのでしょうか?
〇 Worksheet Activate プロシージャから 少し時間をおいて 標準モジュールのプログラムを呼び出すという流れは、シート1が開かないうちにユーザーフォームが表示されて終わってしまうことの防止につながっているような想像をしていますが、そういうことなのでしょうか?
>シート1以外のシートをアクティブ(シート1を非アクティブ)にしてあげる必要があります。
ということは、エクセルが通常開いたときは、最初に開いているシートがアクティブである(がアクティブに変化しないとプロシージャの内容は働かない)ということなのですね、、、。
ということは、シート2を開いた状態で常に閉じるようにすれば、オープン時の命令はシート1をアクティブにする内容だけで足りるということにりますね。
Worksheet_Activate プロシージャ内の 標準モジュールのプログラムを呼び出す内容を、そのままWorksheet_Activate プロシージャ内に書いたのでは、私の考える動きは実現できないのでしょうか?
(やってみますが、)できない場合、その理由を教えていただくと、知りたがり屋の私はとてもありがたいです。
これで最後の質問にします。
本当におつきあいありがとうございました。