BITTE helfen Sie uns HEUTE mit einer SPENDE
Helfen Sie das LibreOffice Forum zu erhalten!

❤️ DANKE >><< DANKE ❤️

> KEINE WERBUNG FÜR REGISTRIERTE BENUTZER!<
Ihre Spende wird für die Deckung der laufenden Kosten sowie den Erhalt und Ausbau 🌱 des LibreOffice Forums verwendet.
🤗 Als Dankeschön werden Sie im Forum als LO-SUPPORTER gekennzeichnet. 🤗

Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Alles zur Programmierung im LibreOffice.
mikele
Beiträge: 1659
Registriert: Mo 1. Aug 2011, 20:51

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von mikele » So 1. Sep 2019, 16:46

Hallo,
da tauchen schon ein paar merkwürdige Dinge auf, die nicht so simple aufzulösen sind.
Für deine Zwecke sollte die Variable oDialog als Global deklariert werden, da in deinem Fall das Ereignis "Auswahl geändert" (auch bei nur einem Klick) mehrfach ausgelöst wird. Das Auftauchen deines Dialoges ist auch ein solcher (der Focus wechselt, zumindest zwischenzeitlich, zum Dialog und wieder zurück). Wird das Tabellenblatt gewechselt, wird das Ereignis auch zweimal ausgelöst (ich vermute mal: 1. Tabellenblatt ausgewählt 2. Zelle ausgewählt).
Als Public deklarierte Variablen behalten ihren Wert nur solange das Makro läuft. Bei jedem Neuaufruf werden sie neu initialisiert.
Bei Global wird das Makro zwar auch mehrfach aufgerufen, aber da ist die Variable oDialog schon belegt und der Dialog wird nicht noch einmal gebaut, sondern "nur" aufgefrischt.
Die Ursache für deine eingangs genannte Fehlermeldung liegt eher daran, dass es eine Weile dauert, bis das Bild wirklich eingefügt ist (Ladezeiten). Um das zu umgehen, baust du eine Waretschleife ein:

Code: Alles auswählen

Global cardGraphic as Object, odialog as object


Sub ShowCardGraphic(cardGraphicName as String)
    Dim oWindow As Object, odlgModel As Object, oMod As Object, oCntrl As Object, oTopWindowsListener As Object, oSimpleFileAccess As Object

	if pathLackeyPlugin = "" then
		cardGraphicName = "http://www.redemptionquick.com/lackey/sets/setimages/general/" & cardGraphicName & ".jpg"
	end if
    If isnull(odialog) Then
	    REM ***** Initialisierung der Eigenschaften des Dialogs
	    odlgModel = CreateUnoService("com.sun.star.awt.UnoControlDialogModel")
	    
	    With odlgModel
'	       .setPropertyValue("FontName", Font)
	       .setPropertyValue("Width", 180)
	       .setPropertyValue("Height", 240)
	       .setPropertyValue("PositionX", -0)
	       .setPropertyValue("PositionY", 80)
	       .setPropertyValue("Title", "Picture")
	       .setPropertyValue("Name", "DLG_PICTURE")
	    End With

		odialog = CreateUnoService("com.sun.star.awt.UnoControlDialog")

	    REM ********** Textlabel erzeugen
	    oMod = odlgModel.createInstance("com.sun.star.awt.UnoControlImageControlModel")
	    
	    With oMod
	       '.setPropertyValue("Label", "X")
	       .setPropertyValue("Name", "IMG1")
	       .setPropertyValue("PositionX", 0)
	       .setPropertyValue("PositionY", 0)
	       .setPropertyValue("Width", 180)
	       .setPropertyValue("Height", 240)
	       .setPropertyValue("ImageURL" ,cardGraphicName)
	       .setPropertyValue("ScaleMode", 1)
	    End With
	    dim x
	    odlgModel.insertByName("IMG1", oMod)
	    odialog.setModel(odlgModel)
	      
	    REM ********** Mittels des Modells den Dialog anzeigen
	    oWindow = CreateUnoService("com.sun.star.awt.Toolkit")
	    odialog.createPeer(oWindow, null)
	    Dim oWindowsListener as Object
	    oTopWindowsListener = CreateUnoListener( "Top_Win_", "com.sun.star.awt.XTopWindowListener" )
	    odialog.addTopWindowListener(oTopWindowsListener)
	    odialog.setVisible(True)
   		do
			oCntrl = odialog.getcontrol("IMG1")
			wait 100
		loop while isnull(ocntrl)

	Else
		if not odialog.isVisible() Then
			odialog.setVisible(True)
		end if
		do
			oCntrl = odialog.getcontrol("IMG1")
			wait 100
		loop while isnull(ocntrl) 
	    oCntrl.model.ImageURL = cardGraphicName
	end if

