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.
Reth
Beiträge: 64
Registriert: Fr 5. Apr 2019, 23:21

Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von Reth » Do 29. Aug 2019, 10:57

Hallo zusammen,

ich habe mit ein paar Makros u.a. ein Fenster erstellt, welches mir ein Bild darstellen kann. Das Fenster kann ganz normal über das X geschlossen werden und mit Hilfe einer Checkbox sichtbar oder unsichtbar geschalten werden. Beim Klicken auf Zellen wird ein passender Name zusammengestellt und das Bild dazu aus dem Web geladen und angezeigt.

Die Variable für den Dialog (Zuweisung in einer Sub durch

Code: Alles auswählen

odialog = CreateUnoService("com.sun.star.awt.UnoControlDialog")
) ist global. Alle anderen Elemente des Dialoges werden nur lokal in der Sub angelegt, dazu gehören:

Code: Alles auswählen

odlgModel = CreateUnoService("com.sun.star.awt.UnoControlDialogModel")
...
oMod = odlgModel.createInstance("com.sun.star.awt.UnoControlImageControlModel")
...
oWindow = CreateUnoService("com.sun.star.awt.Toolkit")
...
oTopWindowsListener = CreateUnoListener( "Top_Win_", "com.sun.star.awt.XTopWindowListener" )
D.h., das Window, der Listener, das Model und das Control sind lokale Variablen in dieser Sub (nur der Dialog selbst ist global, da er in der Sub der Checkbox auf invisible gesetzt wird, wenn diese abgewählt wird [Haken entfernt]).

In der Sub, welche regelmäßig für die Anzeige gerufen wird, wird zuerst geprüft, ob oDialog null ist. Wenn ja, wird er komplett neu angelegt, mit allem was dazugehört (s. Codeausschnitte oben). Ist er nicht null, wird einfach nur eine neue Bild-URL wie folgt gesetzt:

Code: Alles auswählen

if not odialog.isVisible() Then
	odialog.setVisible(True)
end if
oCntrl = odialog.getcontrol("IMG1")
oCntrl.model.ImageURL = cardGraphicName
Und hier habe ich das Problem, dass oCntrl immer mal wieder den Fehler wirft "Objektvariable nicht belegt.". Das kann ich immer mal wieder reproduzieren - aber nie zuverlässig!

Woran könnte das denn liegen? Muss ich alle Elemente, die mit dem Dialog zu tun haben global machen, um das Problem zu umgehen?

Dank euch schon mal für eure Hilfe!

Ciao

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

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von balu » Do 29. Aug 2019, 12:56

Hallo Reth,

ohne eine Beispieldatei ist es schwer dir zu helfen.

Aber ich kann dir schon mal sagen, das Variablen mit Global zu deklarieren nicht unbedingt vorteilhaftt ist. Normalerweise reicht es wenn Du in diesem Falle hier die Deklaration öffentlich (also vor der ersten Sub) machst, entweder mit Dim oder aber mit Public.

Wie gesagt, Beispieldatei ist besser.



Gruß
balu

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

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von Reth » Do 29. Aug 2019, 16:10

Kann leider die Bsp.-Datei nicht anfügen (gibt es eine Größenbeschränkung?).

Sie kann hier herunter geladen werden.
Man muss teilweise ne Weile wild herum experimentieren, um den Fehler zu bekommen - ich hab es zuletzt nicht mehr geschafft.

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

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von balu » Do 29. Aug 2019, 19:30

Hallo Reth,

Oh je!
Du arbeitest nicht mit gezeichneten Dialogen, sondern zur Laufzeit erstellten. Das macht die Sache natürlich etwas komplizierter. Und ich sags dir gleich vorweg, ich glaube kaum das ich dir vollständig helfen kann.

Aber nun gut, kommen wir zu dem was ich schon in meinem ersten Beitrag sagte.

Code: Alles auswählen

REM  *****  BASIC  *****
Option Explicit

Sub Main
	If NOT BasicLibraries.isLibraryLoaded("GetImage") Then
		BasicLibraries.LoadLibrary("GetImage")
	End If
	currentCardName = "http://www.redemptionquick.com/lackey/cardback.jpg"
End Sub

Global currentRow as Long, currentColumn as Long
Global pathLackeyPlugin as String, currentCardName as String
Global cardGraphic as Object, odialog as object

Sub ShowCardGraphic(cardGraphicName as String)
    Dim oWindow As Object, odlgModel As Object
Das sind die errsten Zeilen. Und deine Global deklarierten Variablen sind nicht wirklich öffentlich, weil sie an der falschen Stelle sind. Und Global hat einen Stolperstein, wenn an der richtigen Stelle eingetragen. Selbst wenn das Makro beendet wurde, sind sie noch immer gültig. Und das kann zu Problemen führen.

