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

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

新規登録して質問してみよう
ただいま回答率
85.48%
VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

Q&A

解決済

5回答

2699閲覧

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

u_zu

総合スコア50

VBA

VBAはオブジェクト指向プログラミング言語のひとつで、マクロを作成によりExcelなどのOffice業務を自動化することができます。

Access

Accessはマイクロソフトによるリレーショナルデータベース管理システムです。オブジェクト指向のアプリケーション作成に対応しており、テーブルや編集をはじめ、クエリ生成、入力フォーム作成、レポート作成など一通りの機能を備えています。

0グッド

1クリップ

投稿2019/06/02 09:15

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でも動くんですよね。。)

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

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

質問1

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

vba

1Sub Test2() 2 3Dim str1 As String 4 5Dim i As Integer 6Dim j As Integer 7 8str1 = CurrentProject.Path & "\aaa.xlsx" 9 10 11With Workbooks.Open(str1) 12 13 For i = 1 To 3 14 15 For j = 1 To 3 16 Debug.Print .Worksheets("Sheet1").Cells(i, j).Value 17 Next j 18 Next i 19 Dim App As Excel.Application 20 Set App = .Applcation 'WorkBookの親のエクセルApplcationを取得 21 22 .Close 'WorkBookを閉じる 23 App.Quit 'エクセルApplcationを終了 24 25End With 26 27End Sub

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

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

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

vba

1Sub Test3() 2 3 Dim str1 As String 4 str1 = CurrentProject.Path & "\aaa.xlsx" 5 6 Dim app As Excel.Application 7 Set app = New Excel.Application 'エクセルApplicationの生成 8 9 With app.Workbooks.Open(str1) 10 Dim i As Integer, j As Integer 11 For i = 1 To 3 12 For j = 1 To 3 13 Debug.Print .Worksheets("Sheet1").Cells(i, j).Value 14 Next j 15 Next i 16 .Close 'WorkBookを閉じる 17 End With 18 app.Quit 'エクセルApplcationを終了 19 20End Sub

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

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

vba

1Sub Test4() 2 3 Dim str1 As String 4 str1 = CurrentProject.Path & "\aaa.xlsx" 5 6 With New Excel.Application 7 With .Workbooks.Open(str1) 8 9 '中略 10 11 .Close 'WorkBookを閉じる 12 End With 13 .Quit 'エクセルApplcationを終了 14 End With 15End Sub

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

質問2

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

投稿2019/06/02 18:18

編集2019/06/02 19:20
hatena19

総合スコア33715

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2019/06/03 02:04

検証はどのような環境で行われました? Windows10(64bit), access2016,office2016 上記の環境で質問の内容コードを実行して、タスクマネージャからは消えました。
hatena19

2019/06/03 02:54

「質問の内容コード」とは、どのコードことですか。 質問の Test2() は、質問者自身が、「EXCELアプリケーションが残ったまま」といってます。 当方の環境 (Windows10(64bit), access2019, office2019) でも、タスクマネージャに残るのを確認してます。
sazi

2019/06/03 03:09 編集

「質問の内容コード」とは質問に記述されているコードです。 質問者さんはOffice365と言われてましたので、気になりました。 現象は同じでも、解決策が同じとは限らないので。
hatena19

2019/06/03 03:20

質問には、Test1() と Test2() がありますが、Test2() の方で、タスクマネージャに残りませんか。 また、タスクマネージャで確認する場合、「バッググラウンド プロセス」の方にも残っていないのは確認してますか。
sazi

2019/06/03 04:08

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

2019/06/03 12:48

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

2019/06/03 13:06 編集

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

0

質問1

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

vba

1With Workbooks.Open(str1) 2 '略 3 4 .Application.DisplayAlert = False 5 .Application.Quit 6End With

質問2

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

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

vba

1Sub ExcelTest() 2 3 'With New Excel.Application '参照設定するならコッチのほうが便利かも 4 With CreateObject("Excel.Application") 5 6 '処理 7 8 With .Workbooks.Open(str1, False, True) 9 10 '処理 11 12 .Close False 13 End With 14 15 .DisplayAlerts = False 16 .Quit 17 End With 18 19End Sub

P.S.

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

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

投稿2019/06/02 14:53

編集2019/06/02 14:58
KotorinChunChun

総合スコア73

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

u_zu

2019/06/03 12:55

回答ありがとうございます。どちらの場合もEXCEL消えませんね。。。
KotorinChunChun

2019/06/03 13:06

それはおかしいですね。 後者の場合は適切に生成して破棄しているので、消えないということは考えにくいです。 2はちゃんとテストしていますが、正常にEXCELのプロセスは終了しています。 ただ類似コードをhatenaさんが追記されたので私は降ります。
u_zu

2019/06/04 13:06

>2はちゃんとテストしていますが、正常にEXCELのプロセスは終了しています。 私がテストした限り、Quitの後で、エクセルのプロセスは消えていません(プロシージャを抜ければ消えます)
TanakaHiroaki

