Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1588to1592
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
Array übergeben
16.11.2017 16:03:36
Jens
Hallo zusammen,
ich habe folgendes Problem, welches ich nicht gelöst bekomme:
Im Sub "Dateien_Erstellen()" wird die Prozedur "BossIDs_Einlesen" aufgerufen, diese wird durchlaufen und am Ende steht ein Array ("MatrixListeBossID")das zurück an "Dateinen_Erstellen()" geliefert werden soll und von dort gleich (zusammen mit einer weiteren Variablen "ZaehlerFam") als Input weitergegeben werden soll an die beiden Prozeduren "DatenEinkauf_Einlesen" und "DatenLager_Einlesen" ...
Wenn ich alles in einem Rutsch in einem Sub durchprogrammiere, klappt es, da das Array bzw. die weitere Variable alle im Sub vorliegen. Da der Programmcode allerdings ewig lang ist, möchte ich zur besseren Übersicht splitten und muss das Array bzw. die Variable übergeben, was so nicht klappt.
Bisher habe ich (verkürzt und vereinfacht):
Public Sub PortfolioDateien_Erstellen()
Dim pfad As String
Dim NeueDatei As String
pfad = ThisWorkbook.Path & "\"
NeueDatei = "Daten_201709.xlsx"
Application.Workbooks.Open pfad & NeueDatei
Sheets("Rohdaten").Select
Call BossIDs_Einlesen
DatenEinkauf_Einlesen MatrixListeBossID(), ZaehlerFam
End Sub
Public Sub BossIDs_Einlesen()
Dim i As Integer
Dim j As Integer
Dim ZeileDaten As Integer
Dim strZeileBoss As String
Dim ZaehlerFam As Integer
Dim MatrixListeBossID() As Variant
ReDim strLetters(1 To 1)
ZeileDaten = FreeFile
Open "G:\MeineDaten\bossIDs.txt" For Input As ZeileDaten
Do While Not EOF(ZeileDaten)
ZaehlerFam = ZaehlerFam + 1
Line Input #ZeileDaten, strZeileBoss
ReDim Preserve strLetters(1 To ZaehlerFam)
strLetters(ZaehlerFam) = Split(strZeileBoss, ";")
Loop
Close ZeileDaten
ReDim MatrixListeBossID(1 To ZaehlerFam, 0 To 4) As Variant
For i = 1 To ZaehlerFam
For j = 0 To 4
If i = 1 Then
MatrixListeBossID(i, j) = strLetters(i)(j)
Else
MatrixListeBossID(i, j) = CDbl(strLetters(i)(j))
End If
Next j
Next i
PortfolioDateien_Erstellen MatrixListeBossID(), ZaehlerFam
End Sub
Public Sub DatenEinkauf_Einlesen(ByRef MatrixListeBossID() As Variant, ByRef ZaehlerFam As  _
Integer)
End Sub

9
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Array übergeben
16.11.2017 17:19:07
onur
Hi,
Was soll diese Zeile bewirken?
MatrixListeBossID(i, j) = strLetters(i)(j)