Besser, und auch richtig wäre das nämlich wie folgt.

Code: Alles auswählen

REM  *****  BASIC  *****
Public currentRow as Long, currentColumn as Long
Public pathLackeyPlugin as String, currentCardName as String
Public cardGraphic as Object, odialog as object

    Public oWindow As Object, odlgModel As Object, ......

Option Explicit ' <- Muss nicht unbedingt sein.

Sub Main
	If NOT BasicLibraries.isLibraryLoaded("GetImage") Then
		BasicLibraries.LoadLibrary("GetImage")
	End If
	currentCardName = "http://www.redemptionquick.com/lackey/cardback.jpg"
End Sub

Sub ShowCardGraphic(cardGraphicName as String)
Ich habe das Global durch Public geändert. Dadurch sind die Variablen öffentlich deklariert, und sie stehen jeder Sub in dem selben Modul zur Verfügung. Deine bisherige Variante konnte dies nicht einhalten, weil ja nicht wirklich öffentlich deklariert wurde.

Lese dir auch dazu folgenden Link bei Dannenhöfer bitte durch.
http://www.dannenhoefer.de/faqstarbasic ... ml#Zweig81


Auch wenn Du deine Dialoge zur Laufzeit erstellst, so wäre auch in diesem Falle das zu bedenken was man bei gezeichneten Dialogen beachten sollte.
Jede Variable die direkt mit dem Dialog zu tun hat, sollte man im ersten Modul ganz zu Anfang deklarieren, wie in meiner Änderung zu sehen ist.

Ein kleiner Tipp von mir so am Rande.
Öffentlich deklarierte Variablen setzt Du das Public voran, auch wenn Dim ginge.
Lokal delarierte Variablen, also innerhalb einer Sub, setzt Du das Dim voran.
Vielleicht verschafft dir das einen besseren Überblick. Aber daran halten musst du dich nicht, das ist deine Entscheidung.


Das Problem mit der Größe der Datei hättest Du dadurch umgehen können, das Du pro Tabellenblatt nur so 10 oder 20 Datensätze drin gelassen hättest, den Rest einfach löschen. Und vielleicht noch das ein oder andere unnötige Tabellenblatt löschen was mit der Funktion des Makro nix zu tun hat. Ach ja! Es gibt eine Größenbeschränkung für Anhgänge hier im Forum, aber wie hoch die ist, keine Ahnung (250KB??)

Aber nun überarbeite erstmal das Thema "öffentliche Variablen deklarieren", und schau wie es dann so läuft.



Gruß
balu

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

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von Reth » Fr 30. Aug 2019, 00:11

Danke Dir!

Hab die Änderungen mal ausprobiert, der Code sah dann so aus:

Code: Alles auswählen

Public currentRow as Long, currentColumn as Long
Public pathLackeyPlugin as String, currentCardName as String
Public cardGraphic as Object, odialog as object
Public oWindow As Object, odlgModel As Object, oMod As Object, oCntrl As Object, oTopWindowsListener As Object

Option Explicit

Sub Main
	If NOT BasicLibraries.isLibraryLoaded("GetImage") Then
		BasicLibraries.LoadLibrary("GetImage")
	End If
	currentCardName = "http://www.redemptionquick.com/lackey/cardback.jpg"
	...
Allerdings hat das nur Probleme gemacht. Das Fenster mit dem Bild öffnet sich bei fast jedem Klick gleich 4 Mal übereinander! Das war davor nicht so.
Auch der Fehler, dass die Objektvariable nicht belegt ist erscheint nun wieder häufig - und das obwohl ja nun alle Variablen Public sind.

Habs erst einmal wieder rückgängig gemacht, da ich noch nicht weiß, wo bei der Public-Variante die Fehler liegen und wie ich denen bei komme. Evtl. reicht Public doch nicht, da die Werte zur Laufzeit nicht behalten werden? Oder es liegt daran, dass nun alle Bestandteile des Dialoges Public sind ...

Ciao

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

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von balu » Fr 30. Aug 2019, 12:59

So, ich hab jetzt erstmal die Datei entschlackt.
In jedem Tabellenblatt ab Zeile 21 sämtlichen Text gelöscht.
Nun kann sie hier auch angehängt werden.

Was mir aber beim löschen aufgefallen war, ist folgendes.
Als erstes musste ich den Blattschutz für das Blatt "carddata.txt" entfernen.
Dann hatte ich den Zellbereich von A21:O3525 markiert und den Text gelöscht. Dabei sah ich dann aber auf eiunmal in der Spalte A ein Stück von einem Bild. Das war schon sehr määrkwürrrzik!

