Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


3499 / 13645 ツリー ←次へ | 前へ→

【61806】ModelessなUserFormが消えてしまいます うにボンバー 09/6/5(金) 17:00 質問[未読]
【61807】Re:ModelessなUserFormが消えてしまいます もも 09/6/5(金) 17:53 発言[未読]
【61810】Re:ModelessなUserFormが消えてしまいます ichinose 09/6/5(金) 20:46 発言[未読]
【61811】Re:ModelessなUserFormが消えてしまいます うにボンバー 09/6/6(土) 0:39 発言[未読]
【61812】Re:ModelessなUserFormが消えてしまいます ichinose 09/6/6(土) 7:38 発言[未読]
【61815】Re:ModelessなUserFormが消えてしまいます うにボンバー 09/6/6(土) 10:03 お礼[未読]
【61822】Re:ModelessなUserFormが消えてしまいます もも 09/6/8(月) 8:51 お礼[未読]
【61813】Re:ModelessなUserFormが消えてしまいます Yuki 09/6/6(土) 9:39 発言[未読]
【61814】Re:ModelessなUserFormが消えてしまいます Yuki 09/6/6(土) 9:56 発言[未読]
【61816】Re:ModelessなUserFormが消えてしまいます うにボンバー 09/6/6(土) 10:11 お礼[未読]

【61806】ModelessなUserFormが消えてしまいます
質問  うにボンバー  - 09/6/5(金) 17:00 -

引用なし
パスワード
   はじめまして、検索でこのサイトにたどり着きました。
初めて質問させていただきます
OSはWindowsXP SP3、ExcelはExcel2003です。

まず、やりたいことですが、ModelessなUserFormにいろいろなツール群があって
それを使ったり、または直接Excelのワークシートを編集したり、ということをしたいのですが、
どうしても解決できない問題に行き当たりました。

発生する条件を、可能な限り簡略化すると、
まず、WorksheetにコントロールツールボックスからCheckBoxを一つ貼り付けます。
次に、UserFormをひとつ作成し、Buttonを一つ貼り付けます。

Private Sub CommandButton1_Click()
 Sheet1.CheckBox1.Copy
 Sheet1.Paste Sheet1.Range("C4")
End Sub

という具合に、Worksheetに貼り付けたCheckBoxをCopy & Pasteする
動作を、Buttonに設定します。
また、ShowModalプロパティをFalseに設定してModelessになるようにしておきます。
次に、

Private Sub Workbook_Open()
 UserForm1.Show
End Sub
という具合に、Workbookを開いたときに、そのUserFormが開くようにしておきます。

ここまで記述して、一度保存をして閉じて、もう一度開きます。
ここで、自動的に表示されたUserFormのButtonをクリックすると、
CheckBoxが一つコピーされて、そのままUserFormが消えてしまいます。

なぜ消えるのかわからず、CheckBoxをCopy & Pasteしたあとに、
HideとShowを書いてみたり、UnloadとLoadを書いてみたり、
挙句には、SetWindowPosなんてのを検索から引っ張り出してやってみたのですが
どうしても再表示することができませんでした。

私の力では、もうどうすることもできない状態ですので、
みなさまのお知恵をお借りしたいと思います。
よろしくお願いします。

【61807】Re:ModelessなUserFormが消えてしまいます
発言  もも  - 09/6/5(金) 17:53 -

引用なし
パスワード
   ▼うにボンバー さん:
>なぜ消えるのかわからず、CheckBoxをCopy & Pasteしたあとに、
>HideとShowを書いてみたり、UnloadとLoadを書いてみたり、
>挙句には、SetWindowPosなんてのを検索から引っ張り出してやってみたのですが
>どうしても再表示することができませんでした。

原因は推測ですが、コピペするときにデザインモードに
なっているからではないでしょうか?

だとすれば消えている(見えない)訳ではなくてUnloadされているのだと
思いますが

確実な対処方法はわかりませんが
代替案として、最初からCheckBoxは作っておいてVisibleをFalseにしておき
必要なときだけTrueにして見えるようにするというのはだめでしょうか?

