XL 2021 Forcer Excel à n'ouvrir qu'une seule instance

  • Initiateur de la discussion Initiateur de la discussion Dudu2
  • Date de début Date de début

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

Dudu2

XLDnaute Barbatruc
Bonjour,

Lorsque des macros Complément (AddIn) doivent interagir avec plusieurs classeurs il faut que ces classeurs s'ouvrent dans la même instance d'Excel.
S'il y a plusieurs instances, chacune d'elle charge le(s) Complément(s) et tout ce beau monde travaille en parfaite indépendance. Ce que je voudrais éviter.

Donc y a-t-il un moyen de forcer Excel à n'ouvrir qu'une seule instance pour tous les classeurs ?
 
Solution
Voir cette ressource:

Edit: pour ouvrir un fichier Excel dans une nouvelle instance
1- Clic droit / Ouvrir / puis appuyer immédiatement sur <Alt> et rester appuyé jusqu'au prompt pour ouvrir une nouvelle instance
2 - Barre de recherche / Taper Excel.exe /x (ouvre un nouveau classeur dans une nouvelle instance)
Bonjour @mromain,
@jurassic pork a déniché ce code sur StackOverflow. A voir aussi les autres propositions sans API.
Mais tout est bon à considérer y compris ta correction. Merci.

L'idée (saugrenue) serait de regrouper les classeurs sous la 1ère instance en les ré-ouvrant et en fermant la ou les instances supplémentaires.
Mais ce n'est pas si simple à cause du phénomène de création d'instance temporaire avant merge sur la 1ère.
Et à supposer qu'un Workbooks.Open dans une instance ne créé pas une autre instance.
 
En fait les Instances sont repérées par le Handle de leur Active Application qui peut varier évidemment.
Pour gérer un Merge des Instances ce n'est pas suffisant.

D'où ce code amélioré pour bien identifier de quoi sont constituées les Instances
Code:
Option Explicit

#If VBA7 Then
    Private Declare PtrSafe Function FindWindowExA Lib "user32" (ByVal hWndParent As LongPtr, ByVal hWndChildAfter As LongPtr, ByVal lpszClass As String, ByVal lpszWindow As String) As LongPtr
    Private Declare PtrSafe Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hWnd As LongPtr, ByVal dwId As Long, riid As Any, ppvObject As Object) As Long
#Else
    Private Declare Function AccessibleObjectFromWindow Lib "oleacc" (ByVal hWnd As Long, ByVal dwId As Long, riid As Any, ppvObject As Object) As Long
    Private Declare Function FindWindowExA Lib "user32" (ByVal hWndParent As Long, ByVal hWndChildAfter As Long, ByVal lpszClass As String, ByVal lpszWindow As String) As Long
#End If

'-----------------------
'List of Excel Instances
'-----------------------
Sub ListExcelInstances()
    Dim InstanceActiveWindowHandlesCollection As Collection
    Dim TabInstanceWindowHandlesCollection() As Collection
    Dim i As Integer
    Dim k As Integer
    Dim S As String
   
    Call GetExcelInstances(InstanceActiveWindowHandlesCollection, TabInstanceWindowHandlesCollection)
   
    For i = 1 To InstanceActiveWindowHandlesCollection.Count
        With InstanceActiveWindowHandlesCollection(i).Application
            S = S & vbCrLf & _
                "Instance #" & i & ":" & vbCrLf
           
            S = S & vbTab & "- Active Application " & .hWnd & vbCrLf
               
            S = S & TabInstanceWindowHandlesCollection(i).Count & " Window(s):" & vbCrLf
            For k = 1 To TabInstanceWindowHandlesCollection(i).Count
                S = S & vbTab & _
                    k & "- Application " & TabInstanceWindowHandlesCollection(i)(k) & vbCrLf
            Next k
           
            S = S & .Workbooks.Count & " Workbook(s):" & vbCrLf
            For k = 1 To .Workbooks.Count
                S = S & vbTab & _
                    k & "- Workbook " & .Workbooks(k).Name & vbCrLf
            Next k
        End With
    Next i
   
    MsgBox S