End Sub
Um das Mehrfache Auslösen des Ereignisses ein wenig einzudämmen (ich bin mir nicht sicher, wann es in deinem Fall mit schwebendem Dialog wirklich ausgelöst wird) würde ich es während der Makroausführung auschalten.

Code: Alles auswählen

Sub OnSheetContentChange(e) as boolean
	'when a cell in column card name of sheet List is selected we need to take that name to get the cardimage name from sheet carddata.txt
	Dim oDoc as Object, form as Object, showCardImgCB as Object
	Dim oldRow as Long, oldColumn as Long
	Dim foundCardName as String
	Dim tmpevent 'Zwischenspeicher für Tabellenereignis

	oDoc = thisComponent
	form = oDoc.sheets(0).Drawpage.Forms.getByIndex(0)
	'Tabellenereignis vorläufig entfernen
	tmpevent=odoc.sheets(0).events.getbyname("OnSelect")
	Dim oStruct as new com.sun.star.beans.PropertyValue	
	odoc.sheets(0).events.replaceByName("OnSelect",ostruct)
	'Checkbox auslesen
	showCardImgCB = form.getByName("ShowCardImage")
'print showCardImgCB.currentvalue
	'remember last activated cell
	oldRow = currentRow
	oldColumn = currentColumn
'print "Vorher: oldRow=" & oldRow & " currentRow=" & currentRow	
	currentRow = GetCurrentRow
	currentColumn = GetCurrentColumn
'print "Nachher: oldRow=" & oldRow & " currentRow=" & currentRow	
	'if selected cell has changed and if we are in column B then we can go ahead
	'this unfortunately cannot cover if mouse pointer is over image or has image selected and image was deleted
	if ((oldRow <> currentRow) and (currentColumn = 1)) then
'print currentColumn & " " & currentRow
		foundCardName = oDoc.getcurrentcontroller.activesheet.getCellByPosition(14, currentRow).getString()
		currentCardName = foundCardName
'print oDoc.getcurrentcontroller.activesheet.getCellByPosition(14, currentRow).getString()
	end if
	'only show card image if appropriate checkbox is ticked and if we are in column B
	if (cbool (showCardImgCB.currentvalue) and (currentColumn = 1)) then
		ShowCardGraphic(ByVal currentCardName)
	end if
	
	'Tabellenereigbnis wiederherstellen
	odoc.sheets(0).events.replaceByName("OnSelect",tmpevent)
	OnSheetContentChange=true
End Sub
Mit der letzten Zeile umgeht man ggf. auftretende Probleme, das Klicks während der Makrobearbeitung die Auswahl auf dem Tabellenblatt ändern.
Gruß,
mikele

craig
Beiträge: 1137
Registriert: Do 21. Apr 2016, 11:42

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von craig » So 1. Sep 2019, 17:28

Hallo,

ich bin mir nicht sicher, aber denke dass der Listener nicht richtig deklariert ist.
Einerseits wird er nur in der Prozedur deklariert und ausserdem
ist er falsch geschrieben, oder sehe ich das falsch?

