質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.82%

ACCESSからEXCELのデータを取得する際に、EXCELプログラムを終了させることについて

解決済

回答 5

投稿

  • 評価
  • クリップ 1
  • VIEW 2,297

u_zu

score 35

ACCESSファイルからEXCELファイル(ACCESSファイルと同じフォルダ内にある、[aaa.xlsx])
のデータを取得する際に次のようなコードを書きました。

---------------------------------------
Sub Test1()    '(エクセルの参照設定はしていません)

Dim obj As Object

Set obj = CreateObject("Excel.Application")
obj.Application.Visible = True
Dim str1 As String

Dim i As Integer
Dim j As Integer

str1 = CurrentProject.Path & "\aaa.xlsx"

With obj.Workbooks.Open(str1)

    For i = 1 To 3

           For j = 1 To 3
                Debug.Print .Worksheets("Sheet1").Cells(i, j).Value
           Next j

    Next i

End With

obj.Quit
Set obj = Nothing

End Sub

----------------------------------------------
次に、 エクセルの参照設定をしたうえで、
次のようなコードを書きました。

Sub Test2()

Dim str1 As String

Dim i As Integer
Dim j As Integer

str1 = CurrentProject.Path & "\aaa.xlsx"


With Workbooks.Open(str1)

    For i = 1 To 3

        For j = 1 To 3
        Debug.Print .Worksheets("Sheet1").Cells(i, j).Value
           Next j

    Next i

End With

End Sub

------------------------------------------------


Test2ではEXCELアプリケーションのオブジェクト(CreateObject)は作っていませんが、
プログラムは作動します。
ただ、バックグラウンドで生成された?EXCELアプリケーションが残ったままに
なってしまいました。

質問1

Test2で生成されたEXCELアプリケーションをきちんと消去する方法はありますか?

End with の次に「Excel.Application.Quit」を入れて試しましたが、消えませんでした。

質問2

(質問1に関連しますが)Test2のようなコードの書き方はよくないのでしょうか?
CreateObjectしなくても済むなら。。。。と思ったのですが。

最初に思ったのは、CreateObjectしないから、オブジェクトを終わらせる処理
(Set *** = NothingとかExcel.Application.Quitとか)を入れなくて済む
のではないかと考えましたが、CreateObjectしてもしなくても
EXCELのプロセスが発生するのならば、CreateObjectをして、そのオブジェクトを
Quitするべき、なのでしょうか?(ただ、Test2でも動くんですよね。。)

何かとんちんかんなことを質問しているのかもしれませんが、よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 5

checkベストアンサー

+3

質問1

提示のコードに、エクセルApplcationの終了を追加するなら、下記のコードになりますね
追記: 試してみたら、Set App = .Applcationでエラーになりました。
Withを使わず変数宣言して Set wb = Workbooks.Open(str1) で開いて wb.Application.Quit で終了させたらエラーはなくなりましたが、タスクマネージャで確認したら、エクセルApplcation は残ってました。下記のTest3以降のコードの場合は、エクセルApplcationはきれいに消えました。

Sub Test2()

Dim str1 As String

Dim i As Integer
Dim j As Integer

str1 = CurrentProject.Path & "\aaa.xlsx"


With Workbooks.Open(str1)

    For i = 1 To 3

        For j = 1 To 3
        Debug.Print .Worksheets("Sheet1").Cells(i, j).Value
           Next j
    Next i
    Dim App As Excel.Application
    Set App = .Applcation  'WorkBookの親のエクセルApplcationを取得

    .Close   'WorkBookを閉じる
    App.Quit 'エクセルApplcationを終了

End With

End Sub


下記の点を理解してください。

  • 参照設定してあると、Workbooks.Open すると裏でエクセルApplcationが自動生成される。
  • Workbooks.Open はWorkbookオブジェクトを返す。
  • Workbookの親のエクセルApplcationは、Workbookオブジェクトの Applicationプロパティで取得できる。

ただ、参照設定をしてあるなら、下記のコードが素直で読みやすいコードだと思います。
(ちなみに、私は、変数宣言は使う前にする派です。)

Sub Test3()

    Dim str1 As String
    str1 = CurrentProject.Path & "\aaa.xlsx"

    Dim app As Excel.Application
    Set app = New Excel.Application 'エクセルApplicationの生成

    With app.Workbooks.Open(str1)
        Dim i As Integer, j As Integer
        For i = 1 To 3
            For j = 1 To 3
                Debug.Print .Worksheets("Sheet1").Cells(i, j).Value
            Next j
        Next i
        .Close   'WorkBookを閉じる
    End With
    app.Quit 'エクセルApplcationを終了

End Sub

参照設定をしてある場合、NewステートメントでエクセルApplication を生成します。
CreateObjectでもできますが、普通は New です。

変数宣言をせずに、With を入れ子にする方法もあります。

Sub Test4()

    Dim str1 As String
    str1 = CurrentProject.Path & "\aaa.xlsx"

    With New Excel.Application
        With .Workbooks.Open(str1)

             '中略

            .Close   'WorkBookを閉じる
        End With
        .Quit 'エクセルApplcationを終了
    End With
End Sub


この辺はプログラマーの好みですが、私は前者の変数宣言する方法を採用する場合が多いかな。
入れ子にすると、長いコードだと、どのオプジェクトなのか判別しづらい場合があるので。

質問2

上のコードを見ればわかると思いますが、
Excel.Application を生成したら、自動で破棄してくれませんので、
Quit は必須ですね。
裏で自動で生成されたとしても。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/03 13:08

    バックグラウンド確認していませんでした・・・
    明示的でないExcel.Applicationは、破棄する術がない
    という事ですね。

    キャンセル

  • 2019/06/03 21:48

    どうもありがとうございます。質問とは少しそれますが、Newステートメントなども勉強になりました。
    Sub Test3 の書き方、いいですね。

    キャンセル

  • 2019/06/03 22:05 編集

    横からすみません。
    VBAオブジェクト変数の宣言時にNewステートメントを使用し、1行ですませる方法もよく見かけますが、後でインスタンスを破棄したい場合に問題となります。以下にその理由が書いてあります。
    https://thom.hateblo.jp/entry/2016/09/27/221527

    hatena19さんは、このような内容まで熟知されたうえでTest3のコードを書かれていると思います。

    キャンセル

+1

質問1 ですが、End with の次に以下を追加してはどうでしょうか。

obj.ActiveWorkBook.Close SaveChanges:=False

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/02 18:37

    どうもありがとうございます。 頂いたコードを入れると、「obj」は定義されていないので、エラーになってしまいます。
    ActiveWorkBook.Close SaveChanges:=False だけを入れるとエラーにならず、プログラムは動きますが、EXCELプロセスは消えません。

    キャンセル

+1

DoCmd.TransferSpreadsheetでリンクするとかインポートする方がクエリーとか使えます。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/02 21:10

    それから、
    >With obj.Workbooks.Open(str1)
    >となっているので
    >set wkbk = obj.Workbooks.Open(str1)
    >のように変数に受けて、それをcloseしてみて下さい。

    なるほどです。

    キャンセル

  • 2019/06/03 21:56

    色々、ありがとうございます。

    キャンセル

  • 2019/06/03 23:29

    外部データを扱うのだから、accessで扱いやすい形式にしてから処理するという回答の趣旨さえ汲み取って貰えれば。

    キャンセル

+1

外してるかもですが…
Workbooks.Open でなんか返ってきてないですかね?
http://doctor.ataglance.jp/mini-macro11/

それに対して close なりなんなりするのはどうでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/02 20:51

    回答ありがとうございます。Workbooks.Open でWorkbookオブジェクトが返るのですが、
    Sub Test2() では、その返り値となるWorkbookオブジェクトを生成していないので
    (Test1では [obj]を生成しているのでQuitできる)、Closeできる対象が無いんですよ。
    Closeできる対象を見つける方法がありますか?

    キャンセル

0

質問1

試していませんが、次のようにしては如何でしょうか。

With Workbooks.Open(str1)
    '略

    .Application.DisplayAlert = False
    .Application.Quit
End With

質問2

素直にCreateObjectを使う方法のほうが間違いないと思うのですが、何れにせよQuitは必須す。

Nothingの代入は省略してもあまり問題にならない気がしますが、気持ち悪い場合はWithで固めてしまうという手もあると思います。

Sub ExcelTest()

    'With New Excel.Application '参照設定するならコッチのほうが便利かも
    With CreateObject("Excel.Application")

        '処理

        With .Workbooks.Open(str1, False, True)

            '処理

            .Close False
        End With

        .DisplayAlerts = False
        .Quit
    End With

End Sub

P.S.

End with の次に「Excel.Application.Quit」を入れて試しましたが、消えませんでした。

もしかしたら保存確認メッセージが邪魔してたりして?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/04 23:09 編集

    食い違いの原因がわかったかもしれません。

    With CreateObject("Excel.Application") の場合は、End Withを抜けてもプロセスが落ちませんでした。

    With New Excel.Applicationの場合は、End Withを抜けた後にプロセスが落ちました。

    すでに解決済み案件ではございますが、参考までに結果を教えていただけると嬉しいです。


    この例を提案しておいてアレですが、私もhatenaさんのようにExcel.Applicationは変数に入れて実行するほうが良いと思います。

    ただ、AccessからExcelを呼ぶ時は、参照設定が壊れやすいので、リリース時にはObject型変数に戻して、CreateObject("Excel.Application")に変えるようにしています。

    キャンセル

  • 2019/06/05 05:55

    With new Excel Application の場合は 確かに落ちます、少し時間がかかりますが(3秒くらい)。色々難しいですね。

    キャンセル

  • 2019/06/05 09:11

    報告ありがとうございます。参考になりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.82%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る