[gelöst] Prüfung ob zu öffnendes Dokument bereits geöffnet ist

Programmierung unter AOO/LO (StarBasic, Python, Java, ...)

Moderator: Moderatoren

kilix
****
Beiträge: 128
Registriert: So, 09.04.2023 11:27

[gelöst] Prüfung ob zu öffnendes Dokument bereits geöffnet ist

Beitrag von kilix »

Hallo,
ich habe ein Quell- und ein Zieldokument und übertrage Bereiche von der Quelle zum Ziel. Wenn das Zeildokument geschlossen ist funktioniert das gut. Ist das Zeildokument allerdings bereits geöffnet wird es schreibgeschützt noch einmal geöffnet was natürlich das Makro zum Anstirz bringt.
Wie kann ich im Makro vor dem Öffnen prüfen ob das Ziel bereits offen ist?
Zuletzt geändert von kilix am Sa, 29.07.2023 18:12, insgesamt 1-mal geändert.
Grüße
kilix
kilix
****
Beiträge: 128
Registriert: So, 09.04.2023 11:27

Re: Prüfung ob zu öffnendes Dokument bereits geöffnet ist

Beitrag von kilix »

Ich habe das Problem jetzt mit einem Workaround umgangen da ich verhindern möchte, dass das Makro abstürzt. Durch das Öffnen von Test.ods wird Test.ods geöffnet - auch wenn es bereits geöffnet war - allerdings schreibgeschützt. Daher kann der folgende Befehl: speichern eines Bereichs nicht durchgeführt werden und das Makro stürzt mit Fehler ab.
Daher habe ich den Fehler mit On Error abgefangen und in einer Fehlerroutine verzweigt, die eine Fehlermeldung bringt und die schreibgeschützt geöffnete Datei wieder schließt. Damit wird er Anwender aufgefordert die bereits geöffnete DAtei Test,ods zu schließen und das Makro neu zu starten.

Code: Alles auswählen

Sub Test

	oDoc=ThisComponent

	surl = oDoc.url
	apfad = split(surl,"/")
	apfad(ubound(apfad)) = "test.ods"
   	sURL = convertToURL(join(apfad,"/"))
   	dim myFileProp() as new com.sun.star.beans.PropertyValue
   	On Error Goto FehlerRoutine:
	oODS = StarDesktop.loadComponentFromURL(sURL, "_blank", 0, myFileProp())
	
	'1. Auslesen der Testdaten in Tab: Auswahl
	aDaten = oDoc.Sheets(2).getCellRangeByName("A3:C10003").getDataArray
	'Schreiben der Daten in die aktuelle Datei
	oODS.Sheets(1).getCellRangeByName("A3:C10003").setDataArray(aDaten)
	.
	.
	usw
	.
	.
	oODS.unlockcontrollers
	oODS.store()
	oODS.close(false)
	
	Exit Sub
	
	FehlerRoutine:
	
	MsgBox("Die Datei Test.ods ist bereits geöffnet" + CHR(13) +_
	"Schließen sie diese Datei und starten sie das Makro neu")
	oODS.close(false)		'schließen der schreibgeschützt geöffneten Test.ods
	
End Sub
Schöner wäre es natürlich ich könnte bereits im Vorhinein feststellen, dass die Datei Test.ods bereits geöffnet ist. Dann könnte ich mit dieser Datei weiterarbeiten. Leider habe ich dafür keine Lösung gefunden.
Grüße
kilix
mikeleb
*******
Beiträge: 1316
Registriert: Fr, 09.12.2011 16:50

Re: Prüfung ob zu öffnendes Dokument bereits geöffnet ist

Beitrag von mikeleb »

Hallo,
auf direktem Weg ist das nicht möglich. Es gibt aber folgenden Weg:
Alle geöffneten Fenster (also Dateien, Hilfe, IDE, ...) sind als Komponenten des Stardesktops gelistet. Die kann man durchsuchen, ob die gewünschte dabei ist. Eine ähnliche Funktion findest du hier:
http://www.dannenhoefer.de/faqstarbasic ... terwaehlen
Gruß,
mikeleb
kilix
****
Beiträge: 128
Registriert: So, 09.04.2023 11:27

