tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板 [ツリー表示へ]   [Home]
一括表示(VB6.0)
タイトルExcelタスクの消えるタイミング
記事No13782
投稿日: 2009/07/01(Wed) 09:03
投稿者ケイ

いつも拝見し勉強させていただいております。
今回、ちょっと気になったのでご質問させていただきます。

下の様なプログラムで、Set xlApp = Nothingを処理した時点では
まだタスクマネージャのプロセスにはExcel表示が残っていて、
Form_Load(End Sub)を抜けるとプロセスのExcel表示消えるのは
正解なのでしょうか?

ちなみに「For Each ObjSht In xlBook.Worksheets」の手前に
    Set xlSheet = Nothing
    xlBook.Close
    Set xlBook = Nothing
    xlApp.Quit
    Set xlApp = Nothing
と記述して、「開いてすぐ閉じる」様な記述にしてみれば、
Set xlApp = Nothingを処理した時点でプロセスのExcel表示消えます。
何か「For Each ObjSht In xlBook.Worksheets」〜「Set xlSheet = Nothing」間の
記述で省略形など不適切な部分があるのでしょうか?

ご教示宜しくお願い致します。


Option Explicit
Private TgtShtName As String
Private RetShtName As String
-----------------------------
Private Sub Form_Load()
'参照設定:Microsoft Excel 11.0 Object Library

Dim xlApp   As Excel.Application
Dim xlBook  As Excel.Workbook
Dim xlSheet As Excel.Worksheet
Dim ObjSht  As Excel.Worksheet

  '目的のシート名格納
    TgtShtName = "7月度"
    
    Set xlApp = CreateObject("Excel.Application")
    Set xlBook = xlApp.Workbooks.Open("C:\ExcelTextControl.xls")
    Set xlSheet = xlBook.Worksheets(1)
        
        xlApp.Visible = True
        
        For Each ObjSht In xlBook.Worksheets
            If ObjSht.Name = TgtShtName Then
                RetShtName = ObjSht.Name
                Exit For
            End If
        Next
        
    Set xlSheet = Nothing
    xlBook.Close
    Set xlBook = Nothing
    xlApp.Quit
    Set xlApp = Nothing        
End Sub

[ツリー表示へ]
タイトルRe: Excelタスクの消えるタイミング
記事No13784
投稿日: 2009/07/01(Wed) 09:46
投稿者魔界の仮面弁士
>         For Each ObjSht In xlBook.Worksheets
>             If ObjSht.Name = TgtShtName Then
>                 RetShtName = ObjSht.Name
>                 Exit For
>             End If
>         Next
このコードの意図は、
 「TgtShtName というシートが存在していれば、RetShtName に TgtShtName を代入する」
でしょうか?

> 何か「For Each ObjSht In xlBook.Worksheets」〜「Set xlSheet = Nothing」間の
> 記述で省略形など不適切な部分があるのでしょうか?
おそらくは列挙子が原因だと思います。For Each 構文でループさせた場合、内部で
_NewEnum メソッド/プロパティが呼び出されます(IEnumVARIANT)。このループ変数の
スコープが、プロシージャ終了時まで保持されているのではないでしょうか。
http://www.vb-user.net/images/20090701/NewEnum.png

なおこちらの環境では、下記にて Excel.exe が終了される事を確認しています。


(修正案1)  For〜Next構文に変更する。

Dim n As Integer
For n = 1 To xlBook.Worksheets.Count  '☆
  If xlBook.Worksheets(n).Name = TgtShtName Then
    RetShtName = xlBook.Worksheets(n).Name
    Exit For
  End If
Next


(修正案2) 列挙変数に対して、明示的に Nothing を Set する。

Dim V As Variant
Set V = CVar(xlBook.Worksheets)
For Each ObjSht In V
    If ObjSht.Name = TgtShtName Then
        RetShtName = ObjSht.Name
        Set ObjSht = Nothing   '★
        Exit For
    End If
Next
Set V = Nothing   '★

[ツリー表示へ]
タイトル【解決】Re^2: Excelタスクの消えるタイミング
記事No13785
投稿日: 2009/07/01(Wed) 11:12
投稿者ケイ
> このコードの意図は、
>  「TgtShtName というシートが存在していれば、RetShtName に TgtShtName を代入する」
> でしょうか?

★はい、その通りです、この記述の後ほどに
If Len(RetShtName) = 0 Then 〜 処理 〜 End Ifと言う様な記述があります。

もとはこれらの記述してあるプロシージャー内で既存Excelファイルを開いて
シートのコピーやデータの取得、セルへのデータ書込み等を行い閉じると言う
一連の処理において、処理後「Set xlSheet = Nothing」〜「Set xlApp = Nothing」を
実行しても(End Subはまだ抜けていない状態で)タスクに残ってしまうのはなぜなのか?と
犯人捜しに乗り出しました。

Excel操作を1行処理する度に「Set xlSheet = Nothing」〜「Set xlApp = Nothing」を
記述し、タスクから消えたらこの終了関連の記述を一旦消し、次のExcel操作行の下行にまた
「Set xlSheet = Nothing」〜「Set xlApp = Nothing」を記述するといった様な感じで
問題ヶ所を突き止めました。
そうして「For Each ObjSht In xlBook.Worksheets」の下行に「Set xlSheet = Nothing」〜
「Set xlApp = Nothing」を記述・実行しても消えないことが判明し今回の質問となったわけです。


> おそらくは列挙子が原因だと思います。For Each 構文でループさせた場合、内部で
> _NewEnum メソッド/プロパティが呼び出されます(IEnumVARIANT)。このループ変数の
> スコープが、プロシージャ終了時まで保持されているのではないでしょうか。
★内部的な事は全く分からないのですが、魔界の仮面弁士さんの言われることは
それとなく理解できました。
別段プロシージャーから抜けると、プロセスからExcel.exeが消えるので問題視しなくても
よいと言うことが分かりました。(スッとしました)

私個人的にはFor Each文はあまり好きくないので、魔界の仮面弁士さんが提案くださった
「For n = 1 To xlBook.Worksheets.Count」で作業を進めたいと思います。
(ちなみに当方環境でも修正案2を実行するとプロセスからExcel.exeは消えましたよ〜)

よくこのBBSをROMってますが魔界の仮面弁士さんには、度々関心させられ頭が下がる思いです。
的確に迅速丁寧な対応ありがとうございました。

[ツリー表示へ]