Seite 1 von 1

Probleme mit globalen Variablen

Verfasst: Mi, 07.06.2006 04:02
von christianM
Hallo zusammen,

ich habe in OpenOffice Base ein Problem mit der definition globaler Variablen.
Bei folgendem Code:

Code: Alles auswählen

dim dump

Sub doit
dump = 5
end sub

Sub doit2
dump = 7
end sub

sub outit
msg dump
end sub
bereitet mir Probleme.
Ich habe in den Dokumentationen und im Internet gesucht und gelesen, aber nichts gefunden.
Es heißt zwar daß die zu Anfang des Moduls mit DIM definierten Variablen global sind, dh. die ganze Sitzung lang gelten, rufe ich aber [doit] auf und danach [outit] kennt mein openoffice die Variable <dump> nicht mehr.
Mein Problem besteht konkret darin, daß ich ein Mehrdimensionales Array definieren muß - was syntaktisch kein Problem darstellt - das aber die Werte solange speichern soll, wie das Dokument, in dem ich arbeite offen ist. (Ich muß für spätere Berechnungen auf diese Werte von anderen Sub-Routinen aus zugreifen können)
Die Module sind im Dokument gespeichert.
Es heißt in der Literatur DIM würde für globale Variablen sorgen, nur muß ich DIM schon verwenden um ein Array zu definieren.

Kann mir bitte jemand helfen oder einen Link mit hinreichenden Informationen zu diesem Thema posten?

Danke für die Antwort
Christian Marquardt

Verfasst: Mi, 07.06.2006 07:11
von Toxitom
Hey Christian,

Nun ja, was du schreibst ist alles richtig - und funktioniert auch so. Möglicherweise aber hast du noch einen "Denkfehler". Globale Variable halten auch nur aolange das Basic-Modul aktiv ist (PS: Im code sollte es sicherlich "msgbox" heissen - oder?), das heisst, du musst "im Fluss bleiben". Basic selbst speichert keine Variablen dauerhaft!.
Also, wenn du zuerst das Programm "doit" aufrufst, wird Basic iniitialisiert, liest die Varaiblen von vorne ein und reserviert sozusagen Speicherplatz dafür - Diene globale Varaible ist jetzt im HS, für die Bibliothek "global" verfügbar.
Jetzt rufst du das folgend Makro auf:

Code: Alles auswählen

sub test
  doit
  outit
end sub
dann erkensst du die Arbeitsweise: das Makro "doit" belegt die Variable mit 5 und ist dann beendet. Eine im marko selbst erzeugte Varaibel würde jetzt wieder zerstört, dein dump bleibt erhalten.
Jetzt startet das Makro "outit" und kann diese Varaible weiterverarbeiten - also anzeigen. dann ist das Makro zu Ende und auch dein Testmakro - Basic wird verlassen, alle Variablen werdne zerstört. Startest du jetzt eines der Prozeduren neu, beginnt die initialisierung wieder von vorne - dump wird neu erstellt.
Du könntest das Makro oben zwar auch mit Parameterübergabe realisieren - ohne globale Variable - das ist aber manchmal umständlicher.
Besonders Sinn machen globale Variable im übrigen insbesondere bei Dialogen. Hier bleibt nämlich das Basic-Modul solange aktiv, solange der Dialog noch offen ist. Über Buttons oder Ereignisse kannst du zusätzliche Prozeduren starten - und die können dann auf die globalen Varaiblen zurückgreifen.

Brauchst du sonst Werte, auf die du innerhalb des Programms zurückgreifen willst, so speicher die im Dokument ab - an einer speziellen Stelle, evt. unsichtbar für die Benutzer.

Aber: vielleicht erklärst du, was du machen möchtest -da gibt es möglicherweise auch andere Lösungen. (Zudem in base selbst derzeit gar keine Makros gespeichert weren können - ich nehem daher an, du meinst ein Formular in Base? Und das wäre dann ein Writer-Dokument).

Ich hoffe, das hilft dir erst einmal.

Viele Grüße
Thomas

genauere Erklärung

