Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1152to1156
Aktuelles Verzeichnis
Verzeichnis Index
Übersicht Verzeichnisse
Vorheriger Thread
Rückwärts Blättern
Nächster Thread
Vorwärts blättern
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Inhaltsverzeichnis

Programmierstil in Bezug auf globale Variablen

Programmierstil in Bezug auf globale Variablen
Tommy
Hallo,
ich bin seit zwei Monaten dabei mein erstes VBA Programm für Excel zu schreiben. Nun muss ich meine erste Frage loswerden.
Mein Programm war gut bestückt mit globalen Variablen. Seitdem ich gelesen habe, dass man globale Variablen stets vermeiden sollte, versuche ich dies mit Übergabe von Argumenten usw. zu erreichen.
Jedoch zweifel ich in meinem Fall an dessen Sinnhaftigkeit.
In meinem Programm werden einige Variablen aus einer Excel Tabelle eingelsen, die immer mal wieder Verwendung finden.
Zwei Hauptmakros, die auf einander aufbauen, steuern das Programm.
Die Hauptprozedur_1 wird durch ein CommandButton als erstes ausgeführt. Darauf aufbauend kann man Hauptprozedur_2 mit verschiedenen Eingangsparametern durch Aufruf mit einem zweiten CommandButton testen.
Zunächst war die Struktur ungefär so:

Dim intX as integer ' global
With ThisWorkbook.Worksheets("Parameter")
intX = .Range("I6").Value
Dim VariableName() as double ' global
Dim ...
Sub Hauptprozedur_1()
Call sub1_1   ' hier wird intX benötigt
Call sub1_2
Call sub1_3   ' hier wird intX benötigt
Call sub1_4   ' hier wird intX benötigt
Call sub1_5   ' hier wird intX benötigt
' hier wurde "VariableName" erzeugt
End Sub
Sub Hauptprozedur_2()
' in der Prozedur wird intX auch immer mal wieder benötigt
' zudem werden aber auch Ergebnisse (VariableName) aus Hauptprozedur_1 benötigt
' da die Hauptprozedur_2 ja mit einem eigenem CommandButton aufgerufen wird, muss ich doch  _
diese '"VariableName" global definieren?
End Sub
Wie soll ich dieses Problem denn jetzt lösen. Folgende "Lösung" würde doch auch nicht viel ä _
ndern oder:

' keine globalen Variablen
Sub Hauptprozedur_1()
Dim intX as integer ' nicht merh global, aber trotzdem ständig im Speicher oder?
With ThisWorkbook.Worksheets("Parameter")
intX = .Range("I6").Value
Dim VariableName() as double ' nicht merh global
Dim ...
....
Call sub1_1(intX)     ' hier wird intX benötigt
Call sub1_2
Call sub1_3(intX)     ' hier wird intX benötigt
Call sub1_4(intX)     ' hier wird intX benötigt
Call sub1_5(intX)     ' hier wird intX benötigt
' hier wurde "VariableName" erzeugt
End Sub
Sub Hauptprozedur_2()
' in der Prozedur wird intX auch immer mal wieder benötigt.
Dim intX as integer ' Variable wird nochmal deklariert und dessen Wert eingelesen
With ThisWorkbook.Worksheets("Parameter")
intX = .Range("I6").Value
....
' zudem werden aber auch Ergebnisse (VariableName) aus Hauptprozedur_1 benötigt
' da die Hauptprozedur_2 ja mit einem eigenem CommandButton aufgerufen wird, muss ich doch  _
diese '"VariableName" global definieren?
End Sub