【61810】Re:ModelessなUserFormが消えてしまいます
発言  ichinose  - 09/6/5(金) 20:46 -

引用なし
パスワード
   こんばんは。
もうだいぶ前ですが、私もこんな質問したことがありました。

www.vbalab.net/vbaqa/c-board.cgi?cmd=one;no=7011;id=excel

原因は、同じだと思います。

>原因は推測ですが、コピペするときにデザインモードに
>なっているからではないでしょうか?

これですね!!リンクスレッドにもありますが、
ステップインで実行すると、

Sheet1.Paste Sheet1.Range("C4")
↑ここでエラーとなります。

シートに対するActiveXControlの動的な作成、削除は
不具合のもとです。


>代替案として、最初からCheckBoxは作っておいてVisibleをFalseにしておき
>必要なときだけTrueにして見えるようにするというのはだめでしょうか?

他には、コマンドバー「フォーム」のCheckboxを使う
こっちは、動的な作成・削除が可能です。

プログラムやUserformが存在するブックと
Checkboxをコピーするブックを別のものにする。

なんて方法が考えられます。

【61811】Re:ModelessなUserFormが消えてしまいます
発言  うにボンバー  - 09/6/6(土) 0:39 -

引用なし
パスワード
   こんばんは、さっそくのご教示ありがとうございます

▼もも さん:
>原因は推測ですが、コピペするときにデザインモードに
>なっているからではないでしょうか?

これを読んで、「なるほど!」と声に出して言ってしまいました。
なるほど、言われて見ればその通りですね!

▼ichinose さん:
>シートに対するActiveXControlの動的な作成、削除は
>不具合のもとです。

なるほど・・・ご教示いただいたスレッドを読むと、
そのような感じですね・・・。
基本的に、そのようなコーディングをしない方向で進めるとして、
それはそれとして、問題をもう少し詰めてみました。

まず、UserFormがModalなとき、いくらでもCopy & Paste出来てしまうのが、
何となく納得いきません(汗)
それから

▼もも さん:
>だとすれば消えている(見えない)訳ではなくてUnloadされているのだと
>思いますが

これですが、UserFormのButtonの動作を以下のようにしてみると
「実行時エラー '400':
 フォームは既に表示されているので、モーダル表示することはできません。」
とエラーが出ます。

Private Sub CommandButton1_Click()
 Sheet1.CheckBox1.Copy
 Sheet1.Paste Sheet1.Range("C4")
 UserForm1.Show vbModal
End Sub

つまり、Unloadされているわけでもなく、Hideすらされているわけでもなく、
アプリケーション的にはShowされたまま、
人間の目には(変な言い方ですが)見えなくなっている状態なのではないでしょうか?

加えて、UserFormのすべてのイベントを拾うように書いてみましたが、
人間の目には消えたように見えても、QueryCloseやTerminateはもちろん、
その他のどんなイベントも拾えませんでした。

うーん・・・やっぱり人間の目に見えてないだけで・・・・
ってオカルトじゃないんだから(汗)

すいません、もう少しいろいろ試してみますので、
何か追加情報があればよろしくお願いします。

【61812】Re:ModelessなUserFormが消えてしまいます
発言  ichinose  - 09/6/6(土) 7:38 -

引用なし
パスワード
   おはようございます。
ActiveXControlの作成・削除(貼付けも含む)ことによる
データ初期化のタイミングの問題だと思いますよ!!

新規ブックの標準モジュールにて

'================================================
Private a As Long
Sub main()
  a = 15
  ActiveSheet.OLEObjects.Add _
       ClassType:="Forms.CommandButton.1", Link:=False, _
       DisplayAsIcon:=False, Left:=[a1].Left, _
       Top:=[a1].Top, Width:=[a1].Width, _
       Height:=[a1].Height
  MsgBox a
  'ActiveXControlが作成された直後、変数aの値は、ちゃんと設定値を保持している
  Application.OnTime Now(), "subproc"