End Sub

'---------------------------------------------------------------------------------
'Get Excel Instances
'- InstanceActiveWindowHandlesCollection -> Active Application of the Instances
'- TabInstanceWindowHandlesCollection() -> Application Window Handles per Instance
'---------------------------------------------------------------------------------
Private Sub GetExcelInstances(InstanceActiveWindowHandlesCollection As Collection, TabInstanceWindowHandlesCollection() As Collection)
#If VBA7 Then
    Dim InstanceActiveApplicationHandle As LongPtr
    Dim hWnd As LongPtr
    Dim hWnd2 As LongPtr
    Dim hWnd3 As LongPtr
#Else
    Dim InstanceActiveApplicationHandle As Long
    Dim hWnd As Long
    Dim hWnd2 As Long
    Dim hWnd3 As Long
#End If
    Dim IntanceIndexCollection As Collection
    Dim Index As Integer
    Dim NbInstances As Integer
    Dim ErrNumber As Long
    Dim AccessibleObject As Object
    Dim Guid(0 To 3) As Long
    Guid(0) = &H20400
    Guid(1) = &H0
    Guid(2) = &HC0
    Guid(3) = &H46000000
   
    Set InstanceActiveWindowHandlesCollection = New Collection
    Set IntanceIndexCollection = New Collection
   
    Do
        hWnd = FindWindowExA(0, hWnd, "XLMAIN", vbNullString)
        If hWnd = 0 Then Exit Do
        hWnd2 = FindWindowExA(hWnd, 0, "XLDESK", vbNullString)
        hWnd3 = FindWindowExA(hWnd2, 0, "EXCEL7", vbNullString)
       
        If AccessibleObjectFromWindow(hWnd3, &HFFFFFFF0, Guid(0), AccessibleObject) = 0 Then
            InstanceActiveApplicationHandle = AccessibleObject.Application.hWnd
           
            On Error Resume Next
            Index = IntanceIndexCollection.Item(CStr(InstanceActiveApplicationHandle))
            ErrNumber = Err.Number
            On Error GoTo 0
           
            'Existing Instance
            If ErrNumber = 0 Then
                'Add the Application Window Handle to the Window Handles Collection
                TabInstanceWindowHandlesCollection(Index).Add AccessibleObject.hWnd
               
            'New Instance
            Else
                'Add the Active Application to the Instances Collection
                InstanceActiveWindowHandlesCollection.Add AccessibleObject.Application
                '
                NbInstances = NbInstances + 1
                ReDim Preserve TabInstanceWindowHandlesCollection(1 To NbInstances)
                Set TabInstanceWindowHandlesCollection(NbInstances) = New Collection
                IntanceIndexCollection.Add Item:=NbInstances, Key:=CStr(InstanceActiveApplicationHandle)
               
                'Add the Application Window Handle to the Window Handles Collection
                TabInstanceWindowHandlesCollection(NbInstances).Add AccessibleObject.hWnd
            End If
        End If
    Loop
End Sub

Edit: Note: Les classeurs peuvent avoir plusieurs fenêtres (Affichage / Nouvelle fenêtre)
Il faut connaître leurs Handles pour gérer le Merge des Instances (fichier à venir ?).

1747769177322.png


1747769271238.png
 

Pièces jointes

Dernière édition:
Voir cette ressource:

Edit: pour ouvrir un fichier Excel dans une nouvelle instance
1- Clic droit / Ouvrir / puis appuyer immédiatement sur <Alt> et rester appuyé jusqu'au prompt pour ouvrir une nouvelle instance
2 - Barre de recherche / Taper Excel.exe /x (ouvre un nouveau classeur dans une nouvelle instance)
 
Dernière édition:
- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

Z
Réponses
2
Affichages
4 K
Z
Retour