Enums - intelligent!

.. das wohl mächtigste Werkzeug in Bill Gates' Büro-Sippe. Ob reine Formeln, PowerQuery oder VBA. Hier bleiben kaum Wünsche unerfüllt.
Benutzeravatar
thowe
Beiträge: 209
Registriert: 12. Sep 2022, 16:57
Hat sich bedankt: 79 Mal
Danksagung erhalten: 67 Mal
Kontaktdaten:

Enums - intelligent!

#1

Beitrag von thowe »

Hallo an alle!

Ich spiele derzeit mit Enums. Ich bin davon überzeugt, dass Enumerations den Code lesbarer machen.
Hier ein Beispiel - mit ein paar weiteren "Helpers" (als Zugabe...)

In diesem Beispiel wird für .Cells (row, Column) bei Columns die Enumeration verwendet anstatt die Spaltennummer, oder Spaltenbuchstabe

Bitte beachtet auch die Namenskonventionen: für Module immer Plural (also mit angehängtem "s" am Ende), Subs, Functions und Enums immer Singular. Weiters bei Variablen, camelCase, und vor allem - wenn geht - "sprechende" Variablenamen.

Modul: modEnums

Code: Alles auswählen

'-------------------------------------------------------------
'
' purpose:      Enumerations of Columns in the Sheet 
'                    "wksSession"
' @params:      -
' @return:      -
' author:       thowe, Thomas Weber
' @version:     1.0.6
' @depreciated: None
' @source:      inspired by Excel Macro Mastery
'
'-------------------------------------------------------------

Public Enum eColumnSession
    ecNone = 0
    [_First] = 1
    ecNumber = [_First]
    ecDatum
    ecUhrzeit
    ecVermittler
    [_Last]
End Enum
Modul: modSessions

Code: Alles auswählen

'-------------------------------------------------------------
'
' purpose:      populates Session data into the specified
'               Columns. The columns are enumerated in the
'               Modul "modEnum"
' @params:      -
' @return:      -
' author:       thowe, Thomas Weber
' @version:     1.0.6
' @depreciated: None
' @source:      inspired by Excel Macro Mastery
'
'-------------------------------------------------------------

Sub WriteDataToSheetSession(intRow As Integer)
    
    Dim varDate As Variant 'Variable: The actual Date
    Dim VarTime As Variant 'Variable: The actual Hour
    
    'initialize
    varDate = Date
    VarTime = Time
    
    
    With wksSession
        .Cells(intRow, ecNumber) = intRow - 1
        .Cells(intRow, ecDatum) = varDate
        .Cells(intRow, ecUhrzeit) = VarTime
        
    End With

End Sub
Die kleinen Helferleins:
Modul: modSheetHelpers

Code: Alles auswählen

'-------------------------------------------------------------
'
' purpose:      Check if the targeted Worksheet exists
' @params:      strSheetName, objWorkbook
' @return:      Boolean
' author:       thowe, Thomas Weber
' @version:     0.0.9
' @depreciated: None
' @source:
'
'-------------------------------------------------------------

Function WorksheetExists(strSheetName As String, Optional objWorkbook As Excel.Workbook) As Boolean

    Dim objWorkSheet As Excel.Worksheet
    
    
    If objWorkbook Is Nothing Then Set objWorkbook = ThisWorkbook
    On Error Resume Next
    Set objWorkSheet = objWorkbook.Sheets(strSheetName)
    On Error GoTo 0
    WorksheetExists = Not objWorkSheet Is Nothing
    'reset, unset, delete
    
    Set objWorkSheet = Nothing
    Set objWorkbook = Nothing

End Function

'-------------------------------------------------------------
'
' purpose:      get the SheetName of the targeted Worksheet by
'               CodeName of the Sheet
' @params:      strSheetCodeName, objWorkbook
' @return:      Boolean
' author:       thowe, Thomas Weber
' @version:     0.0.9
' @depreciated: None
' @source:
'
'-------------------------------------------------------------


