ExcelVBA、Bookを開かずデータを取得する方法

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 29K+

aruheno

score 34

いつもお世話になっています。

今回は
「ExcelVBAで、Excelファイルを開かずにデータを取得する方法」
についてご質問いたします。

前提条件・要望

  1. 対象のExcelBookを開かずに、VBAでセルのデータ・存在するシート名一覧などを取得できる
  2. 対象Bookはネットワーク上に置いてあり、複数のユーザが同時に開く・編集する可能性がある
  3. 自他問わず対象Bookを開いていても、VBAから取得できるようにしたい

現在の状況

Bookを開かずに値を取得する事は成功しました。
しかしVBAプログラムを持つExcelファイルを作業後閉じて再度開くと、
開かなかったはずの対象Bookが一緒に開かれてしまうという症状が出てしまいました。
オブジェクトの解放も問題なくできているはずですし、
そもそもExcelファイルが開いたときに何かをするマクロも入れていません。

ソースコード

https://teratail.com/questions/37322
こちらの質問を参考に、Excel.Applicationを用いたプログラムを作成しました。
以下がソースコードになります。

'ネットワーク上の自分の親の親フォルダをカレントする
With CreateObject("WScript.Shell")
.CurrentDirectory = ThisWorkbook.Path & "\..\..\"
End With

'ファイル読み込みダイアログを開く。選択されたファイルのフルパスを取得する
fn = Application.GetOpenFilename("ファイルフルパステキスト,*.xls?")

'正常にファイルが選択されファイルパスを取得できていなければエラーフラグを立てる
If fn = "False" Then
ErroeFlag = True

'そうでなければ、選択ファイルをCreateObjectで生成する
Else
Set xlApp = CreateObject("Excel.Application")
xlApp.Workbooks.Open fileName:=fn, ReadOnly:=True
Set tergetBook = xlApp.Workbooks(Dir(fn))
End If

'エラーフラグが立っていなければ、取得作業を行う
If ErroeFlag = False Then

'取得作業

End If

'オブジェクトを解放する
Set xlApp = Nothing

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

+2

Workbookオブジェクトを開いたら、閉じなければいけません。
大雑把な流れとして、

Dim xlApp as Excel.Application
Dim xlWB as Excel.Workbook

Set xlApp = CreateObject("Excel.Application")

Set xlWB = xlApp.Workbooks.Open([ファイルのパスを指定])

' ・・・・・・開いたブックに対する処理 ・・・・・・・

' Excel ワークブックオブジェクトを閉じて解放
xlWB.Close False  ' 上書き保存せずに閉じる場合
Set xlWB = Nothing

' Excel アプリケーションオブジェクトを閉じて解放
xlApp.quit
Set xlApp = Nothing

こんな流れになります。
なお、この処理自体がExcel VBAで書いている場合、xlApp は省略可能です。
(すでに起動されているExcel上での処理となるため)

VBAを動かすExcelとは別にExcelアプリケーションを起動させる場合は上記のコード例のような書き方となります。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/08/15 10:51

    追加報告をいたします。

    回答では「xlAppでアプリケーションから開くのは省略可能」とありましたが、
    省略して記述すると、ファイルの2重展開ができないことが分かりました。
    省略せずに記述すると、既に開いているファイルを対象に取っても2重展開のマクロエラーが出ず、正常に動作しました。

    おそらく
    ・同一アプリケーションで同名ファイルを開こうとすると、2重展開の判定がされる
    ・アプリケーションを別に定義(開く?)してアプリケーションごとにファイルを開くと、2重展開の判定がされない
    のだと思いますが、あくまで想像なので確信が持てません。
    この考え方で合っているでしょうか?

    キャンセル

  • 2016/08/15 12:25

    VBAでやれることは、基本的に手作業でやった際の動作と同じです。

    Excelを(ファイルをダブルクリックではなく)スタートメニューから1つ起動した際、ファイルを開くで同一ファイルは開けませんよね。
    (既に開いています、が出ますよね)

    その「Excel」が xlApp に当たります。
    省略した場合は今扱っている(VBAを動かした)Excel上で操作する、となります。

    そのためVBA内で扱うファイルのうち、すでにExcelで開いている可能性があるものがあるのであれば、たしかにxlApp を省略すると2重起動のアラートが出ると思います。


    ただ、Excelの多重起動はそもそもバッティングした時の動作等の危険度は高いので、なるべくそのような状態が起こらないロジックを組む方が適切です。
    例えば、既に開かれている場合で

    - そのブックは読み取りしかしないのであれば改めて開かない
    - 読み書きがあり得るのであれば、「警告を表示」「1度閉じて開きなおす」「処理のキャンセル」などの処理を加える

    といった仕様を考えた方がいいかと思います。

    キャンセル

  • 2016/08/15 13:28

    ありがとうございます。
    多重起動は作成依頼者様からの要望だったので、バッティングの危険性も踏まえて説得してみようと思います。

    キャンセル

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

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