Probleme in VBA mit der UCase Function

Ich habe ein Programm in VBA geschrieben um in Excel den U-Wert eines Bauteils zu berechnen. Dazu muss das Programm die Wärmeleitzahl und die Dicke der einzelnen Schichten im Bauteil kennen.
Zusätzlich fragt das Programm den Baustoff der einzelnen Schichten ab und ordnet sie der variable k zu, damit die Zahlen in der Tabelle den Baustoffen zugeordnet werden können.
Ich dachte mir, dass es ja umständlich ist, wenn man für jeden einzelnen Baustoff immer die Wärmeleitzahl in Tabellen suchen muss, also habe ich eine Function geschrieben, die anhand einer Tabelle den Baustoffen die Wärmeleitzahl automatisch zuordnet. Dazu wird Die Bezeichnung des Baustoffs, die ja schon abgefragt wurde in die Function übergeben und dort mittels eines Select Case Befehls den entsprechenden Wärmeleitzahlen zugeordnet.
Das Problem ist, wenn der eingegebene Baustoff in der Groß- und Kleinschreibung nicht den Baustoffen in der Tabelle entspricht, wird der Fall in der Tabelle übergangen und die Wärmeleitzahl nicht zugeordnet.

Ich dachte eigentlich, dass ich das mit der UCase Function beheben kann.
Dann würde ich in der Tabelle alles Groß schreiben und in der Sub, nach der Zuordnung des Baustoffs zur variable k schreiben: UCase(k)
Dann müsste der Text in der Variable k ja eigentlich groß sein und es dürfte keine Probleme mehr geben, wenn k an die Function übergeben wird.

Funktioniert aber nicht. Wenn die Variable k die Ucase Function durchlaufen hat, dann ist der text in Variable k immer noch klein geschrieben.
Woran liegt das?
 
Ich habe ein Programm in VBA geschrieben um in Excel den U-Wert eines Bauteils zu berechnen.
[...]
Funktioniert aber nicht. Wenn die Variable k die Ucase Function durchlaufen hat, dann ist der text in Variable k immer noch klein geschrieben.
Woran liegt das?
Ich vermute mal, an der falschen Verwendung von UCase.

Nun aber mal ernsthaft... woher sollen wir das wissen, wenn du nicht eine Zeile Code postest?!
 
Ich vermute mal, an der falschen Verwendung von UCase.

Nun aber mal ernsthaft... woher sollen wir das wissen, wenn du nicht eine Zeile Code postest?!

Das Problem ist, dass wir an der FH ein VBA Schulungsprogramm bekommen haben. In dem Programm hat unser Prof viele Befehle umbenannt. Das Fach ist Bauinformatik, es geht dem Prof denke ich eher darum uns die Logik des Programmierens näher zu bringen, deswegen haben wir halt dieses Programm bekommen, was diese einfachereren Befehle verwendet.
Aber ich kann den Code ja trotzdem mal posten. Ich denke die meisten Befehle erklären sich aufgrund ihres Namen von selbst. Und das Programm an sich Funktioniert ja auch, nur halt dieses UCase nciht.

Code:
Public Sub U_wert()
Dim x, k As String, kk, n, nn, i, j, s, q, Rsi, w
'x=Anzahlder Schichten, b=Baustoff der Schichten, kk=Dicke Schicht,n=Wärmeleitzahl,nn=wärmewiderstand,i=Schleifenindex,j=Schleifenindex,q=Wärmestromrichtung,Rsi=Konstanter Übergangswiderstand innen
öffne_lösch_Tabelle "Ergebnis"

