[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2007/07/28(Sat) 08:50
投稿者名:のぞみ
Eメール:
URL :
タイトル:
エクセルがタスクマネージャに残ってしまいます。
いつも楽しく読ませていただいて諸先生方の凄さに
驚き関心さてられています。

今回、自力で解決できない問題があるので質問させていただきました。
尚、質問前には本サイトの下記Pageは読ませていただきました。
・VBからExcel及びWordを操作する時の注意事項(最初に必ずお読み下さい)
・Excel のタスクを正常に終了できない現象(こちらも合せてお読み下さい)
・VBからエクセルを操作する(その1)
・VBからエクセルを操作する(その2)
・既存のエクセルファイルを開く
そこでご質問なのですが、

==============Program==============
Option Explicit

Public xlApp As Excel.Application
Public xlBook As Excel.Workbook
Public xlSheet As Excel.Worksheet
Public DataPath , TargetFilePath , DefaultSheetName As String

Public Sub TargetFileOpen()
1.  DataPath = App.Path & "\data"
2.  TargetFilePath = DataPath & "\working.xls"
3.  DefaultSheetName = "Default"
4.      Set xlApp = CreateObject("Excel.Application")
5.      Set xlBook = xlApp.Workbooks.Open(TargetFilePath)
6.      Set xlSheet = xlBook.Worksheets(DefaultSheetName)
7. Call SheetCheck
End Sub

Public Sub SheetCheck()
Dim ObjSheet As Worksheet
Dim SheetNum As Integer
1.  For Each ObjSheet In xlApp.Worksheets
2.  SheetNum = SheetNum + 1
3.    IF SheetNum > 6 Then
4.       処理
5.     xlApp.Quit
6.     Set xlSheet = Nothing
7.     Set xlBook = Nothing
8.     Set xlApp = Nothing
9.   End If
10. Next
End Sub

以上の様なProgramなのですが「Public Sub SheetCheck()」の
End Subまで行ってもタスクマネージャのプロセスに『EXCEL.EXE』が
残ってしまいます。
注)
1.working.xlsにはマクロのある/なしに関わらず残る
2.『Public Sub SheetCheck()』1行目『For Each ObjSheet In xlApp.Worksheets』の前に
 5行目「xlApp.Quit」〜8行目「Set xlApp = Nothing」を置けば当然プロセスには
 残らず正常に終了出来る。
3.『Public Sub SheetCheck()』1行目『For Each ObjSheet In xlApp.Worksheets』と
 2行目の「SheetNum= heetNum+1」の間に5〜8行目の終了処理を置いたらプロセスに残る
このことから『For Each ObjSheet In xlApp.Worksheets』が悪いのが分かり、
For〜xlBook.Worksheetsや単にFor〜Worksheetsなどに変えてみてもダメでした。
また、元のProgramでも終了処理8行目まで行きVBのProgramを終了すると残りません。

どうかご指導の程宜しくお願いいたします。

投稿時間:2007/07/28(Sat) 10:24
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re: エクセルがタスクマネージャに残ってしまいます。
> Public DataPath , TargetFilePath , DefaultSheetName As String
DataPath や TargetFilePath に As がありません。
この場合、これらは既定のデータ型(初期設定では Variant)になってしまいます。

> 4.      Set xlApp = CreateObject("Excel.Application")
こっちで呼ぶなら、Excel を参照設定する必要は無いかも。
参照設定を外して、変数を As Object に変更した場合はどうなりますか?

> 1.  For Each ObjSheet In xlApp.Worksheets
これだと、どのブックのシートなのかが曖昧になってしまうような。
xlApp ではなく、xlBook の方を使うべきかと。

> For〜xlBook.Worksheetsや単にFor〜Worksheetsなどに変えてみてもダメでした。
For Each 〜 Next を For 〜 Next に変えてみるとどうですか? そうすれば、
> 2.  SheetNum = SheetNum + 1
> 3.    IF SheetNum > 6 Then
シート数は Count プロパティで取れるので、ここでカウントする必要が無くなるかと。

