Schließen des Basisfensters

Betrifft: Schließen des Basisfensters
von: Hans-Jürgen
Geschrieben am: 19.10.2020 17:18:22
Hallo Wissende
ich programmiere gerade eine VBA-Anwendung, die - für den Anwender - ausschließlich in einer Userform stattfindet. Das Hauptfenster braucht es nicht.
Konkret passiert dort lediglich über Open_Workbooks eine Prüfung, ob alle benötigten Datenbanken erreichbar sind. Dann wird das Fenster minimiert und die Userform wird aufgerufen.
Ich habe eine Sub "ProgrammBeenden", die in Aktion tritt, wenn der Anwender in der UserForm auf das rote Kreuz klickt (oder wenn es gar nicht so weit kommt, weil die Datenbanken nicht erreichbar sind). In diesem Programm werden einige Werte wieder zurückgesetzt, die DAO-Verbindung getrennt und - jetzt kommen wir zum Thema - das Anwendungsfenster geschlossen.
Ich möchte gern, dass es im Normalbetrieb wie folgt funktioniert:
- wenn die geöffnete Instanz die einzige Excel-Instanz ist: Excel schließen
- wenn weitere Excel-Instanzen offen sind: Die aktuelle Instanz schließen und alle anderen unberührt lassen
Hinweis: Die Anwendung dient nur der "Fernsteuerung", es sollen keine Änderungen gespeichert werden.
Der Nicht-Normalbetrieb ist daran erkennbar, dass die Anwendung nicht Archiv.xlsm handelt. (Während der Entwicklung nehme ich andere Dateinamen, und da soll er gar nichts schließen, damit ich relativ einfach an den VBA-Code komme)
Ich habe also folgenden Schnipsel ganz ans Ende meiner Beenden-Sub geschrieben:
If ActiveWorkbook.Name = "Archiv.xlsm" Then
If Workbooks.Count = 1 Then
Application.Quit
Else
Workbooks(ActiveWorkbook.Name).Close SaveChanges:=True
End If
End If
Wenn der Dateiname abweicht (also gar nichts geschlossen wird) funktioniert es wie gewünscht. Das gleiche gilt, wenn nur diese eine Instanz offen ist, sie wird "gekillt". Wenn allerdings eine weitere Instanz offen ist, bleibt das Fenster trotz des Close erhalten und muss manuell geschlossen werden, was ich vermeiden möchte.
Wo steckt der Fehler? Oder muss ich das komplett anders aufsetzen?
Vielen Dank
Hans-Jürgen

Betrifft: AW: Zeig den ganzen Code der Beenden-Sub! (owT)
von: EtoPHG
Geschrieben am: 19.10.2020 17:52:12

Betrifft: AW: Zeig den ganzen Code der Beenden-Sub! (owT)
von: Hans-Jürgen
Geschrieben am: 20.10.2020 07:46:53
Bitteschön... dankeschön!
Public Sub ProgrammBeenden()
If Not objADODB Is Nothing Then
If objADODB.State = adStateOpen Then
objADODB.Close
End If
End If
Set rstDaten = Nothing
Application.WindowState = xlNormal
If ActiveWorkbook.Name = "Archiv.xlsm" Then
If Workbooks.Count = 1 Then
Application.Quit
Else
Workbooks(ActiveWorkbook.Name).Close SaveChanges:=True
End If
End If
End Sub

Betrifft: AW: Zeig den ganzen Code der Beenden-Sub! (owT)
von: Hans-Jürgen
Geschrieben am: 20.10.2020 07:51:01

Betrifft: ActiveWorkbook <> Thisworkbook
von: EtoPHG
Geschrieben am: 20.10.2020 14:40:53
Hallo Hans-Jürgen,
Ich kann Deinen Gedankengängen nur schwer folgen. Insbesondere verstehe ich das Konzept mit den 2 Instanzen von Excel nicht.
Meine Vermutung ist, dass
ThisWorkbook (Arbeitsmappe in welcher der Code läuft) und
ActiveWorkbook (zum Zeitpunkt der Codeausführung aktive Mappe) nicht die gleichen sind. Also bleibt, nach Codeabschluss der Sub, das
ThisWorkbook offen.
Gruess Hansueli