Re: Prüfung ob zu öffnendes Dokument bereits geöffnet ist

Beitrag von kilix »

Hallo mikeleb,

danke für die Antwort. Genau in diesem Dokument habe ich ich schon etwas gefunden.

Code: Alles auswählen

Sub Datei_suchen
	GesuchteDatei="einritte.ods"
	Dim oDesktop As Object, oDocs As Object
	Dim oDoc As Object, oComponents As Object
	oComponents = StarDesktop.getComponents()
	oDocs = oComponents.createEnumeration()
	Do While oDocs.hasMoreElements()
		oDoc = oDocs.nextElement()
		datei=odoc.geturl()
		FileN=FileNameoutofPath(datei)
		if FileN=GesuchteDatei then
			print "gefunden"
		End If
	Loop
End sub
Soweit ich es verstanden habe werden hier die die geöffneten Dateien durchsucht und geprüft ob die gesuchte dabei ist (ich habe den Code leicht modifiziert). In diesem Code kommt exakt die gleiche Zeile wie in dem von dir kopierten Code vor

FileN=FileNameoutofPath(datei)

Genau in dieser Zeile stürzt die Sub mit der Meldung: "Basic-Laufzeitfehler, Sub- oder Function-Procedur nicht definiert."
Dannenhöfer schreibt: "Dies geht mit FileNameoutofPath aus der Bibliothek Tools."

Er hat in seinem Dokument einen Abschnitt mit Tools aber dort habe ich nichts passendes gefunden. Ich weiß auch nicht wo es diese Bibliothek Tools gibt.

Ein weiteres Problem ist, dass ich wenn ich die Datei als geöffnet identifiziert habe nur eine Meldung sinden kann, die dem Anwender sagt, schließe zuerst diese Datei und starte das Makro neu. Das Widersinnige dabei ist, dass das Makro genau diese Datei dann selbst öffnet. Für mich logischer wäre es, wenn ich die URL schone kenne und weiß, dass diese Datei geöffnet ist, die gleich zu verwenden und dazu habe ich nichts gefunden. Ich weiß zwar wie man mit einer bekannten URL eine Datei öffnen kann
(oODS = StarDesktop.loadComponentFromURL(sURL, "_blank", 0, myFileProp())
aber nicht wie ich die Variable oODS (in diesem Beispiel) bei einer bereits geöffneten Datei befüllen kann. Könnte ich das dann bräuchte ich keine Fehlermeldung und könnte die gesammte Verarbeitung durchführen, egal ob die Datei zu öffnen ist oder die bereits geöffnete verwendet wird.
Grüße
kilix
mikeleb
*******
Beiträge: 1316
Registriert: Fr, 09.12.2011 16:50

Re: Prüfung ob zu öffnendes Dokument bereits geöffnet ist

Beitrag von mikeleb »

Hallo,
es gibt so ein paar Hürden zu überwinden, die manchmal nicht so offensichtlich sind:
1) Die Prozedur FileNameoutofPath extrahiert den Dateinamen aus der URL. Diese Prozedur ist in der mitgelieferten Bibliothek Tools enthalten. Um darauf zuzugreifen, muss diese Bibliothek am Anfang deines Makros geladen werden:

Code: Alles auswählen

GlobalScope.BasicLibraries.LoadLibrary("Tools")
Nun kannst du alle Prozeduren dieser Bibliothek nutzen.
2) Nicht jedes Element von StarDesktop.getComponents() besitzt die Methode .getUrl. In dem Fall würde es einen Abbruch des Makros geben.
3) Der Dateiname definiert das Fenster nicht eindeutig. Im Gegensatz zu MS Office können mehrere Dateien mit dem Namen test.ods geöffnet sein, wenn sie in verschiedenen Verzeichnissen liegen.
Der Dateiname taucht zwar im Titel des Fensters auf. Er muss es aber nicht. Ungespeicherte Dateien haben eine leere Url, heißen im Fenster aber z. B."Unbenannt1.ods"
Mit den Vorbemerkungen schlage ich folgendes Makro vor:

