Open in a new Excel application

dewfall

New Member
Joined
Apr 21, 2006
Messages
4
Hi Folks, :)

First time poster here. I hope I'm doing this right.

I have a situation where I'd like to open a special workbook (loaded with code for security, disabling certain toolbars and menus, and appearances) in its own Excel Application object. I don't want other workbooks, opened before or after, to be subject to those settings, so I'd like to find a way to force them to open in another separate instance of the Excel application object.

Thanks for any good suggestions. :)
 
Jaafar. Giving a workbook the ability to close it'self and then reopen in another instance without it becoming read-only would require some kind of third party source. For example, if the code were contained in the workbook it'self, the code to reopen could not run because the workbook would be closed before running any code to reopen. So the workbook creates a vbscript file on the fly that gets a reference to the current application object(auxiliaryinstance), closes the workbook, creates a new application object, and reopens the workbook in the newly created instance. Once opened the script passes a reference to the auxiliaryinstance property of the workbook. This auxiliaryinstance is then available to open any workbook that the user attempts to open in the new orphaned workbook instance. Clear? :)

Hi Tom,

I'm not sure of the necessity of the VBS. How about changing the workbook's read-only property during and then opening the workbook in a new instance e.g.

Code:
Sub TransferWBToOtherInstance()
    Dim xlApp As Excel.Application, xlWb As Workbook


    'Will "transfer" this workbook to another instance of Excel

    If ThisWorkbook.ReadOnly = False Then
        ThisWorkbook.ChangeFileAccess xlReadOnly
    End If


    Set xlApp = New Excel.Application
    Set xlWb = xlApp.Workbooks.Open(ThisWorkbook.FullName)
    xlApp.UserControl = True
    xlApp.Visible = True

    'Workbook is now open in another instance so can close this one.
    ThisWorkbook.Close savechanges:=False
End Sub

In my brief test this successfully opened the workbook containing the code in another instance as read/write. Not meant to be a dig at your code, just wanted to add to a potentially interesting discussion. :)

Cheers
Dan
 
Upvote 0

Excel Facts

Whats the difference between CONCAT and CONCATENATE?
The newer CONCAT function can reference a range of cells. =CONCATENATE(A1,A2,A3,A4,A5) becomes =CONCAT(A1:A5)
Thanks DK. Your code is much better that creating a VBScript file. The only problem I am having is the ability to set the AuxiliaryInstance property in the newly opened workbook. To clarify...

An instance of Excel is running with workbook A opened.

User tries to open Orphan.xls in this same instance. The code disallows this by closing orphan work and then reopening in a new instance.

However, we need to retain a reference to the application object containing workbook A. We will use this to host any workbooks opened or created in the new instance. Hence the following property set:

<table border="1" bgcolor="White"><caption ALIGN=left><font size="2" face=Courier New>Example VBA Code:</FONT></caption><tr><td><font size="2" face=Courier New>  <font color="#008000">'should only set this reference from VBScript</font>
  <font color="#0000A0">Public</font> <font color="#0000A0">Property</font> <font color="#0000A0">Set</font> AuxiliaryInstance(app <font color="#0000A0">As</font> Excel.Application)
       <font color="#0000A0">If</font> pAuxiliaryInstance <font color="#0000A0">Is</font> <font color="#0000A0">Nothing</font> <font color="#0000A0">Then</font>
           <font color="#0000A0">Set</font> pAuxiliaryInstance = app
       <font color="#0000A0">End</font> <font color="#0000A0">If</font>
  <font color="#0000A0">End</font> <font color="#0000A0">Property</font>
</FONT></td></tr></table>

I replaced my code with yours in this procedure...