Betrifft: AW: ActiveWorkbook <> Thisworkbook
von: Hans-Jürgen
Geschrieben am: 20.10.2020 18:31:57
Hallo Hansueli,
jaja, ich weiß, ist sehr kompliziert bei mir.
Ich werde das mal mit deinem Hinweis testen. Wenns klappt, ist gut, wenn nicht, muss der Anwender selbst schließen. Das ist letztlich nur ein „nice to have“ womit ich eure und meine Kapazitäten nicht überbelasten will.
Viele Grüße
Hans-Jürgen

Betrifft: AW: ActiveWorkbook <> Thisworkbook
von: Hans-Jürgen
Geschrieben am: 20.10.2020 18:31:58
Hallo Hansueli,
jaja, ich weiß, ist sehr kompliziert bei mir.
Ich werde das mal mit deinem Hinweis testen. Wenns klappt, ist gut, wenn nicht, muss der Anwender selbst schließen. Das ist letztlich nur ein „nice to have“ womit ich eure und meine Kapazitäten nicht überbelasten will.
Viele Grüße
Hans-Jürgen

Betrifft: AW: ActiveWorkbook <> Thisworkbook
von: Hans-Jürgen
Geschrieben am: 20.10.2020 20:26:39
Hallo Hansueli,
jaja, ich weiß, ist sehr kompliziert bei mir.
Ich werde das mal mit deinem Hinweis testen. Wenns klappt, ist gut, wenn nicht, muss der Anwender selbst schließen. Das ist letztlich nur ein „nice to have“ womit ich eure und meine Kapazitäten nicht überbelasten will.
Viele Grüße
Hans-Jürgen