Als ich das Bild anklickte erschien ein Blanko Dialog-Fenster namens "Picture". Und als ich das geschlossen hatte wollte ich wieder auf das Bild klicken um es zu löschen, jedoch erschien beim anklicken wieder das genannte Fenster. Das ging eine sehr lange Zeit so, bis das das Bild sich doch löschen lies. Das dumme an der Sache war nur, das nicht nur ein Bild zu sehen war, sondern 4 Stück, alle schön untereinander. Und beim löschen trat jedes mal das gleiche Problem auf, Dialog-Fenster etc.

Es hatte wohl recht lange gedauert bis das ich die Bilder entlich alle entfernt hatte, aber ich hatte es dennoch geschafft.

Das ganze machte mich doch arg Stutzig, und so schaute ich mal nach was ich zu sehen bekomme wenn ich einen Rechtsklick auf den Blattreiter vom besagtem Blatt mache und nachschaue was denn bei "Tabellenereignisse" zu sehen ist.
Und siehe da!
Bei "Auswahl geändert" steht das hier drim => Standard.GetImage.OnSheetContentChange
Fragen:
Muss das so seien? Ist das mit Absicht so gewollt?

Ich VERMUTE mal, das dies so nicht sein soll. Denn bei jedem klick in die Spalte A im besagtem Blatt popt das Dialog-Fenster auf, mal leer, mal mit einem neuen Bild.

Also mehr kann ich momentan nicht weiter helfen. Aber vielleicht hilft ja jetzt meine Beobachtung bei der weiteren Fehleranalyse.



Gruß
balu
RCM_0.6_x0.ods
(149 KiB) 169-mal heruntergeladen

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

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von Reth » Fr 30. Aug 2019, 17:09

Danke Dir. Au weia - dachte, ich hätte alle Bilder aus früheren Versuchen entfernt.

Das Verhalten mit dem ständigen Erscheinen des Dialoges, wenn man auf Spalte B klickt (wo die Kartennamen drin stehen) ist absolut so gewollt, auch dass dann der Dialog immer wieder erscheint (daher auch die Aktion beim Ereignis "Auswahl geändert" - ich hab da nix anderes adäquates gefunden).
Das Tool soll immer das Kartenbild der gewählten Karte anzeigen - darum geht auch der Dialog immer wieder auf! In der neuen Version kann man das per Checkbox auch de-/aktivieren und das Bild erscheint, egal, wo man in der Zeile hinklickt (nicht nur bei Spalte B).
Der Blattschutz ist auch gewollt.

In der Variante von Dir, mit allen Variablen des Dialoges als Public hatte sich der Dialog aber pro Klick bis zu 4 Mal geöffnet - in meiner Version öffnet er sich genau einmal. Da bin ich noch nicht dahinter gestiegen wieso. Vllt. probier ich mal meine Version, aber ohne Global, stattdessen Public.

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

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von craig » Fr 30. Aug 2019, 18:02

Hallo Reth,

Deine ursprüngliche Anfrage "Objektvaraible nicht belegt" wird vermutlich durch
diese falsch geschriebene Messagebox-Anweisung erzeugt:
Zeile 198 = MsbBox "Sheet carddata.txt not found!"

Richtig:

Code: Alles auswählen

MsgBox "Sheet carddata.txt not found!"
Warum der Interpreter trotz des verwendeten "Option Explicit" hier nicht direkt
bei Start des Programms meckert, ist mir ein Rätsel.

Ausserdem gehört die "Option Explicit" Anweisung immer an die erste Stelle,
also auch vor die Deklaration der Variablen.
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 » Fr 30. Aug 2019, 19:20

Danke Dir! Gar nicht gesehen. Allerdings wird der Teil eh nie ausgeführt (der Fall tritt nicht ein).
Und die Fehlermeldung wird wenn sie kommt für Zeile 81 im letzten Bsp.-Dokument angezeigt.

Hab zum Test mal in meiner Version die Variablen von Global auf Public geändert. => Selbes Problem: Der Dialog für die Bildanzeige funktioniert quasi nicht mehr. Er wird immer direkt mehrfach geöffnet und auch das Ein- und Ausschalten mit Checkbox funktioniert nicht mehr.
Meine Vermutung ist, dass die Public-Variablen ihre Werte zwischen 2 Aufrufen nicht behalten - die Globals aber schon. Da aus mir noch unbekanntem Grund bei einem Klick im Blatt das Ereignis "Auswahl geändert" teilweise bis zu 4 Mal gerufen wird (hab ich mal mit Ausgaben geprüft) erklärt dies das bis zu 4-malige Öffnen des Dialoges.

Jetzt hab ich noch ein neues Problem: Seit heute, wenn ich die aktuelle Version lade stürzt LO direkt beim Laden ab - immer. Erst das Wiederherstellen tut, dann geht aber zunächst mal die Bildanzeige nicht und auch kein einziges Makro (die werden nicht mal bei "Auswahl geändert" aufgerufen - hab ich getestet). Was könnte das denn sein => aber sollte ich wohl besser n neuen Thread für aufmachen ...

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

Re: Objektvariable (Controlelement eines Dialogmodels) manchmal nicht belegt

Beitrag von balu » Sa 31. Aug 2019, 14:12

Halo Reth,

nur damit das abgeklärt ist:
Hatte deine Datei in irgendeiner Art und Weise mal Kontakt mit Excel gehabt?
Au weia - dachte, ich hätte alle Bilder aus früheren Versuchen entfernt.
Und wie kommt es das 4 Bilder IN DER DATEI eingebunden sind?
Mach mal folgendes.
- Schließe deine Datei, falls sie in deinem Office geladen ist.
- Rufe deinen Dateimanager auf.
- Suche deine Datei.
- Klicke sie an.
-Entzippe sie "nach .....". Nicht einfach entzippen sondern entzippen zu einem Ordner mit dem Dateinamen (hoffe Du verstehst was ich meine).

Wenn Du jetzt in den eben erstellten Ordner mit den Dateinamen wechselst, siehst Du dort diverse andere Ordner und einige Dateien mit der Endung ".xml".

Dich interessiert jetzt aber nur der Ordner "Pictures". Wechsle zu ihm, und Du wirst dort 4 Bilder sehen. Also die sind IN DER DATEI.

Was ich aber in meiner Antwort von Freitagmittag vergessen hatte zu erwähnen war, das bei der Löschaktion der Bilder auch Bilder dabei waren die nicht in der Datei gespeichert waren, sondern "frisch" aus dem Internet geladen wurden. Und diese Aktion, das Laden eines Bildes aus dem Intrnet, steht ja auch in deinem Makro. Schau selber mal danach.


Und nur zur Info.
Ich hatte in der Datei, die ich hier angehängt hatte, nix am Makro geändert.

Achtung!
Ich fange jetzt an zu määäckkern ;-)
Das hier, als ein Beispiel

Code: Alles auswählen

	exit sub
	
	finish:
		 MsgBox
hast Du nicht nur einmal drin.
Okay, es gibt Situationen wo man mit EXIT eie Sub oder Function zwangsweise verlassen kann. Aber das ist nicht immer Ratsam, besonders dann, wenn man es auch einfacher gestalten kann um eine bestimmte Zeile nicht auszuführen.

Code: Alles auswählen

	finish:
		 ' MsgBox
In meiner eingebauten Online-Hilfe (F1) steht unter anderem zu EXIT folgendes.
Online-Hilfe (F1) hat geschrieben: Eine Exit-Anweisung definiert nicht das Ende einer Struktur und ist nicht mit der End-Anweisung zu verwechseln.
Also EXIT ist nicht das gleiche wie END. Ich wäre also extrem Vorsichtig mit dem Einsatz von EXIT um eine SUB oder FUNCTION zu beenden. Bei einer Schleife des Typs Do...Loop oder For...Next mag das noch etwas anderes sein, und dort habe ich auch schon so einige male EXIT angewendet (besonders bei FOR...), aber nicht um eine SUB zu verlassen.


Wenn ich mir so den gesamten Code anschaue, zweifle ich doch daran das Du ihn selbst erstellt hast. Kann mich aber auch täuschen, und Du hast das Recht es mir zu sagen wenn ich falsch liege.


Um jetzt aber auf dein anderes Problem zu kommen, das mit der "4 fachen Ausführung" (wofür Du auch einen neuen Thread eröffnet hast: viewtopic.php?f=12&t=23286) zu tun hat, kann ich persönlich dir erstmal nur folgendes empfehlen.
- Bende deine SUBs ordentlich mit END SUB und erzwinge keinen unnötigen Notausgang mit EXIT.
- Hilft das nicht, oder kaum weiter, dann gehts mit dem folgendem weiter.
- Nimm eine neue und leere Datei.
- Konzentriere dich nur auf dies Problem.
- Nimm nur ein Tabellenblatt.
- Überleg dir was Du an Makro-Code alles brauchst um dein Problem nachzustellen.
- Welche von den beiden folgenden SUBs brauchst Du wirklich?
Sub OnSheetContentChange(e)
Sub OnSheetContentChangeOld(e)
- Lade keine Bilder ausm Internet, sondern nimm irgend etwas kleines von der Platte oder von deinem Office.
- Schmeiß alles raus was mit Größenbrechnung und Positionierung des Bildes zu tun hat einfach raus. Mit anderen Worten, stampfe den Code auf das wirklich nötige zu recht.
- Berichte wie weit Du gekommen bist, mit Beispieldatei.

Das wars dann erstmal.



Gruß
balu

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