Code: Alles auswählen

Sub Datei_suchen

	Dim oDesktop As Object, oDocs As Object
	Dim oDoc As Object, oComponents As Object

	GlobalScope.BasicLibraries.LoadLibrary("Tools")
	GesuchteDatei="einritte.ods"
	oComponents = StarDesktop.getComponents()
	oDocs = oComponents.createEnumeration()
	gefunden=false
	Do While oDocs.hasMoreElements() and gefunden=false
		oDoc = oDocs.nextElement()
		if odoc.supportsservice("com.sun.star.document.OfficeDocument") then
			sdatei=odoc.geturl()
			if sDatei<>"" then
				sdateiname=FileNameoutofPath(sdatei)
			end if
			if sdateiname=GesuchteDatei then
				gefunden=true
			End If
		End if
	Loop
	'die Schleife bricht ab, wenn alle Fenster durchlaufen wurde oder wenn die Datei gefunden wurde
	'wenn die Datei gefunden wurde, referenziert die Variable oDoc auf diese Datei, ansonsten auf das letzte Fenster!
	If gefunden then
		msgbox "gefunden"
		'nun zum Beispiel die Anzeige der kompletten Url der Datei
		msgbox odoc.url	
	else
		odoc=nothing
	end if

	'jetzt enthält odoc entweder die gesuchte Datei oder die Variable ist leer
	
End sub
Gruß,
mikeleb
kilix
****
Beiträge: 128
Registriert: So, 09.04.2023 11:27

Re: Prüfung ob zu öffnendes Dokument bereits geöffnet ist

Beitrag von kilix »

Hallo mikeleb,
vielen DAnk für deine Sub!
Ich habe sie etwas verändert damit ich sie auf für andere Subs mit ähnlicher Aufgabe (z.B. öffnen eines anderen Dokuments) verwenden kann. Außerdem habe zwei Variable als Public definiert damit ich das Ergebnis im Makro weiterverwenden kann.
So sieht der Code jetzt aus:

Code: Alles auswählen

Beginn des Makros:
Public oDoc1 as Object
Public gefunden as Boolean

Sub Einritte_erfassen
	
	Datei_suchen("Einritte.ods")
	.
	.
	.
End sub
	
Sub Datei_suchen(Dateiname)		' so kann ich auch andere Dateinamen einsetzen
	
	Dim oDesktop As Object, oDocs As Object
