VBA: KeyPress-Routine für 10 Comboxen'auslagern'?

Hi,
folgende Prüfroutine benötige ich in etlichen Comboboxen:
Private Sub cbo01_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
Select Case KeyAscii
Case vbKey0 To vbKey9, vbKeyBack, 44, 46
Case Else
KeyAscii = 0
MsgBox „Nur Zahlen, Punkt und Komma zulässig!“, vbExclamation
End Select
End Sub

Frage an Euch: Muß ich die Prüfroutine in das KeyPress-Ereignis jeder Combobox einfügen, oder gibt es eine Möglichkeit, die Routine für alle Comboboxen in eine ge-meinsame Prozedur „auszulagern“?

Hallo!

Frage an Euch: Muß ich die Prüfroutine in das
KeyPress-Ereignis jeder Combobox einfügen, oder gibt es eine
Möglichkeit, die Routine für alle Comboboxen in eine
ge-meinsame Prozedur „auszulagern“?

Es gibt zwei Varianten. Die erste ist, dass Du eine Funktion schreibst, die analog Deiner Ereignisprozedur den KeyAscii-Wert setzt. Dann musst Du in jede Ereignisprozedur die Zuweisung

KeyAscii = meineKonvertierung(KeyAscii)

schreiben.

Die andere Variante wäre einfacher: Du erzeugst ein Steuerelementefeld, für das Du nur eine Ereignisprozedur benötigst. Du bekommst als Parameter den Index des gerade aktiven Controls, welches Du ja aber ignorieren kannst.

Obwohl, igitt: Redest Du gerade von VB (siehe Forum) oder von VBA (siehe Thread)? Dann (VBA) geht Variante 2 leider nicht.

Also bleibt nur

Function KeyPressNurZahlen(KeyAscii As Integer) As Integer
 Select Case KeyAscii
 Case vbKey0 To vbKey9, vbKeyBack, 44, 46 
 KeyPressNurZahlen = KeyAscii
 Case Else
 KeyPressNurZahlen = 0
 MsgBox "Nur Zahlen, Punkt und Komma zulässig!", vbExclamation
 End Select
End Function

Private Sub cboXXX\_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
 KeyAscii = KeyPressNurZahlen(KeyAscii)
End Sub

Aber Du hast immer noch eine (immer noch identische) Ereignisprozedur für alle Komboboxen…
Gruß, Manfred

Also bleibt nur

Function KeyPressNurZahlen(KeyAscii As
Integer) As Integer
Select Case KeyAscii
Case vbKey0 To vbKey9, vbKeyBack, 44, 46
KeyPressNurZahlen = KeyAscii
Case Else
KeyPressNurZahlen = 0
MsgBox „Nur Zahlen, Punkt und Komma zulässig!“,
vbExclamation
End Select
End Function

Private Sub cboXXX_KeyPress(ByVal KeyAscii As
MSForms.ReturnInteger)
KeyAscii = KeyPressNurZahlen(KeyAscii)
End Sub

Hi,
ich habe vorhin den Code eingebaut. Beim Eingeben des ersten Zeichens in die Box erscheint folgende Fehlermeldung:

„Fehler beim Kompilieren - Argumenttyp ByRef unverträglich“

Was mache ich falsch?

Gruss Wilhelm

Hallo Wilhelm,

Private Sub Combo1_KeyPress(KeyAscii As Integer)
KeyAscii = KeyPressNurZahlen(KeyAscii)
End Sub

Private Sub Combo2_KeyPress(KeyAscii As Integer)
KeyAscii = KeyPressNurZahlen(KeyAscii)
End Sub

Function KeyPressNurZahlen(KeyAscii As Integer) As Integer
Select Case KeyAscii
Case vbKey0 To vbKey9, vbKeyBack, 44, 46
KeyPressNurZahlen = KeyAscii
Case Else
KeyPressNurZahlen = 0
MsgBox „Nur Zahlen, Punkt und Komma zulässig!“, vbExclamation
End Select
End Function

Functioniert einwandfrei :smile:

Aber einfacher geht es wenn du ein Control mit dem Index 0 erstellst und dann 9 weitere Controls mit dem Index 1 -9 dann schreibe einfach

Private Sub Combo1_KeyPress(Index As Integer, KeyAscii As Integer)
Select Case KeyAscii
Case vbKey0 To vbKey9, vbKeyBack, 44, 46
KeyPressNurZahlen = KeyAscii
Case Else
KeyPressNurZahlen = 0
MsgBox „Nur Zahlen, Punkt und Komma zulässig!“, vbExclamation
End Select
End Sub

