Live-Forum - Die aktuellen Beiträge
Anzeige
Archiv - Navigation
1836to1840
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

Array übergeben

Array übergeben
23.06.2021 19:02:05
Flo
Hallo zusammen! :)
Könnte mir bitte jemand erklären, weshalb in folgendem Code Variante 1 funktioniert, es bei Variante 2 allerdings folgende Fehlermeldung gibt:
Fehler beim Kompilieren: Unverträglicher Typ: Datenfeld oder benutzerdefinierter Typ erwartet
Die Test Prozedur möchte überprüfen, ob sich ein bestimmter Inhalt in dem Array befindet, das der Prozedur übergeben wurde. Der folgende Ausschnitt ist natürlich nur ein vereinfachtes Beispiel des gesamten Programms!
Da das Programm nicht von mir geschrieben ist und ich es lediglich erweitern möchte, habe ich nicht die Möglichkeit die ist_Wort_in_Array-Funktion zu verändern. Die Art und Weise, wie ich es in Sub_Eins gelöst habe, wirkt mir nicht elegant. Gibt es da eine bessere Möglichkeit?

Option Explicit
Sub Array_Erzeugen()
Dim arr(1 To 10) As Variant
arr(5) = "hallo"
'Variante 1: (funktioniert)
Call Test_Eins(arr)
'Variante 2: (funktioniert nicht)
Call Test_Zwei(arr)
End Sub
Sub Test_Eins(Optional inp_arr As Variant)
Dim arr() As Variant
arr = inp_arr
Debug.Print ist_Wort_in_Array(arr, "hallo")
End Sub
Sub Test_Zwei(Optional inp_arr As Variant)
Debug.Print ist_Wort_in_Array(inp_arr, "hallo")
End Sub
Function ist_Wort_in_Array(ByRef inp_arr() As Variant, wort As String) As Boolean
Dim i As Integer
For i = LBound(inp_arr) To UBound(inp_arr)
If inp_arr(i) = wort Then
ist_Wort_in_Array = True
Exit Function
End If
Next i
End Function
Herzlichen Dank vorab!!!

13
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: Array übergeben
23.06.2021 19:09:42
Nepumuk
Hallo Flo,
teste mal so:
Code:

[Cc]

Function ist_Wort_in_Array(ByRef inp_arr As Variant, wort As String) As Boolean Dim i As Integer For i = LBound(inp_arr) To UBound(inp_arr) If inp_arr(i) = wort Then ist_Wort_in_Array = True Exit Function End If Next i End Function

Gruß
Nepumuk
Anzeige
AW: Array übergeben
23.06.2021 19:15:47
Mullit
Hallo,
Deine Funktion ist_Wort_in_Array erwartet als Param ein Array, als mußt Du auch eines übergeben:

Sub Test_Zwei(inp_arr() As Variant)
Debug.Print ist_Wort_in_Array(inp_arr, "hallo")
End Sub
Dann ist der Param allerdings nicht mehr Optional....
Gruß, Mullit
AW: ah, Nepumuk war schneller..;-) owT
23.06.2021 19:21:31
Mullit
AW: Array übergeben
23.06.2021 23:06:08
Flo
Hallo ihr zwei, vielen Dank für die schnellen Antworten! :)
@Nepumuk: Vielen Dank, funktioniert auch bei mir. Das Problem ist nur, dass ich diese Funktion nicht verändern möchte. Sie befindet sich in einem sehr umfangreichen Programm, welches ich nicht selbst geschrieben habe. Sprich: Es greifen auch andere Prozeduren darauf zu und es besteht somit die Gefahr, dass ich dadurch etwas "kaputt mache"
@Mullit: Die Sache mit dem Optional ist zwingend erforderlich, aus ähnlichem Grund wie oben beschrieben. Kannst Du Dir eine Lösung vorstellen, um den Parameter weiterhin optional zu lassen? Und warum ist Optional inp_arr() As Variant nicht möglich? - Denn damit würde ich doch tatsächlich ein Array übergeben, oder? Bzw. anders gefragt, warum erkennt die Prozedur Sub_Eins es als Array, obwohl es wie folgt übergeben wird? Sub Test_Eins(Optional inp_arr As Variant)
Vielen Dank vorab, ich weiß jede Hilfe wirklich sehr zu schätzen! Ich möchte es verstehen und daran lernen :)
Beste Grüße, Flo
Anzeige
Wenn die Fkt nicht verändert wdn soll, ...
24.06.2021 04:11:41
Luc:-?
…Flo,
bleibt dir wohl nichts Anderes übrig, als ihren Aufruf entsprd anzupassen, d.h., nur Variante1 zu verwenden, denn beim Kompilieren ist für den Compiler (noch) nicht ersichtlich, ob der Parameter der 2.SubProz tatsächlich das von der Fkt verlangte DatenfeldArgument enthält. Bei der 1.SubProz ist das dagg klar, da dieses Argument direkt in der SubProz deklariert wird. Und das liegt in 1.Linie an deinem 2stufigen Aufruf! Würdest du die Fkt direkt aus der HptProz aufrufen, hättest du das Problem erst gar nicht.
Übrigens ist die Fkt nicht sonderlich professionell. Es würde auch Folgendes ausreichen:


Function ist_Wort_in_Array(ParamArray inp_arg()) As Boolean Dim i As Integer For i = LBound(inp_arg(0)) To UBound(inp_arg(0)) ist_Wort_in_Array = inp_arg(0)(i) = inp_arg(1) If ist_Wort_in_Array Then Exit For Next i End Function
In diesem Fall sollte man aber auch überprüfen, ob die Elemente des ParamArray ggf fehlen, denn das könnte ja auch mal der Fall sein, selbst für das letzte Element, falls wenigstens ein ListenTrennZeichen angegeben wurde, denn ein ParamArray ist immer in Gänze Optional und Variant, so dass nicht nur alle Elemente fehlen können [IsMissing(inp_arg) oder Ubound(inp_arg)=-1], sondern auch jedes einzelne, wenn es eben ausgelassen wird (nur zugehöriges ListenTrennZeichen notiert).
Desweiteren verhindert ein Festlegen des Datentyps des Fktsergebnisses die Rückgabe differenzierter Fehlerwerte, falls so etwas, zB beim ZellFmlEinsatz einer UDF, mal erforderlich sein sollte. Das nur als Anmerkung.
Morhn, Luc :-?
Anzeige
AW: Wenn die Fkt nicht verändert wdn soll, ...
24.06.2021 12:22:24
Flo
Hi Luc,
vielen Dank für Deine ausführliche Antwort!
Verstehe ich es richtig, dass ein nicht optionaler Parameter von dem Compiler demnach schon dahingehend überprüft werden kann, ob es das richtige Datenfeld Argument für die Funktion ist? Warum macht das so einen großen Unterschied?
Und zur Funktion: Herzlichen Dank, dass Du mir da auch einen Verbesserungsvorschlag gibst. Ich meine das auch soweit nachvollziehen zu können...
inp_arg() ist selbst ein Array, welches an der Stelle 0 ein Array und an Stelle 1 das Wort beinhalten soll, oder?
Ich werde mir diese Herangehensweise merken, kann ich sicherlich irgendwann in einem "eigenen Code" umsetzen :)
Nochmal besten Dank und viele Grüße, Flo
Anzeige
AW: Array übergeben
24.06.2021 12:06:11
Planlos
Bei der sub test_eins wird zur Laufzeit versucht den parameter inp_arr in ein array zu überführen. Würde der Inhalt des parameters inp_arr kein array beinhalten, weil z.b. der Aufruf "call test_eins("eene meene muh")" lautet, würde es zur Laufzeit des programmes zum Fehler führen.
Bei der der sub test_zwei wird zur kompilerzeit versucht den parameter inp_arr selbst als byref, sprich den pointer von inp_arr, an die Funktion zu übergeben. Nur ist diese parameter kein array sondern ein variant, daher meldet der kompiler einen Fehler. Der Inhalt dieses parameters (array, string, long etc...) ist zu diesem Zeitpunkt nicht vorhanden weil das prog nicht ausgeführt wird.
Anzeige
AW: Array übergeben
24.06.2021 12:42:07
Flo
ah verstehe. Denn Variant kann ja vieles sein und muss nicht zwingend ein Array sein.
Dafür schon Mal vielen Dank, die Erklärung habe ich verstanden! :)
Somit funktioniert folgendes, weil ich durch die Klammern deutlich mache, dass es sich um ein Array handelt?

Sub Test_Zwei(inp_arr() As Variant)
Debug.Print ist_Wort_in_Array(inp_arr, "hallo")
End Sub
Aber warum ist das dann nicht möglich? (mit Optional)

Sub Test_Zwei(optional inp_arr() As Variant)
Debug.Print ist_Wort_in_Array(inp_arr, "hallo")
End Sub

Anzeige
AW: Array übergeben
24.06.2021 14:00:07
Planlos
Bei VBA vermute ich mal das ein "optional Arr() as ..." mit dem "paramarray vArr() as variant" kolidiert (beide optionale Schlüsselwörter kann man nicht gleichzeitig in einer Funktionsbeschreibung verwenden), weil ein optional übergebenes Array für das schlüsselwort paramarray reserviert ist.
Es hat den gleichen Grund, ...
24.06.2021 18:35:50
Luc:-?
…Flo,
Variante2 kann nicht kompiliert wdn, weil sie bei Prüfung auf Kompilierbarkeit durchfällt. Ein optionaler Parameter darf auch fehlen, ein zwingend vorgeschriebenes Argument aber nicht. Das prüft der Compiler (vergleicht ParameterKopf der SubProz mit ArgumenteKopf der Fktsproz) und stellt so eine NormAbweichung fest.
D.h. nicht, dass es nicht fktionieren könnte*, aber der Compiler geht auf Nr Sicher und verweigert das Kompilieren.
Ein ParamArray ist dagg immer nur als letztes/r Argument/Parameter zulässig und muss alle optionalen Arg/Param enthalten, denn vor ihm dürfen nur erforderliche ExtraArg/-Param aufgeführt wdn. Das könnten dann auch andere Arrays sein.
* Das bemerkt man, wenn man eine solche Fkt (UDF) in einer ZellFml einsetzt. Auch zwingend erforderliche Argumente der Fkt können dann unargumentiert bleiben (ListenTrennZeichen darf aber nicht fehlen!), man muss für diesen Fall nur innerhalb der Fkt Vorsorge treffen. Diese nutzt aber nichts, wenn die Fkt innerhalb einer SubProz aufgerufen wird, denn dann muss an dieser Stelle auch ein zulässiges Argument übergeben wdn (erkennbar aus der SubProz!), sonst wird die SubProz nicht kompiliert.
Luc :-?
Anzeige
AW: Es hat den gleichen Grund, ...
28.06.2021 11:49:10
Flo
Dass der Compiler auf Nr Sicher gehen will, find ich zwar doof, aber kann ich nachvollziehen...
Du schreibst: "Ein optionaler Parameter darf auch fehlen, ein zwingend vorgeschriebenes Argument aber nicht."
Aber das ist doch ein optionaler Parameter in Variante 2, oder?
Also ich verstehe auch, dass er sich beschwert, wie es aktuell aussieht. Nur folgendes funktioniert auch nicht:

Sub Test_Zwei(Optional inp_arr As Variant)
If IsMissing(inp_arr) = True Then Debug.Print ist_Wort_in_Array(inp_arr, "hallo")
End Sub
obwohl das hier ohne Probleme funktioniert:

Sub Test_Drei(Optional str As Variant)
If IsMissing(str) = True Then Debug.Print str
End Sub
Nochmals herzlichen Dank für die ausführliche Antwort! Ich weiß es wirklich sehr zu schätzen, dass sich ein Fremder so viel Zeit nimmt mir etwas zu erklären.
Auch habe ich volles Verständnis, wenn du bzw. ihr dich dem jetzt lange genug gewidmet hast. Danke anyways :)
VG Flo
Anzeige
Eben, ...
28.06.2021 20:57:25
Luc:-?
…Flo,
und weil in der SubProz Var2 der Parameter optional ist, ohne dass im ProzKörper eine Ersetzung durch eine andere Variable vorgenommen wird, die dann an die ein nicht-optionales Argument verlangende Fkt übergeben wird, kann diese SubProz nicht kompiliert wdn! Der Compiler arbeitet ja im Vorhinein und nicht zur LaufZeit. Dafür wäre ein Interpreter zuständig, der zB bei ByName-ReferenzTypen zum Einsatz käme. Die gibt's aber nicht für VBA-ProzKöpfe, sondern nur als Methode innerhalb von ProzKörpern. Deshalb fktioniert das ggf auch bei UDFs in ZellFmln, denn auf dem Xl-Blatt greift ein FmlText-Interpreter ein.
Was das problemlose Fktionieren der SubProz Test_Drei zur (Er-)Klärung beitragen soll, ist mir unklar. Natürlich wird da nicht gemeckert, denn Debug.Print ist herzlich egal, ob die auszugebende Variant-Variable leer ist oder nicht. Im LeerFall gibt sie eben auch nichts (Leerzeile) aus.
Übrigens, If IsMissing(str) = True Then schreiben nur Anfänger, denn IsMissing liefert schon einen Booleschen Wert, der von If … Then auch verlangt und ggf entsprd umgewandelt wird, was hier nicht mal erforderlich ist. Das = True ist also „doppelt gemoppelt“ und somit überflüssig. Im Falle einer auf False aufsetzenden Bedingung schreibt man dann auch besser If Not IsMissing(…) Then.
Gruß, Luc :-?
Anzeige
AW: Eben, ...
30.06.2021 10:04:01
Flo
Super Luc, nochmals besten Dank!!!
Ja... das mit dem isMissing() = True weiß ich eigentlich, aber wenn ich nicht aufmerksam bin, kommt immer wieder mein "alter" Programmierstiel durch. Trotzdem Danke für den Hinweis, genau so kann man sich verbessern! Hab mir alles selbst beigebracht und nie drum gekümmert, was jetzt richtig ist. Hauptsache es funktioniert^^ Aber diese Vorgehensweise versuche ich zu ändern. Für sowas ist ein Luc natürlich besonders hilfreich ;D
Viele Grüße, Flo

Beliebteste Forumthreads (12 Monate)

Anzeige

Beliebteste Forumthreads (12 Monate)

Anzeige
Anzeige
Anzeige