<table border="1" bgcolor="White"><caption ALIGN=left><font size="2" face=Courier New>Example VBA Code:</FONT></caption><tr><td><font size="2" face=Courier New>  <font color="#0000A0">Private</font> <font color="#0000A0">Sub</font> CloseMeAndStartMeInNewInstance()
   
       <font color="#0000A0">Dim</font> xlApp <font color="#0000A0">As</font> Excel.Application, xlWb <font color="#0000A0">As</font> Workbook
  
  
      <font color="#008000"> 'Will "transfer" this workbook to another instance of Excel</font>
       Application.DisplayAlerts = False
       ThisWorkbook.Saved = True
       <font color="#0000A0">If</font> ThisWorkbook.ReadOnly = False <font color="#0000A0">Then</font>
           ThisWorkbook.ChangeFileAccess xlReadOnly
       <font color="#0000A0">End</font> <font color="#0000A0">If</font>
       Application.DisplayAlerts = True
  
       <font color="#0000A0">Set</font> xlApp = <font color="#0000A0">New</font> Excel.Application
       <font color="#0000A0">Set</font> xlWb = xlApp.Workbooks.Open(ThisWorkbook.FullName)
      
      <font color="#008000"> '##########################################</font>
      <font color="#008000"> 'this is where I am having a problem. I cannot set the reference</font>
      <font color="#008000"> 'for some reason</font>
      <font color="#008000"> 'get a ref to the current instance</font>
       <font color="#0000A0">Set</font> xlWb.AuxiliaryInstance = Application
      <font color="#008000"> '##########################################</font>
      
       xlApp.UserControl = True
       xlApp.Visible = True
       Application.DisplayAlerts = True
       ThisWorkbook.Close savechanges:=False
  
  
    <font color="#0000A0">End</font> <font color="#0000A0">Sub</font>
</FONT></td></tr></table>

Any idea why this is working from VBScript and not from Excel?

Thanks!
 
Upvote 0
DK. I would like to get your method to work. It's much cleaner and probably less error prone. If you don't mind, please download and extract this:

DK_MyLonelyWorkbook.zip

Open Excel with at least one workbook opened. Then open "DK_MyLonelyWorkbook.xls" in the same instance. The code will stop in the relevant procedure and you can then step through to see the error. xlWb.AuxiliaryInstance . This is a valid public property in the newly opened workbook but I can't set the property for some reason...
 
Upvote 0
Hi Tom,

Had a quick look at this. I think there is some limitation in being able to access properties/methods from another workbook or instance in this case. I had a quick search on Google Groups and found a few postings by Chip Pearson but nothing concrete.

Anyway, I did manage to get to set the variable for the auxiliary application by doing the following:

1. Insert a standard module and add this function:

Code:
Public Function AuxInstance(app As Excel.Application)
Set ThisWorkbook.AuxiliaryInstance = app
End Function

2. Next, rather than attempting to set the property within the code I called the Function AuxInstance i.e.

Code:
Application.Run xlWb.Name & "!AuxInstance", ThisWorkbook.Parent

This code executes and successfully calls the function in the other instance (which you can see if you step through). I guess in theory that you should then be able to monitor application level events in both instances but I haven't tried this yet. If you can get it to work I'd be interested to see the results.

DK_MyLonelyWorkbook.zip


I'll take a look tomorrow when I'm back at work :biggrin:

Cheers
Dan
 
Upvote 0
2. Next, rather than attempting to set the property within the code I called the Function AuxInstance i.e.

Code:
Application.Run xlWb.Name & "!AuxInstance", ThisWorkbook.Parent

Dan

Unless I am missing something here, I think the above line would only set the AuxiliaryInstance Property of the ReadOnly version Not that of the actual xlWb!

I may be wrong but I thought the Run Method coudn't acess Procedures residing in foreign applications. !


Regards.


Late Edit : Actually, I was wrong. I have just tested the code using DK's function and it does work for ensuring the specific wb is on its own.! Only problem I have noticed is that more than 1 XL instance is created for new workbooks.

I am learning a few things here :)
 
Upvote 0
DK. I came to the same conclusion.