Code: Alles auswählen

    
Dim oWindowsListener as Object
oTopWindowsListener = CreateUnoListener( "Top_Win_", "com.sun.star.awt.XTopWindowListener" )
odialog.addTopWindowListener(oTopWindowsListener)
Auch wundert es mich, dass der Interpreter trotz des "Option Explicit" nicht anspringt :roll:
Gruß

Craig

Nie die Sicherungskopie vergessen!

════════════════════════════════════════════════
WIN 10 Pro 64-Bit • LO 7.4.5.1 (x64) • AOO 4.1.8

mikele
Beiträge: 1659
Registriert: Mo 1. Aug 2011, 20:51

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von mikele » So 1. Sep 2019, 18:00

Hallo,
die Variable oTopWindowsListener ist am Prozeduranfang deklariert worden. Die Zeile

Code: Alles auswählen

Dim oWindowsListener as Object
somit sinnlos.
Gruß,
mikele

craig
Beiträge: 1137
Registriert: Do 21. Apr 2016, 11:42

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von craig » So 1. Sep 2019, 18:26

@mikele
Ich stimme zu, dass dieses ein nicht genutztes Objekt ist.
Nehme also die Sache mit dem Schreibfehler zurück.

Code: Alles auswählen

Dim oWindowsListener as Object
Aber die Deklaration des Listeners erfolgt innerhalb einer Prozedur und ist somit nur in dieser gültig.

Code: Alles auswählen

Sub ShowCardGraphic(cardGraphicName as String)
    Dim oWindow As Object, odlgModel As Object, oMod As Object, oCntrl As Object, oTopWindowsListener As Object, oSimpleFileAccess As Object
Aus meiner Sicht sollte ein Listener mindestens innerhalb des gesamten Moduls Gültigkeit
haben und ist somit unterhalb von "Option Explicit" per DIM- oder PUBLIC-Anweisung zu deklarieren.

Oder sehe ich dies falsch?
Gruß

Craig

Nie die Sicherungskopie vergessen!

════════════════════════════════════════════════
WIN 10 Pro 64-Bit • LO 7.4.5.1 (x64) • AOO 4.1.8

Reth
Beiträge: 64
Registriert: Fr 5. Apr 2019, 23:21

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von Reth » So 1. Sep 2019, 21:56

Wow! Da hab ich ja ganz schön was aufzuarbeiten! Vielen Dank für eure Rückmeldungen/Beteiligungen.

Ich versuch mal oben anzufangen...

@balu:
Also ich finde Deine Annahmen/Behauptungen merkwürdig bzw. weiss nicht, was ich davon halten soll. Aber hier mal meine Antworten dazu:
Die Sachen sind natürlich von mir programmiert bzw. zusammengestellt, da ich das Rad ja nicht neu erfinde, sondern (v.a. als StarBasic-Neuling) nach Vorlagen im Web (u.a. hier, bei Dannenhöfer, im Makrokochbuch usw. usf.) suche und diese nutze. Und nein: Meine Datei hatte nie Kontakt mit Excel - alles ist komplett und ausschließlich in LO entstanden.

Die 4 Bilder habe ich gefunden und wieder entfernt. Wie ich bereits erwähnt hatte waren sie Überbleibsel aus meinen früheren Versuchen, die Bilder direkt im Tabellenblatt anzuzeigen - ohne eigenes Fenster/eigenen Dialog.

Zum Thema ExitSub usw.: Das hab ich als empfohlenes Beispiel für Fehlerbehandlungen (v.a. wenn man wie ich lokale Fehlerbehandlungen nutzen will und auch eine Ausgabe der betroffenen Zeile haben möchte) in verschiedenen Stellen im Web gefunden, u.a. bei Dannenhöfer (schon bevor ich den Thread hier aufgemacht hab).

Dass Public hier wohl nicht funktioniert, sondern nur Global war meine Annahme - bisher hat sich das durch das Laufzeitverhalten bestätigt und wurde auch von einem Folgeposter nochmals bestätigt. Dein anderer Hinweis mit dem Entschlacken wurde ja auch in Folgeposts aufgegriffen (Warteschleife). Vielen Dank dafür.

@mikele:
Vielen Dank für Deine Tipps und Erklärungen. Das mit den Ladezeiten klingt plausibel - hätte gar nicht gedacht, dass es damit zusammenhängen könnte, da ich annahm, dass wenn man im Else-Teil ist, der Dialog inkl. Model und Control schon existiert und dann auch ausgelesen werden kann, wenn der Dialog sichtbar gemacht wird.
Auch vielen Dank für den Tipp mit dem Mehrfachauslösen, während ich im selben Blatt bin. Werde das mal untersuchen und rückmelden, was ich rausgefunden habe.

@mikele und craig:
Danke auch für den Tip mit dem Fehler der 2. Listenervariable. Hab die sinnlose Dim-Zeile gelöscht. Das mit dem Listener hab ich auch noch nicht ganz durchdrungen - hier muss ich mir noch einiges zu durchlesen, z.B., wieso die ganzen Funktionen des Listeners im selben Modul implementiert sein müssen, während der Listener selbst "nur" in einer lokalen Variablen steckt (also wieso wird zur Laufzeit dann im selben Modul nach den Listenerfunktionen gesucht und könnte man diese auch in ein anderes Modul packen etc. etc.). Nehme an, das liegt am Aufbau des Basic.
Das Nutzen der Top_Win_windowClosing( oEvent )-Funktion klappt jedenfalls scheinbar problemlos.

Vielen Dank nochmals, werde die Sachen mal angehen.
Warum Option Explicit nirgends meckert hat mich auch schon an der einen oder anderen Stelle gewundert.

balu
Beiträge: 370
Registriert: Mi 1. Jun 2011, 16:21

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von balu » Mo 2. Sep 2019, 09:18

Hallo Reth,

okay, ich glaube dir das der Code von dir ist. Ich bin es halt nicht gewöhnt das in einem Code von einem deutschsprachigen so viele englische Kommentare drin stehen.

Kommen wir zu dem EXIT.
Ich geh mich selbst mal ne Runde (oder zwei oder drei) in den allerwertesten treten.
Hatte mich jetzt aktuell auch gewundert warum deine Fehlerbehandlung so anfängt.

Code: Alles auswählen

on local error goto
Diese Art war mir geläufiger

Code: Alles auswählen

on error goto
Und das gehört jetzt echt zu den Punkt: "Ich habe x-verschiedene Office auf meiner Platte, das ich den Überblick verlor."
In OO.o 3.2.1 gibt es die "Anweisung" LOCAL nicht. In darauf folgenden Versionen aber schon. Und jetzt hats auch bei mir klick gemacht. Also der Punkt kann abgehackt werden.

Und nein: Meine Datei hatte nie Kontakt mit Excel
Dir mag vielleicht das ein Rätsel sein warum ich das wissen wollte. Aber es hat schon Fälle gegeben wo der Kontakt mit Excel für Probleme sorgte. So das die dementsprechende Datei komplett neu erstellt werden musste, um das Problem zu beseitigen.


Das mit den Ladezeiten klingt plausibel - hätte gar nicht gedacht, dass es damit zusammenhängen könnte, da ich annahm, dass wenn man im Else-Teil ist, der Dialog inkl. Model und Control schon existiert und dann auch ausgelesen werden kann, wenn der Dialog sichtbar gemacht wird.
Deine bisherige Annahme ist nicht nur dir schon mal so durch den Kopf gegangen. Vor dem Problem stand ich aber auch schon mal vor sehr langer Zeit. Da hatte ich wohl mit gezeichneten Dialogen gearbeitet, aber mich trotzdem gewundert warum ein Dialog per "setVisible" überhaupt nicht sichtbar wurde. Erst als ich den WAIT-Befehl einbaute, so wie mir dies in einem anderen Forum erklärt wurde, wurde der Dialog "sichtbar geschaltet". Das liegt aber daran, das die Ausführung der Codezeilen schneller ist, als der grafische Aufbau eines Dialog. Primitiv ausgedrückt heisst das: "Codezeilen und Grafik sprechen nicht freiwillig miteinander"

