Basic-Problem mit persistenten Daten zwischen verschiedenen Events

Hi *,

als blutiger Basic-Laie kämpfe ich heute mit dem Problem, das Daten
zwischen verschienenen Events verloren gehen.

Anbei ein Beispiel-Dokument, dass auf das Problem runtergebrochen ist,
d.h. das echte Dokument liest seine Daten aus einer anderen Datei, und
die Strukturen sind ein bisserl komplexer.

Absicht: Lese Daten aus einem anderen Tabellendokument (hier Tabelle2
des selben Dokuments), und befülle die Comboboxen damit. Wenn der
Benutzer einen Eintrag wählt (hier Fahrer), sollte das
korrespondierende Fahrzeug in der zweiten CB erscheinen, aber dennoch
änderbar sein (also ein default Wert).

Das Problem: Wenn das Dokument geladen wird, oder der "Neu laden" Knopf
gedrückt wird, triggert dies die OnLoad Funktion, die die Combos
initialisiert. Wenn der Benutzer nun einen Fahrer wählt, wird die
OnDriverChanged Funktion getriggert, die jetzt das passende Fahrzeug
anzeigen sollte, aber das vehicleList Array ist leer (UBound: -1) :-(.
Igendetwas hat die Daten zwischenzeitlich gefressen.. Eigentlich dachte
ich, das Array vehicleList as Private zu deklarieren, müsste reichen,
aber selbst Global geht offenbar nicht.

Hat hier jemand eine Idee, was ich falsch mache?

Eine modul-globale Private Deklaration sollte doch zur Laufzeit des
Moduls (Dokuments) erhalten bleiben.

Eine Erhellung ist leidenschaftlich erwünscht :wink:
Pete

Da Anlagen von der Mailingsoftware automatisch entfernt werden, das Dokument bitte mittels öffentlichem Link verfügbar machen.

Gruß
Uwe

Hrmpf, sorry:

ftp://urpla.net/combotest.ods

Pete

Woher soll die Funktion wissen, welche Daten gebraucht werden?
Die Quellangaben sind nicht vorhanden.

Ich bin blutiger Basic Anfänger, welche Quellangaben fehlen? Muss ich in
der Funktion bekannt geben, dass ich auf eine globale Modulvariable
zugreifen will?

Heisst dass, diese Deklaration zu Beginn des Moduls ist nicht
ausreichend:

Type Vehicle
  Vehicle as String
  Driver as String
End Type
Global vehicleList() as Vehicle
Global driverList() as String

Alles, was ich brauche, ist sowas wie Static auf Modulebene.

Sorry for being so dense.

Pete

>
> Woher soll die Funktion wissen, welche Daten gebraucht werden?
> Die Quellangaben sind nicht vorhanden.

Wenn ich Datenquellen richtig verstehe, dann arbeite ich tatsächlich
ohne (weil das Zuweisen der Daten als Datenquelle starr ist, ich aber
während des manuellen Einlesens Strukturen fülle, die ich später noch
brauche und Ende-Kriterien auswerte, die nur sinnvolle Daten
durchlassen.

Wie gesagt, dies ist ein stark reduziertes Beispiel eines komplexeren
Dokuments: Fahrtanweisung in einer Spedition, wo es Zugmaschinen,
Motorwagen, Auflieger und Anhänger gibt, die nicht beliebig gemixt
werden können, einen Stammfahrer haben, etc..

Ich bin blutiger Basic Anfänger, welche Quellangaben fehlen? Muss ich
in der Funktion bekannt geben, dass ich auf eine globale
Modulvariable zugreifen will?

Heisst dass, diese Deklaration zu Beginn des Moduls ist nicht
ausreichend:

Type Vehicle
  Vehicle as String
  Driver as String
End Type
Global vehicleList() as Vehicle
Global driverList() as String

Alles, was ich brauche, ist sowas wie Static auf Modulebene.

Also nochmal zum Verständnis:

Beim Laden des Dokuments wird das Makro OnLoad ausgeführt
(Ereignis: "Laden des Dokuments beendet" in
Extras->Anpassen->Ereignisse). Diese Funktion liest im Beispiel die
Daten manuell aus Tabelle2 und besetzt sowohl die Comboboxen
(driverListBox und vehicleListBox), als auch das globale Feld
vehicleList. Nach Laden des Dokuments zeigt die MsgBox, dass die 3
Beispiel-Datensätze korrekt geladen wurden:

  LBound: 0, UBound: 3

Wenn der Benutzer nun einen Fahrer auswählt, wird das Makro
OnDriverChanged ausgeführt (Ereignis: "Text modifiziert" von
Kombinationsfeld driverListBox).

Eigentlich erwartete ich, den Inhalt von vehicleList unversehrt
wiederzufinden. Die MsgBox zeigt nun aber:

  driver: <Name des ausgewählten Fahrers>, vehicle: <>
  LBound: 0, UBound: -1

Die letzte Zeile ist mein Problem: sie dokumentiert, dass das Feld
vehicleList von irgendwas zwischenzeitlich geleert wurde. Dieses Feld,
als

Global vehicleList() as Vehicle

deklariert, verliert zwischen den beiden Events seinen Inhalt. Es
scheint, dass jeder Event-Aufruf das gesamte Modul erneut
initialisiert, und die Frage ist, wie kann ich den Inhalt einer
globalen Modul-Variable von einem zum anderen Event hinüber retten,
oder bin ich hier total auf dem Holzweg?

Pete

Hallo Hans-Peter,

...

Also nochmal zum Verständnis:

Beim Laden des Dokuments wird das Makro OnLoad ausgeführt (Ereignis:
"Laden des Dokuments beendet" in Extras->Anpassen->Ereignisse).
Diese Funktion liest im Beispiel die Daten manuell aus Tabelle2 und
besetzt sowohl die Comboboxen (driverListBox und vehicleListBox), als
auch das globale Feld vehicleList. Nach Laden des Dokuments zeigt
die MsgBox, dass die 3 Beispiel-Datensätze korrekt geladen wurden:

LBound: 0, UBound: 3

Wenn der Benutzer nun einen Fahrer auswählt, wird das Makro
OnDriverChanged ausgeführt (Ereignis: "Text modifiziert" von
Kombinationsfeld driverListBox).

Eigentlich erwartete ich, den Inhalt von vehicleList unversehrt
wiederzufinden. Die MsgBox zeigt nun aber:

driver: <Name des ausgewählten Fahrers>, vehicle: <> LBound: 0,
UBound: -1

Die letzte Zeile ist mein Problem: sie dokumentiert, dass das Feld
vehicleList von irgendwas zwischenzeitlich geleert wurde. Dieses
Feld, als

Global vehicleList() as Vehicle

deklariert, verliert zwischen den beiden Events seinen Inhalt. Es
scheint, dass jeder Event-Aufruf das gesamte Modul erneut
initialisiert, und die Frage ist, wie kann ich den Inhalt einer
globalen Modul-Variable von einem zum anderen Event hinüber retten,
oder bin ich hier total auf dem Holzweg?

In der Annahme, das Du mit Event nicht Events (so wie der Eventhandler sie verwendet) meinst, sondern Module oder gar Funktionen, hilft Dir vielleicht
dies hier:
http://wiki.services.openoffice.org/wiki/Documentation/BASIC_Guide/Scope_of_Variables
weiter?

Gruß
Volker

PS.: Bevor Du jedoch noch viel Zeit in Diese Arbeit steckst...
Gehst Du davon aus, das das was Du vor hast für längere Zeit Bestand haben soll?
Wird Deine Tabellen ggf. sogar produktiv genutzt werden? Oder handelt es sich lediglich um eine "Machbarkeitsstudie"?
Wenn letzteres nicht zutreffen sollte, dann beachte den experimentellen Status der Makrofunktion!
Denke auch daran, das sich Basicfunktionen innerhalb von Libre- und auch Openoffice von Version zu Version ändern können.

So wie es aussieht möchtest Du eigentlich Daten verwalten. Das kann eine Datenbank ggf. besser tun als eine Tabelle mit eingebettetem Formular.

Hallo Volker,

Hallo Hans-Peter,

> ...
>
> Also nochmal zum Verständnis:
>
> Beim Laden des Dokuments wird das Makro OnLoad ausgeführt
> (Ereignis: "Laden des Dokuments beendet" in
> Extras->Anpassen->Ereignisse). Diese Funktion liest im Beispiel die
> Daten manuell aus Tabelle2 und besetzt sowohl die Comboboxen
> (driverListBox und vehicleListBox), als auch das globale Feld
> vehicleList. Nach Laden des Dokuments zeigt die MsgBox, dass die 3
> Beispiel-Datensätze korrekt geladen wurden:
>
> LBound: 0, UBound: 3
>
> Wenn der Benutzer nun einen Fahrer auswählt, wird das Makro
> OnDriverChanged ausgeführt (Ereignis: "Text modifiziert" von
> Kombinationsfeld driverListBox).
>
> Eigentlich erwartete ich, den Inhalt von vehicleList unversehrt
> wiederzufinden. Die MsgBox zeigt nun aber:
>
> driver: <Name des ausgewählten Fahrers>, vehicle: <> LBound: 0,
> UBound: -1
>
> Die letzte Zeile ist mein Problem: sie dokumentiert, dass das Feld
> vehicleList von irgendwas zwischenzeitlich geleert wurde. Dieses
> Feld, als
>
> Global vehicleList() as Vehicle
>
> deklariert, verliert zwischen den beiden Events seinen Inhalt. Es
> scheint, dass jeder Event-Aufruf das gesamte Modul erneut
> initialisiert, und die Frage ist, wie kann ich den Inhalt einer
> globalen Modul-Variable von einem zum anderen Event hinüber
> retten, oder bin ich hier total auf dem Holzweg?

In der Annahme, das Du mit Event nicht Events (so wie der
Eventhandler sie verwendet) meinst, sondern Module oder gar
Funktionen, hilft Dir vielleicht
dies hier:
http://wiki.services.openoffice.org/wiki/Documentation/BASIC_Guide/Sc
ope_of_Variables weiter?

Ja, auf dieser Basis habe ich interpretiert, dass ein Private
Deklaration eigentlich am Besten passen würde, da ich ja nur eine
modul-globale Variable bräuchte.

BTW, ich habe das Problem inzwischen gefunden: es ist der neue Datentyp
Vehicle für das Array. Wenn ich die Funktionen so umschreibe, dass nur
noch generische Typen verwandt werden, klappt es, solange ich das Array
zugleich auch Global definiere :frowning: ..

Offenbar werden in globale Arrays geschriebene Werte bestehend aus
eigenen Typen garbarge collected (riecht nach Bug).

Fehlerhaft: ftp://urpla.net/combotest-fail-with-type.ods
Funktioniert: ftp://urpla.net/combotest.ods

Gruß
Volker

PS.: Bevor Du jedoch noch viel Zeit in Diese Arbeit steckst...
Gehst Du davon aus, das das was Du vor hast für längere Zeit Bestand
haben soll?

Eigentlich ja.

Wird Deine Tabellen ggf. sogar produktiv genutzt werden? Oder
handelt es sich lediglich um eine "Machbarkeitsstudie"?

Werden sie bereits, heftigst. Ich pimpe sie nur noch ein bisschen auf,
um das Arbeiten damit komportabler zu machen und menschliche Fehler zu
vermeiden.

Wenn letzteres nicht zutreffen sollte, dann beachte den
experimentellen Status der Makrofunktion!

Heisst das, alle BASIC-Erweiterungen sind experimentell oder meinst Du
den Makro-Rekorder über den Event-Dispatcher (der in LO scheinbar eh
deaktiviert wurde)?

Nicht zuletzt dank Deiner Warnung bin ich übrigens dem Fehler auf die
Schliche gekommen und habe die einfachere Variable mit beobachtet, und
siehe da, die hielt an ihrem Inhalt fest.

Denke auch daran, das sich Basicfunktionen innerhalb von Libre- und
auch Openoffice von Version zu Version ändern können.

Ich will dieses und ein weiteres Projekt nutzen, um die
Langzeit-Stabilität der BASIC-API zu testen. Ganz so einfach
können "die" die API auch nicht ändern, zumindest nicht innerhalb von
Revisionen, ohne tausendfache Aufschreie zu riskieren.. (hoffe ich
zumindest). Anpassungen bei Versionswechsel sind eine andere
Geschichte, aber in meinem Fall den Aufwand wert. Daher versuche ich
auch, möglichst konservative Logik zu erzeugen.

So wie es aussieht möchtest Du eigentlich Daten verwalten. Das kann
eine Datenbank ggf. besser tun als eine Tabelle mit eingebettetem
Formular.

Ja, aber die Daten brauchen leider noch ein bisserl __nicht_lineare__
Logik, die ich hier in Basic beisteuern will.

In meinen richtigen Datenbank-Projekten (in denen ich die Oberfläche
übrigens seit Jahren mit PyQt realisiere) hat sich die Erstellung der
OO/LO Dokumente mit Variablen und Mithilfe von ooopy bewährt (wenn ich
nicht gleich xls-Dateien für Kunden brauche, dann bleibt nur der noch
aufwändigere Einsatz entsprechender Module: xlrd, xlwt, xlutils: __da_
machste_was_mit__..).

Danke für die Tips und Gruß an Alle,
Pete