はじめに
GetObjectの第1引数指定時の動作を知っておくと、便利な場面もあるという話。
具体例
Excel外部から特定のExcelファイル(例:C:\hoge.xlsx)を操作する場合、以下のような記述をしたとする。
Dim fileName As String
fileName = "C:\hoge.xlsx"
Const XlProgID$ = "Excel.Application"
Dim xlApp As Object 'As Excel.Application
On Error Resume Next
Set xlApp = VBA.GetObject(, XlProgID)
On Error GoTo 0
If xlApp Is Nothing Then
Set xlApp = VBA.CreateObject(XlProgID)
End If
Dim myWorkBook As Object 'As Excel.Workbook
Set myWorkBook = xlApp.Workbooks.Open(fileName)
対象のファイルがすでにExcelで開かれているとき、この記述だと以下のような問題が発生する。
- 2重に開くことになるので存在判定が必要
- Excelが複数起動している場合、GetObjectで取得したExcelとは別のExcelでファイルが開かれている可能性がある(読み取り専用で開かれる)
GetObject(PathName)を使うと
上の記述はGetObject(PathName)を使用することで以下のようにできる。
Dim fileName As String
fileName = "C:\hoge.xlsx"
Dim myWorkBook As Object 'As Excel.Workbook
Set myWorkBook = VBA.GetObject(fileName)
Dim xlApp As Object 'As Excel.Application
Set xlApp = myWorkBook.Application
GetObject(PathName)の動作(例:Excel)
Excelが起動していない場合
Excelを非表示で起動し、対象のファイルを非表示状態で開く。
開いたファイル(Excel.Workbook)を返す。
Excelが起動しているが、対象のファイルが開かれていない場合
すでに起動しているExcelのインスタンスで、対象のファイルを非表示状態で開く。
開いたファイル(Excel.Workbook)を返す。
Excelが起動していて、対象のファイルが開かれている場合
現在開かれている対象のファイル(Excel.Workbook)を返す。
複数のExcelが起動していても、現在編集中のファイルが捕捉される。
メリット
確実に対象のファイルを捕捉できる。
デメリット
テンプレート(.xltxなど)の場合、新規作成では無くテンプレートそのものを開いてしまう。
インターネット上のファイル(OneDrive上など)にはうまく動作しない。