> 4.       処理
この部分に問題があるという可能性はありませんか?

投稿時間:2007/07/28(Sat) 11:51
投稿者名:のぞみ
Eメール:
URL :
タイトル:
Re^2: エクセルがタスクマネージャに残ってしまいます。
おはようございます。早々の回答ありがとうございます魔界の仮面弁士様(^^)
魔界の仮面弁士様からご回答頂いたことにちょっと興奮気味です(^^)
そんな中、早速なのですが
> > Public DataPath , TargetFilePath , DefaultSheetName As String
> DataPath や TargetFilePath に As がありません。
> この場合、これらは既定のデータ型(初期設定では Variant)になってしまいます。
★すみません。本当は1つ1つ個別に〜As Stringで宣言しています。
(ここの文章を少しでも少なくしようと思い、そ〜書いてしまいました)

【A】
> > 4.      Set xlApp = CreateObject("Excel.Application")
> こっちで呼ぶなら、Excel を参照設定する必要は無いかも。
> 参照設定を外して、変数を As Object に変更した場合はどうなりますか?
★参照設定のチェックを外し(ちなみにVer11.0)、xlApp、xlBook、xlSheet、ObjSheetを
〜As Objectにしてもダメでした。
(xlAppだけAs ObjectにするとxlBook、xlSheet、ObjSheetがそれぞれ『コンパイル エラー:
ユーザ定義型は定義されていません。』と怒られたので、順次As Objectに変更しました。)

【B】
> > 1.  For Each ObjSheet In xlApp.Worksheets
> これだと、どのブックのシートなのかが曖昧になってしまうような。
> xlApp ではなく、xlBook の方を使うべきかと。
★For Each ObjSheet In xlBook.Worksheetsにしてもダメでした。