End Sub
'======================================================================
Sub subproc()
  MsgBox a
  'Ontimeメソッドによって、起動されたSubprocでは変数aは、0 初期化されている
End Sub

上記のmainを実行すると
ActiveXControlを動的に作成したmainのプロシジャーが終了するまでは、
変数aの値は保持されています。
が、mainのプロシジャーが終了してOntimeメソッドにより直ちに実行されたSubprocでは、既に変数aの値は、初期化されています。
Ontimeメソッドの実行は、

Private a As Long
Sub main()
  a = 15
  ActiveSheet.OLEObjects.Add _
       ClassType:="Forms.CommandButton.1", Link:=False, _
       DisplayAsIcon:=False, Left:=[a1].Left, _
       Top:=[a1].Top, Width:=[a1].Width, _
       Height:=[a1].Height
  MsgBox a
End Sub
Sub subproc()
  MsgBox a
End Sub

上記のmainを実行した直後に手動操作でsubprocを実行することと同じです。

つまり、デザインモードになる
(正確には、三角定規のアイコンをクリックし、デザインモードにしてから、再度
三角定規のアイコンをクリックし、デザインモードを終了するという
操作を行った効果)のは、
ActiveXControlの作成・削除(貼付けも含む)を行った
プロシジャーの実行が終了した時点で発生する ということです。


よって、うにボンバーさん事例に戻すと

モーダルモードでは、

>いくらでもCopy & Paste出来てしまう

のは、モーダルモードでは、
コマンドボタンクリックする時点では、
プログラムの制御は、Showメソッドのラインで止まったままです。

sub main()
  userform1.show
ens sub

つまり、
ActiveXControlの作成・削除(貼付けも含む)を行った
プロシジャーの実行が終了していません。

つまり、ボタンクリックという操作の時点では、まだmainは終了していないのです。

よって、コピー&ペーストが可能になります。

デザインモードになっていないのですから・・・。


これが、モーダレスモードでユーザーフォームを表示させると、

sub main()
  userform1.show Vbmodeless
end sub

mainの実行が終了してから、コマンドボタンクリックされる
という流れになります。
既にmainプロシジャーの実行が終了した時点で
ActiveXControlの作成・削除(貼付けも含む)を行いますから、
CommandButton1_Click()の実行が終了して時点で
デザインモードになりますから、ユーザーフォームが消えてしまいます。

又、

Private Sub CommandButton1_Click()
 Sheet1.CheckBox1.Copy
 Sheet1.Paste Sheet1.Range("C4")
 UserForm1.Show vbModal
End Sub

これに関しては、
ActiveXControlの作成・削除を行ったCommandButton1_Clickが
未だ終了していない時点での

UserForm1.Show vbModal

ですから、

「フォームは既に表示されているので・・・」

のエラーが発生するのです。


以上ですが、デザインモードなる時期(タイミング)の問題だと思います

【61813】Re:ModelessなUserFormが消えてしまいます
発言  Yuki  - 09/6/6(土) 9:39 -

引用なし
パスワード
   ▼うにボンバー さん:
たくさんの回答者さんの意見がありますが。

どうしてもというのなら
OnTime を使用して
Private Sub CommandButton1_Click()
  Application.OnTime [=NOW() + TIMEVALUE("00:00:00.1")], "FormShow"
  UserForm1.Hide
  DoEvents
  Sheet1.CheckBox1.Copy
  Sheet1.Paste Sheet1.Range("C4")
  Application.CutCopyMode = False
  DoEvents
End Sub

標準モジュールに
Public Sub FormShow()
  UserForm1.Show 0
End Sub

とでもすればいいでしょう。
でもシートがデザインモードになった時点でApplicationが初期化
されますのでそれを踏まえた上で使用されたほうが宜しいかと思います。

【61814】Re:ModelessなUserFormが消えてしまいます
発言  Yuki  - 09/6/6(土) 9:56 -

引用なし
パスワード
   ▼うにボンバー さん:

訂正です。

>Public Sub FormShow()
>  UserForm1.Show 0
   Application.ScreenUpdating = True '<=追加して下さい。
   ' 黒枠のオバケみたいなのが残りますので