Ich hoffe für dich das Du durch die zusätzlichen Tipps der anderen User weiter kommst.



Gruß
balu

gogo
Beiträge: 1072
Registriert: Sa 5. Feb 2011, 19:07

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von gogo » Mo 2. Sep 2019, 09:26

Ohne auf Details Deiner Programmierung einzugehen:
Das "mehrfache Starten" eines Ereignisses lässt sich quick and dirty mit einer globalen Variable verhindern:

Code: Alles auswählen

REM  *****  BASIC  *****
OPTION EXPLICIT
global gs_SUB_X_RUNNING as string ' reduces multiple calls
...
...
...
SUB X(oEvent)
  if gs_SUB_X_RUNNING = "###RUNNING###" then
	EXIT SUB
  else
	gs_SUB_X_RUNNING = "###RUNNING###"
  end if
...
gs_SUB_X_RUNNING = "###NOT_RUNNING###"
END SUB
...
...
Exit sub und exit function können problemlos als Ausstieg aus einer Prozedur verwendet werden - sieht zwar nicht schön aus, aber Sprungmarken wären die Alternative und die schauen auch nicht toll aus ;)
Tipp am Rande: Wenn Du Dir mit Starbasic noch nicht so sicher bist solltest Du nicht unbedingt mit einem Listener beginnen...
g
2008 LucidL./MaverickM./WinXP LibreOffice 3.3.2 > 02/13 LinuxMint13/Xubuntu > 09/13 Debian Wheezy+LO3.5.4.2 > 01/15 Debian Jessie KDE+LO4.3.3.2/Mint17 openbox auf USB+LO4.2.8.2 > 03/16 ArchLin & LO5.1+ff > 02/18 Kubuntu

Reth
Beiträge: 64
Registriert: Fr 5. Apr 2019, 23:21

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von Reth » Di 3. Sep 2019, 00:21

Vielen Dank.

@balu: Das mit dem Excel hatte ich mir schon genau so gedacht. Ist ja immer so, dass die Programme der anderen Hersteller irgendwelche Formatanpassungen machen (nehme ich zumindest bei LO und OO auch an, wenn man dort MS-Dateien rein lädt).
Das mit den englischen Kommentaren liegt daran, dass die Zielgruppe für mein Werk 99,99% in USA ist. Falls sich dort jemand das Ganze dann nach seinem/ihrem Gusto anpassen will hat er/sie es hoffentlich etwas einfacher. :D
gogo hat geschrieben:
Mo 2. Sep 2019, 09:26
Ohne auf Details Deiner Programmierung einzugehen:
Schade - würde mich sehr interessieren (denke mal, dass v.a. mein recht unstrukturiertes Vorgehen bei der SourceCodeGestaltung negativ auffällt - leider eine schlechte Angewohnheit von mir :D ).
Aber vielen Dank für den Tipp mit dem Pseudo-Semaphore! Muss ich alleridngs noch ausprobieren!

An alle, die das LibreOffice-Forum nutzen:


Bitte beteiligen Sie sich mit 7 Euro pro Monat und helfen uns bei unserem Budget für das Jahr 2024.
Einfach per Kreditkarte oder PayPal.
Als Dankeschön werden Sie im Forum als LO-SUPPORTER gekennzeichnet.

❤️ Vielen lieben Dank für Ihre Unterstützung ❤️

Antworten