Somit hast du 1 Prozedur die dir alle Combo Boxen prüft :smile: VLG Alex

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Hi,
mich packt die reine Verzweiflung: Beide von Euch angebotenen Alternativen habe ich sowohl unter Windows NT als auch unter Windows XP Home Edition getestet. Es erscheinen die jeweils unter REM von mir eingefügten Fehlermeldungen. Könnt Ihr mir noch irgendwie weiterhelfen? Ich würde den Code so gut gebrauchen können:

Option Explicit
Alternative 1:
Function KeyPressNurZahlen(KeyAscii As Integer) As Integer
Select Case KeyAscii
Case vbKey0 To vbKey9, vbKeyBack, 44, 46
KeyPressNurZahlen = KeyAscii
Case Else
KeyPressNurZahlen = 0
MsgBox „Nur Zahlen, Punkt und Komma zulässig!“, vbExclamation
End Select
End Function

Private Sub cboXXX_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
KeyAscii = KeyPressNurZahlen(KeyAscii)
End Sub

Rem *** Fehler beim Kompilieren - Argumenttyp ByRef unverträglich ***


Private Sub cboXXX_KeyPress(KeyAscii As Integer)
Rem *** Ereignisprozedurdeklaration entspricht nicht der Beschreibung eines Ereignisses mit demselben Namen ***
KeyAscii = KeyPressNurZahlen(KeyAscii)
End Sub

Function KeyPressNurZahlen(KeyAscii As Integer) As Integer
Select Case KeyAscii
Case vbKey0 To vbKey9, vbKeyBack, 44, 46
KeyPressNurZahlen = KeyAscii
Case Else
KeyPressNurZahlen = 0
MsgBox „Nur Zahlen, Punkt und Komma zulässig!“, vbExclamation
End Select
End Function

Gruss Wilhelm

Hallo Wilhelm,

sodele wollen wir mal :smile:

Also in dem 2 Bsp. war es so das da normale Comboboxen eingesetzt waren :S Diese Sub sollte erscheinen bei einen Doppelclick auf die Combobox :smile: Dadurch du die erste mit dem Index 0 erstellst und die anderen dann fortlafd. nummerierst bekommst du nur die Prozedur. Bedenke aber das das normale Comboboxen sind.
Am einfachsten ist es eine auf die Form zu ziehen dann STRG +C und dann STRG +V sooft du magst :wink:
Meine Variante geht da da der Wert Keypress als Referenz uebergeben wird und somit geaendert werden kann.

Zu Deinem ersten Beispiel:

Private Sub cboXXX_KeyPress(ByVal KeyAscii As
MSForms.ReturnInteger)

Das Byval gibt an das der Wert Keyascii nur gelesen werden kann aber nicht geaendert werden kann. dies kann man nur wenn der Wert als Byref übergeben wird. Du kannst die untenstehende Prozedur folgend aufrufen
KeyAscii = KeyPressNurZahlen(byvalKeyAscii)

aber dann meckert er spätestens bei der Zuweisung

KeyPressNurZahlen = KeyAscii
Case Else
KeyPressNurZahlen = 0

in der anderen Prozedur rum, da du den Wert als Byval übergeben hast, also nicht aenderbar.

Wie du siehst klappt dein Vorhaben so nicht :frowning:

Aber eine andere Variante ist es, sich der Function Sendkeys zu schaffen machen. dabei musst du aber ein wenig mehr tippseln.
Mache das dann wiefolgt.

Private Sub cboXXX_KeyPress(KeyAscii As Integer)
KeyPressNurZahlen keyAscii
End Sub

Private sub KeyPressNurZahlen(KeyAscii As Integer)
Select Case KeyAscii
Case vbKey0 To vbKey9, vbKeyBack, 44, 46
exit sub
Case Else
sendkeys „{BS}“
MsgBox „Nur Zahlen, Punkt und Komma zulässig!“, vbExclamation
End Select
End Function

Funktionsprinzip:

in der Combobox wird eine Taste gedrueckt. diese wird dann in der Combobox angezeigt. Es wird sofort die zu prüfende Prozedur aufgerufen.
Ist die Eingabe OK so wird diese Prozedur gleich verlassen, wenn nicht dann wird die Taste Backspace an das selektierte Steuerelement ( was ja die Combobox ist) geschickt und somit das eingegebene Zeichen gelöscht. danach wird die Meldung angezeigt und die zu prüfende Prozedur verlassen :smile:

Ich hoffe du konntest verstehen was ich meine :smile:

VLG Alex

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]

Erläuterung ByVal und Byref
Hallo Wilhelm,

anbei noch schnell eine Erklärung

ByRef-Parameter
Eine Parameter-Übergabe „By Reference“ bedeutet, dass die Adresse der übergebenen Variable an die Prozedur übergeben wird. Die Prozedur kann dadurch auf den Originalwert der Variable operieren, und daher auch den Inhalt ändern.

Gekennzeichnet wird ein solcher Parameter durch das Schlüsselwort ByRef. Bis einschließlich VB6 ist dies übrigens die Default-Methode der Parameter-Übergabe, daher kann die Deklaration aus obigem Beispiel auch so geschrieben werden:

Function Beispiel(ByRef n As Long) As Long

Ich empfehle dringend, dieses Schlüsselwort zu nutzen. Einerseits wird die Art der Parameter-Übergabe besser Dokumentiert, d.h. der Anwender der Prozedur ist „vorgewarnt“, dass sich eventuell die Inhalte seiner Parameter-Variablen ändern können. Andererseits wird ab VB7 (VB.NET) die Default-Methode „By Value“ sein!

Wichtiger Hinweis: Da bei Nutzung von „By Reference“ nur Adressen bewegt werden, müssen die Datentypen der Übergabe-Variablen und des Parameters exakt übereinstimmen. Dies wird von VB streng kontrolliert (Fehlermeldung 13, „Type mismatch“) und zwar vor dem Aufruf, da ansonsten „Allgemeine Schutzverletzungen“ die Folge wären (Weitere Gründe für Variablen-Deklarationen: „Pfui oder Hui? - Schöner programmieren!“).

ByVal-Parameter
Bei einer „By Value“ Parameter-Übergabe erzeugt VB erst eine komplette Kopie des Parameter-Werts. Die Prozedur operiert also immer auf eine Kopie des Parameters, der Originalwert der Variablen ist also sicher vor Veränderungen.

Gekennzeichnet wird ein solcher Parameter durch das Schlüsselwort ByVal. Ändern wir die obige Parameter-Deklaration auf „By Value“, also

Function Beispiel(ByVal n As Long) As Long

Wichtiger Hinweis: Objekt-Variablen enthalten intern sowieso nur einen Zeiger auf das Objekt. Daher ist es egal, welche Methode hier zur Parameter-Übergabe verwendet wird: Die Eigenschaften des Objekts sind in der Prozedur immer änderbar.

Tipps zur Verwendung
Da ByVal erst eine Kopie der Parameter macht, ist diese Methode sicher vor unerwünschten Nebenwirkungen. Allerdings kostet das Kopieren Zeit, insbesondere bei umfangreichen Parametern (z.B. langen Strings). Daher empfehle ich die Nutzung von ByRef aus folgenden Gründen:

Der Parameter muss verändert werden können, da er einen Rückgabewert liefern soll.
Es werden (lange) Strings übergeben. (Ausnahme: In der Prozedur wird sowieso eine Kopie des Strings benötigt, siehe Beispiel.)
Der Parameter ist eine Objekt-Instanz.
Die Nutzung von ByRef zur Beschleunigung der Parameter-Übergabe bei einfachen Datentypen wie z.B. Long ist sinnlos, da in diesen Fällen die Kopie (hier 4 Bytes) nicht größer ist, als die zu bewegende Adresse (immer 4 Bytes)! Dieses gilt im Wesentlichen auch für die anderen Datentypen (Integer, Single, …).

Hinweis: Sie können einen „By Reference“-Parameter beim Aufruf durch einfache Klammerung der zu übergebenen Variable in einen „By Value“-Parameter umwandeln. Im folgenden Beispiel ist x sicher vor jeder Veränderung, d.h. egal wie die Funktions-Parameter deklariert sind, der Aufruf verhält sich wie bei ByVal:

Function Beispiel((n)) As Long

VLG Alex

Hallo Alex,

Du hast Dir so viel Mühe mit mir gegeben! Aber: Deine formulierte Hoffnung, ich hätte verstanden, was Du meinst, ist leider umsonst. Darf ich Dir einfach mal meine Form per email schicken, damit Du diesen Code, der ja für Wissende offenbar allersimpelst ist, einbaust und die wer-weiss-was-Gemeinde sich nicht noch mehr über mein Nichtwissen aufregen muß? Herzlichen Dank auf jeden Fall schon mal für Deinen großen, wenn auch z.Zt. noch nicht erfolgreichen Einsatz.

Gruss
Wilhelm

Hallo Wilhelm,

habe dir eben eine E - Mail geschrieben :smile:

VLG Alex

[Bei dieser Antwort wurde das Vollzitat nachträglich automatisiert entfernt]