53462


# お助けください

excel2010で上手く動いたマクロが、excel2016だと上手く動きません。

親excelから、子excelを自動起動し、子excelのマクロが動き自動終了し、  
その後、親マクロの処理を継続したいと考えています。

# 再現方法

１つのフォルダの中にmother.xlsm（親excel）とchild.xlsm（子excel）を作成し、  
それぞれのファイルに下のプログラムを設定します。  
その後、親excelのマクロを実行します。

■caseA  
Windows7+Excel2010環境だと、親excelから子excelを起動することに問題ない。  
・子でApplication.Quitすると、子ブックだけ閉じて、親のマクロは継続する（finを表示する）

■caseB  
Windows10+Excel2016環境だと、親excelから子excelを起動すると問題ある。  
・子でApplication.Quitすると、親子のブックが同時に閉じる  
・子でApplication.QuitせずにThisWorkbook.Closeすると、子ブックだけ閉じて、  
親のブックは閉じないけど親のマクロが止まる（finが表示されない）  
・本当は、caseAの様に、子ブックだけ閉じて、親のマクロを継続したい（finを表示したい）

▼mother.xlsm（標準モジュール）

[code]

    Private Declare PtrSafe Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As LongPtr
    Private Declare PtrSafe Function GetExitCodeProcess Lib "kernel32" (ByVal hProcess As LongPtr, lpExitCode As Long) As Long
    Sub MotherExec()
        Dim W_Instance As Long, W_Process As LongPtr, ret As Long, OFF_CODE As Long
        childbook = "child.xlsm"
        cmd = """" & Application.Path & "\excel.exe""" & " /r """ & ThisWorkbook.Path & "\" & childbook & """"
        Set shl = CreateObject("WScript.Shell")
        W_Instance = shl.Run(cmd, 1, True)
        W_Process = OpenProcess(&H400 Or &H100000, True, W_Instance)
        Do
            ret = GetExitCodeProcess(W_Process, OFF_CODE)
            DoEvents
        Loop Until OFF_CODE <> &H103&
        MsgBox "fin"
    End Sub
    
[/code]

▼child.xlsm（ThisWorkbookモジュール）

[code]

    Sub workbook_open()
        MsgBox "workbook_open"
        If ThisWorkbook.ReadOnly = False Then Exit Sub
        Application.Quit
        'コメントアウト ThisWorkbook.Close
    End Sub
    
[/code]

# 補足

  * 実際の子excelでは、重い処理が走るため、メモリリーク対策で、この構成になってます
  * /rは、readonlyにしたい訳ではなく、workbook_openの実行/抑制を制御するためのトリックです
  * 子excelにてworkbook_openの代わりにauto_openを試したところ、caseAでは動いたけど、caseBだと動かなかったのも不思議です

どなたか、お分かりになれば、よろしくお願いします。m(_ _)m


CC BY-SA 4.0
2019-03-15T01:58:39.633
53437
2019-03-24T01:11:31.803
2019-03-16T01:28:53.830
31158
31158
question
vba excel
親excelからShellで子excelを起動し、子excelが処理した後、親excelの処理を継続したい


Officeは従来、MDI; 親ウィンドウ内に子ウィンドウを開くスタイルでした。その後SDI;
ドキュメント毎にウィンドウを開くスタイルに切り替えていきました。Excelは対応が遅れて[Excel
2013でSDI化](https://social.msdn.microsoft.com/Forums/ja-
JP/a74ebdc3-9c37-46a1-8521-3cac24965e18/excel-2013?forum=officesupportteamja)が行われました。

この際、仕様変更があり、`EXCEL.EXE`プロセスを起動しても既存のインスタンスにドキュメントを引き渡すようになりました。Excel
2010以前と同様に独立したインスタンスで処理させたい場合、[コマンドラインオプション`/X`](https://support.office.com/ja-
jp/article/microsoft-
office-%E8%A3%BD%E5%93%81%E3%81%AE%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89-%E3%83%A9%E3%82%A4%E3%83%B3-%E3%82%B9%E3%82%A4%E3%83%83%E3%83%81-079164cd-4ef5-4178-b235-441737deb3a6#ID0EAABAAA=Excel)を追加することで制御できます。

ただし、この場合でも制御しきれないことがあるため、`CreateObject`で明示的に別インスタンスを生成することが推奨されています。

[code]

    Dim xlApp As Excel.Application
    Set xlApp = CreateObject("Excel.Application") 
    xlApp.Workbooks.Open FileName:=ThisWorkbook.Path & "\" & childbook, ReadOnly:=True
    ...
    
[/code]


CC BY-SA 4.0
2019-03-16T02:20:26.980
53462
2019-03-24T01:11:31.803
2019-03-24T01:11:31.803
4236
4236
53437
answer