Option Explicit
'-------------------------------------------------------------------------------------------------------------------------
'Un UserForm détaché doit être un UserForm non Modal (UserForm.Show vbModeless).
'
'Un UserForm détaché est un UserForm dont le Owner initialement défini par Excel à sa Window de création a été forcé à 0
'via l'API SetWindowLongPtr UserFormHandle, GWL_HWNDPARENT, 0
'Cela pour éviter que la fermeture de sa Window de création ne le ferme également laissant les éventuelles autres
'Windows du classeur dépourvues du UserForm qui leur est potentiellement utile.
'
'Le problème est qu'à la fermeture du classeur, le UserForm normalement fermé à la fermeture de sa Window de création
'n'est pas fermé si un autre classeur est ouvert car tant que le classeur ou le complément créateur du UserForm est actif,
'l'instance du UserForm restera présente.
'
'Il faut donc un mécanisme de fermeture des UserForms détachés à la fermeture du classeur qui les a vu naître.
'-------------------------------------------------------------------------------------------------------------------------
'https://docs.microsoft.com/fr-fr/office/vba/api/excel.application(object)
Public WithEvents App As Application
Private Type UserFormWindowFree
UserForm As Object
Workbook As Workbook
End Type
Private TabUserFormWindowFree() As UserFormWindowFree
Private NbUserFormWindowFree As Integer
'------------------------------------------------
'Sub to call when setting the UserForm Owner to 0
'------------------------------------------------
Sub Add(UserForm As Object)
Dim i As Integer
'UserForm already stored ?
For i = 1 To NbUserFormWindowFree
If TabUserFormWindowFree(i).UserForm Is UserForm _
And TabUserFormWindowFree(i).Workbook Is ActiveWorkbook Then Exit For
Next i
'Yes
If i <= NbUserFormWindowFree Then Exit Sub
'Add the UserForm
NbUserFormWindowFree = NbUserFormWindowFree + 1
ReDim Preserve TabUserFormWindowFree(1 To NbUserFormWindowFree)
Set TabUserFormWindowFree(NbUserFormWindowFree).UserForm = UserForm
Set TabUserFormWindowFree(NbUserFormWindowFree).Workbook = ActiveWorkbook
End Sub
'------------------------
'App_WorkbookBeforeClose
'------------------------
Private Sub App_WorkbookBeforeClose(ByVal Wb As Workbook, Cancel As Boolean)
Dim i As Integer
Dim k As Integer
'Close Workbook UserForms
i = 1
Do While i <= NbUserFormWindowFree
If TabUserFormWindowFree(i).Workbook Is Wb Then
Unload TabUserFormWindowFree(i).UserForm
'Remove table item
For k = i To NbUserFormWindowFree - 1
TabUserFormWindowFree(k) = TabUserFormWindowFree(k + 1)
Next k
NbUserFormWindowFree = NbUserFormWindowFree - 1
If NbUserFormWindowFree = 0 Then
Erase TabUserFormWindowFree
Else
ReDim Preserve TabUserFormWindowFree(1 To NbUserFormWindowFree)
End If
i = i - 1
End If
i = i + 1
Loop
End Sub