As far as monitoring events in both applications? It's a certainty as far as I know.

Simply changing this declaration:
Private pAuxiliaryInstance As Application
To this:
Private WithEvents pAuxiliaryInstance As Application

However, there is no need for it in this workbook. You can also assign a latebound reference to an an early bound variable declared withevents. I have found this useful at times. Thanks for the tips. The usercontrol property was also a new one for me...

DK_MyLonelyWorkbook2.zip

Jaafar,
Unless I am missing something here, I think the above line would only set the AuxiliaryInstance Property of the ReadOnly version Not that of the actual xlWb!
This is what we want. A reference to the current application hosting the readonly version sent to the newly created application which will now be hosting the non readonly version. pParentApp hold a reference to the actual parent application. The non readonly version will then have a reference to the first instance to refer to in the case of a user trying to open or create any workbooks in the new instance.
Only problem I have noticed is that more than 1 XL instance is created for new workbooks.
There should only be two instances. The instance hosting orphan.xls and the instance hosting all other workbooks...


<table border="1" bgcolor="White"><caption ALIGN=left><font size="2" face=Courier New>Example VBA Code:</FONT></caption><tr><td><font size="2" face=Courier New>  <font color="#0000A0">Option</font> <font color="#0000A0">Explicit</font>
  
  <font color="#0000A0">Private</font> <font color="#0000A0">Declare</font> <font color="#0000A0">Function</font> SetForegroundWindow <font color="#0000A0">Lib</font> "user32" _
       (ByVal hWnd <font color="#0000A0">As</font> Long) <font color="#0000A0">As</font> <font color="#0000A0">Long</font>
      
  <font color="#0000A0">Private</font> <font color="#0000A0">Declare</font> <font color="#0000A0">Function</font> FindWindow <font color="#0000A0">Lib</font> "user32" <font color="#0000A0">Alias</font> "FindWindowA" _
       (ByVal lpClassName <font color="#0000A0">As</font> String, <font color="#0000A0">ByVal</font> lpWindowName <font color="#0000A0">As</font> String) <font color="#0000A0">As</font> <font color="#0000A0">Long</font>
  
  <font color="#0000A0">Private</font> <font color="#0000A0">WithEvents</font> pParentApp <font color="#0000A0">As</font> Application
  <font color="#0000A0">Private</font> pAuxiliaryInstance <font color="#0000A0">As</font> Application
  <font color="#0000A0">Private</font> pPersonalXls <font color="#0000A0">As</font> <font color="#0000A0">String</font>
  
  <font color="#0000A0">Private</font> <font color="#0000A0">Sub</font> Workbook_Open()
       <font color="#0000A0">If</font> ThisWorkbook.ReadOnly <font color="#0000A0">Then</font> ThisWorkbook.Close False
       SetUpOrpan
  <font color="#0000A0">End</font> <font color="#0000A0">Sub</font>
  
  <font color="#0000A0">Private</font> <font color="#0000A0">Sub</font> SetUpOrpan()
       <font color="#0000A0">Dim</font> wb <font color="#0000A0">As</font> Workbook
      
      <font color="#008000"> 'get an instance to "PERSONAL.XLS" if it is loaded</font>
       <font color="#0000A0">On</font> <font color="#0000A0">Error</font> <font color="#0000A0">Resume</font> <font color="#0000A0">Next</font>
       <font color="#0000A0">Set</font> wb = Workbooks("PERSONAL.XLS")
       <font color="#0000A0">On</font> <font color="#0000A0">Error</font> <font color="#0000A0">GoTo</font> 0
      
       <font color="#0000A0">If</font> Workbooks.Count > 1 <font color="#0000A0">And</font> wb <font color="#0000A0">Is</font> <font color="#0000A0">Nothing</font> <font color="#0000A0">Then</font>
          <font color="#008000"> 'PERSONAL.XLS not loaded</font>
          <font color="#008000"> 'other workbooks are already open in this instance</font>
          <font color="#008000"> 'open ThisWorkbook in a new instance of Excel.Application</font>
           CloseMeAndStartMeInNewInstance
       <font color="#0000A0">ElseIf</font> Workbooks.Count > 2 <font color="#0000A0">Then</font>
          <font color="#008000"> 'PERSONAL.XLS may or may not be loaded. Does not matter at this point</font>
          <font color="#008000"> 'other workbooks are already open in this instance</font>
          <font color="#008000"> 'open ThisWorkbook in a new instance of Excel.Application</font>
           CloseMeAndStartMeInNewInstance
       <font color="#0000A0">Else</font>
          <font color="#008000"> 'this instance is ok to open ThisWorkbook</font>
          <font color="#008000"> 'close PERSONAL.XLS in this instance</font>
           <font color="#0000A0">If</font> <font color="#0000A0">Not</font> wb <font color="#0000A0">Is</font> <font color="#0000A0">Nothing</font> <font color="#0000A0">Then</font>
               pPersonalXls = wb.FullName
               wb.Close
           <font color="#0000A0">End</font> <font color="#0000A0">If</font>
          <font color="#008000"> 'continue opening in this instance</font>
          <font color="#008000"> 'start watching the application level events to</font>
          <font color="#008000"> 'respond to any attempts to create a new workbook</font>
          <font color="#008000"> 'or to open an existing workbook</font>
           <font color="#0000A0">Set</font> pParentApp = Application
       <font color="#0000A0">End</font> <font color="#0000A0">If</font>
  <font color="#0000A0">End</font> <font color="#0000A0">Sub</font>
  
  <font color="#0000A0">Private</font> <font color="#0000A0">Sub</font> SetAuxiliaryInstance(App <font color="#0000A0">As</font> Excel.Application)
       <font color="#0000A0">If</font> pAuxiliaryInstance <font color="#0000A0">Is</font> <font color="#0000A0">Nothing</font> <font color="#0000A0">Then</font>
           <font color="#0000A0">Set</font> pAuxiliaryInstance = App
       <font color="#0000A0">End</font> <font color="#0000A0">If</font>
  <font color="#0000A0">End</font> <font color="#0000A0">Sub</font>
  
  <font color="#0000A0">Private</font> <font color="#0000A0">Sub</font> Workbook_BeforeClose(Cancel <font color="#0000A0">As</font> Boolean)
       <font color="#0000A0">If</font> <font color="#0000A0">Not</font> pAuxiliaryInstance <font color="#0000A0">Is</font> <font color="#0000A0">Nothing</font> <font color="#0000A0">Then</font>
          <font color="#008000"> 'if the user closes the Auxiliary Instance but we still have a reference</font>
          <font color="#008000"> 'to the application, we will have an orphaned proccess running invisibly</font>
          <font color="#008000"> 'this will close it</font>
           <font color="#0000A0">If</font> <font color="#0000A0">Not</font> pAuxiliaryInstance.Visible <font color="#0000A0">Then</font>
               pAuxiliaryInstance.Quit
               <font color="#0000A0">Set</font> pAuxiliaryInstance = <font color="#0000A0">Nothing</font>
           <font color="#0000A0">End</font> <font color="#0000A0">If</font>
       <font color="#0000A0">End</font> <font color="#0000A0">If</font>
  <font color="#0000A0">End</font> <font color="#0000A0">Sub</font>
  
  <font color="#0000A0">Private</font> <font color="#0000A0">Sub</font> pParentApp_NewWorkbook(ByVal wb <font color="#0000A0">As</font> Workbook)
      <font color="#008000"> 'close the newly created workbook and open it in the Auxiliary Instance</font>
       wb.Close False
       CreateNewOrGetExistingInstance
       pAuxiliaryInstance.Workbooks.Add
       SetForegroundWindow FindWindow("XLMAIN", pAuxiliaryInstance.Caption)
  <font color="#0000A0">End</font> <font color="#0000A0">Sub</font>
  
  <font color="#0000A0">Private</font> <font color="#0000A0">Sub</font> pParentApp_WorkbookOpen(ByVal wb <font color="#0000A0">As</font> Workbook)
      <font color="#008000"> 'close the newly opened workbook and re-open it in the Auxiliary Instance</font>
       <font color="#0000A0">Dim</font> WorkbookFullName <font color="#0000A0">As</font> <font color="#0000A0">String</font>
       <font color="#0000A0">If</font> wb.FullName = ThisWorkbook.FullName <font color="#0000A0">Then</font> <font color="#0000A0">Exit</font> <font color="#0000A0">Sub</font>
       WorkbookFullName = wb.FullName
       wb.Close False
       CreateNewOrGetExistingInstance
       pAuxiliaryInstance.Workbooks.Open WorkbookFullName
       SetForegroundWindow FindWindow("XLMAIN", pAuxiliaryInstance.Caption)
  <font color="#0000A0">End</font> <font color="#0000A0">Sub</font>
  
  <font color="#0000A0">Private</font> <font color="#0000A0">Sub</font> CreateNewOrGetExistingInstance()
       <font color="#0000A0">If</font> pAuxiliaryInstance <font color="#0000A0">Is</font> <font color="#0000A0">Nothing</font> <font color="#0000A0">Then</font>
           <font color="#0000A0">Set</font> pAuxiliaryInstance = <font color="#0000A0">New</font> Application
           <font color="#0000A0">If</font> pAuxiliaryInstance.Workbooks.Count = 0 <font color="#0000A0">And</font> pPersonalXls <> "" <font color="#0000A0">Then</font>
               pAuxiliaryInstance.Workbooks.Open pPersonalXls
           <font color="#0000A0">End</font> <font color="#0000A0">If</font>
       <font color="#0000A0">End</font> <font color="#0000A0">If</font>
      <font color="#008000"> 'always set the visiblility to True because the user may have closed</font>
      <font color="#008000"> 'the application but it is still running invisibly if we have a reference to it</font>
       pAuxiliaryInstance.Visible = True
  <font color="#0000A0">End</font> <font color="#0000A0">Sub</font>
  
  <font color="#0000A0">Private</font> <font color="#0000A0">Sub</font> CloseMeAndStartMeInNewInstance()
   
       <font color="#0000A0">Dim</font> xlApp <font color="#0000A0">As</font> Excel.Application
  
      <font color="#008000"> 'Will "transfer" this workbook to another instance of Excel</font>
       Application.DisplayAlerts = False
       ThisWorkbook.Saved = True
       <font color="#0000A0">If</font> ThisWorkbook.ReadOnly = False <font color="#0000A0">Then</font>
           ThisWorkbook.ChangeFileAccess xlReadOnly
       <font color="#0000A0">End</font> <font color="#0000A0">If</font>
       Application.DisplayAlerts = True
  
       <font color="#0000A0">Set</font> xlApp = <font color="#0000A0">New</font> Excel.Application
       xlApp.Workbooks.Open ThisWorkbook.FullName
       xlApp.UserControl = True
       xlApp.Visible = True
      
       xlApp.Run ThisWorkbook.Name & "!Thisworkbook.SetAuxiliaryInstance", Application
  
       ThisWorkbook.Close savechanges:=False
  
    <font color="#0000A0">End</font> <font color="#0000A0">Sub</font>
</FONT></td></tr></table>
 
Upvote 0
Hi Guys,

Just wanted to extend my sincere thanks to Right_Click, rafaaj2000, and DK. I've gotten my application to work more or less perfectly using the solution you provided. :biggrin:

Rob[/list][/code]
 
Upvote 0

Forum statistics

Threads
1,216,081
Messages
6,128,696
Members
449,464
Latest member
againofsoul

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top