【C】
> > For〜xlBook.Worksheetsや単にFor〜Worksheetsなどに変えてみてもダメでした。
> For Each 〜 Next を For 〜 Next に変えてみるとどうですか? そうすれば、
> > 2.  SheetNum = SheetNum + 1
> > 3.    IF SheetNum > 6 Then
> シート数は Count プロパティで取れるので、ここでカウントする必要が無くなるかと。
★『For ObjSheet In xlBook.Worksheets』にしてRunしました。
コンパイルエラー・構文エラーとなりました。
エラーとなったので「シート数は Countプロパティで取れる」は確認していません。
尚、ObjSheet.Countでとれるのですか?
ObjSheet.と.打ったとき自動のメソッドやプロパティが出てこないのですが・・・(^^;A

> > 4.       処理
> この部分に問題があるという可能性はありませんか?
★無いと思います。原文の注記2および3にも書きましたが『For Each ObjSheet In xlApp.Worksheets』の
前後に終了処理を記述したとき、前置きの場合正常終了、すぐ後に終了処理を置いた場合
ダメだったので「処理」に行く以前の問題だと判断しています。

【A】と【B】を同時に処理してもダメでしたρ(--、)シクシク

投稿時間:2007/07/28(Sat) 13:10
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re^3: エクセルがタスクマネージャに残ってしまいます。
> ★『For ObjSheet In xlBook.Worksheets』にしてRunしました。
そうではなく、こういうことで。

 For I = 1 To xlBook.Worksheets.Count
  Set ObjSheet = xlBook.Worksheets(I)
    :
    :
 Next

投稿時間:2007/07/28(Sat) 11:22
投稿者名:YK
Eメール:
URL :
タイトル:
Re: エクセルがタスクマネージャに残ってしまいます。
こんにちは。

> 1.  For Each ObjSheet In xlApp.Worksheets
1.  For Each ObjSheet In xlBook.Worksheets

> 2.  SheetNum = SheetNum + 1
> 3.    IF SheetNum > 6 Then
    この値が5で終わったらエクセルは終了しないですよね。
    チェックされましたか。

投稿時間:2007/07/28(Sat) 12:05
投稿者名:のぞみ
Eメール:
URL :
タイトル:
Re^2: エクセルがタスクマネージャに残ってしまいます。
こんにちわ〜YK様m(_ _)m
ご回答ありがとうございます。
> > 1.  For Each ObjSheet In xlApp.Worksheets
>  1.  For Each ObjSheet In xlBook.Worksheets
>
> > 2.  SheetNum = SheetNum + 1
> > 3.    IF SheetNum > 6 Then
>     この値が5で終わったらエクセルは終了しないですよね。
>     チェックされましたか。

★原文の注記2および3に書きましたが、
『1.  For Each ObjSheet In xlBook.Worksheets』の前後に終了処理した場合、

【前置きの場合】・・・正常終了
Public Sub TargetFileOpen()
変数への格納は記述省略
xlApp.Quit
Set xlSheet = Nothing
Set xlBook = Nothing
Set xlApp = Nothing・・・・実行した時点で正常にEXCEL.EXE終了
 For Each ObjSheet In xlBook.Worksheets
  ・
  ・
  ・
 Next

【後置きの場合】・・・異常(プロセスにEXCEL.EXEが残ります)
Public Sub TargetFileOpen()
変数への格納は記述省略
 For Each ObjSheet In xlBook.Worksheets
   xlApp.Quit
   Set xlSheet = Nothing
   Set xlBook = Nothing
   Set xlApp = Nothing・・・この処理を実行してもプロセスにEXCEL.EXEが残ります
      ・
      ・
      ・
 Next

したがいまして「この値が5で終わったらエクセルは終了しないですよね。」の
以前の問題かと判断しています。
ちなみにSheetNumが5以下でForを抜けた場合は抜けた後に終了処理を記述していますので
Openしっ放しと言うことはないですよ〜(^^)

投稿時間:2007/07/28(Sat) 13:13
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re^3: エクセルがタスクマネージャに残ってしまいます。
>  For Each ObjSheet In xlBook.Worksheets
>    xlApp.Quit
子オブジェクトの列挙処理中に、親オブジェクトを終了させるのは避けましょう。
子オブジェクトをすべて使用し終わった後で終了させた方が無難です。

> ちなみにSheetNumが5以下でForを抜けた場合は抜けた後に終了処理を記述していますので
であれば、それらのコードも書いてくださいませ。
第三者が再現可能なソースコードを提示してもらわないと、検証のしようがないので。

投稿時間:2007/07/29(Sun) 13:01
投稿者名:のぞみ
Eメール:
URL :
タイトル:
Re^4: エクセルがタスクマネージャに残ってしまいます。
魔界の仮面弁士様、YK様おはようございます。
ちゅ〜かもうお昼回ってますね!!

> >  For Each ObjSheet In xlBook.Worksheets
> >    xlApp.Quit
> 子オブジェクトの列挙処理中に、親オブジェクトを終了させるのは避けましょう。
> 子オブジェクトをすべて使用し終わった後で終了させた方が無難です。
★xlApp.Quit・・・親オブジェクト
 xlSheet・・・・子オブジェクト
 xlBook・・・・子オブジェクトと解釈していますが、
この処理順番は本サイト「http://hanatyan.sakura.ne.jp/vbhlp/excelframe.htm」で
紹介されているものをそのままなのですがダメなのかな(ノ_`)

> > ちなみにSheetNumが5以下でForを抜けた場合は抜けた後に終了処理を記述していますので
> であれば、それらのコードも書いてくださいませ。
> 第三者が再現可能なソースコードを提示してもらわないと、検証のしようがないので。
★端折って簡潔に書かないとかなり多くなるのと、その処理「SheetNumが5以下」に行くまでに
プロセスに残ると言う事象が発生してるので最小限エリアで解決して行こうと思ったからです。
http://hanatyan.sakura.ne.jp/vb60bbs/wforum.cgi?no=9803&reno=9801&oya=9799&mode=msgview&page=0

やりたいことは、シート枚数が5以上あればファイル名前を変えて保存し、元々開いた
「working.xls」のシート名"Default"を残してシートを削除したいのです。
再現確認していただけるのなら、

宣言・working.xlsの準備等の事前準備はここでは省略させていただいて
Public Sub TargetFileOpen()     'ファイルオープン
 DataPath = App.Path & "\data"
 TargetFilePath = DataPath & "\working.xls"
 DefaultSheetName = "Default"
 Set xlApp = CreateObject("Excel.Application")
 Set xlBook = xlApp.Workbooks.Open(TargetFilePath)
 Set xlSheet = xlBook.Worksheets(DefaultSheetName)
 Call SheetCheck
End Sub

【終了確認パーン1】
Public Sub SheetCheck()      '【終了処理をFor処理の前置きの場合】・・・正常終了
'ファイルオープンして別のプロシージャーに入ったらすぐ終了して試してみる。
 xlApp.Quit
 Set xlSheet = Nothing
 Set xlBook = Nothing
 Set xlApp = Nothing    '←実行した時点で正常にEXCEL.EXE終了
  For Each ObjSheet In xlBook.Worksheets
   '処理
  Next
End Sub
【終了確認パーン2】
Public Sub SheetCheck()      '【終了処理をFor処理の後置きの場合】・・・NG
'ファイルオープンして別のプロシージャーのFor文に入ったらすぐ終了して試してみまる
 For Each ObjSheet In xlBook.Worksheets
   xlApp.Quit
   Set xlSheet = Nothing
   Set xlBook = Nothing
   Set xlApp = Nothing・・・この処理を実行してもプロセスにEXCEL.EXEが残ります
   '処理
  Next
End Sub

ここで分かったこと、「For Each ObjSheet In xlBook.Worksheets」が悪さをしてるのでは
ないかってことです。


> そうではなく、こういうことで。
>  For I = 1 To xlBook.Worksheets.Count
>   Set ObjSheet = xlBook.Worksheets(I)
>     :
>     :
>  Next
★上のパターン2に於いて、ご教示していただいた「Each」を使わない
Forにしても結果はパターン2と同じでした

あまり文章が上手くなく誤解等ありますけどすみません。
それと初めに断るべきだったのでしょうが私、VB初心者ですm(_ _)m
ごめんなさい。

投稿時間:2007/07/29(Sun) 22:13
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re^5: エクセルがタスクマネージャに残ってしまいます。
> この処理順番は本サイト「http://hanatyan.sakura.ne.jp/vbhlp/excelframe.htm」で
> 紹介されているものをそのままなのですがダメなのかな(ノ_`)
いえ、「そのまま」にはなっていないと思いますよ…。

正直なところ、そこに書かれた手順も、あまり好ましくは無いと思います。
Sheet 解放 → Book 解放 → Quit → Application 解放の順が推奨されるでしょう。

ただ、(VB6 なら)解放順に関してはある程度融通が利くので、そこに書かれた手順でも
さほど問題はないと思います。しかし、のぞみさんが行っているような手順、すなわち、
下位のオブジェクトを処理中に、上位のオブジェクトを Close / Quit したり、あるいは
Close / Quit 処理後に、それらのオブジェクトを操作するのは問題があるということです。


> ★端折って簡潔に書かないとかなり多くなるのと、
(中略)
> 最小限エリアで解決して行こうと思ったからです。
もちろん、コードが多いならば、最低限の長さまで縮めることは確かに必要なのですが、
肝心な部分が端折られた、部分的な投稿にはならないようにして欲しいのです。

少なくとも、For Each しただけ(ループ内には 1 行もコードを書かない)ならば、
問題は出ません。ですから、ループ処理の中で「やってはいけないこと」を
書いてしまっている可能性が高いと予想されるのです。

重要な部分は端折らずに投稿してください。そうでないと間違いを指摘できません。

それに、もし同一のコードを使っても、のぞみさんの環境でしか問題が発生しないのなら、
それは「プログラム上のミス」ではなく、「環境自体に不具合がある」のかも知れません。
その可能性を探る意味でも、省略されていない(かつ、長くない)コードが必要なのです。


> 【終了確認パーン1】
> Public Sub SheetCheck()      '【終了処理をFor処理の前置きの場合】・・・正常終了
> 'ファイルオープンして別のプロシージャーに入ったらすぐ終了して試してみる。
>  xlApp.Quit
>  Set xlSheet = Nothing
>  Set xlBook = Nothing
>  Set xlApp = Nothing    '←実行した時点で正常にEXCEL.EXE終了
>   For Each ObjSheet In xlBook.Worksheets
>    '処理
>   Next
> End Sub
このコードには、2 つの問題があるように見えます。

まず 1 つめに…… Excel が終了するかどうか以前の問題として、xlBook が Nothing の
状態で xlBook.Worksheets を実行すれば、その時点で処理が失敗するはずです。
もし、事後の処理でエラー等が発生していないというのであれば、
 (a) On Error を使って、実行時エラーを握りつぶしている。
 (b) 変数宣言時に New キーワードを補っている。
のいずれかの状態だと思いますし、その場合、a,b の処理には問題があるでしょう。
(逆に、エラーが起きているなら、事後にそのような処理を書く事自体が問題です)


2 つめの問題点は、処理手順自体の間違いです。そもそも xlApp.Quit させた後で、
他の Excel オブジェクトを操作しようとすること自体、処理としては NG でしょう。

Quit は、Excel アプリ本体を終了させる命令ですから、Quit を呼び出した後では、
一切、Excel 系のオブジェクトを操作すべきではありません。


> 【終了確認パーン2】
> Public Sub SheetCheck()      '【終了処理をFor処理の後置きの場合】・・・NG
> 'ファイルオープンして別のプロシージャーのFor文に入ったらすぐ終了して試してみまる
>  For Each ObjSheet In xlBook.Worksheets
>    xlApp.Quit
すでに先に回答したことの繰り返しになりますが、マズイです。

For Each 中は、列挙オブジェクトが保持された状態となります。安全のため、
Quit メソッドを呼ぶなら、Exit For などで ループを抜けた後に行いましょう。


For Each ではなく For であれば、列挙オブジェクトを使用しないので、
オブジェクトが保持された状態にはならないでしょうけれど、その場合でも、ループ中に
> xlApp.Quit
> Set xlSheet = Nothing
> Set xlBook = Nothing
> Set xlApp = Nothing・・・この処理を実行してもプロセスにEXCEL.EXEが残ります
> '処理
のようなコードを記述することには問題があります(「処理」部で何をさせるにしても)。

1回目のループで終了処理を行ったのなら、2回目のループでは何を終了させるのでしょう?



> ここで分かったこと、「For Each ObjSheet In xlBook.Worksheets」が悪さをしてるのでは
> ないかってことです。
ループを行うこと自体には、終了/解放処理の妨げにはなりません。
それでも問題が起きているのだとすれば、その使い方が間違っているのだと思いますよ。

投稿時間:2007/07/29(Sun) 13:32
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^3: エクセルがタスクマネージャに残ってしまいます。
>  For Each ObjSheet In xlBook.Worksheets
>    xlApp.Quit
>    Set xlSheet = Nothing
>    Set xlBook = Nothing
>    Set xlApp = Nothing・・・この処理を実行してもプロセスにEXCEL.EXEが残ります


上記のコードの意味(やっている事)を理解して使っておられるのでしょうか?

基本的な事をキチンと理解してから次に移るようにしないとハマるばかりです。

初心者だと言うのなら、まず、起動と終了だけのプログラムを作って残っているか
確認しながら、少しずつコードを追加して、テストを繰り返しながら進めるように
すれば、どこに問題があるのかもすぐ掴めると思いますよ。

投稿時間:2007/07/29(Sun) 19:11
投稿者名:のぞみ
Eメール:
URL :
タイトル:
Re^4: エクセルがタスクマネージャに残ってしまいます。
> 起動と終了だけのプログラムを作って残っているか確認しながら
★はい、ファイルオープンして、他になんの処理もせず、その同プロシージャー内で
終了処理を記述し、正常に終了することを確認して、どんどんエリアを絞ってきて、
結局このFor Each ObjSheet In xlBook.Worksheetsを境に正常終了できなくなりました。
このことは質問当初から書いているのですが、書き方が悪いのか、何故か伝わってないのが
悲しいです。

【原文引用】
注)
1.working.xlsにはマクロのある/なしに関わらず残る
2.『Public Sub SheetCheck()』1行目『For Each ObjSheet In xlApp.Worksheets』の前に
 5行目「xlApp.Quit」〜8行目「Set xlApp = Nothing」を置けば当然プロセスには
 残らず正常に終了出来る。