Verfasst: Mi, 07.06.2006 10:45
von christianM
Hallo Thomas,

danke für die Erklärungen.
Aber dennoch habe ich das Problem. Ich habe den Begriff der globalen Variablen falsch verstanden; okey. Ich versuche mal das Problem zu schildern.
Ich habe in meiner Tabelle ein Blatt [Einstellungen], in diesem Blatt stehen Werte. Von diesen Werten hängt es ab, wie sich Funktionen die im Blatt [Daten] angewendet werden verhalten.
Nun will ich die Werte fest speichern, sodaß jede Sub / jedes Makro auf diese Werte zugreifen kann.

Zum Beispiel
In [Einstellungen](D5) steht die max. Geschwindigkeit.
Die will ich auslesen mit einem Makro [ReadGeschwindigkeit].
Auf einem zweiten Tabellenblatt stehen Geschwindigkeitswerte. Dahinter wird in Abhängigkeit von der max. Geschwindigkeit eine Formel berechnet; die eben eine Fallunterscheidung oder Verzweigung macht, je nachdem, ob die "gelesene" max. Geschwindigkeit sagen wir größer 100 ist, oder nicht. Das heißt die Formel soll in Abhängigkeit der Max.Geschwindigkeit etwas berechnen.
Mein Problem ist nun, daß ich ca. 30 solche Einstellungsvariablen habe, die ich nicht einfach als Paramter übergeben kann oder will.
Die Lösung die Du vorgeschlagen hast ist deshalb schwer umsetzbar, weil Funktionen mit den gelesenen Werten arbeiten müssen.
Ich könnte natürlich Konstanten am Anfang des Dokumentes fest vorgeben, dann kann die Berechnung vom benutzer allerdings nichtmehr gesteuert werden.

Nochmal kurz und knapp:
Gibt es eine Möglichkeit Werte aus einem Tabellenblatt auszulesen und diese Werte in eine andere Berechnung einer Funktion einfließen zu lassen, ohne daß die Funktion selbst die Tabellenwerte jedes mal neu abfragen muß (also die Werte solange erhalten bleiben, bis sie neu geladen werden).
Die Funktionen die auf den gelesenen Werten arbeiten werden nämlich sehr of aufgerufen und ich wollte nicht bei jeder Berechnung wieder auf das Tabellenblatt zugreifen müssen, u.a. um die Berechnungen schneller zu machen.

Konkret:

Code: Alles auswählen

Sub LeseEinstellungen
...
a = otabell.getCellByRange(1,2)
.
.
.
z = otabell.getCellByRange(1,27)

End Sub

Function f(x1 as double,x2 as double) as double
erg = x1 + x2
if (a > 0) then 
  erg = erg * a
else
 erg = erg * a*a
end if
End Fucntion
Wo und wie soll ich nun die Variablen [a] bis [z] definieren?
Die Funktion f soll dabei während der gesamten Sitzung korrekte Ergebnisse liefern (und nicht mit den Werten a = b = ... = z = 0 rechnen).
Zudem muß f im gesamten Tabellendokument als Funktion in einer beliebigen Zelle anwendbar sein.
Ich will keine Parameterübergabe wegen der Anzahl und Bedeutung der Variablen verweden. Hier sieht es aus als seien [a] bis [z] Parameter; in wirklichkeit hat die Funktion f noch eigene Parameter x1 bis xn.
[a] bis [z] sollen also keine Parameter der Funktion f sein, die Berechnung hängt dennoch von ihnen ab.

**************************************************************************************

In Java wären [a] - [z] statische Variablen in einer Klasse, die während des gesamten Programms in jeder beliebigen Klasse verfügbar sind;

Code: Alles auswählen

public ?static? class Einstell
{
public static final int einstell1 = 7 
.
.
.
public static final int einstell30 = 4
}

// final enspricht const -  das sind aber trotzdem Variablen! - nach Java Konvention
damit kann man dann in der Main-Routine rechnen:

Code: Alles auswählen

public class Run
{

   public static void main(String[] args)
   {
        Einstell.einstell1 = Einstell.einstell2 * Einstell.einstell3
        int a = 5;
        if(Einstell.einstell1 > 4) then a-- else a++
        System.out.println(a);
        ...
   }
}
So sähe das glaube ich in Java aus; Bei dem [?static?] bin ich selbst jetzt nicht ganz sicher.


Hier will ich diese Variablen solange zur Verfügung haben, wie meine Tabellendatei geöffnet ist.

Danke für die Mühe und Antworten
Christian Marquardt

PS: Das Buch [Makros für OOo 2.0] liegt vor mir, hilft mir aber in dem Punkt leider auch nicht weiter... =(

Verfasst: Mi, 07.06.2006 12:13
von Toxitom
Hey Christian,

hmm, also wenn ich dich recht verstehen, benötigst du die Varaiblen innerhalb von benutzerdefineirten Funktionen in Calc?

Na, dann sollte es gehen. Eine solche Funktion musst du nämlich iin der Bibliothek "Standard" des Platzes "Meine Makros" speichern. Diese wiederum bleibt aktiv - solange das Calc-Fenster geöffnet ist. Dort kannst du also schon Zwischenwerte abspeichern.
Habe gerade folgendes ausprobiert: (in der Bibliothek Standard des Platzes "Meine Makros"):

Code: Alles auswählen

Global test as integer

sub variablefuellen
  test = 7
end sub

function myTest()
    myTest = test * 3
end function
habe ich jetzt ein Calc-Dokument, und rufe zuerst das Makro "varaibelfuellen" auf (über Extras - Makros - ausführen"), so ist die Testvaraibel gefüllt und kann zu jedem Zeitpunkt abgerufen werden.
Also: Füge ich danach irgendwo die Formel: =myTest() in eine Zelle ein, erscheint folgerichtig 21.

So sollte das funktionieren. Ich würde - glaube ich - die benötigten Werte zunächst über ein Makro in einen Array einlesen ( mit Start des Dokumentes verbinden?) - und dann auf diesen zugreifen. Aber da gibt es dann ja viele Möglichkeiten.

Gruss
Thomas

Verfasst: Mi, 07.06.2006 17:28
von ykcim
Hallo Thomas, Hallo Christian

irgendwas läuft da schief. Thoams widerspricht sich.

Globale Variable halten auch nur aolange das Basic-Modul aktiv ist
.....
Stimmt so nicht.

Dazu die Online-Hilfe:
l
Diese Variable bleibt während die gesamte OpenOffice.org-Sitzung gültig.
Wenn Christian den Code ändert in:

Code: Alles auswählen

Global dump as Integer

Sub doit
dump = 5
end sub

Sub doit2
dump = 7
end sub

sub outit
msgbox  dump
end sub 
Nun kann er nach einem einmaligen Aufruf von doit jederzeit, auch aus jedem neuen Dokument, outit aufrufen und erhält die 5. (Nicht aus einem Makros des neuen Dokumentes!)

Das sollte dann beim Christain mit einem einmaligen Auslesen der Werte in ein globales Array gehen.

Code: Alles auswählen


Global myArray(5) as integer

sub variablefuellen
  '( Zellen A1:A6)
  myDoc = thisComponent
  mySheet = myDoc.sheets(0)
  for i=0 to 5 
    mycell = mysheet.getCellByPosition(0,i)
    myarray(i)=mycell.value
  next i    
end sub

function myTest
  msgbox myArray(2)
end function 

mfg
Michael

es klappt

Verfasst: Mi, 07.06.2006 18:10
von christianM
Hi ykcim,

danke für den Tip.
Wenn man das array so definiert braucht man dim nicht mehr und macht damit die Variable tatsächlich global und es klappt auch jetzt.
Herzlichen Dank soweit an alle. Ich hoffe ich kann mich nochmal melden, wenn irgendwas in der hinsicht wieder nicht funktionieren solle. Dann poste ich einfach nochmal munter weiter.
Aber nun klappt es ja und danke für die Tipps

Christian Marquardt :D