'	Dim oDoc1 As Object			' oDoc1 weil ich im Makro schon oDoc verwende (wäre 
							' wahrscheinlich nicht nötig da diese Variable nur un der Sub gilt
	Dim oComponents As Object

	GlobalScope.BasicLibraries.LoadLibrary("Tools")
	GesuchteDatei=Dateiname
	oComponents = StarDesktop.getComponents()
	oDocs = oComponents.createEnumeration()
	gefunden=false
	Do While oDocs.hasMoreElements() and gefunden=false
		oDoc1 = oDocs.nextElement()
		if odoc1.supportsservice("com.sun.star.document.OfficeDocument") then
			sdatei=odoc1.geturl()
			if sDatei<>"" then
				sdateiname=FileNameoutofPath(sdatei)
			end if
			if lcase(sdateiname)=lcase(GesuchteDatei) then
				gefunden=true
			End If
		End if
	Loop
	'die Schleife bricht ab, wenn alle Fenster durchlaufen wurde oder wenn die Datei gefunden wurde
	'wenn die Datei gefunden wurde, referenziert die Variable oDoc auf diese Datei, ansonsten auf das letzte Fenster!
	If gefunden then
		MsgBox ("Einritte.ods ist bereits geöffnet - mit Menü: Fenster in der Vordergrund holen")
		' ich suche noch eine Möglichkeit das bereits geöffnete Dokument in den Vordergrund zu bringen. 
		' Vorläufig genügt dieser Hinweis
	Else	
		odoc1=nothing
	end if

	'jetzt enthält odoc entweder die gesuchte Datei oder die Variable ist leer
	
End sub
Grüße
kilix
mikeleb
*******
Beiträge: 1316
Registriert: Fr, 09.12.2011 16:50

Re: Prüfung ob zu öffnendes Dokument bereits geöffnet ist

Beitrag von mikeleb »

Hallo,
wenn du es als function nutzt, kannst du dir die public-Variablen sparen

Code: Alles auswählen

Beginn des Makros:

Sub Einritte_erfassen
	
	oDoc1=Datei_suchen("Einritte.ods")
	'um zu testen, ob etwas gefunden wurde:
	if isnull(oDoc1) ....
	.
	.
End sub
	
Function Datei_suchen(Dateiname)		' so kann ich auch andere Dateinamen einsetzen
	
	Dim oDesktop As Object, oDocs As Object
'	Dim oDoc1 As Object			' oDoc1 weil ich im Makro schon oDoc verwende (wäre 
							' wahrscheinlich nicht nötig da diese Variable nur un der Sub gilt
	Dim oComponents As Object

	GlobalScope.BasicLibraries.LoadLibrary("Tools")
	GesuchteDatei=Dateiname
	oComponents = StarDesktop.getComponents()
	oDocs = oComponents.createEnumeration()
	gefunden=false
	Do While oDocs.hasMoreElements() and gefunden=false
		oDoc1 = oDocs.nextElement()
		if odoc1.supportsservice("com.sun.star.document.OfficeDocument") then
			sdatei=odoc1.geturl()
			if sDatei<>"" then
				sdateiname=FileNameoutofPath(sdatei)
			end if
			if lcase(sdateiname)=lcase(GesuchteDatei) then
				gefunden=true
			End If
		End if
	Loop
	'die Schleife bricht ab, wenn alle Fenster durchlaufen wurde oder wenn die Datei gefunden wurde
	'wenn die Datei gefunden wurde, referenziert die Variable oDoc auf diese Datei, ansonsten auf das letzte Fenster!
	If gefunden then
		MsgBox ("Einritte.ods ist bereits geöffnet - mit Menü: Fenster in der Vordergrund holen")
		' ich suche noch eine Möglichkeit das bereits geöffnete Dokument in den Vordergrund zu bringen. 
		' Vorläufig genügt dieser Hinweis
	Else	
		odoc1=nothing
	end if
	Datei_suchen=oDoc1
	
	
End sub
Gruß,
mikeleb
kilix
****
Beiträge: 128
Registriert: So, 09.04.2023 11:27

Re: Prüfung ob zu öffnendes Dokument bereits geöffnet ist

Beitrag von kilix »

Danke! Ich hatte schon versucht diese Sub als Funktion zu schreiben. Bin dabei aber an einem Punkt hängen geblieben. Das ist die Zeile in deinem Beispiel:

Datei_suchen=oDoc1

Das hat mir gefehlt denn ich bekam keinen Wert zurück. Bei FreeBasic würde es heißen Result = oDoc1 aber jetzt hab ich gesehen, dass du den Namen der Funktion verwendest!
Grüße
kilix
mikeleb
*******
Beiträge: 1316
Registriert: Fr, 09.12.2011 16:50

Re: Prüfung ob zu öffnendes Dokument bereits geöffnet ist

Beitrag von mikeleb »

Hallo,
Und am Ende muss es

Code: Alles auswählen

end function 
heißen
Gruß,
mikeleb
kilix
****
Beiträge: 128
Registriert: So, 09.04.2023 11:27

Re: Prüfung ob zu öffnendes Dokument bereits geöffnet ist

Beitrag von kilix »

Danke. Das ist klar. So etwas übersieht man leicht :)
Grüße
kilix
Antworten