Für die Konstruktion einer Datenbank suche ich die Möglichkeit, per Makro eine Datenbankdatei und gegebenenfalls auch den gesamten Star-Desktop zu schließen.
Unter Extras → Anpassen → Ereignisse → Unterdokument wurde geschlossen
habe ich dafür ein Makro eingebaut, das erst dann das Schließen veranlassen soll, wenn kein Formularfenster (und auch keine Abfragefenster o.ä.) noch offen ist.
Ich habe jetzt insgesamt 4 Varianten durchgetestet:
oDoc.Close(True)
→ Scheinbar funktioniert alles. ImHintergrund bleibt aber LibreOffice offen, so dass ein Neustart unter Windows nicht funktioniert.
oDispatcher.executeDispatch(oDoc, ".uno:Quit", "", 0, Array())
→ gleiches ergebnis wie der direkte vorhergehende Befehl.
.uno:CloseWin
und .uno:CloseDoc
→ beide lassen den Desktop stehen, funktionieren aber wenigstens so weit, dass eben die Base-Datei geschlossen wird, wenn das Formular geschlossen wird.
Ich hänge einmal die Base-Datei an. Es handelt sich um eine Weiterentwicklung der DB für die XRechnungen. Makros müssen dafür natürlich angeschaltet sein.
XRechnung_V2408_003.odb (529.4 KB)
Die fraglichen Passagen befinden sich im Modul “Backup” → “DatabaseClose”
Ziel wäre, dass LibreOffice komplett geschlossen wird, also keine versteckten Prozesse noch aktiv sind, wenn nicht das Makrofenster oder sonst ein anderes Fenster von LibreOffice noch geöffnet ist. Der Desktop soll also auch anstandslos geschlossen werden.
StarDesktop.terminate()
@Villeroy : Du hast Recht. Das hatte ich nicht auf dem Schirm. Es schließt das Dokument und den Desktop. Bei offenen anderen Dokumenten kommt jetzt natürlich die Nachfrage, ob der Inhalt gespeichert werden soll. Vielleicht muss ich da noch etwas schauen, dass ich vorher klar kriege, ob noch Fenster außer dem von Base offen sind. Wird ja über StarDesktop.getFrames()
möglich sein.
Oder gleich StarDesktop.getComponents()
Sehr geehrter Herr Robert,
Warum genuegte es Dir die Kombination Alt+F4 nicht?
Verzeihe mich, aber ich mag keinen Makros in meinem Dateibearbeitung.
Grueße Sie freundlich.
Was der Herr Robert da treibt, nennt sich “Anwendungsentwicklung”. In diesem Fall ist das wohl so gedacht: “Installieren Sie LibreOffice, öffnen Sie diese Datei, tragen Ihre Firmendaten hier, die Inkassodaten dort ein, und drücken Sie diese Schaltfläche, um Emails mit gültigen PDF/XML-Rechnungsanhängen zu erzeugen. Die gesamte Anwendung wird mit jener Schaltfläche beendet.”
Der tag “basic” ist ja leider nicht vorhanden. Daher habe ich “base” und “meta” gewählt.
Natürlich vermeide ich Makros, wenn es anders geht. Nur sind eben manche unbedarfteren Anwender überfordert, wenn da plötzlich eine Base-Oberfläche zu sehen ist. Deswegen: Automatischer Start eines Formulars direkt am Anfang mit voller Bildschirmgröße und automatisches Schließen zum Schluss.
… nur leider funktioniert das mit dem Schließen doch noch nicht so ganz zufriedenstellend. Die Windows-Welt zeigt beim StarDesktop.terminate() ein hängendes Base-Fenster an. Unter Linux werden hingegen die Restprozesse anschließend im Verborgenen geschlossen …
Ich habe den Thread deshalb wieder geöffnet. Wenn ich die Base-Datei über “LibreOffice Beenden” (Strg+Q) beende, dann schließt sich LO komplett. Mache ich das mit .uno:Quit, was der zugrundeliegende Befehl ist, dann stürzt LO ab bzw. hängt. Das ist gleich dem, was das “StarDesktop.terminate” bewirkt.
Die Sprache heißt ja auch “StarBasic”, und der Tag ist vorhanden. Zum Problem mit Windows kann ich jetzt leider nichts beitragen, außer das auf forum.openoffice.org viel Material zu finden ist, wenn man nach StarDesktop.terminate sucht.
Ich habe das jetzt einmal stark verkürzt noch in der englischsprachigen Variante beschreiben:
Ich habe das Ganze jetzt auf eine simple Datenbankdatei begrenzen können. Die folgende Datei lässt unter Linux manchmal keinen Prozess zurück, führt aber unter Windows 10 wohl weiter zum Absturz:
DocClose.odb (4.8 KB)
Das darin enthaltene Makro hat den folgenden Code:
SUB BaseClose
oDoc = ThisDatabaseDocument
oDoc.DataSource.flush
oDoc.CurrentController.ActiveConnection.close()
StarDesktop.Terminate()
END SUB
Speichere ich nicht mit flush
und schließe ich nicht die Verbindung, so bleibt unter Linux immer ein Prozess offen.
Das Makro wird ausgelöst, indem die enthaltene simple Abfrage einmal ausgeführt wird und danach wieder geschlossen wird.
Beende ich das Makro unter Linux mit oDoc.Close statt mit StarDesktop.Terminate, so schließt das komplette LO nur im Vordergrund. Ich kann dann sehr schnell LO wieder starten - so ungefähr, als wäre das Fenster nur unsichtbar.
Habe jetzt wohl mit Hilfe dieses Threads
die Lösung für das Problem.
Folgenden Code habe ich in eine separate Bibliothek unter “Meine Makros” gepackt:
Sub AsyncClose(Byval oDoc As Object)
CreateUnoService("com.sun.star.awt.AsyncCallback").addCallback(CreateUnoListener("AsyncClose_","com.sun.star.awt.XCallback"),oDoc)
End Sub
Sub AsyncClose_notify(arg)
arg.Close(True)
oFrames = StarDesktop.Frames
n = oFrames.Count
IF n = 0 THEN StarDesktop.Terminate()
End Sub
Das Schließen des Dektops kann erst dann stattfinden, wenn die Base-Datei geschlossen ist. Deshalb muss der gesamte Code außerhalb der Base-Datei gelagert werden.
In dem Datanbankdokument wird an Extras → Anpassen → Ereignisse → Unterdokument wurde geschlossen
die folgende Prozedur gebunden:
SUB DatabaseClose
DIM oDoc AS OBJECT
oDoc = ThisDatabaseDocument
REM Nur bei einem leeren Array (alle Subdokumente geschlossen) wird für UBound der Wert -1 ausgegeben
IF LBound(oDoc.CurrentController.SubComponents()) > UBound(oDoc.CurrentController.SubComponents()) THEN
GlobalScope.BasicLibraries.loadLibrary("XRechnung")
DataWrite
AsyncClose(oDoc)
END IF
END SUB
Wenn das leste Unterfenster geschlossen wurde, wird die Bibliothek geladen, die außerhalb der Base-Datei liegt. Die verbleibenden Daten werden noch in die DB geschrieben. Dann wird das (asynchrone) Schließen aufgerufen.
Nach dem Schließen der Base-Datei über close(true)
läuft LibreOffice im Hintergrund weiter. Ist kein Fenster mehr offen, dann wird auch StarDesktop
mit dem Befehl Terminate()
geschlossen.