strLetters ist doch eindimensional und was soll die zweite Klammer (selbst wenn sie 2-dimensional wäre, käme nur eine Fehlermeldung)
Wieso willst du MatrixListeBossID() überhaupt übergeben - deklariere sie in einem Modul als "Public" und du kannst in jedem Modul/Sub damit arbeiten.
Du irrst hierbei, ...
16.11.2017 19:08:53
Luc:-?
…Onur;
strLetters ist zwar 1dimensional, seine Elemente bestehen aber aus ebenfalls 1dimensionalen Arrays, deren Elemente so indiziert wdn müssen und auf diese Weise in ein 2dimensionales Array übertragen wdn sollen. Darüber wurde schon des Öfteren hier und anderswo geschrieben (auch von mir; → Arrays in Arrays).
🙈 🙉 🙊 🐵 Gruß, Luc :-?
„Die Intelligenzmenge ist auf diesem Planeten eine Konstante, die Bevölkerung nimmt aber zu!“ Auch deshalb informieren mit …
Anzeige
Keine globalen Variablen, Rückgabe mit Funktionen
16.11.2017 21:46:54
Zwenn
Hallo zusammen,
ich frage mich, warum hier so viele Leute globale Variablen verwenden und auch noch empfehlen, als wenn das total klasse ist. Vor allem wundere ich mich, wenn es Leute sind, die nachweislich echt richtig gute Lösungen liefern, von denen auch ich schon viel gelernt habe, was VBA für Excel angeht. Bitte bitte, nehmt Euch ein beliebiges Skript zur Einführung in die Programmierung einer beliebigen Hochschule und ich verwette meinen Arsch darauf, dass zu den beiden Pestbringern des Spaghettiocodes GoTo und globale Variablen, erklärt wird, dass sie mindestens schlechter Programmierstil sind. In allen mir bekannten Kursen sind sie verboten und wer sie verwendet, dem fliegt sein Code um die Ohren. Das ist auch keine neue Erkenntnis, dass habe ich bereits in der 90 Jahren an der FH Kiel so kennengelernt.
Auszug aus dem Skript Einführung in die imperative Programmierung, Seite 163, Kurs 01613 der Feruni Hagen:
3. Prozeduren unterstützen die Wiederverwendung von Programmkomponenten
in verschiedenen Programmen. Die einfachsten Beispiele bilden die in Pascal
vordefinierten Standardfunktionen wie z.B. abs, sqr, succ, ord sowie die
Standardprozeduren read und write. Jeder Programmierer kann und sollte
sich eine Bibliothek von Prozeduren einrichten, die er typischerweise für seinen
Anwendungsbereich benötigt. (Im Fall einer Softwarefirma sollte eine
einzige Bibliothek angelegt werden, die von allen Programmierern gemeinsam
benutzt wird.) Diese vorgefertigten Bausteine erleichtern und beschleunigen
nicht nur die Programmentwicklung, sondern unterstützen auch die
Fehlerfreiheit des Programms (vorausgesetzt, die Bausteine selbst sind fehlerfrei).
Eine solche Bibliothek könnte z.B. die Prozedur FeldSortieren aus
dem Programm FeldSort4 (vgl. Aufgabe 5.1.2.1 ) enthalten, mit der Felder
(von integer-Zahlen) unterschiedlicher Länge sortiert werden können. Die
Wiederverwendung solcher Bausteine funktioniert aber nur effizient, wenn
sämtliche benötigte Information über die Baustein-Schnittstelle fließt und
keine Annahmen über globale Variablen getroffen werden müssen. Wäre das
nämlich der Fall, dann müßte der Programmierer zunächst den Programmcode
des Bausteins aus der Bibliothek untersuchen, um die global benutzten Variablen
zu finden, damit er sie in seinem Programm entsprechend deklariert.
Bei Vermeidung globaler Variablen genügt ein Blick auf die Schnittstelle, um
die benötigte Information zu identifizieren; das lästige, mit Fehlern behaftete
Lesen des Programmcodes entfällt
(vgl. dazu auch den Abschnitt über "Seiteneffekte"
in den Programmierstilausführungen).

Globale Variablen sind die Pest und sollten niemals verwendet werden! (Dieser Satz ist nicht mehr aus dem Skript ;-))
Ein umfangreicheres Programm hat immer eine Hauptroutine und Unterprogramme. In VBA ist die Hauptroutine immer eine Sub, während Unterprogramme eine Sub oder eine Funktion sein können.
Der Unterschied ist, das eine Sub lediglich Code ausführt und dann zur aufrufenden Routine zurückkehrt, während eine Funktion eine Variable an die aufrufende Routine zurückgibt. Die aufrufende Routine muss dabei nicht die Hauptfunktion sein. Eine zurückgegebene Variable (der Rückgabeparameter) kann natürlich auch ein Array sein.
Um die zurückgegebene Variable aufnehmen zu können, muss in der aufrufenden Routine eine entsprechende Variable deklariert sein. Im vorliegenden Fall heißt dass, in der Sub Dateien_Erstellen() muss zusätzlich ein Array deklariert werden, welches dann durch den Rückgabewert der von einer Sub zu einer Funktion zu wandelnden Routine BossIDs_Einlesen gefüllt wird. Wird aus DatenEinkauf_Einlesen und DatenLager_Einlesen auch ein Rückgabeparameter erwartet, muss es sich ebenfalls um Funktionen handeln.
Ich nehme im folgenden mal PortfolioDateien_Erstellen() als aufrufende Routine und BossIDs_Einlesen() als zurückgebende Funktion:

Sub PortfolioDateien_Erstellen()
Dim pfad As String
Dim NeueDatei As String
Dim rueckgabeArrayAufnehmen() As Variant 'Zusätzliches Array
pfad = ThisWorkbook.Path & "\"
NeueDatei = "Daten_201709.xlsx"
Application.Workbooks.Open pfad & NeueDatei
Sheets("Rohdaten").Select
'Zusätzlich deklariertes Array durch Funktion befüllen
rueckgabeArrayAufnehmen = BossIDs_Einlesen()
'Sollte durch die folgenden Aufrufe ein Rückgabewert erwartet
'werden, muss statt Call eine Variable geschrieben werden die
'so wie das Array in dieser Routine deklariert werden muss.
'Auf den Datentyp achten!
'PortfolioDateien_Erstellen() aus BossIDs_Einlesen() hier her
'verfrachtet. Sofern möglich, Prozeduraufrufe immer aus der
'Hauptroutine durchführen, das dient der Übersichtlichkeit
'und ggf. der Wiederverwendbarkeit von Code.
'Es ist einfacher eine Routine wiederzuverwenden, die nicht an den
'Aufruf einer weiteren Routine gekoppelt ist.
Call PortfolioDateien_Erstellen(rueckgabeArrayAufnehmen(), ZaehlerFam)
Call DatenEinkauf_Einlesen(rueckgabeArrayAufnehmen(), ZaehlerFam)
End Sub

Function BossIDs_Einlesen() As Variant
Dim i As Integer
Dim j As Integer
Dim ZeileDaten As Integer
Dim strZeileBoss As String
Dim ZaehlerFam As Integer
Dim MatrixListeBossID() As Variant
ReDim strLetters(1 To 1)
ZeileDaten = FreeFile
Open "G:\MeineDaten\bossIDs.txt" For Input As ZeileDaten
Do While Not EOF(ZeileDaten)
ZaehlerFam = ZaehlerFam + 1
Line Input #ZeileDaten, strZeileBoss
ReDim Preserve strLetters(1 To ZaehlerFam)
strLetters(ZaehlerFam) = Split(strZeileBoss, ";")
Loop
Close ZeileDaten
ReDim MatrixListeBossID(1 To ZaehlerFam, 0 To 4) As Variant
For i = 1 To ZaehlerFam
For j = 0 To 4
If i = 1 Then
MatrixListeBossID(i, j) = strLetters(i)(j)
Else
MatrixListeBossID(i, j) = CDbl(strLetters(i)(j))
End If
Next j
Next i
'Hier wird das Array an die aufrufende Routine zurückgegeben
BossIDs_Einlesen = MatrixListeBossID
End Function