>End Sub
>

【61815】Re:ModelessなUserFormが消えてしまいます
お礼  うにボンバー  - 09/6/6(土) 10:03 -

引用なし
パスワード
   おはようございます。
さっそくのレス、ありがとうございます。

▼ichinose さん:
>ActiveXControlの作成・削除(貼付けも含む)ことによる
>データ初期化のタイミングの問題だと思いますよ!!

なるほど!思わず唸ってしまいました。
流石と言うほかはありません。完璧に納得いたしました。

以降、蛇足ですが・・・

>  Application.OnTime Now(), "subproc"

ここにヒントがありました。

Private Sub CommandButton1_Click()
 Sheet1.CheckBox1.Copy
 Sheet1.Paste Sheet1.Range("C4")
 Application.OnTime Now(), "UserFormShow"
End Sub

Sub UserFormShow()
 UserForm1.Show
End Sub

と言う具合にすれば、とりあえずUserFormの再表示は出来てしまいました(^^;;
私のやろうとしていることは、UserForm上のツールを使いながら、
Worksheetを編集していく作業ですが、実際のところ、
UserForm上のボタンが押されてから、Worksheet上の値を読み込んで、
なんらかの処理を施す、と言った流れです。
ので、保持しなければならない変数はありませんので、
(当該マクロは会社にありますので、月曜日まで試せませんが)
今のところ、おそらく上記で事足りるような気がします。

が、ここまでご教授いただいた内容を考えますと、
どう考えても、将来的にどこかで何らかの不測の不具合をもたらすであろうことは
想像に難くありませんので、やはり、ActiveXコントロールそのものを
使わない方向で書き直すこととします。

最後になりましたが、
ももさん、ichinoseさん、ほんとうにありがとうございました。
具体的な例を示していただきながらの、わかりやすい解説で、
大変勉強になりました。
これからも微力ながら、VBA道に精進したいと思います(苦笑)

それでは、失礼いたします。

【61816】Re:ModelessなUserFormが消えてしまいます
お礼  うにボンバー  - 09/6/6(土) 10:11 -

引用なし
パスワード
   レスありがとうございます。
ももさん、ichinoseさんへのお礼レスを書いている間に、
新しいレスをいただいていたようで、ありがとうございます。

▼Yuki さん:
>Private Sub CommandButton1_Click()
>  Application.OnTime [=NOW() + TIMEVALUE("00:00:00.1")], "FormShow"
>  UserForm1.Hide
>  DoEvents
>  Sheet1.CheckBox1.Copy
>  Sheet1.Paste Sheet1.Range("C4")
>  Application.CutCopyMode = False
>  DoEvents
>End Sub
>
>標準モジュールに
>Public Sub FormShow()
>  UserForm1.Show 0
>End Sub
>
>とでもすればいいでしょう。
>でもシートがデザインモードになった時点でApplicationが初期化
>されますのでそれを踏まえた上で使用されたほうが宜しいかと思います。

>▼うにボンバー さん:
>
>訂正です。
>
>>Public Sub FormShow()
>>  UserForm1.Show 0
>   Application.ScreenUpdating = True '<=追加して下さい。
>   ' 黒枠のオバケみたいなのが残りますので
>>End Sub
>>

なるほど、ちゃんとした記述をするためには、
このように書くのですね・・・・。
また一つ勉強になりました。
ありがとうございました。

【61822】Re:ModelessなUserFormが消えてしまいます
お礼  もも  - 09/6/8(月) 8:51 -

引用なし
パスワード
   ▼ichinose さん:
こんにちは

>以上ですが、デザインモードなる時期(タイミング)の問題だと思います

デザインモードの「タイミング」。なるほど勉強になります。
モーダルの場合とモードレスでのコードの進み具合(?)
というか止まるか動ききってしまうかの違いも納得です。
(というか忘れていました)

安直な回答してしまって恥ずかしいですが
私も勉強になりました。ありがとうございます。

3499 / 13645 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free