Betrifft: AW: Schließen des Basisfensters
von: volti
Geschrieben am: 19.10.2020 18:15:11
Hallo Hans-Jürgen,
vielleicht kannst Du mit nachfolgendem Code als Anregung etwas anfangen...
Er ermittelt alle vorhandenen Instanzen und gibt auch die Instanz des gesuchten Workbooks zurück.
Code:
[Cc][+][-]
Option Explicit
Private Declare PtrSafe Function GetClassNameA Lib "user32" ( _
ByVal hWnd As LongPtr, ByVal lpClassName As String, _
ByVal nMaxCount As Long) As Long
Private Declare PtrSafe Function EnumWindows Lib "user32" ( _
ByVal lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long
Private Declare PtrSafe Function EnumChildWindows Lib "user32" ( _
ByVal hWndParent As LongPtr, ByVal lpEnumFunc As LongPtr, _
ByVal lParam As LongPtr) As Long
Private Declare PtrSafe Sub IIDFromString Lib "ole32.dll" ( _
ByVal lpsz As String, ByRef lpiid As GUID)
Private Declare PtrSafe Sub AccessibleObjectFromWindow Lib "oleacc.dll" ( _
ByVal hWnd As LongPtr, ByVal dwId As Long, ByRef riid As GUID, _
ByRef ppvObject As Any)
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
Private Const IID_EXCELWINDOW = "{00020893-0000-0000-C000-000000000046}"
Private Const OBJID_NATIVEOM = &HFFFFFFF0
Private hWndChild() As LongPtr, iChildCount As Long
Private hWwndMain() As LongPtr, iWindowCount As Long
Private sAllHandles As String
Private Function GetApplications() As Application()
Dim i As Long, iCount As Long
Dim udtGuid As GUID, oWin As Window
Dim oTmpApplications() As Application
Erase hWndChild: iChildCount = 0 'Variablen zurücksetzen
Erase hWwndMain: iWindowCount = 0
Call IIDFromString(StrConv(IID_EXCELWINDOW, vbUnicode), udtGuid)
Call EnumWindows(AddressOf EnumWindowProc, ByVal 0&)
For i = LBound(hWwndMain) To UBound(hWwndMain)
Call EnumChildWindows(hWwndMain(i), _
AddressOf EnumChildWindowProc, ByVal 0&)
Next i
'Alle Kinder-Fenster durchgehen
sAllHandles = ","
For i = LBound(hWndChild) To UBound(hWndChild)
Call AccessibleObjectFromWindow(hWndChild(i), _
OBJID_NATIVEOM, udtGuid, oWin)
If Not oWin Is Nothing Then
If InStr(sAllHandles, "," & CStr(oWin.Application.hWnd) & ",") = 0 Then
ReDim Preserve oTmpApplications(iCount)
Set oTmpApplications(iCount) = oWin.Application
iCount = iCount + 1
sAllHandles = sAllHandles & CStr(oWin.Application.hWnd) & ","
End If
End If
Next i
GetApplications = oTmpApplications
End Function
Private Function EnumWindowProc(ByVal hWnd As LongPtr, ByVal lParam As Long) As Long
'Durchlaufe alle Fenster und merke Excelfenster
Dim sClassName As String * 256
If Left$(sClassName, GetClassNameA(hWnd, sClassName, Len(sClassName))) _
= "XLMAIN" Then 'Ist es ein Excelfenster?
ReDim Preserve hWwndMain(iWindowCount) 'Array dimensionieren
hWwndMain(iWindowCount) = hWnd 'Fenster-Handle merken
iWindowCount = iWindowCount + 1 'Weiterzählen
End If
EnumWindowProc = 1
End Function
Private Function EnumChildWindowProc(ByVal hWnd As LongPtr, ByVal lParam As Long) As Long
'Durchlaufe alle Kinder-Fenster und merke Excelfenster
Dim sClassName As String * 256
If Left$(sClassName, GetClassNameA(hWnd, sClassName, Len(sClassName))) _
= "EXCEL7" Then
ReDim Preserve hWndChild(iChildCount) 'Array dimensionieren
hWndChild(iChildCount) = hWnd 'Fenster-Handle merken
iChildCount = iChildCount + 1 'Weiterzählen
EnumChildWindowProc = 0
Else
EnumChildWindowProc = 1
End If
End Function
Sub SucheOffeneExcelmappe()
Dim oApplications() As Application, WkB As Workbook
Dim i As Long
Dim sSuch As String
sSuch = "Archiv.xlsm"
oApplications = GetApplications
For i = LBound(oApplications) To UBound(oApplications)
For Each WkB In oApplications(i).Workbooks
If WkB.Name Like sSuch Then
'Mach was.....
MsgBox "Workbook " & WkB.Name & " wurde gefunden!", vbInformation, "Excel-Instanzen"
' WkB.Close SaveChanges:=True 'Workbook schließen
' oApplications(i).Quit 'Diese Excel-Instanz beenden
Exit Sub
End If
Next WkB
Next i
MsgBox "Mappe '" & sSuch & "' ist ncht geöffnet!", vbInformation
End Sub
____________________
viele Grüße aus Freigericht
Karl-Heinz

Betrifft: AW: Schließen des Basisfensters
von: Hans-Jürgen
Geschrieben am: 20.10.2020 07:48:52
Hallo Karl-Heinz,
vielen Dank, das nehme ich gern in meine Code-Sammlung auf. Ich gehe das nach und nach durch und versuche, den Ablauf zu verstehen. (Ich möchte gern nur Code verarbeiten, von dem ich selbst weiß, was er macht). Und ich habe das nicht verstanden, was da abgeht.
Trotzdem vielen Dank
Hans-Jürgen
Beiträge aus dem Excel-Forum zum Thema "Schließen des Basisfensters"