Hinweis: Ich habe den Code der vorgegebenen Routinen nicht auf Fehler geprüft. Es geht mir hier nur um das Prinzip, wie Arrays übergeben werden, ohne globale Variablen einzusetzen.
Viele Grüße,
Zwenn
Anzeige
AW: Brüder Grimm
16.11.2017 22:29:18
Gerd
Moin Zwenn,
was du eben erzählt hast, ist schlicht substanzslos :-)
Gruß Gerd
AW: Brüder Grimm
16.11.2017 22:52:58
Zwenn
Hallo Gerd,
dann ordne ich Dich mal als Hobbyprogrammierer ein. Aber vielleicht hast Du ja sogar Argumente?
Gruß,
Zwenn
AW: Keine globalen Variablen, Rückgabe mit Funktionen
16.11.2017 22:38:04
onur
Hi Zwenn,
Wenn Du mich meinst, kannst du mich ruhig auch direkt ansprechen.
Du hast schon insofern Recht, dass mann sowas nicht unbedingt Anfängern raten sollte.
Aber ich persönlich benutze globale Variablen, so oft ich glaube, das sie nützlich und effektiv sind.
Gefährlich ist es auch, Benzindämpfe mit Sauerstoff zu vermischen und anzuzünden, aber wenn man damit umgehen kann, kann man dadurch schöne Sachen wie einen Porsche bauen.
Um das, was üblich oder guter Stil ist, habe ich mich eigentlich selten gekümmert, es geht mir eigentlich mehr um Effizienz, so lange etwas mir nützt und funktioniert, benutze ich es auch, selbst wenn es evtl. unüblich sein sollte. Selbst in der Schule habe ich bei Mathe-Arbeiten sehr oft einen ganz anderen Lösungsweg genommen, als den, den der Lehrer sehen wollte, aber er musste mir trotzdem die volle Punktzahl geben, weil mein Lösungweg ebenso zum richtigen Ergebnis führte.
Jahrzehnte lang mussten Generationen von Kindern Spinat essen, weil es "Allgemeinwissen" war, dass Spinat viel Eisen enthält.
Selbst jetzt müssen Kinder "darunter leiden", obwohl man längst weiss, dass der Arzt, der diese Behauptung in die Welt gesetzt hatte, beim Eisengehalt das Komma versehentlich um eine Stelle nach rechts verschoben hatte.
Ich will ja keinesfalls behaupten, dass du oder die Anderen Unrecht haben, aber ich werde globale Variablen benutzen, so oft ich meine, dass sie mir nützlich sind, egal was die "Volksmeinung" dazu sagt.
Gruß
Onur
Anzeige
AW: Keine globalen Variablen, Rückgabe mit Funktionen
16.11.2017 23:18:03
Zwenn
Hallo Onur,
ja, in diesem Fall meine ich Dich sogar ganz direkt ;-) Ich denke auch, das geht aus meinem Text hervor, da ich direkt auf Deinen Beitrag geantwortet habe. Es geht mir ja auch nicht um "echten" Streit, wenn ich meinen Standpunkt vertrete, was Du auch so aufgefasst hast, wie ich Deinen sonstigen Ausführungen entnehme.
Das Porsche Beispiel verstehe ich leider nicht, was daran liegt, dass ich absolut keine Ahnung von Autos habe. Aus der Wärmelehre kenne ich noch das Karnaugh Veitch Diagramm und habe auch verstanden, warum ein Diesel rein wirkungsgradbezogen die bessere Wahl ist, aber Autos ansich? Sorry, nicht meins.
Bekanntermaßen gibt es für jedes Problem mehrere Lösungen, vor allem in der Mathematik. Manche sind besser, manche sind schlechter. Natürlich kommt man auch mit globalen Variablen an sein Ziel, keine Frage. Du gehörst vermutlich auch zu den Praktikern, hinter denen ich mit meiner Erfahrung eine Stunde lang spazieren gehen kann, ohne dass man mich sieht. Ganz nebenbei gelte auch ich nicht grade als Mainstream. Bei bestimmten Dingen bin ich aber eher "fundamentalistisch" unterwegs. Globale Variablen gehören ganz sicher dazu. Ich halte die nicht nur für schlecht, ich halte die für grundlegend falsch.
Die Sache mit dem Spinat und dem falschen Komma ist mir bekannt. Allerdings hatte ich das Glück, Spinat auch als Kind zu mögen :-) Bei globalen variablen handelt es sich allerdings nicht um die Frage, ob ein Komma richtig oder falsch gesetzt ist. Wie es aussieht, handelt es sich eher darum, ob man ein Konzept annimmt oder eben nicht.
Ich finde es völlig in Ordnung, wenn Du als erfahrener Entwickler globale Variablen einsetzt. Auch wenn ich mich frage, ob Du eher für Dich selbst entwickelst oder ob es auch Kollegen gibt, die Deinen Code lesen und nachvollziehen müssen? Bei kurzen Codes mag das mit den globalen Variablen auch als "quick and dirty" ok sein. Ich bin ja selbst weit davon entfernt, tollen Code zu produzieren. Globale Variablen würde ich aber trotzdem niemals einsetzen.
Wahrscheinlich habe ich das dermaßen inhaliert, dass sich mir die Nackenhaare aufstellen, wenn sie von jemandem verwendet werden ;-)
In diesem Sinne, ich freue mich aus weiterem Code von Dir lernen zu dürfen :-)
Viele Grüße,
Zwenn
Anzeige
Erfahrene Entwickler kennen aber auch ...
17.11.2017 03:09:17
Luc:-?
…die unterschiedlichen Array-Typen, Zwenn,
und nicht nur die, die auf gewissen VBA-Spar- bzw -Anfänger-WebSites vorgestellt wdn. Schon die VBE-Hilfe kennt auch einen Vari­ant mit einem Array, der hier vom Fragesteller verwendet wurde, nur erwähnt sie nur den Unterschied ohne auf weitere Beson­der­heiten einzugehen (auch bei ParamArray nicht!): Obwohl ein Variant, der ein Datenfeld enthält, sich konzeptionell von einem Datenfeld unterscheidet, dessen Elemente vom Typ Variant sind, erfolgt der Zugriff auf die Daten­feld­Elemente in gleicher Weise.
Das VBE-Hilfe-Zitat berücksichtigt gerade diese Art von Datenfeldern, zu denen auch das hier benutzte gehört, nicht ausreichend. Man könnte ja auch ein solches auf diese Weise erzeugen:
Dim arVar As Variant
arVar = Array(Array(1, 2, 3), Array(4, 5, 6))

Wieviele Dimensionen hat dann wohl arVar…? ;-]
An der Diskussion um GlobalVariablen beteilige ich mich nicht, denn meine Meinung kennst du bereits. Hier nur soviel, ich benutze sowohl diese als auch Variablen-Übergabe. Da ich überwiegend UDFs schreibe, fallen GlobalVariablen eher in Form von Enumera­tio­nen oder (Text-)Konstanten, die ich nicht in einem Pgm unterbringen kann u/o will, an. Das alles müsste ich unterlassen, wenn ich modischen Dogmen folgen wollte. Ich pgmmiere seit 1969/70 und schon damals waren Spaghetti-Codes eine deutliche Warnung wert. Folglich pgmmiere ich auch keine, obwohl ich in VBA auch (On xyz )GoTo und (~)GoSub verwende. Ich lasse mir doch nichts ver­bieten, was zum Inventar einer PgmmierSprache gehört. Auch hier kommt's doch in 1.Linie darauf an, wofür das bestimmt ist und wie das ArbeitsUmfeld aussieht. Die Enumerationen in VBA zB wurden ja auch geschaffen, um Team-Pgmmierern die Arbeit zu erleichtern! Und gerade in VBA ist auch nicht viel mit Bibliotheken, es sei denn, man nutzt die WinAPI oder gleich VB.Net! Anderenfalls muss man die selbst anlegen, was (vor allem im Rahmen eines größeren Projekts in TeamWork) sehr sinnvoll sein kann (aber nicht zwingend muss).
Hier im Forum dominieren allerdings die EinzelAnfertigungen, quasi auf Zuruf (vor Nutzung des Archivs), weil nahezu jeder VBA-Kun­dige sich (auch mal) beweisen will, was verständlich ist, aber von den Fragern berück­sichtigt wdn sollte!
🙈 🙉 🙊 🐵 Morrn, Luc :-?
Anzeige
Der Geltungsbereich für diese Empfehlung ist doch
17.11.2017 00:02:10
Daniel
klar beschrieben und auch eindeutig abgerenzt:
Die Empfehlung gilt doch im Prinzip nur für solche Prozeduren, die so allgemein gehalten sind, dass sie eben nicht nur in einen bestimmten Projekt einsetzbar sind, sondern auch von den unterschiedlichsten Projekten verwendet werden können und daher sinnvoller weise in einer Bibliothek allgemein verfügbar gemacht werden sollen.
Nur wird es selten gelingen, ein vollständiges Programmprojekt nur aus einer Ansammlung von solchen allgemeinen Teilbausteinen zu erstellen, sondern man wird in der Regel immer auch eine Anzahl von speziellen Prozeduren benötigen, die eben nur in diesem einen Projekt sinnvoll einsetzbar sind und deswegen auch nicht in eine Bibliothek gehören.
Und für diese speziellen Prozeduren gilt diese Empfehlung nicht mehr, dort gelten dann andere Regeln.
und wie Zwenn ja selbst schreibt, die Aussage des Scriptes ist nicht:
"Globale Variablen ... sollten niemals verwendet werden!"
Sondern die Aussage des Scriptes ist viel mehr:
"Globale Variablen sollten in diesem Anwendungsfall nicht verwendet werden"
daraus abzuleiten, dass globale Variablen generell zu vermeiden sind, halte ich für eine Fehlinterpretation, das steht in dem Scriptauschnitt nicht drin.
Gruß Daniel
Anzeige
Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige