[[20150503143714]] 『ユーザーフォームShowでエクセルが強制終了される』(ku) ページの最後に飛ぶ

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

 

『ユーザーフォームShowでエクセルが強制終了される』(ku)

お世話になります。
ユーザーフォームShowでエクセルが強制終了されて困っています。
エラーは「Automation Error 例外が発生しました」、もしくはそのエラーもなく、強制終了になります。
あらかじめVBAでフォームを開いていると、問題なくフォームが開き、全ての動作が正常に働きます。

デバグはハイライトされないのでコード的には問題ないと思われ、ステップで確認すると、Form.Showから始まってInitializeに飛び、上から順にEnd Subまで反転します。
一部他のプロシージャに飛んでいた箇所がありましたので、それはActivate()に移したところ飛ばなくなりました。
ちなみに、Initializeから他のプロシージャに飛ぶのはマズいですか?

End Subの時点で、エクセルでフォームが開きます。
VBAを開けていると開くように、何でもなかったようにフォームが開きます。

現在フォームが開くファイル(コード未完成)のものがありますが、フォームを閉じる時にはフォーム上で編集した個所をエクセルに書き込んでいくわけですが、問題なく作業をしています。
作業に入る前に、空白枠をそのままにするかどうかの確認画面のメッセージボックスが出ます。
YESは戻って編集を続け、Noはそのままシートへの書き込み作業に入り終了後にフォームがが消えるようになっています。
そのフォームが開くファイルで、編集しようとしまいと、保存してしまったら、次にファイルを開いたときにフォームは開かないのです。
プロシージャを修正して保存したら当然開かなくなります。
どうしてこの時点でフォームが問題なく開くファイルができたのかはわかりませんが。。。

似てるかと思われるフォームが開かない問題の投稿を他で見まして、その場合は原因はマルチページとのことでした。
フォームにはマルチページを使っていますが、
古いバージョンで既に同じマルチページを使っており問題なく実用しています。
あえて言うと、新しいものはそれにもう2つマルチページを使っている違いがあります。
その為かとも思い、追加したマルチページを取り除いて、コードもそれに併せて修正してみましたが、一度保存するとフォームが開かなくなります。

Initializeではフォームを事前に準備する作業、例えばプルダウンの選択値やシートからのデータ読込、条件によるテキストボックスのロックなどの作業をCallで入れています。
これらをActivate()に移したファイルを作ってみましたが、それでもフォーム自体がまず立ち上がらずに強制終了するのです。
なのでInitializeで時間がかかる作業でハングアップしているとは考え難いです。

どうしたら原因がわかるか、どう修正したらいいか、ご教授頂けると幸いです。
よろしくお願いいたします。

< 使用 Excel:Excel2013、使用 OS:Windows8 >


 概念的に、構成を説明してもらっても、なんともコメントしづらいですねぇ。
 コードをすべてアップされれば、なにか発見があるかもしれませんが。

 ただ、こちらが考える上でのヒントとしては、「あらかじめVBAでフォームを開いていると問題なくフォームが開き、全ての動作が正常に働きます」

 この意味は、「VBE画面でステップ実行をすると正常にいくけど、通常の実行方法(マクロでのユーザーフォーム.Show)ではエラー」

 こういう意味でしょうか?

 それなら、根が深いかもしれません。(ケースによっては根が浅いかも?)

 このユーザーフォーム上に配置してあるコントロールの数が、すごく多いということはないですか?
 とくに、Frame や MultiPage 上に、多くのコントロールが配置されていませんか?

 だめもとで、コード内のすべてのコントロールを

 ユーザーフォーム直下のものは Me.TextBox1 とか、Frame上のものは Me.Frame1.Label2 とか、
 Frameの上にFrameがあって、そこにコントーるがある場合は、Me.Frame1.Frame3.CheckBox4 とか
 Me.MultiPage1.Pages(0).CommandButton5 とか Me.MultiPage1.Pages(1).OPtionButton8 

 といったようにすべての、オブジェクト参照をその階層を省略せずに記述 してやると、どうなるでしょうか?

(β) 2015/05/05(火) 05:45


 過去スレで、以下が参考になるかもしれないです。

[[20120924182634]] 『オートメーションエラーです,,,』(ちか)

 あるいは 「オートメーションエラー」で検索すると

http://oshiete.goo.ne.jp/qa/4719888.html

 といった参考ページもでてくると思います。

(β) 2015/05/05(火) 07:05


 ちょっと比喩的に。

 紹介したページでもふれているように、仮に、オブジェクト階層を省略しないで記述してOKになったとしても
 これだけでは根本的な解決にはならないと思います。(つまり【根が浅い】解決方法にすぎません)

 たとえば、ドライブスルーのハンバーガーショップがあったとして、通常は、

 ・Aさんが注文を受けて、調理場につなぐ。(パン)
 ・Bさんが調理場で、注文の品物を袋に入れて、受け渡し窓口に差し出す。(パン)
 ・Cさんが、それを受け取り、お客に渡す。(パン)

 これがスムーズに流れて、Cさんは、Aさんの注文連絡を受けて、パン、パン、パン のリズムで袋をお客に渡す。
 でも、ある日、急に注文が多くなった。Aさんから注文連絡を受けたBさんは、いつものリズムで仕事をこなせず
 パン が パ〜〜〜・・・・〜〜ン のリズムになってしまう。
 でも、Cさんは、お構いなしに、パン、パン、パンのリズムで袋をとろうとして、そこに袋がないので空振り。

 ステップ実行してうまくいくのは、ステップ実行は、実際の自動処理に比べて、とてつもなく、遅い処理になるわけで
 パン、パン、パン が パ〜〜〜・・・・〜〜ン、パ〜〜〜・・・・〜〜ン、パ〜〜〜・・・・〜〜ン。
 なので、調理場が混雑していても、まぁ、なんとかこなせるということです。

 で、オブジェクト階層の明示化というのは、単に、フィッシュバーガーはこの棚、ポテトフライはこの棚というように
 Bさんが、一瞬、あれは、どこにあったかなと考え、取り出す、その作業を、少〜〜しだけ効率化するものであって
 根本的にには、調理場を拡張、あるいは、商品別に調理場を分ける。そういった手をいれないと、また、いつか
 今より注文が多くなれば発生してしまうということになる可能性が高いです。(なので、【根が深い】)

(β) 2015/05/05(火) 07:31


 こちらも参考に...
http://officetanaka.com/patio/patio.cgi?mode=view&no=3845
 .
(kanabun) 2015/05/05(火) 10:09

 なるほど。時系列から見ると、なかなかすっと解決しなかったので、こちらにもという感じですかね。

 あちらで取り上げられていた DoEvents は、今回の場合は、無駄かも?

 AAA 処理コード

 DoEvents

 BBB 処理コード

 のように、AAA 処理が若干遅くて、BBB 処理に間に合わない場合に有効ですが、おそらく、今回のエラーは
 AAA 処理コードの中でのことだと推測しますので。

 Me.TextBox1 = "こんにちは" という、その Me.TextBox1 への参照が、値の代入においついていないということかなと。
 まぁ、想像以外の何物でもないですが。

(β) 2015/05/05(火) 10:26


わっ、大変失礼しました。
できる方はこちらでも力になっていただいているんですね。ありがとうございます。
お手数おかけします。

「あらかじめVBAでフォームを開いていると問題なくフォームが開き、全ての動作が正常に働きます」の意味は、
ステップじゃなくても、VBEでフォームを開いているだけで、エクセルでもフォームが開くと言う意味です。
VBEを開いているだけではフォームは開きません。同じように強制終了になります。
VBEでフォームを開いていないとダメなんです。

それから、いろいろ試して新しく発見したことがあります。
通常はwindows8, Excel2013で作業をしていますが、windows7, Excel2007でも同じファイル達を開いてみました。
結果、

A.
フォームが開くファイルはどちらでも開く。

B.
Win8でフォームを使って記述した後保存したファイルを、Win8で次に開けるとフォームを開こうとすると強制終了する。
同ファイルをWin7で開くとフォームも開く。

C.
Win7でフォームを使って記述し保存したファイルを一旦閉じ、次に開けるとフォームは立ち上がらず強制終了。
そのファイルをWin8で開くとフォームが開く。

・・・・冗談みたいですが昨晩何度も試して上記のようになり、悲しくなってきました。
これは、Initializeのコードの問題ではないような気がします。
フォームが開くファイルも開かないファイルも、まったく同じInitializeです。

コードではなく、フォームが立ち上がる際に必要なものって、きっとアドインとかになると思うのですが、どこが問題になっているか調べる方法ってありますか?
フォームによって、それらを破損することってあるのでしょうか?
フォームはアレコレ情報をブックから呼んできてあらかじめ表記し、変更や追記があれば編集してブックに記述する単純な作業しか入れてないです。

保存時に何かを破損してしまうこととかありますか?

どうぞよろしくお願いします。

(ku) 2015/05/06(水) 01:45


こんにちは。

エクセルごと落ちるケースで典型的なのは、コントロールの数が多すぎるケースです。
掲示板の回答者から「なぜそんなにたくさんxxボックスが必要なのですか」と訊かれるレベル。
該当しませんか?

> Win7でフォームを使って記述し保存したファイルを一旦閉じ、次に開けるとフォームは立ち上がらず強制終了。
> そのファイルをWin8で開くとフォームが開く。
エクセルが落ちたのはメモリの書き込み異常と考えます。
たとえ同一の端末だとしても、OSが違えばメモリの管理は別々ですから
とくに不思議なことではありません。

つまりエクセルVBAでまともに管理できる数を超えてコントロールを追加してしまったので
それらのコントロールに関する情報を、エクセルVBA君がメモリに書き込むときに、
間違ってエクセルのメモリ領域にまで書き込んでしまう。
こういうことと思われます。

マイクロソフトの製品で経験したことですが。
・処理できる数や条件を超えて設定できてしまう
・設定した時点で警告も何も出ない
・その機能を使おうとして初めて不都合が発現する(エラーとは限らない)
正直、できないなら設定の時点でそう言ってくれと思いますが

単純な解決方法は、

コントロールの数を減らすことと イニシャライズ時の処理を減らすこと

と思いますが、絶対確実かといわれると断言はできません。
自信度70パーセントくらいです。

( 佳 ) 2015/05/06(水) 10:05


 ブック破損によるオートメーションエラーも確かにあるのですが、これは根が浅いですね。
 ブックを正常化すればなくなるわけですから。

 大半は、佳さんが指摘、また私のコメントやアップした参考URLでもふれている、コントロールの数が
 膨大になって、ActiveXとの連携が切れるということでしょうね。

 なので、ここは、コントロールの数を減らす方向で、デザインで工夫、ユーザーフォームの分割、等々が
 必要だと思いますよ。

 ためしに、今、エラーになっている環境で、コントロール数をぐ〜んと減らしたものを Show すると、どうなりますか?

(β) 2015/05/06(水) 10:33


おぉ・・・数が多い、まさにその通りです。
Initializeをかなり整理し、さらにActivateなどに分散したのですが
保存時に書き込む数は変わらず多いまま。
どれも書き込まなきゃいけない部分だから減らすわけにはいかないんです。。。
あれ・・・? 書き込まなきゃいけないんじゃなくて、
既に入力がある部分の変更や、空白部分への記入、だけをしたいんですが、それって全部書き込みすることで処理しちゃってますが、マズかったでしょうか?

ブックを正常化するってどうしたら良いのでしょうか?
機能的には、フォームを分散すると効率が下がるために、できれば一つでハンドルしたいです。

とにかく、まずはアドバイス通りコントロールを減らしたファイルででどうなるか、ですね。
帰宅したら、フォームの一部を取ったフォームでどうなるか、サンプルを作ってみます!
有難うございます! なんか光が見えてきた気がしてます。
(ku) 2015/05/07(木) 07:23


 >Initializeをかなり整理し、さらにActivateなどに分散したのですが

 確かに、こういうコード分散も効果がある場合もあるでしょう。
 また紹介したスレでコメントあがっていた、一部分の標準モジュールへの分散も、もしかしたら効果があるかもしれません。

 しかし、多くの場合、コード数がどうこうということではなく、コードで処理していないとしても、ユーザーフォームのメモリー空間(?)に浮遊している
 ActiveXコントロールが、あまりにも多くて、超混雑。なので、特定のコントロールにアクセスしようとして
 その連携がとれないというのが原因のように思います。

 こうなれば

 >できれば一つでハンドルしたいです。

 という気持ちはわかりますが、やむなしかなと。

(β) 2015/05/07(木) 08:17


Initialize中に処理を盛り込みすぎているように思いますね。とっとと表示を完了させましょう。

データ読み込み等の時間のかかる部分は後回しにして、フォーム表示後に、ボタン押下またはOnTimeメソッドなんかで残りを処理してはいかがでしょうか。
(???) 2015/05/07(木) 09:42


皆さん有難うございます。

サンプルを作ってみました。

パターン1
Initializeはそのまま
Activateはそのまま
フォーム内のコードはそのまま
フォームを閉じる時の書き込みのボタンを押した際にActivateで読み込んだデータの書き込みを無効に
結果はダメでした。

パターン2
Initializeはそのまま
Activateは無効
フォーム内のコードはそのまま
フォームを閉じる時の書き込みのボタンを押した際にActivateで読み込んだデータの書き込みを無効に(読み込んでないし)
結果は・・・成功!

フォームで編集し、書き込んだ後保存、いったん閉じて開いたときにもフォームは問題なく開きます! 保存を2,3度繰り返してみたけど大丈夫!

読み込んでいるデータは全部で150くらい、書き込みも同じです。
この量だと処理できないということですね。。。
最初に読み込まなかったデータを、フォームが立ち上がった後に別のタイミングで読み込んで、最後の書き込み前に別に書き込ませるなど、悪あがきして試してみます。
ダメだったらフォームを分けるしかないということですね。

βさん、kanabunさん、佳さん、???さん、本当にありがとうございました。
(ku) 2015/05/07(木) 13:20


 あまり覚えてないのだけれど。
 なんとなくなんだけど、エクセルがフォーカスを見失っている??とか・・。

 前に、やたらとフォームを切り替えたり、フォーカスをテキストボックスにしたり
 リストボックスに移動したりとか、色々遊び?で、テストしてい時に
 オートメーションエラーとかで、泥沼にはまった時に思っただけなんだけどね。
 簡単に言うと、アクティブイベントで動いた後、End subにたどり着いた時に
 フォーカスがそこに無かった時にエラーになってたような????
 結局解決させずに、それっきりで止めたので良く解らずだけど。
 やたらと、Activateイベントは使うもんじゃないと???
 BJ

あ・・・保存時ですが、フォームのデータをシートに転記する作業の前に、空白情報をメッセージボックスにリストして、空白のまま書き込んでいいか警告を出すんですが、フォームに戻って修正するを選んだ場合、空白にフォーカスするようにしています。
が、そのコードは、何せ、いかさないです。
何故なら、あまり重視していなかったので、Ifで空白にフォーカスするようにしているものの、順番に必要な部分をリストしてるから、フォームに戻った時にフォーカスが行っているのは、最初から順番にフォーカスされた後に最後に落ち着いたところなんだと思います。
ステップでフォームの内容を終えないのでわかりませんが、空白が多い状態のシートだと20個くらいフォーカス移動していると思います。
これってメモリ食いますかね?

情報をグループ分けして、空白がどこかにあったらこの変にフォーカスする〜の程度にした方が良いかもですね。
有難うございます。
(ku) 2015/05/09(土) 01:06


コメント返信:

[ 一覧(最新更新順) ]


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