Function GetSheetNameByCodeName(strSheetCodeName As String, Optional objWorkbook As Excel.Workbook) As String

    Dim wksSheet As Excel.Worksheet
    Dim strSheetName As String
    
    'initialize
    strSheetName = ""
    If objWorkbook Is Nothing Then Set objWorkbook = ThisWorkbook
    
    
    For Each wksSheet In objWorkbook.Worksheets
        If wksSheet.CodeName = strSheetCodeName Then
            strSheetName = wksSheet.Name
            Exit For
        End If
        
    Next
    
    If Not strSheetName = "" Then GetSheetNameByCodeName = strSheetName
    'reset, unset, delete
    
    Set objWorkbook = Nothing
    
End Function


Der Trigger (Auslöser des Events)
Prinzipell löse ich den Dateneintrag mit dem Event "Workbook_BeforeClose(Cancel As Boolean)" aus

Klasse: DieseArbeitsmappe

Code: Alles auswählen

'-------------------------------------------------------------
'
' purpose:      Before cloing ThisWorkbook we populate some
'               data into the Worksheet "wksSession"
' @params:
' @return:
' author:       thowe, Thomas Weber
' @version:     0.0.9
' @depreciated: None
' @source:
'
'-------------------------------------------------------------

Private Sub Workbook_BeforeClose(Cancel As Boolean)

    Dim intLastRow As Integer 'Variable: the first empty row in Sheet "wksSession"

    If WorksheetExists("wksSession") Then 'Call the Helper WorksheetExist in modWorksheets
        intLastRow = GetLastRow("wksSession") + 1 '+1: add 1 to get the next empty row
        Call WriteDataToSheetSession(intLastRow - 1) '-1: this representates the counter (=total number of entries in wksSession)
    
    End If

End Sub
Bitte beachtet, ich bin Autodidakt und uralt aber enthusiastisch...

LG
Benutzeravatar
d'r Bastler
Beiträge: 683
Registriert: 29. Aug 2022, 13:20
Hat sich bedankt: 177 Mal
Danksagung erhalten: 91 Mal

Re: Enums - intelligent!

#2

Beitrag von d'r Bastler »

Moin Thomas,

erstmal herzlichen Dank für die super Helferleins!

Ich muss Dich dazu allerdings mit der Bitte um ein wenig Erläuterung belästigen. Für meine bisherigen Herausforderungen hatte ich noch keinen Bedarf, mich an anderen Variablen als den üblichen Verdächtigen zu betätigen. Nicht einmal, dass ich z.B. eine const deklarieren musste, weil ich gerade die Änderbarkeit zur Laufzeit so sehr schätze und statische Aufzählungen so ganz gegen das Konzept der variablen spricht.

Was ich glaube aus ein wenig Literatur zum Thema verstanden zu haben, ist, dass man mit diesen Aufzählungen bequem auf Listen mit fixen Werten als .Eigenschaft einer Enum zugreifen kann, wie man das z.B. mit den Farbwerten/Indizes für Cells.Interior., die der VBE dort als Intellisense-Liste anbietet. Also habe ich mal ein bisschen herumprobiert:

Code: Alles auswählen

Option Explicit
Enum Population
    Ghana = 30.79
    Mali = 19.55
    Benin = 12.1
End Enum

Sub EnumTest()
Dim vPop
vPop = Population.Mali
MsgBox vPop
End Sub
und tatsächlich erscheinen die Population.Eigenschaften wie in der Enum vorbereitet. Soweit also schon mal erfolgreich. In einer Erläuterung hatte ich gelesen, dass Enum-Werte nicht in Verbindung mit With genutzt werden können, was sich aber durch einen Test
With ActiveSheet _ .Cells(1,1) = vPop _ End with
widerlegen ließ. Aber dennoch gibt es wohl deutliche Einschränkungen in dieser Technik: Erstens werden die jetzt in der Enum hinterlegten Werte in der Ausgabe gerundet, egal ob ich die Zielvariable als Double oder String definiere. Zweitens hatte ich anfangs versucht, statt der Bevölkerung bekannte Musikernamen zuzuordnen. Strings werden aber schon mal per se nicht akzeptiert. Eine bessere Übersichtlichkeit kann ich so nicht erkennen.

Damit fällt mir im Moment nicht eine sinnvolle Verwendung dieser Technik ein, lasse mich gerne eines Besseren belehren - bin nämlich auch ziemlich automenthusiatisch. Nachdem ich aber überzeugt bin, das Du das Thema sinnvoll einsetzen kannst: Vielleicht machst Du einen entsprechendes Tutorial daraus?

Schöne Grüße!
Folgende Benutzer bedankten sich beim Autor d'r Bastler für den Beitrag:
thowe
d'r Bastler von den VBAsteleien.de
Win 10 + Office 2019 & Win11 + Office 2021 + Visio 2019 pro & macOS.X15 + Office2019pro & Android12 & XL365
Benutzeravatar
thowe
Beiträge: 209
Registriert: 12. Sep 2022, 16:57
Hat sich bedankt: 79 Mal
Danksagung erhalten: 67 Mal
Kontaktdaten:

Re: Enums - intelligent!

#3

Beitrag von thowe »

Hallo d'r Bastler

Der Vorteil liegt mit der Intellisense beim Coden und ist der Code meines Erachtens auch lesbarer
Folgend ein paar Spielereien

Code: Alles auswählen


Option Explicit

Enum ePopulation
    [_First]
    epNone = 0
    epGhana = 30.79
    epMali = 19.55
    epBenin = 12.1
    [_Last]
End Enum

Enum eCountry
    [_First]
    ecNone
    ecGhana
    ecMali
    ecBenin
    [_Last]
End Enum

Sub EnumLoop()
    Dim population As ePopulation
    For population = [_First] To [_Last]
        Debug.Print population
    Next
End Sub
Sub EnumConditions()
    Dim population As ePopulation
    population = epBenin
    If population = epBenin Then
        Debug.Print "Benin formerly known as Dahomey"
    ElseIf population = epGhana Then
        'nothing else yet
    Else
        'nothing else yet
    End If
End Sub

Function CalculateShippingCosts(amount As Currency, country As eCountry) As Currency

    Select Case country
        Case ecGhana: CalculateShippingCosts = amount * 0.11
        Case ecMali: CalculateShippingCosts = amount * 0.21
        Case ecBenin: CalculateShippingCosts = amount * 0.015
        Case Else: MsgBox "Invalid Country"
    End Select
    
End Function
Sub TestCaCalculateShippingCosts()
    Debug.Print CalculateShippingCosts(100, ecBenin)
End Sub

Sub PlayEnumWith()
    Dim population As ePopulation
    
    'This occurs an Error
    With population
        If population = epBenin Then Debug.Print "Benin formerly known as Dahomey"
    End With
End Sub

Vor allem bei der Eingabe von

Code: Alles auswählen

Debug.Print CalculateShippingCosts(100, ecBenin)
unterstützt die Intellisense ungemein....

LG aus dem Schnitzelland
Folgende Benutzer bedankten sich beim Autor thowe für den Beitrag:
d'r Bastler
Benutzeravatar
d'r Bastler
Beiträge: 683
Registriert: 29. Aug 2022, 13:20
Hat sich bedankt: 177 Mal
Danksagung erhalten: 91 Mal

Re: Enums - intelligent!

#4

Beitrag von d'r Bastler »

Moin Thomas,

Dank für Deine Erläuterungen! Ich fürchte allerdings, dass unsere Ansichten zum Thema übersichtlicher Code sich doch deutlich unterscheiden. Für mich bleibt nur der von Dir genannte Vorteil des individuell konfigurierbaren IntelliSense übrig, den ich mal kurz nach meinem Konzept nachgebaut habe: mithilfe einer simplen Userform und drei Mini-Arrays als Datenfutter. Anders als beim IntelliSense reagiert die genutzte ComboBox schon auf jedes eingegebenes Zeichen, reduziert auf die tatsächlich benötigten Werte.

Aufwand : eine kleine Userform mit 25 Zeilen Code (10 Minuten) und ein Modul mit knapp 10 Zeilen Code (5 Minuten). Die Control und Variablen-Benennungen folgen in etwa Deinem Schema, sind aber auch leicht nachvollziehbar. Die USF öffnet sich beim Start der Mappe automatisch. (Ooops noch drei Zeilen, schäm!!)

Viel Spaß!
Simple Data.xlsb
(18.19 KiB) Noch nie heruntergeladen
d'r Bastler von den VBAsteleien.de
Win 10 + Office 2019 & Win11 + Office 2021 + Visio 2019 pro & macOS.X15 + Office2019pro & Android12 & XL365
Benutzeravatar
thowe
Beiträge: 209
Registriert: 12. Sep 2022, 16:57
Hat sich bedankt: 79 Mal
Danksagung erhalten: 67 Mal
Kontaktdaten:

Re: Enums - intelligent!

#5

Beitrag von thowe »

Hallöchen,

dann nehme ich dir ein wenig die Furcht...

2 Anwendungsbeispiele:

1. "zentrales" Festlegen der Schriftgrößen

Code: Alles auswählen

Enum eFontSize
    efXXL = 24
    efXL = 18
    efL = 16
    efM = 12
    efS = 10
    efXS = 8
End Enum
Sub SetFontSize()
    ActiveCell.Font.Size = eFontSize.efM
End Sub
2. "zentrales" Festlegen der verwendeten Farben

Code: Alles auswählen

Enum eRGBColors
    'note the scheme of colors is BBGGRR and not RRGGBB (=RGB) with hex-values
    eBlack = &H383330 'Hex(#303338)
    eGreen = &H34843A 'Hex(#3A8434)
    eRed = &H34209E   'Hex(#9E2034)
End Enum

Sub SetColor()
    ActiveCell.Interior.Color = eColorsHex.eGreen
End Sub
Das kann sowohl für Arbeitsblätter als auch für Userforms verwenden.
Ich denke mir, dass dies das Schreiben und Lesen (auch mit dem Hintergedanken ein paar Jahre Später) leichter macht. Man muss sich nicht die Schriftgröße merken, nicht die Hex und/oder RGB Werte der Farben...

LG
Folgende Benutzer bedankten sich beim Autor thowe für den Beitrag:
d'r Bastler
Benutzeravatar
d'r Bastler
Beiträge: 683
Registriert: 29. Aug 2022, 13:20
Hat sich bedankt: 177 Mal
Danksagung erhalten: 91 Mal

Re: Enums - intelligent!

#6

Beitrag von d'r Bastler »

Moin Thomas,

ein englischer Beitrag, der Dir sicher Spaß machen wird:

https://stackoverflow.com/questions/563 ... m-with-vba

Diese enums mag ich mal gleich auch :D

Grüße
d'r Bastler von den VBAsteleien.de
Win 10 + Office 2019 & Win11 + Office 2021 + Visio 2019 pro & macOS.X15 + Office2019pro & Android12 & XL365
Sulprobil
Beiträge: 22
Registriert: 23. Sep 2022, 05:54
Hat sich bedankt: 3 Mal
Danksagung erhalten: 14 Mal
Kontaktdaten:

Re: Enums - intelligent!

#7

Beitrag von Sulprobil »

Hallo,

IntelliSense ist natürlich hilfreich.

Ich verwende gern
Private Enum xlCI 'Excel Color Index
: xlCIBlack = 1: xlCIWhite: xlCIRed: xlCIBrightGreen: xlCIBlue '1 - 5
: xlCIYellow: xlCIPink: xlCITurquoise: xlCIDarkRed: xlCIGreen '6 - 10
: xlCIDarkBlue: xlCIDarkYellow: xlCIViolet: xlCITeal: xlCIGray25 '11 - 15
: xlCIGray50: xlCIPeriwinkle: xlCIPlum: xlCIIvory: xlCILightTurquoise '16 - 20
: xlCIDarkPurple: xlCICoral: xlCIOceanBlue: xlCIIceBlue: xlCILightBrown '21 - 25
: xlCIMagenta2: xlCIYellow2: xlCICyan2: xlCIDarkPink: xlCIDarkBrown '26 - 30
: xlCIDarkTurquoise: xlCISeaBlue: xlCISkyBlue: xlCILightTurquoise2: xlCILightGreen '31 - 35
: xlCILightYellow: xlCIPaleBlue: xlCIRose: xlCILavender: xlCITan '36 - 40
: xlCILightBlue: xlCIAqua: xlCILime: xlCIGold: xlCILightOrange '41 - 45
: xlCIOrange: xlCIBlueGray: xlCIGray40: xlCIDarkTeal: xlCISeaGreen '46 - 50
: xlCIDarkGreen: xlCIGreenBrown: xlCIBrown: xlCIDarkPink2: xlCIIndigo '51 - 55
: xlCIGray80 '56
End Enum
Aber allgemein nutze ich Enums für Spaltennummerierungen, damit sich der Programmcode bei Änderungen automatisch anpasst - siehe z. B.
https://www.sulprobil.com/sbgenerateteams_en/

Viele Grüße,
Bernd
Benutzeravatar
thowe
Beiträge: 209
Registriert: 12. Sep 2022, 16:57
Hat sich bedankt: 79 Mal
Danksagung erhalten: 67 Mal
Kontaktdaten:

Re: Enums - intelligent!

#8

Beitrag von thowe »

Hallo Bernd,

danke für deinen Beitrag,
JA! Auch bei mir der Hauptanwendungsfall..... (Spaltennummerierungen)

LG
Folgende Benutzer bedankten sich beim Autor thowe für den Beitrag:
Sulprobil
Benutzeravatar
d'r Bastler
Beiträge: 683
Registriert: 29. Aug 2022, 13:20
Hat sich bedankt: 177 Mal
Danksagung erhalten: 91 Mal

Re: Enums - intelligent!

#9

Beitrag von d'r Bastler »

Moin! Ihr intelligente Numeratoren ;)

Jetzt habe ich endlich einen für mich überzeugenden Anwendungsfalls für eNums gefunden und prompt scheitert's an der Fehlermeldung Konstanter Ausdruck erforderlich. Mist!

Was habe ich vor? Für den dynamischen Aufbau von Sheets zur Datenerfassung benötige ich einige mathematische Zeichen, wie z.B. die Doppel-Tilde (ungefähr gleich), ein PlusMinus (Toleranzbereich), u.Ä. Für die Doppel-Tilde gilt ChrW(8776), was ich auch prima z.B. aus einem Array in das Sheet einfügen kann.

Also habe ich mir für's Erste ein Mini-eNum eSymb gebastelt, das sich auch prima im IntelliSense wiederfindet:

Code: Alles auswählen

Enum eSym
 DoppelTilde = ChrW(7668)    'alternativ: =sDT (siehe unten)
End Enum
Klappt aber eben nicht. Selbst wenn ich zusätzlich eine Public Const cTD = ChrW(7668) definiere, mault der VBE.

Gibt es einen Trick eine Liste von individuellen Symbolen in ein eNum zu schreiben und dann per IntelliSense einzufügen?

Liebe Grüße und ebensolchen Dank!
d'r Bastler von den VBAsteleien.de
Win 10 + Office 2019 & Win11 + Office 2021 + Visio 2019 pro & macOS.X15 + Office2019pro & Android12 & XL365
Benutzeravatar
thowe
Beiträge: 209
Registriert: 12. Sep 2022, 16:57
Hat sich bedankt: 79 Mal
Danksagung erhalten: 67 Mal
Kontaktdaten:

Re: Enums - intelligent!

#10

Beitrag von thowe »

Hallo Heb,

Enum (eine Aufzähöung) ist eine Liste von benannten ganzen Zahlen, die als gemeinsamer Typ deklariert sind. Enum-Typen werden verwendet, um eine Gruppe von Elementen darzustellen, die durch ein Konzept miteinander verbunden sind, wie z. B. eine Liste von Farben, wie ich bereits in einem Post davor gezeigt habe (#2 Pkt. 2)

------------------------------------------
Ergänzende Anmerkung zu Enum
------------------------------------------
  • Enum-Namen müssen eindeutig sein und können innerhalb desselben Bereichs nicht neu definiert werden.
  • Enum-Namen können nicht als Variablen, Objekte oder Prozedurnamen verwendet werden.
  • Ein Enum-Name kann als Argument für Prozeduraufrufe verwendet werden, einschließlich anderer Enum-Namen.
  • Enum-Konstanten können in Ausdrücken verwendet werden, außer bei Verwendung einiger mathematischer Operatoren
Was auch eine denkbare Einsatzmägichkeit ist sind eigene Erros: zB:

Code: Alles auswählen

Enum MyErrors
    DataNotFound = 1001
    DataInvalid = 1002
    UpdateFailed = 1003
    '...
End Enum

Antworten

Wer ist online?

Mitglieder in diesem Forum: Semrush [Bot] und 0 Gäste