2019/06/04 13:12

End With の後でプロセスが終了するのではないでしょうか?
u_zu

2019/06/04 13:26

いえ、End Withのあとでは消えません。End Subまでいかないと消えません(失礼ですが、試されましたか?)
KotorinChunChun

2019/06/04 13:42 編集

確かに、Quitの時点ではまだWithが捕まえているので消えないでしょうね。 でもEnd Withの後に消えると思います。 ``` End With Stop End Sub ``` のようにしたり、End Subにブレークポイントを設定して確認した所、こちらの環境では正常にExcelのプロセスは消滅を確認しました。 ただし、Excelのプロセスが消えるまでには1,2秒のラグがあります。それで誤解した可能性もありますし、もう一度試されては如何でしょうか。
TanakaHiroaki

2019/06/04 13:52 編集

私はACCESSを持っていないのでEXCELからWORDを起動して処理するケースで試してみました。 .Quitの後で、WORDのプロセスが消えました。(EXCEL2016/WORD2016)
u_zu

2019/06/04 13:52

こちらの環境では 1分以上経過しても消えませんね。。。タスクマネージャーのバックラウンドプロセスにエクセルが残ったままです。
TanakaHiroaki

2019/06/04 13:56

環境の違いによるものかもしれません。 必要であれば、プロセスハンドルを捕まえてEXCELを終了させるコードを書くとよいでしょう。
KotorinChunChun

2019/06/04 14:12 編集

食い違いの原因がわかったかもしれません。 With CreateObject("Excel.Application") の場合は、End Withを抜けてもプロセスが落ちませんでした。 With New Excel.Applicationの場合は、End Withを抜けた後にプロセスが落ちました。 すでに解決済み案件ではございますが、参考までに結果を教えていただけると嬉しいです。 この例を提案しておいてアレですが、私もhatenaさんのようにExcel.Applicationは変数に入れて実行するほうが良いと思います。 ただ、AccessからExcelを呼ぶ時は、参照設定が壊れやすいので、リリース時にはObject型変数に戻して、CreateObject("Excel.Application")に変えるようにしています。
u_zu

2019/06/04 20:55

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

2019/06/05 00:11

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

0

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

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

投稿2019/06/02 11:38

takasima20

総合スコア7458

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

u_zu

2019/06/02 11:51

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

0

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

投稿2019/06/02 09:43

sazi

総合スコア25184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

u_zu

2019/06/02 10:07

回答ありがとうございます。それもあると思うのですが、データを細かく編集したりすることもあるので。。。 私のイメージでは、accessでいう、Recordsetのようなものにエクセルのデータを格納して、いろいろとやれるように(運用上の柔軟性を持たせたい)したいのですが。
sazi

2019/06/02 10:10

リンクテーブルをRecordsetで開いてあげれば良いのでは? リンクテーブルならエクセルが残る問題は解決しますよ
u_zu

2019/06/02 10:37

なるほど。。。ありがとうございます。参考にします。 それとは別に、純粋に質問の方はやはりACCESSからEXCELという、あるアプリから異なるアプリを操作している以上、別のアプリ(この場合はEXCEL)をCreateObjectで参照する変数を作るべきなのでしょうか?
sazi

2019/06/02 11:54 編集

close入れても終了しないとの事なので、何か見落としがあるかもしれませんね。 ちょっと古いですけど、以下参考に。 Application.Quitの誤解(http://www.asahi-net.or.jp/~ef2o-inue/vba_o/sub05_800_060.html ) 因みに、accessとエクセルのバージョンは何でしょう?
u_zu

2019/06/02 10:50

バージョンはOffice365 soloです(Office2016相当?バージョン1905)。 書いていただいたURLは開くことができないです。。。(HTTP404未検出)
sazi

2019/06/02 11:58 編集

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

2019/06/02 12:07

ありがとうございます。頂いたURLの記事では、EXCELプログラムの中で、そのEXCELを 終了する、という内容だと思います(EXCELのモジュール内で、「Application.Quit」と 記述するということは、「Application」はEXCELを指しますよね?)。 私の質問の方では、ACCESSからEXCELファイルを操作するので、「Application.Quit」の 「Application」の対象はACCESSだと思います、 TanakaHiroakiさんの回答に返答した、「ActiveWorkBook.Close SaveChanges:=False 」と いう部分のところでも、ActiveWorkbook自体が非表示の状態なのでうまくいかないのではないか? と想像しております。。。 Excel.Applicationを指定する方法があるのか、分かりません。。。
u_zu

2019/06/02 12:10

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

2019/06/03 12:56

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

2019/06/03 14:29

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

0

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

VBA

1obj.ActiveWorkBook.Close SaveChanges:=False

投稿2019/06/02 09:25

編集2019/06/02 09:28
TanakaHiroaki

総合スコア1063

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

u_zu

2019/06/02 09:37

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問