'Fragt die Zahl der Schichten ab
tipp_ein x, "Wie viele Schichten hat das Bauteil?"
If Not (Entspricht_Ganzzahl(x)) Then GoTo Fehler_a
        
        'erzeugt das farbige Fenster in der richtigen Größe
        For i = 1 To 6
                    Zeile_Spalte_Zellenfarbe 1, i, 41
                Next i
        For i = 1 To 6
            For j = 2 To x + 6
                Zeile_Spalte_Zellenfarbe j, i, 15
            Next j
        Next i
    
    'Fügt fester Tete und Werte ein
    Cells(1, 2) = "Baustoff"
    Cells(1, 3) = "Dicke"
    Cells(1, 4) = "Wärmeleitzahl"
    Cells(1, 5) = "Wärmewiderstand"
    Cells(2, 2) = "Rsi"
    Cells(x + 3, 2) = "Rse"
    Cells(x + 3, 5) = 0.04
    
        'Ermittelt den richtigen Rsi Wert
        tipp_ein q, "Ist der Wärmestrom (1)Aufwärts, (2)Horizontal oder (3)Abwärts gerichtet?"
        Groß (q)
        Select Case q
            Case 1
                Rsi = 0.1
            Case 2
                Rsi = 0.13
            Case 3
                Rsi = 0.17
            Case Else
                GoTo Fehler_b
            End Select
            
        Cells(2, 5) = Rsi
    
    'Sonderfall es gibt nur eine Schicht im Bauteil
    Select Case x
        Case 1
            tipp_ein_Text k, "Aus welchem Material ist das Bauteil?"
            UCase (k)
            tipp_ein kk, "Wie Dick ist das Bauteil?"
                                
            nn = kk / WL(k)
             
            Cells(3, 2) = k
            Cells(3, 3) = kk
            Cells(3, 4) = WL(k)
            Cells(3, 5) = nn
    
            s = nn
                  
        Case 2 To 10
            tipp_ein_Text k, "Aus welchem Material ist die erste Schicht im Bauteil?"
            UCase (k)
            tipp_ein kk, "Wie Dick ist die erste Schicht?"
                For i = 1 To 6
                    Zeile_Spalte_Zellenfarbe 1, i, 41
                Next i
            
            Cells(3, 2) = k
            Cells(3, 3) = kk
            Cells(3, 4) = WL(k)
            nn = kk / WL(k)
            Cells(3, 5) = nn
            s = nn
                For i = 2 To x
                    tipp_ein_Text k, "Aus welchem Material ist die nächste Schicht im Bauteil?"
                    UCase (k)
                    tipp_ein kk, "Wie Dick ist die nächste Schicht?"
                    Cells(i + 2, 2) = k
                    Cells(i + 2, 3) = kk
                    Cells(i + 2, 4) = WL(k)
                    nn = kk / WL(k)
                    Cells(i + 2, 5) = nn
                    s = s + nn
                Next i
    End Select
           
    
    Zeile_Spalte_Schriftfarbe x + 5, 4, 3
    Zeile_Spalte_Schriftfarbe x + 5, 5, 3
    Cells(x + 5, 4) = "U-Wert"
    Cells(x + 5, 5) = 1 / (s + Rsi + 0.04)

Exit Sub
Fehler_a:
    Beep
    MsgBox ("Nur ganze Zahlen möglich")
Fehler_b:
    Beep
    MsgBox ("Erlaubte Eingaben:1,2,3")
End Sub



Public Function WL(k)
Dim n, ww
'k=Baustoff, n=Wärmeleitzahl, ww=Wärmeleitzahlmaximal
        Select Case k
        
        'Baustoffe
        Case "Stahl unlegiert"
            WL = 48
            'ww = 58
        Case "Stahl niedrig legiert"
            WL = 42
        Case "Stahl hochlegiert"
            WL = 15
        Case "Granit"
            WL = 2.8
        Case "Beton"
            WL = 2.1
        Case "Zementstrich"
            WL = 1.4
        Case "Kalkzement-Putz"
            WL = 1
        Case "Glas"
            WL = 0.76
        Case "Mauerziegel"
            WL = 0.5
            'ww = 1.4
        Case "Holz"
            WL = 0.09
            'ww = 0.19
        Case "Gummi"
            WL = 0.16
        Case "Poroton"
            WL = 0.08
            'ww = 0.45
        Case "Porenbeton"
            WL = 0.08
            'ww = 0.25
        Case "Lehm"
            WL = 0.47
            'ww = 0.93
        Case "Sand"
            WL = 0.58
        Case "Sandstein"
            WL = 2.3
        Case "Mamor"
            WL = 2.8
        Case "Kalkstein"
            WL = 2.2
        Case "Epoxidharzmörtel mit 85 % Quarzsand"
            WL = 1.2
        'Dämmstoffe
        Case "Aerogel"
            WL = 0.02
        Case "Schaumglas"
            WL = 0.04
        Case "Glasschaum-Granulat"
            WL = 0.08
        Case "Glaswolle"
            WL = 0.032
            'ww = 0.05
        Case "Stroh"
            WL = 0.038
            'ww = 0.067
        Case "expandiertes Polystyrol"
            WL = 0.035
            'ww = 0.05
        Case "extrudiertes Polystyrol"
            WL = 0.032
            'ww = 0.04
        Case "Polyethylen"
            WL = 0.0034
            'ww = 0.04
        Case "Polyurethan"
            WL = 0.024
            'ww = 0.035
        Case "Vakuumdämmplatte"
            WL = 0.004
            'ww = 0.006
        Case "Kork"
            WL = 0.035
            'ww = 0.046
        Case "Wolle"
            WL = 0.035
        Case "Perlit"
            WL = 0.04
            'ww = 0.07
        Case "Mineralwolle"
            WL = 0.035
            'ww = 0.045
        Case Else
            tipp_ein WL, "Wärmeleitzahl"
    End Select
            
End Function
 
In dem Code wird die UCase-Funktion zwar aufgerufen, aber der Rückgabewert von UCase wird nicht behandelt. Die Routine arbeitet also mit dem alten Variablenwert weiter.

So wäre es richtig:
Code:
Dim x as String
x = UCase("test")     'x beinhaltet nun "TEST"
 
Aber wenn ich den Text als Argument in den UCase Befehl setzen muss, wie kann ich dann unterscheiden?

Also ich will ja, dass das Programm, wenn ich z.B. Granit als Baustoff eingebe per WL Function die zugehörige Wärmeleitzahl raussucht.
Das klappt auch, so lange ich Granit schreibe und nicht gRanit.
Deswegen wollte ich ja in der Tabelle in der Function alle Baustoffe groß schreiben und dann den inhalt von k per UCase auch vergrößern.
Wenn ich jetzt aber k=UCase(gRanit) schrieben muss, dann funktioniert es ja nciht, wenn ich dann z.B. Mineralwolle eingebe.
Oder muss ich jetzt nach der EIngabeaufforderung von k eine richtig umständliche case select schreiben?
Also so in der Art.

Code:
Select Case k
        
        Dim k As String

        Case "Stahl unlegiert"
            k = UCase("Stahl unlegiert")
        Case "Stahl niedrig legiert"
            k = UCase("Stahl niedrig legiert")
        Case "Stahl hochlegiert"
            k = UCase("Stahl hochlegiert")
        Case "Granit"
            k = UCase("Granit")
        Case "Beton"
            k = UCase("Beton")
        Case "Zementestrich"
            k = UCase("Zementestrich")
        Case "Kalkzement-Putz"
            k = UCase("Kalkzement-Putz")
        .................

Ist es überhaupt vernünftig das so zu machen? Also ich meine, dass man die Wärmeleitzahl durch so eine Function zuordnet in der es so eine Tabelle gibt.

Mein Wunsch wäre es, dass es eine Prozedur eine Tabelle beinhaltet, in der alle Stoffkenngrößen dem Stoff zugeordnet sind, also nicht nur die Wärmeleitzahl, sondern auch Werte wie z.B. Dichte oder Biegefestigkeit. So dass ich mit verschiedenen Programmen auf die Prozedur zugreifen kann, und die Prozedur mir halt immer die erforderlichen Stoffkenngrößen ausgibt.
Ich habe aber keine Idee, wie ich sowas anstellen könnte, da eine Function ja immer nur einen Wert ausgibt.
 
Mein Beispiel war einfach allgemein formuliert. Du kannst Variablen verwenden, wie du willst bzw. sie benötigst. Eine Variable ist ja, grob gesagt, nichts weiter als ein Container für einen Wert. Und ob du nun die Variable k der Funktion übergibst, oder Variable F oder direkt den Wert (z.B. "test") ist der Funktion egal.

Code:
Dim x as String
Dim y as String
x = "TeSt"
y = UCase(x)
Wäre auch eine Möglichkeit. Bzw in deinem Fall:
Code:
Dim x as String
x = UCase(k)
Und danach arbeitest du mit x statt mit k.

Evtl. geht in VBA auch folgendes Konstrukt (nicht getestet):
Code:
k = UCase(k)
Soweit ich mich erinnere arbeitet VBA den Code von rechts nach links ab. Das heißt er wertet erst UCase(k) aus und überschreibt k mit diesem neu berechneten Wert. Mit dieser Variante müsstest du die wenigsten Änderungen am Code vornehmen.

Wie du letzendlich dein Programm strukturierst bleibt dir überlassen. Da führen bekanntlich 1000 Wege nach Rom. Allerdings sollten Funktionen immer so minimalistisch wie möglich sein. Größere Arbeiten erledigt man in Prozeduren und Routinen und kleinere, immer wiederkehrende Arbeiten lagert man in Funktionen aus.
 
Zuletzt bearbeitet von einem Moderator:
Alles klar, jetzt klappt es. Vielen Dank =)

Jetzt habe ich aber gleich 2 neue Fragen.

Das Programm ruft die Funktion mehrere Male auf z.B. hier

Code:
Cells(3, 4) = WL(k)
            nn = kk / WL(k)
Also halt einmal um WL(k) auszugeben und einemal um damit den Wärmewiderstand zu berechnen.

Wenn in die Funktion ein k eingegeben wird, was auch in der Tabelle vorkommt, merkt man das gar nicht, aber ich habe ja in die Function als Case Else gesetzt, dass man dann die Wärmeleitzahl selbst eingeben muss. Das muss man dann aber 2 mal hintereinander, was ziemlich nervig ist.
Kann man das irgendwie umgehen?

Und meine 2. Frage bezieht sich darauf, dass du sagtest, dass man größere Sachen nciht in eine Function packt, sondern in Prozeduren und Routinen. Was sind Prozeduren und Routinen? Wo kann ich solche Dinge, von denen ich mal denke, dass sie eigentlich Basiswissen sind im Programmieren, nachlesen? Und wie kann ich, wenn ich z.B. die Tabelle in eine Prozedur schreibe und da mehrere Werte zu jedem Baustoff gespeichert habe, die Prozedur von meiner Sub aufrufen?
 
Naja, da Funktionen meist für wiederkehrende Aufgaben gedacht sind, baut man normalerweise solch' ein Error-Handling an dieser Stelle auch nicht ein. Lass dir im Case Else-Zweig einfach 0,-1 oder 9999 oder sonst eine Zahl zurückgeben, sodass du weißt, dass es sich um einen Error-Wert handelt und behandel diesen außerhalb der Funktion.
Außerdem macht es mehr Sinn die zurückgegebenen Daten zwischenzuspeichern, statt die Funktion ständig neu aufzurufen, wenn sich k nicht geändert hat.

Aus deinem Beispiel:
Code:
Dim Result as String
[i]'Programmiere WL so, dass -1 zurückgegeben wird, wenn nichts passt[/i]
Result = WL(k)
[i]'Überprüfen ob WL -1 zurückgeliefert hat[/i]
If Result = "-1" Then
  [i]'Falls ja, lass den Benutzer einen Wert eingeben[/i]
  tipp_ein WL, "Wärmeleitzahl"
  [i]'Weise der Variable Result den eingegebenen Wert zu[/i]
  Result = Wärmeleitzahl
End If
[i]'Arbeite mit Result weiter...[/i]
Cells(3, 4) = Result
nn = kk / Result
Entweder liefert die Funktion eine passende Wärmeleitzahl zurück, oder -1. Wenn -1 zurückgeliefert wird, muss der Benutzer eine Zahl eingeben und diese Zahl wird in Result gespeichert. So kannst du danach mit Result weiterarbeiten und es hat auf jeden Fall eine Wärmeleitzahl bzw. den Benutzer einmalig aufgefordert eine Zahl einzugeben.

Und meine 2. Frage bezieht sich darauf, dass du sagtest, dass man größere Sachen nciht in eine Function packt, sondern in Prozeduren und Routinen. Was sind Prozeduren und Routinen?
In VBA bezeichnet man Funktionen und Sub's als Prozeduren. Routinen sind quasi Unterprogramme, die nur eine Teilaufgabe bewältigen.

Als Beispiel (auf VBA bezogen):
Du hast mehrere Buttons mit unterschiedlichen Aufgaben. Jeder ruft eine andere Sub-Prozedur auf. Eine Sub-Prozedur liest nun in einer Schleife nacheinander Werte aus einer Spalte aus, übergibt diese Werte nacheinander an eine Funktion, die etwas damit macht und einen anderen Wert zurückliefert. Diese andere Werte sollen nun in einer anderen Spalte ausgegeben und zudem einer ComboBox hinzugefügt und sortiert werden.
Da man das Hinzufügen von Elementen zu einer ComboBox und das Sortieren derselbigen auch für andere Buttons gebrauchen könnte, würde es unter Umständen Sinn machen, diese Code in eine eigene Sub-Prozedur auszulagern, damit man ihn (genau wie eine Funktion) mehrfach aufrufen kann. Eine Funktion ist dafür jedoch unnötig, da man keinen Rückgabewert braucht.
Diese ausgelagerte Sub-Prozedur, die nur eine Teilaufgabe löst, würde man als Routine bezeichnen.

Auf die Schnelle hab ich zu VBA dieses Openbook gefunden. Vielleicht hilft's dir ja auf die Sprünge. ;)
 
Zurück
Oben