3.『Public Sub SheetCheck()』1行目『For Each ObjSheet In xlApp.Worksheets』と
 2行目の「SheetNum= heetNum+1」の間に5〜8行目の終了処理を置いたらプロセスに残る
このことから『For Each ObjSheet In xlApp.Worksheets』が悪いのが分かり、
For〜xlBook.Worksheetsや単にFor〜Worksheetsなどに変えてみてもダメでした。
また、元のProgramでも終了処理8行目まで行きVBのProgramを終了すると残りません。

投稿時間:2007/07/30(Mon) 11:35
投稿者名:よねKEN
Eメール:
URL :
タイトル:
Re^5: エクセルがタスクマネージャに残ってしまいます。
No.9803でのYKさんへのレスで、
> したがいまして「この値が5で終わったらエクセルは終了しないですよね。」の
> 以前の問題かと判断しています。
> ちなみにSheetNumが5以下でForを抜けた場合は抜けた後に終了処理を記述していますので
> Openしっ放しと言うことはないですよ〜(^^)

とコメントされていますが、ご自身だけで判断せずに、
第三者にも判断できるようその判断材料となる実際のソースをご提示ください。

また、問題を絞り込む際の実験の仕方についてですが、

>【終了確認パーン1】
>Public Sub SheetCheck()      '【終了処理をFor処理の前置きの場合】・・・正常終了
>'ファイルオープンして別のプロシージャーに入ったらすぐ終了して試してみる。
> xlApp.Quit
> Set xlSheet = Nothing
> Set xlBook = Nothing
> Set xlApp = Nothing    '←実行した時点で正常にEXCEL.EXE終了
>  For Each ObjSheet In xlBook.Worksheets
>   '処理
>  Next
>End Sub
>【終了確認パーン2】
>Public Sub SheetCheck()      '【終了処理をFor処理の後置きの場合】・・・NG
>'ファイルオープンして別のプロシージャーのFor文に入ったらすぐ終了して試してみまる
> For Each ObjSheet In xlBook.Worksheets
>   xlApp.Quit
>   Set xlSheet = Nothing
>   Set xlBook = Nothing
>   Set xlApp = Nothing・・・この処理を実行してもプロセスにEXCEL.EXEが残ります
>   '処理
>  Next
>End Sub

以上のコードはどちらもxlApp.Quitした後にも他のオブジェトを操作している節があり、
実験コードとして非常に怪しいので、この動作結果を参考にするのは危険だと思います。
(まずい実験方法に基づいた結果を元に原因を探ると余計に迷子になる恐れもあります)

--
No.9809の魔界の仮面弁士さんのレスにある以下のことをまず実行してください。

>もちろん、コードが多いならば、最低限の長さまで縮めることは確かに必要なのですが、
>肝心な部分が端折られた、部分的な投稿にはならないようにして欲しいのです。