Optionale Arrays als Übergabewerte für Funktionen

  • VB.NET

Es gibt 11 Antworten in diesem Thema. Der letzte Beitrag () ist von JosenOne.

    Optionale Arrays als Übergabewerte für Funktionen

    Hallo zusammen,

    ich arbeite gerade daran eine handvoll UDFs aus Excel-vba mit Hilfe von VB.net in Excel-DNA addins umzuwandeln. Alle Funktionen konnten in vba fehlerfrei ausgeführt werden. Das soll hier nicht weiter thematisiert werden.

    Das hier zu diskutierende Problem soll anhand folgender Funktion gezeigt werden:

    VB.NET-Quellcode

    1. Function GasHumid_phi(ByVal T As Double, ByVal p As Double, ByVal Y As Double, Optional ByVal RngComponents As Object() = Nothing, Optional ByVal RngComposition As Object() = Nothing) As Double
    2. Dim pi As Double
    3. Dim M_H2O, M_air As Double
    4. If RngComponents(0) Is Nothing Then
    5. M_air = 0.0289583
    6. Else
    7. M_air = Gas_M(RngComponents, RngComposition) / 1000
    8. End If
    9. M_H2O = 0.01801528
    10. pi = Y / 1000 * M_air / M_H2O * p / (1 + Y / 1000 * M_air / M_H2O)
    11. GasHumid_phi = pi / Water_ps(T)
    12. End Function


    Der Funktion werden verschiedene Werte übergeben, dazu gehören auch zwei Arrays (RngComponents, RngCompositions) deren Übergabe allerdings optional sein soll.

    Zuerst hatte ich versucht die Funktion wie folgt aufzurufen:

    VB.NET-Quellcode

    1. Function GasHumid_phi(ByVal T As Double, ByVal p As Double, ByVal Y As Double, Optional ByVal RngComponents As Object(), Optional ByVal RngComposition As Object()) As Double


    Hier wird mir Fehlercode BC30812 "Optional parameters must specify a default value." angezeigt.
    Durch verschiedene Foreneinträge bin ich dann bei folgender Darstellung gelandet:

    VB.NET-Quellcode

    1. Function GasHumid_phi(ByVal T As Double, ByVal p As Double, ByVal Y As Double, Optional ByVal RngComponents As Object() = Nothing, Optional ByVal RngComposition As Object() = Nothing) As Double


    Die Funktion kann damit ausgeführt werden, allerdings wird, im Fall dass kein Array übergeben wird, das in folgender Abfrage nicht erkannt:

    VB.NET-Quellcode

    1. If RngComponents(0) Is Nothing Then
    2. M_air = 0.0289583
    3. Else


    Es ist aber essentiell, dass im Fall, dass kein Array übergeben wird die Variable M_air mit dem angegebenen Wert belegt wird.
    Schaue ich mir das Array im debugging an, ist {Length=1} und der Wert wird Stelle (0) mit {Excel.Integration.ExcelMissing} angegeben.

    Anpassen der If-Abrage wie folgt hat keine Verbesserung gebracht:

    VB.NET-Quellcode

    1. If RngComponents(0) Is "{Excel.Integration.ExcelMissing}" Then
    2. If RngComponents(0) Is Excel.Integration.ExcelMissing} Then
    3. If RngComponents(0) Is "Excel.Integration.ExcelMissing" Then
    4. If RngComponents(0) Is "" Then
    5. If RngComponents(0) Is 0 Then



    Im Fall, dass belegte Arrays übergeben werden läuft die Funktion übrigens fehlerfrei und liefert das gewünschte Ergebnis.
    Ich hoffe, dass ich das Problem verständlich beschreiben konnte. Gibt es irgendwelche Lösungsvorschläge von eurer Seite?

    MFG
    Josen

    Verschoben. ~Trade

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „Trade“ ()

    Wo kommt das Array her? Ist dies ein Excel-Range-Object?

    Du solltest prüfen ob das Array Nothing ist und nicht ob der erste Wert des Arrays Nothing ist.
    Des Weiteren sollten beide Array geprüft werde und nicht nur eins.

    Nicht schön aber machbar:

    VB.NET-Quellcode

    1. M_air = 0.0289583
    2. If RngComponents(0) Not Is Nothing Then
    3. M_air = Gas_M(RngComponents, RngComposition) / 1000
    4. End If
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    Hallo INOPIAE,

    danke für die schnelle Rückmeldung!
    Ja, das Array ist, falls dann verwendet, ein Excel-Range-Object.

    Folgendes habe ich jetzt probiert und hat nicht zur Lösung geführt:

    1) Array auf "Nothing" geprüft

    VB.NET-Quellcode

    1. If RngComponents Is Nothing Then
    2. M_air = 0.0289583
    3. Else
    4. M_air = Gas_M(RngComponents, RngComposition) / 1000
    5. End If


    2)

    VB.NET-Quellcode

    1. M_air = 0.0289583
    2. If RngComponents(0) IsNot Nothing Then
    3. M_air = Gas_M(RngComponents, RngComposition) / 1000
    4. End If


    3)

    VB.NET-Quellcode

    1. M_air = 0.0289583
    2. If RngComponents IsNot Nothing Then
    3. M_air = Gas_M(RngComponents, RngComposition) / 1000
    4. End If


    In den Fällen 2 und 3 wird "Nothing" wohl nicht als nothing erkannt und der Befehl in der Abfrage trotzdem ausgeführt.

    Noch der Vollständigkeit halber: was meinst du genau mit "lesbaren Namen", bzw. welcher Name ist hier nicht lesbar? Habe da auf die schnelle in dem genannten Forumeintrag nichts gefunden.
    Wenn es die Arrays Range Objecte sind, dann übergebe diese doch auch als Range-Object.

    VB.NET-Quellcode

    1. ​Function GasHumid_phi(ByVal T As Double, ByVal p As Double, ByVal Y As Double, Optional ByVal RngComponents As Excel.Range = Nothing, Optional ByVal RngComposition As Excel.Range= Nothing) As Double


    Hier findest Du den entsprechende Code für VBA. Den musst Du nur noch umbauen. stackoverflow.com/questions/38…-parameters-for-functions
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).
    Zeig mal ein paar RngComponents Arrays, die du da reinsetzt, wenn du welche reinsetzt. (Wenn also nicht der Default verwendet wird.)

    Ich frag mich außerdem: Ist das Code in VBA oder in .NET?
    Denn du schriebst zu Beginn von beidem.

    Schuss ins Blaue:
    Ich würde mal versuchen einen echten Default zu definieren, wenn das mit den Null-Typen nicht so hinhaut wie geplant.

    VB.NET-Quellcode

    1. Function GasHumid_phi(T As Double, p As Double, Y As Double, Optional RngComponents As Object() = {"Nüscht"}, Optional RngComposition As Object() = {"Nüscht"}) As Double
    2. ...
    3. If RngComponents(0) = "Nüscht" Then M_air = 0.0289583

    Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Ich muss mich korrigieren.
    Schau Dir mal dies an excel-dna.net/docs/guides-basi…-range-parameters-in-udfs
    NB. Es ist doch schön, wenn man lesbare Namen vergibt. Siehe auch [VB.NET] Beispiele für guten und schlechten Code (Stil).

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „INOPIAE“ ()

    Vollzitat eines Vorposts an dieser Stelle entfernt ~VaporiZed

    das
    Hilft erstmal nicht weiter, da ich mit dem Aufruf der Range-Parameter
    aus Excel keine Probleme habe. Die Probleme beginnen erst, wenn ich
    keine Argumente übergebe. Da das Array mit
    "{Excel.Integration.ExcelMissing}" belegt is vermute ich, dass hier
    obwohl kein Range übergeben wird der default Wert "Nothing" mit
    {Excel.Integration.ExcelMissing} überschrieben wird. Für
    {Excel.Integration.ExcelMissing} habe ich noch keine passende Abfrage
    gefunden.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „VaporiZed“ ()

    Ups, ja ein Array kann keine Konstante sein.
    Mach auch mal Option Strict On, sieht man sofort.

    Optional ist mal wieder so eine Sache, die man fast nie benutzt.
    Wie geschieht denn der Aufruf von GasHumid_phi?
    Kannst du da schon unterscheiden, ob Arrays reingehen oder nicht?

    JosenOne schrieb:

    {Excel.Integration.ExcelMissing} habe ich noch keine passende Abfragegefunden.
    kann es sein, dass ExcelDNA.Integration.ExcelMissing eine Klasse ist und brauchst noch eine Instanz?
    Probier mal If RngComponents(0) = ExcelDNA.Integration.ExcelMissing.Value Then
    Und sonstIf RngComponents(0) = ExcelDNA.Integration.ExcelMissing Then
    Kenne ExcelDNA Namespace nicht, aber wenn das geht umso wichtiger, dass du mal Option Strict On schalten solltest, denn das hätte man dann auch sofort gesehen.
    Mit Is werden außerdem nur Nothing oder Zeiger verglichen (Naja Nothing ist auch ein Zeiger bzw. der Nichtzeiger)

    Dieser Beitrag wurde bereits 8 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Vollzitat eines Vorposts an dieser Stelle entfernt ~VaporiZed

    Da möchte ich nochmal drauf eingehen: also 2 und 3 sind Unfug - das ist einigermassen ersichtlich.
    Aber inwiefern hat auch 1 nicht zur Lösung geführt?

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „VaporiZed“ ()

    Fall 3 ist nur die Negation von Fall 1.
    RngComponents ist in diesem Fall ein initialisiertes Array also eben nicht Nothing. Post 1 nach dem 4. Snippet
    Aber warum wurde noch nicht verraten.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Haudruferzappeltnoch“ ()

    Hallo Kollegen, ich habe die Lösung:

    VB.NET-Quellcode

    1. If TypeOf RngComponents Is ExcelMissing Then
    2. M_air = 0.0289583
    3. Else
    4. M_air = Gas_M(RngComponents, RngComposition) / 1000
    5. End If


    Der Parametertyp bei der Übergabe musste noch auf "Object" anstelle von "Object()" gesetzt werden.
    Vielen Dank für eure Unterstützung

    Lg
    Josen