Es ergeben sich zwei Fragen.
1. Was mache ich mit einer Variable wie intX? Zweimal deklarieren?
Und vor allen Dingen: Ändert das was? Ist intX im zweiten BEispiel nicht auch immer im Speicher und das Programm wird dadurch auch nicht schneller?
2. Wie gehe ich mit einer Variablen wie "VariableName" um, die in einer Prozedur erstellt wird, jedoch in einer anderen wieder gebraucht wird?
Das ganze ist leider etwas lang geworden.
Ich hoffe ihr könnt mir helfen, da ich mir schon seit Wochen darüber den Kopf zerbreche!
Danke.
Wenn man mit GlobalVar arbeiten will/muss,...
19.04.2010 15:15:11
Luc:-?
…Tommy,
sollten diese…
1. möglichst eindeutig, einzigartig und unverwechselbar bezeichnet wdn und…
2. ihr Einsatz in den verschiedenen Pgmm stets kontrolliert und für nur 1 Zweck pro Variable erfolgen.
D.h., der Inhalt der Variablen muss jederzeit eindeutig und bestimmbar sein, dann wird auch nichts schief gehen (vgl die von MS in xlVBA reichlich verwendeten Enumerationsvariablen).
Wenn man Pech hat, kann man mit einer engl Bezeichnung (ob Variable oder Prozedur) den Namen eines ActiveX-Elements oder von etwas Anderem in verwiesenen Projekten u.DLLs erwischen. Dafür kann dann die Festlegung der Rangfolge bei Projektverweisen wichtig sein (allerdings darf dadurch die Gesamtfkt nicht beeinträchtigt wdn).
Wenn du eine Globalvariable in mehreren vbProjekten gleichzeitig verwenden willst, musst du in allen anderen Projekten (im VBE) auf das Projekt verweisen, in dem sie deklariert ist.
Vor der Anwendung von Globalvariablen wird wohl nur deshalb gewarnt, weil ihr unkontrolliert regelloser Einsatz eine der Hpt- und je nach Projektgröße schwer aufzuspürenden Fehler­quellen beim VBA-Einsatz sein kann.
Ansonsten muss man sich halt mit Parameterübergabe behelfen. Ich mache von Fall zu Fall das Eine, aber auch das Andere… ;-)
Gruß Luc :-?
Anzeige
AW: Wenn man mit GlobalVar arbeiten will/muss,...
19.04.2010 15:50:07
Tommy
Luc, danke für deine Antwort.
Werde deine Ratschläge bzgl. Bezeichnungen berücksichtigen.
Angenommen ich habe nur ein einzige Hauptprozedur, die andere Prozederun aufruft. Macht es dann überhaupt einen Unterschied ob ich eine Variable global vor der Hauptprozedur deklariere oder in der Hauptprozedur selbst deklariere? Die Hauptprozedur wird ja nie richtig verlassen. Dann ist es doch egal, ob ich diese Variable (fast) immer übergeben wird oder ob ich die Variable gleich global definiere. (bezogen auf Speicherbedarf, Schenlligkeit). so wie im obigen Beispiel Variable "intX".
Gibt es eignentlich im obigen Beispiel überhaupt eine andere Möglichkeit, als die Varibale "VariableName" global zu definieren? Denn an Hauptprozedur_2 übergeben kann ich ja nicht, da diese ja separat über einen CommandButton aufgerufen wird. Das einzige was mir einfällt, wäre diese Variable am Ende von Hauptprozedur_1 in ein ExcelSheet zu schreiben und dann diese WErte wieder in Hauptprozedur 2 einzulesen. Aber das ist doch nun wirklich nicht gerade elegant.
Gruß
Tommy
Anzeige
Wenn man eine Variable als Parameter...
19.04.2010 17:47:32
Luc:-?
…an ein UP übergibt (bspw die Aufrufe aus Hptproz), Tommy,
und die dort verändert wird, hat die Hptproz nur dann den veränderten VarWert, wenn der Param im UP als ByRef deklariert wurde, was ohnehin vbStandard ist. Mit ByVal wäre das nicht der Fall. Insofern würde ich unter Beachtung der Deklaration in deinem Fall die Param-Übergabe bevorzugen. Der ParamName kann sich dabei auch vom Namen der HptprozVar unterscheiden.
Die Hptproz wird allerdings schon verlassen, nur wird normalerweise wieder in sie zurückgekehrt, es sei denn, ein Fehler oder irgendein(e) andere(s) Vorkommnis/Ereignis/Aktion beendet das UP irregulär. Das darf dann natürl nicht passieren…
Bei physisch getrenntem Mehrfachaufruf einer Proz im Gesamtablauf kann man auch mit Static-Variablen arbeiten. Die behalten ihren (erreichten) Wert zwischen den einzelnen Aufrufen. Allerdings kannst du eine Button-Proz nicht parametrieren. Die müsste dann ein UP parametriert aufrufen, aber wo soll hier der Param herkommen? Der müsste tatsächl zuvor in eine GlobalVar oder anderswo eingetragen worden sein. Alternativ könnte natürlich auch die Hptproz oder ein UP aufgerufen wdn, das den nötigen Param enthält/kennt. Bei diesem Verfahren wäre ggf ein spez Aufruf-Param vorzusehen, der bewirkt, dass aus dieser Proz nur die eigentl von der Button-Proz aufzurufende Proz mit dem gewünschten Param aufgerufen und die Proz dann wieder verlassen wird. Dabei ist sicherzustellen, dass in die Button-Proz zurückgekehrt wird. Also alles etwas komplizierter, aber machbar…
Gruß Luc :-?
Anzeige
AW: Wenn man eine Variable als Parameter...
19.04.2010 20:12:16
Tommy

Die Hptproz wird allerdings schon verlassen, nur wird normalerweise wieder in sie zurückgekehrt …

D.h. wenn eine Variable in der Hauptprozedur deklariert wurde und dann eine Unterprozedur aufgerufen, der NICHT diese Variable übergeben wird, dann ist diese Variable "vorübergehend" nicht im Speicher? oder eben doch, genauso wie eine globale Variable?

Alternativ könnte natürlich auch die Hptproz oder ein UP aufgerufen wdn, das den nötigen Param enthält/kennt. Bei diesem Verfahren wäre ggf ein spez Aufruf-Param vorzusehen, der bewirkt, dass aus dieser Proz nur die eigentl von der Button-Proz aufzurufende Proz mit dem gewünschten Param aufgerufen und die Proz dann wieder verlassen wird. Dabei ist sicherzustellen, dass in die Button-Proz zurückgekehrt wird.

Ansatzweise glaube ich zu vermuten, was du meinst. Aber wenn ich in Hauptprozedur_2 eine Prozedur aus Hauptprozedur_1 aufrufe, braucht diese Prozedur um den richitgen Wert für diese Variable zu haben alle zuvor in Hauptfunktion_1 durchgeführten Berechnungen. D.h- im Grunde müsste alles nochmal durchgerechnet werden. Sehe ich das richtig?
Anzeige
AW: Wenn man eine Variable als Parameter...
19.04.2010 20:16:42
Tommy
Sorry, jetzt sieht es etwas besser aus.
Die Hptproz wird allerdings schon verlassen, nur wird normalerweise wieder in sie zurückgekehrt …
D.h. wenn eine Variable in der Hauptprozedur deklariert wurde und dann eine Unterprozedur aufgerufen,
der NICHT diese Variable übergeben wird, dann ist diese Variable "vorübergehend" nicht im Speicher?
oder eben doch, genauso wie eine globale Variable?

Alternativ könnte natürlich auch die Hptproz oder ein UP aufgerufen wdn, das den nötigen Param
enthält/kennt. Bei diesem Verfahren wäre ggf ein spez Aufruf-Param vorzusehen, der bewirkt,
dass aus dieser Proz nur die eigentl von der Button-Proz aufzurufende Proz mit dem gewünschten
Param aufgerufen und die Proz dann wieder verlassen wird. Dabei ist sicherzustellen, dass
in die Button-Proz zurückgekehrt wird.
Ansatzweise glaube ich zu vermuten, was du meinst. Aber wenn ich in Hauptprozedur_2 eine Prozedur
aus Hauptprozedur_1 aufrufe, braucht diese Prozedur um den richitgen Wert für diese Variable zu haben
alle zuvor in Hauptfunktion_1 durchgeführten Berechnungen. D.h- im Grunde müsste alles nochmal
durchgerechnet werden. Sehe ich das richtig?
Anzeige
Nein, wieso? Wenn die Variable ursprgl in...
19.04.2010 21:34:33
Luc:-?
…nur einer Hptproz deklariert wurde, Tommy,
und dann immer per ByRef-Parameter weitergereicht wird, ist ihr Inhalt auch immer aktuell. Nur, wenn sie zwischendurch als ByVal-Param übergeben wird, wdn die in dieser Proz vorgenommenen Änderungen nicht in der ursprgl Variablen wirksam. Da ByRef ja soviel wie als Bezug heißt, muss die ursprgl Variable im HptSpeicher anwesend sein, sonst würde das ja nicht fkt. Erst, wenn das UP irregulär oder die Hptproz (ir)regulär beendet wird, wird sie dort nicht mehr benötigt. Mit ByVal wird dahingg nur der Wert der ursprgl Variablen in die neue Parametervariable gespeichert. Das ist so ähnl wie der Unterschied zwischen Set und Let, wobei ja Let als Default-Zuweisungsbefehlswort nicht geschrieben wdn muss.
Gruß Luc :-?
Anzeige
AW: Nein, wieso? Wenn die Variable ursprgl in...
19.04.2010 22:21:36
Tommy
Der Unterschied zwischen byval und byref ist mir klar.
Was ich meinte, ist: Wenn die Hauptprozedur_1 schon beendet wurde und ich im zweiten schritt mit hilfe eines CommandButtons die Hauptprozedur_2 aufrufe, diese aber einen WErt, der zuvor durch Hauptprozedur_1 berechnet wurde, braucht; dann kann Hauptprozedur_2 diesen Wert nur bekommen, wenn die besagte Variable global definiert wurde. Da durch das beenden von Hauptprozedur_1 alle in ihr deklarierten Variablen verloren.
Somit geht es doch garnicht anders als mit einer globalen Variablen. Das alles gilt mit Hinblick darauf, dass die beiden Hauptprozeduren separat mit CommandButton aufgerufen werden sollen. Wobei die Prozedur_2 berechnete WErte aus Prozedur 1 braucht.
Sehe ich das richig?
Wäre super, wenn du mir darauf noch antworten kannst.
Danke!!
Anzeige
Jein, wenn die als Static-Variable deklariert...
19.04.2010 22:42:52
Luc:-?
…wurde, was ich übrigens schon mal angemerkt hatte, Tommy,
bleibt ihr letzter Wert erhalten. Bei erneutem Aufruf einer Proz mit einem ByRef-Parameter, der auf diese Bezug nimmt, sollte ihr letzter Wert zV stehen…
Probier's einfach mal aus! Ein kleines Bsp ist doch schnell gemacht!
Gute Nacht, Luc :-?
So, nun hab ich's selber gemacht und...
20.04.2010 02:02:16
Luc:-?
…kann dir versichern, Tommy,
es fktioniert, wenn du das geschickt organisierst. Mit einem quasi Hintereingang (seit mind 40 Jahren in der Pgmierung üblich) in der Hptproz oder einem passenden UP, kannst du den aktuellen Stand der Static-Variable aus der Hptproz abfragen.
Morrn, Luc :-?
Anzeige
AW: So, nun hab ich's selber gemacht und...
20.04.2010 16:15:22
Tommy
Hi Luc,
ja jetzt verstehe ich das, wie du das mit static meinst. Das ist natürlich wirklich ne Idee.
Ich bin jetzt grad dabei, dass zu testen. Jedoch finde ich diesen "Hintereingang" nicht.
Ich weiß einfach nicht, wie ich die Variable in die zweite Prozedur bekomme.
WEnn ich eine Variable der ersten Prozedur übergebe um den WErt der Static-Variable zu bekommen, dann wird der WErt bevor ich ihn mir nehmen kann, gelöscht (da neu deklariert).
DAs hier war mein Ansatz:
Sub proz_statisch(Optional ByRef Var1 As Double)
If Var1 = true Then
Var1 = zelle
Else
Static zelle As Double
zelle = Worksheets(1).Range("E1").Value
Debug.Print zelle
End If
End Sub
Sub proz_holen()
Dim Var2 As Double
Call proz_statisch(Var2)
Worksheets(1).Range("a1").Value = Var2
End Sub
Ja scheiße, so gehts nicht. Ich bekomme es nicht hin.
Anzeige
So, hier nun meine BeispielPgmme,...
20.04.2010 23:46:58
Luc:-?
…Tommy…
Sub Haupt(Optional nb)
Static parm
If IsMissing(nb) Then
parm = "Test"
Call Unter1(parm)
MsgBox parm, vbOKOnly, "Haupt n.U1 - ByVal"
Call Unter2(parm)
MsgBox parm, vbOKOnly, "Haupt n.U2 - ByRef"
Else: nb = parm
End If
End Sub
Sub Unter1(ByVal pm)
pm = pm & " 08/15"
MsgBox pm, vbOKOnly, "Unter1 - ByVal"
End Sub
Sub Unter2(pm)
pm = pm & " 08/15"
MsgBox pm, vbOKOnly, "Unter2 - ByRef"
End Sub
Sub Neben()
Dim nbpm
nbpm = True
Call Haupt(nbpm)
MsgBox nbpm, vbOKOnly, "Neben - ByRef + Static-Effekt"
End Sub
Im MakroAssi erscheinen nur die Subroutinen Haupt und Neben, da die anderen keine optionalen Parameter haben und deshalb von dort aus nicht aufgerufen wdn können. Der Parameter von Haupt ist optional und Variant, deshalb wird die Proz angezeigt. Der „Haupteingang“ in die Subroutine ist parameterlos — die Übergabe eines Parameters bei Aufruf ist quasi der „Schlüssel zum Nebeneingang“, der dann natürl auch einen gesonderten Weg durch die Proz bewirkt.
Gruß Luc :-?
AW: So, hier nun meine BeispielPgmme,...
21.04.2010 11:54:34
Tommy
Super Danke, Luc.
Ich hatte es dann auch noch hinbekommen. .
Ok dann habe ich jetzt drei Möglichkeiten (globale variblen / neu deklarieren und einlesen / Hintertür mit static und referenz).
Luc, lassen sich die Eingriffe des Anwenders tatsächlich vermeiden. Gibt es da irgendeinen Schutz oder war das nur so daher gesagt?
Ansonsten wurde meine Frage nun beantwortet und ich danke euch beiden für eure Hilfe.
Gruß
Tommy
Z.T. mit .Protect und UserInterfaceOnly:=True
22.04.2010 01:33:25
Luc:-?
Aber mit entsprechender „krimineller“ Energie kann das ein allzu neugieriger Freak schon unterlaufen, Tommy…
Gruß + viel Erfolg! Luc :-?
AW: Und konkret?
19.04.2010 22:01:30
Gerd
Hallo Tommy,
ändert sich der Wert in ThisWorkbook.Worksheets("Parameter").Range("I6").Value,
der in intX eingelesen wird zur Laufzeit der Hauptprozedur1 bzw. vor oder während der Laufzeit der Hauptprozedur2 ?
Wie wird VariableName ermittelt? Und die gleiche Frage zur Datenbasis wie oben.
P.S.: Ein Beinbruch sind globale Variablen nicht, ob hier nötig, ergibt sich ggf. aus deiner Antwort.
Gruß Gerd
AW: Und konkret?
19.04.2010 22:36:17
Tommy
Hallo Gerd,
Der Wert in ThisWorkbook.Worksheets("Parameter").Range("I6").Value ändert sich nicht. Auch wird intX nie verändert. intX arbeitet wie eine Konstante. Der Wert wird einmal eingelsen und wird in vielen Prozeduren benötigt.
VariableName ist ein Array, dass durch eine in Hauptprozedur_1 aufgerufene Prozedur erstellt wird und dann in weiteren Prozeduren innerhalb von Hauptprozedur_1 verändert wird. Die Werte, die VariableName am Ende von Hauptprozedur_1 enthält, werden zunächst noch durch Hauptprozedur_1 in ein ExcelSheet eingetragen und sollen dann in Hauptprozedur_2 verwendet werden.
Das Proplem ist nun, dass Hauptprozedur_2 nicht in Hauptprozedur_1 aufgerufen werden soll (dann könnte ich ja VariableName übergeben). Sondern erst ein CommandButton soll Hauptprozedur_2 aufrufen. Jedoch wäre ja VariableName, wenn in Hauptprozedur_1 deklariert, nicht mehr verfügbar.
Ich hoffe jetzt ist es klarer geworden und bin gespannt auf die Antwort.
Gruß
Tommy
AW: Und konkret?
20.04.2010 00:39:58
Gerd
Hallo Tommy,
unter deiner Prämisse würde ich in beiden Fällen in Hauptprozedur2
die Werte aus der Tabelle in neue lokale Variablen einlesen, Speicher hin, Laufzeitverhalten her.
Dies hätte den Vorteil, dass ein zwischenzeitlicher Wechsel in den Entwurfsmodus
oder Schließen der Datei für HPrz2 :-) unschädlich wäre.
Gruß Gerd
AW: Und konkret?
20.04.2010 16:24:31
Tommy
Hallo Gerd,
danke für deine Empfehlung.
Das der WErt einer Variable gelöscht wird, wenn der Entwurfsmodus geöffnet wird, wusste ich ganricht. Passiert dies nur, wenn man in Excel auf den Button klickt oder kann das auch so automatisch passieren?
Das heißt in meinem Fall, würde es keinen Unterschied bzgl. SPeicher und Laufzeitverhalten machen, ob ich die Variablen global deklariere oder jeweils lokal in den beiden Hauptprozeduren?
Der einzige Unterschied wäre dann das mit dem Entwurfsmodus, richtig?
Gibt es da eigentlich ne möglich um zu verhindern das zwischenzeitlich der Entwurfsmodus geöffnet wird?
Grüße
Tommy
So etwas (kann) passiert/en eigentl nur,...
20.04.2010 19:35:45
Luc:-?
…wenn du zwischenzeitl den Code editierst (automat → Entwurfsmodus), Tommy!
Das wird ja wohl im Normalbetrieb nicht der Fall sein!
Gruß Luc :-?
PS: Meine kleinen Bspp bekommst du heute noch!
AW: nur ?
20.04.2010 21:17:12
Gerd
....wenn jemandem die CmdButton-Farben nicht gefallen oder ....Escape drückt ... oder ...
Gruß Gerd
AW: nur ?
20.04.2010 22:12:26
Tommy
Herzlichen Dank euch beiden! Mir ist so einiges klarer geworden.
:)
Auf das kleine Beipielprogramm bin ich noch gespannt.
Solche Useraktionen sollte man verhindern! orT
21.04.2010 00:02:34
Luc:-?
Gruß Luc :-?

Links zu Excel-Dialogen

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige