[[20191114201326]] 『ユーザーフォームのボタンで別のユーザーフォーム』(マクロ覚えたて初心者) ページの最後に飛ぶ

[ 初めての方へ | 一覧(最新更新順) | 全文検索 | 過去ログ ]

 

『ユーザーフォームのボタンで別のユーザーフォームを呼び出すと強制終了する』(マクロ覚えたて初心者)

私はよくユーザーフォームの中にボタンを設置し、そのボタンを押すことで「表示中のフォームを閉じ、別のフォームを開く」動作を用いています。

コードは以下のようになります。

private sub フォーム2呼び出し_Click()
フォーム2.show
unload me
end sub

普段は問題なく起動するマクロなのですが、ある日唐突にフォームのボタンを押すと、エクセル自体が強制終了するようになります。
強制終了するようになってしまったら、PCやエクセルを再起動しても毎回必ず強制終了してしまいます。

現状の対処法としては以下のようにしております。
1当該フォームのコードを表示
2当該フォームのコードを閉じる

コードそのものには一切手を付けず、コードを開いて閉じるだけで正しく起動するようになります。
その後は、正しく起動するようになりますが、またある日突然に強制終了するようになる。の繰り返しです。

特定のフォームでのみこの問題が発生するのではなく、フォーム間の移動のあるコードであればどのフォームでも発生します。

対処法自体は大した手間ではありませんが、問題が発生する以上、同僚のPCに組み込むことが出来ません。
OS・エクセルともに古いバージョンで申し訳ありませんが、何卒ご助力をお願いいたします。

< 使用 Excel:Excel2004(Mac)、使用 OS:MacOSX >


回答ではありませんが、
このサイトの校内全文検索で「ユーザーフォーム 強制終了」で検索をかけてみると
古い相談も含めいくつかのトピックが見つかります。
もしかしたら問題解決につながるヒントがあるかもしれません。
(黄色い循環参照) 2019/11/15(金) 02:44

 MACで可能かどうかわかりませんが

 ・ユーザーフォームモジュールを含めて、すべてのモジュールをエキスポート
 ・モジュールを全削除
 ・マクロなしでいったん保存して閉じる
 ・再度開いて、インポート

 でどうなるでしょう。

 xlsm になって変わったかもしれませんが、
 以前は中間コードのゴミがたまって、容量が肥大したものを上記の手順で、ダイエットした記憶があります。
 誤作動の解決にもなるかもしれません。

(渡辺ひかる) 2019/11/15(金) 08:58


 >private sub フォーム2呼び出し_Click() 
 >フォーム2.show 
 >unload me 
 >end sub

 このコードを書いているフォームをモードレスで開いているとか・・・?。

 それと、過去にといっても20年以上前だけど、プロシジャー名に日本語を使うと
 ファイルすら開けなると言った事があるので、止めといた方が良いかも。
 MacとMSのことなので、何かしらの不具合が残っていそう。
(BJ) 2019/11/15(金) 13:38

こんなにたくさんのお返事を頂き、有難う御座います。

黄色い循環参照 様
拝見させて頂いたのですが、私の事例とは少々違う問題のようですので、新たに質問させて頂いた次第です。
一つ近い事例として、メモリ制限に引っかかるのではないか?とも考えたのですが、フォームを呼び出すフォーム・・・と言いますか。コマンドボタン8個且つ、全てがForm.Show & Unload Me で構成されているフォームでも問題が生じたため、制限に引っかかるほどのコントロールを設置しているわけでも、コードが長すぎるわけでもないかと考えます。

渡辺ひかる 様
私の使用しているMACでもエクスポートは可能のようです。
しかし、エクスポートを行った時点でfrxファイルが作成され、「消してはいけない」「ファイルを移動させる場合はfrxファイルも一緒に移動する」という制限が付いてしまうようです。
提案して頂いて申し訳ないのですが、それでは業務に支障が出てしまう可能性が高いため、この手段を取ることが出来ません。

BJ 様
モードレスという言葉自体が初耳でした。調べてみましたが、モードレスで開いているわけではありません。
プロシージャ名に日本語を使うと〜の件も初耳でした。日本語で作成する癖がついていましたので、急いで変更しようと思います。有難う御座います。

後付けになってしまって申し訳ないのですが、現状では私が個人的に業務を効率化するためにマクロを使用しているに過ぎなかったため、対処法を行って騙し騙し使っておりました。
しかし、他の従業員のためにマクロを作成する必要が出てしまい、問題が発生したり、あまりパソコンが得意ではない従業員だと間違えやすいこと(frxファイルの移動し忘れ)は極力排除したいと考えています。

なお、私がマクロを使っているPCはインターネットに繋がっておらず、アップデートを行うことが出来ません。
それらに起因する事であれば手を付けられないのが現状ですが・・・

わがままばかりで申し訳ありませんが、引き続き皆様のご助力をお願いいたします。
(マクロ覚えたて初心者) 2019/11/15(金) 17:37


 >しかし、エクスポートを行った時点でfrxファイルが作成され、
 >「消してはいけない」「ファイルを移動させる場合はfrxファイルも一緒に移動する」
 >という制限が付いてしまうようです。 

 どんな制限なのか理解できません。

 少なくともWindowsの場合ですが

 ユーザーフォームモジュールをエクスポートするということは、
 UserForm1.frmとUserForm1.frx が生成されるということです。
 前者は、モジュールのコード、後者はユーザーフォーム本体のデータ が書きだされます。
 それだけです。

 仮に2つのファイルを削除、移動しても、マクロファイルには影響しません。

 私のアドバイスを再掲しますが

 ・ユーザーフォームモジュールを含めて、すべてのモジュールをエキスポート
 ・モジュールを全削除
 ・マクロなしでいったん保存して閉じる
 ・再度開いて、インポート

 この後に、エキスポートしたファイルを削除しても何の問題もありません。

 何か勘違いされていませんか?

(渡辺ひかる) 2019/11/16(土) 13:05


渡辺ひかる 様
大変失礼いたしました。まさしく勘違いしていたようです。
elsファイルとともにfrm・frxファイルも移動しなければならないのかと思っておりました。

しかし、テスト用のファイルを作成し、実際にエクスポート・インポートを行ってみたところ、インポートがうまくいきません。

シート1のみのファイルを作製し、A1に「テスト」と記入。
標準モジュール「Module1」にUserForm1.Showを記述。
ユーザーフォーム「UserForm1」にコマンドボタンを一つ設置し、Unload Meを記述。

Module2に上記コードを入力し、Userform1とModule1のエクスポートを行なった際、
UserForm1.frm・UserForm1..frx・Module1.bas の3つのファイルが作成されました。
frxファイルの.が2個になっているのが気になります。

この状態で、UserForm1.frmとModule1.basのインポートを行なった際、Module.basは問題なく取り込むことが出来ましたが、UserForm1.frmはメモリ不足と表示され、取り込むことが出来ませんでした。
frmファイルの容量は4kbで、メモリが足りなくなる様な量ではないかと思われます。
また、frxファイルの.を一つ減らしても結果は変わりませんでした。

インポートが行えない為、この方法での軽量化は難しいようです。

ところで、「中間コードのごみ」とは一体どのようなものなのでしょうか?
例えば、手作業で全てのモジュールとフォームをコピーする、といった方法でも、軽量化は可能なのでしょうか?
(マクロ覚えたて初心者) 2019/11/16(土) 16:10


誤解が解けてよかったです。

ただ、エキスポート、インポートの不具合に関してはなんとも言えません。
MacのEXCELがそこまでサポートしていない可能性もあります。

ちなみに、エキスポートしたあとモジュールをすべて削除して、
一旦保存して、閉じて、再度開いてから、インポートしたのですよね?

中間コードのゴミについては、私も確認したわけではありません。
ただ、昔はマクロの編集を繰り返すとそれだけでファイルが肥大化し、
エキスポート、インポートの処理でダイエットが出来た、と言うのは、事実です。
私のアドバイスは多分外していると思います。
参考程度に受け取ってください。
(渡辺ひかる) 2019/11/16(土) 16:37


渡辺ひかる 様
色々調べてみたものの、原因がわからず…どうにも難しいですね。
module2も含め全てのモジュール・フォームを削除した後に保存、再度開いてmodule2を改めて作成し、module1とUserForm1の取り込みを試みましたので、やり方は間違っていないと思うのですが…

かしこまりました、参考として覚えておこうと思います。
完成したマクロで、編集などは行なっていないにも関わらずこの問題が発生してしまうため、確かに原因としては考えにくいですね。
仮にこれが原因だったとすれば、対処法の無い問題となってしまいますし、むしろ違って良かったとも思えます。

引き続き、問題の解決策を探しております。ご存知の方がいらっしゃいましたら、何卒宜しくお願い致します。
(マクロ覚えたて初心者) 2019/11/18(月) 10:09


 Macにtempフォルダがあるのか解らないし、エクセルが1次ファイルを作るのか不明だけど、
 これらを探して、全部移動か削除してみたらどうでしょうか?
 なんかこれらが悪さをしているような気も・・・。

 それと、ユーザフォーム上で綱渡りをしているようだけど、帰路の事も考えてフォーム上では
 hideで、標準モジュールの戻ってからunloadした方が・・・。

 >メモリ不足と表示され

 Mac版はエラーのアラートがあまり用意されてないのか、こういった意味不明のエラーがでてた。
(BJ) 2019/11/18(月) 10:29

BJ様

macでもcashesというフォルダに一時ファイルは作成されますが、それは定期的に削除しておりますので問題ないかと思われます。

帰路の事も考えてフォーム上ではhideで標準モジュールに戻ってからunload hideメソッドについては考えた事もありませんでした。
現状「ユーザーフォームの表示が消え、次のフォームが表示される前に強制終了が行われる」ので、showに問題があるかと思っておりましたが、Unload Meの方とも考えられるのですね。
実際にコードを変更して試してみて、しばらく様子を見ようと思います。

エラーのアラートについてはあまり考えた事もありませんでした。ネットで検索しても出てこないとは…
その場合、実際はメモリ不足ではなく他に原因が考えられそうですが、そちらに関しても何が問題となっているやら。

ひとまず、BJ様が仰って頂いた方法で試して見ようと思います。
情報は引き続き募集致しますが、経過をみてまた報告に上がりますので、宜しくお願い致します。
(マクロ覚えたて初心者) 2019/11/18(月) 15:57


 >現状「ユーザーフォームの表示が消え、次のフォームが表示される前に強制終了が行われる」ので、
 >showに問題があるかと思っておりましたが、Unload Meの方とも考えられるのですね

 Showするユーザーフォームのintialize(スペル間違ってるかも)や他のコード、ユーザーフォーム上の
 オブジェクト等に問題がある場合もあります。
(BJ) 2019/11/18(月) 20:44

BJ様
initializeの処理は普段は特に問題なく動いておりますが、コードの長さとしてはループを加味して100行分ほどになります。
配置しているコントロールはフォームにもよりますが、最大で10程度。基本的にコマンドボタンで、フォームによってはリストボックスが1つ追加されます(ボックスの要素数は50程度)

一つ例をあげるとすれば以下のような感じです。

Private Sub UserForm_Initialize()
Application.ScreenUpdating = False
Range("B12") = "資材費"
Range("I1") = "2"
ActiveSheet.Name = "○○課" & Range("B9") & "資材費"
Range("A13") = WorksheetFunction.Max(Worksheets(ActiveSheet.Index - 1).Range("A12:A30"))
RowCount = 13
SumsRows = Cells.Find("*領*収*書*").Row - 1

ItemListPath = ThisWorkbook.Path & ":資材単価表"
Workbooks.Open (ItemListPath)
Set ItemList = Workbooks("資材単価表").Worksheets("企業A")
ItemListEnd = ItemList.Range("B65536").End(xlUp).Row

For i = 2 To ItemListEnd

    ItemBox.AddItem ItemList.Cells(i, 2) & ":" & ItemList.Cells(i, 3)
Next i
ThisWorkbook.Activate
Application.ScreenUpdating = True
End Sub

シートに対するちょっとした処理と、同フォルダ内にある別ブック”資材単価表"を起動し、その内の"企業A"シートの資材リストをリストボックスに追加する処理を行なっております。

先ほど、また同じ問題が発生したため色々試してみました。
今後は以下のように呼称します。
普段使っている移動前フォーム=フォームA 移動後のフォーム=フォームB
あらかじめ作成しておいた、フォームBに移動するボタンの入っているフォーム=フォームC

私が今までに行なっていた対処法は以下の通りです。
フォームAのコードを開く→閉じる ○

今試してみたのは以下の通りです。
フォームBのコードを開く→閉じる ×
フォームAを開く→閉じる ×
フォームBを開く→閉じる ×
フォームCのコードを開く→閉じてフォームCからフォームBに移動する ○
フォームCのコードを開く→閉じてフォームAからフォームBに移動する ○

新たな標準モジュールに
sub TestCode()
FormB.Show
End Sub
と記述して、モジュールを閉じないままフォームAからフォームBに移動する ○
→モジュールを閉じても問題なく移動出来ます。

以上から、FormB.Showと記述してあるコードを作るか開くかすれば正しく移動するようになるようですが、どのフォームA・フォームCのどちらからも同じタイミングで移動出来なくなった事を考えると、BJ様の仰る通り、フォームBの内容自体に問題があると考えた方が良さそうですね…

ちなみにこのFormBは先ほど例にあげたフォームのことです。何か問題が分かれば良いのですが…
(マクロ覚えたて初心者) 2019/11/19(火) 09:50


マクロをデバッグ中、強制終了を何度か経験したことがあります。
私の場合はコードに問題がありました。
ステップ実行やブレークポイントまで実行をしながら、
問題のコードまでたどり着き、修正しました。
ただ、何が問題だったかの記憶が定かでなく・・・
環境は、Win8Excel2010でした。
(tkit) 2019/11/19(火) 11:15

tkit様

情報有難う御座います。
私の場合はShowで呼び出すのではなく、直接当該フォームのinitializeを直接起動すると正常に動作するため、コードの問題ではないような気がします。
 
 
 
先ほどと同じくフォームA・B・Cを使って更に検証を重ねたところ、コードに問題があるのではなく、PC自体やバージョン自体の問題のような気がしてきました。

(問題が発生しなくなる為には何をすれば良いかを検証)
・対処法を行う→上書き保存→ブックを閉じる→ブックを開く→実行  問題が発生します。
・対処法を行う→上書き保存→実行→保存せず終了  次回に開いた際に再度問題が発生します。
・対処法を行う→実行→手作業で元の状態に戻す→上書き保存  問題が発生しなくなります。

(対処法の簡略化を検証)
・ブックを開く→何も考えず上書き保存→実行  正常に動作します。但し上書き保存しないと次回開いた際に問題が発生します。
・ブックを開く→上書き保存→ブックを閉じる→ブックを開く→実行  問題が発生します。
※コードを開いたりせずとも、ただ保存だけで実行出来ることが分かりました。

(ステップ実行をしながら確かめていると、シートをコピーした段階で上書き保存して終了すると問題が発生しなくなった為、追加検証)
・適当なシートをコピー→上書き保存して終了  ×
・ブック内に標準モジュールを新設し、マクロでコピー→上書き保存して終了 ○
・個人用マクロブック内に標準モジュールを新設し、マクロでコピー→上書き保存して終了 ×
 
 
また、今の現状問題が再発していることから
・キャッシュの削除
・プロシージャに日本語
はどちらも今回の事例に該当しないようですs。
標準モジュールに戻ってからunloadはまだ修正する前だった為、未検証となっております。
 
 
ここまで来ると私の頭ではもはや理解不能ですが、「何も考えず上書き保存してから実行しろ」という簡単な対応策を見つけることが出来ましたので、未解決のままでもなんとかなりそうです。

もし解決策をご存知の方や、恐らくこうではないかという考えのお持ちの方がいらっしゃいましたら引き続き募集致します。
宜しくお願い致します。
(マクロ覚えたて初心者) 2019/11/19(火) 14:36


 >WorksheetFunction.Max(Worksheets(ActiveSheet.Index - 1).Range("A12:A30"))

 >Cells.Find("*領*収*書*")

 >RowCount
 こういうプロパティがあるとは知らなかったけど。
https://docs.microsoft.com/ja-jp/office/vba/api/office.officedatasourceobject.rowcount

 コードが短い方がカッコいいと思わない。
 結果の有無が解らないものをそのまま使わない。

 Initialize の下に Stop と入れておけば、Showで落ちずに
 ここで止まって、ステップ実行できるんじゃないかと??
(BJ) 2019/11/20(水) 10:00

BJ様

RowCountプロパティは私も初耳です。ただヘルプにも記載されない為、私の使っているエクセルでは対応していないプロパティなのではないでしょうか。
このコードに記述しているRowCountは通常の変数ですので、問題はないかと思われます。

WorksheetFunctionやFindに何か問題があるのでしょうか?
 
 
また、せっかく提案していただいて非常に申し訳ないのですが、上記でも触れております通り「同僚が問題なく使えるマクロ」を目指しております。
同僚の中にはエクセルに詳しくない者もおります。VBEを表示させると間違えてコードを変えてしまったりする可能性がありますので、可能であれば他の手段を取りたいと考えております。
(マクロ覚えたて初心者) 2019/11/20(水) 14:51


 >RowCountプロパティは私も初耳です。ただヘルプにも記載されない為、私の使っているエクセルでは対応していないプロパティなのではないでしょうか。
このコードに記述しているRowCountは通常の変数ですので、問題はないかと思われます

 その辺は、私には解りません。
 2007には、そういったプロパティがあっただけです。 

 >せっかく提案していただいて非常に申し訳ないのですが、上記でも触れております通り「同僚が問題なく使えるマクロ」を目指しております。

 意味がわかなければ、勝手にやれば良いです。

(BJ) 2019/11/20(水) 15:00


 >私はよくユーザーフォームの中にボタンを設置し、そのボタンを押すことで「表示中のフォームを閉じ、別のフォームを開く」動作を用いています。
 >コードは以下のようになります。
 >private sub フォーム2呼び出し_Click()
 >フォーム2.show
 >unload me
 >end sub

 ご理解できているなら、無視してください。
 上記コードは、「表示中のフォームを閉じ、別のフォームを開く」動作はしていません。

                      表示中フォーム    フォーム2 
 フォーム2呼び出し前  Load              unLoad
 >フォーム2.show'     Load              Load

 ※フォーム2がHideまたはunLoad後、次に進みます

 >unload me          unLoad            Hide or unLoad
 >end sub

 ですので、場合によっては、別のフォームが閉じた後に閉じる動作となります。

 再帰的にフォームが呼び出されて、ハングアップしてるように感じます。

 モードレスでフォームを開くか、標準モジュール上で、フォーム表示非表示をコントロールすると改善するかもしれません。
 まずは、ステップ実行で強制終了が再現するか確認してみましょう。
(tkit) 2019/11/20(水) 16:52

BJ様
私の不勉強と我儘により大変不快な思いをさせてしまい申し訳ありません。
幾度もアドバイスを頂き有難う御座いました。

tkit様
これは盲点でした。確かに言われてみればshow→unloadでは「閉じてから開く」ではありませんでした。
・モードレス表示
・標準モジュールでの表示非表示のコントロール
以上2点、早急に取り掛かろうと思います。
 
ステップ実行では強制終了することなく正しく起動いたします。
また、ステップ実行を行わずとも、「コードを開いた状態で実行」としても、正しく起動いたします。

(マクロ覚えたて初心者) 2019/11/20(水) 20:33


コメント返信:

[ 一覧(最新更新順) ]


YukiWiki 1.6.7 Copyright (C) 2000,2001 by Hiroshi Yuki. Modified by kazu.