Not numeric middels _KeyDown ipv _Change

Status
Niet open voor verdere reacties.

masala09

Gebruiker
Lid geworden
6 aug 2012
Berichten
886
Onderstaand een code om te zorgen dat er in alle TextBoxen alleen cijfers kunnen worden ingevoerd. Voor de textboxen 9 tot en met 11 mogen er ook enkel punten en komma's toegelaten worden. Deze zijn voor bedragen. Spaties zijn in alle TextBoxen niet toegestaan.

De code werkt, maar ik heb deze naar mijn gevoel omslachtig neergezet.

Wie kan mij correcties geven. Ik zie het even niet meer.

Alvast bedankt.


Code:
Private Sub KeyBoard(Optional ByVal KeyCode As MSForms.ReturnInteger, Optional ByVal Shift As Integer)
    If KeyCode = vbKeySpace Then KeyCode = 0
    
    With activecontrol
            For i = 1 To 7
                If .Name = "TextBox" & i Then            
                    If KeyCode <> 8 And KeyCode <> 9 And KeyCode <> 39 Then
                    If KeyCode < 48 Or KeyCode > 57 Then KeyCode = 0
                    End If
                End If
            Next
    
        If .Name = "TextBox9" And CheckBox1 Or .Name = "TextBox11" And Not CheckBox1 Then
            If .Value <> vbNullString Then
                If KeyCode = vbKeyTab Then Cb_Invoeren.Enabled = True
            End If
        End If
    End With
    
End Sub
 
Laatst bewerkt:
Ik heb de code iets aangepast waardoor deze wel langer wordt. Zie onderstaand.

Code:
Private Sub KeyBoard(Optional ByVal KeyCode As MSForms.ReturnInteger, Optional ByVal Shift As Integer)
    With activecontrol
        For i = 1 To 7
            If .Name = "TextBox" & i Then
                If KeyCode <> 8 And KeyCode <> 9 And KeyCode <> 39 And KeyCode < 48 Or KeyCode > 57 Then KeyCode = 0
            End If
        Next
        
        For i = 8 To 11
            If .Name = "TextBox" & i Then
                If KeyCode <> 8 And KeyCode <> 9 And KeyCode <> 39 And KeyCode < 48 Or KeyCode > 57 _
                    [COLOR="#FF0000"]And KeyCode <> 188 And KeyCode <> 190[/COLOR] Then KeyCode = 0
            End If
        Next
        
        If .Name = "TextBox9" And CheckBox1 Or .Name = "TextBox11" And Not CheckBox1 Then
            If .Value <> vbNullString Then
                If KeyCode = 9 Then Cb_Invoeren.Enabled = True
            End If
        End If
    End With
    
End Sub


Toch blijf ik hangen op een paar kleine punten en ik weet niet wat ik ermee moet.

Voor textbox 1 tot en met 11 geldt feitelijk hetzelfde alleen met het verschil dat voor textbox 9 tot en met 11 ook de komma (keycode 188) en de punt (keycode 190) moet werken. Echter ik kan nu in textbox 9 tot en met 11 meerdere punten en komma's plaatsen. Iets wat met If Not IsNumeric niet kan daar er hier maar 1 komma en 1 punt wordt toegestaan.

Ook heb ik het idee dat de code simpeler kan.

Is er dan niemand die mij kort antwoord kan en of wilt geven.



Aanvullende info over KeyCode zodat het ASCII tabel niet hoeft te worden nageslagen:

KeyCode 8 is BACKSPACE
KeyCode 9 is TAB
KeyCode 39 is PIJLTJE RECHTS
KeyCode 188 is KOMMA
KeyCode 190 is PUNT
KeyCode 48 tot en met Keycode 57 zijn de cijfers 0 tot en met 9.
 
Laatst bewerkt:
Dag masala09 !

In de titel staat o.a. "_KeyDown" en "_Change", dat zijn event-procedures, maar de "Private Sub KeyBoard(...)" is toch geen event-procedure? Dat begrijp ik niet goed.
Maar hier is alleszins een link naar een goede inspiratiebron:

http://www.cpearson.com/excel/TextBox.htm

Grtz,
MDN111.
 
MDN klopt helemaal. Goed dat je het schrijft.

Ik ga met alle textboxen middels het event _KeyDown naar de routine KeyBoard.

Onderstaande even snel een voorbeeldje van 1 van de textboxen.

Code:
Private Sub TextBox10_KeyDown(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
    KeyBoard KeyCode

End Sub
 
Dag masala09 !

De textboxen nrs. 1 t/m 8, van de Userform van het bestand in de bijlage, aanvaarden alleen cijfers.
De textboxen nrs. 9 t/m 11 aanvaarden cijfers, punten en komma's (je kan dat beperken tot één punt en één komma, zoals in de voorbeeld van de "inspiratielink").

Grtz,
MDN111.
 

Bijlagen

  • keyboard.xls
    28 KB · Weergaven: 44
Hoi MDN111,

Dank voor je genomen moeite. Nog voordat ik jouw bericht had gelezen met daarin die link van jou, was ik al redelijk uitgedokterd. Kwam aardig op hetzelfde neer. Die van mij is iets uitgebreider omdat ik nog een aantal extra toetsen zoals de BACKSPACE (8), de TAB(9), de ENTER(13), de ARROW RIGHT(39) en de KOMMA(188) wilde laten werken. Sommige moesten wel daar anders andere zoals de TAB i.v.m. de AutoTab. De ARROW RIGHT i.v.m. de SENDKEYS RIGHT opdracht voor textbox 4 en 7 niet meer werkt.

Dus uiteindelijk kwam ik tot de conclusie dat voor de textboxen 1 tot en met 7 en textboxen 8 tot en met 11 de ene toets wel en de andere weer niet mocht werken. Dit resulteerde in toch 2 coderegels die eerst op elkaar lijken, maar waar toch verschil in zit.

De instructie voor maximaal 1 komma in textboxen 8 tot en met 11, heb ik uiteindelijk zelf bedacht. De punt is komen te vervallen.

Mocht je aanvullingen of verbeteringen zien, ga je gang en ik wacht af. Mijn twijfel ligt nu voornamelijk op het laatste deel speciaal voor textbox9 en 11. Naar mijn idee kan dit anders of nog in een For geplaatst worden.

Code:
Private Sub KeyBoard(Optional ByVal KeyCode As MSForms.ReturnInteger, Optional ByVal Shift As Integer)
    With activecontrol
        For i = 1 To 7
            If .Name = "TextBox" & i Then
                If KeyCode <> 8 And KeyCode <> 9 And KeyCode <> 39 And KeyCode < 48 Or KeyCode > 57 Then KeyCode = 0
            End If
        Next
    
        For j = 8 To 11
            If .Name = "TextBox" & j Then
                If InStr(.Value, ",") Then
                    If KeyCode = 188 Then KeyCode = 0
                End If
                
                If KeyCode <> 8 And KeyCode <> 9 And KeyCode <> 13 And KeyCode <> 39 And KeyCode < 48 Or KeyCode > 57 _
                    And KeyCode <> 188 Then KeyCode = 0
            End If
        Next
        
        If .Name = "TextBox9" And CheckBox1 Or .Name = "TextBox11" And Not CheckBox1 Then
            If .Value <> vbNullString Then
                If KeyCode = 9 Or KeyCode = 13 Then Cb_Invoeren.Enabled = True
            End If
        End If
    End With
    
End Sub
 
Laatst bewerkt:
Dag masala09 !

- De reden voor de For-Next-lussen begrijp ik niet. Je kan de actieve textbox onmiddellijk bepalen aan de hand van de naam.
- Er zit ook redundante code in. De evaluatie van een aantal KeyCodes staat zowel in de eerste als in de tweede lus.
Dit zijn echter maar opmerkingen over elegantie of smaak, als je wil. Dus dat is niet erg.

Zonder de volledige contekst te kennen heb ik getracht je code te testen op het formulier van #5 en daarbij kwamen enkele functionele onvolkomenheden aan het licht:

- Het is niet mogelijk om cijfers in te voeren via het numeriek klavier, doch alleen met de toetsen bovenaan (met de Shift-toets).
- Als je de toetsen bovenaan gebruikt en de Shift-toets niet indrukt dan kan je de andere tekens (& é " ' ( § è ! ç à) invoeren.

Om dat te vermijden moet je ook de Shift-parameter van de KeyDown-procedure gebruiken.

In de nieuwe bijlage vind je een herwerkte Keyboard-procedure die je misschien kan gebruiken.

Grtz,
MDN111.
 

Bijlagen

  • keyboard_09.xls
    44 KB · Weergaven: 44
Laatst bewerkt:
Hai MDN111,

Dank voor jouw reactie. Ik heb jouw code opgeslagen voor toekomstige doeleinden. De wijze van jou bepalen welke textbox actief is, kende ik nog niet. Daar ga ik even mee oefenen en deze eigen maken. De reden dat ik deze nu nog niet verwerk, is omdat voordat ik een code wil gaan gebruiken ik deze ook wil begrijpen al stelt dit volgens mij als ik snel kijk niet heel erg veel voor. Echter ik zal dan ook weer andere routines moeten aanpassen daar ik liever 1 wijze hanteer dan meerdere door elkaar. Gezien dat de For lus zijn werk doet, laat ik het voor dit project even voor wat het is tenzij dit de werking van de code onnodig lang maakt. Ik heb namelijk, al weet ik niet precies wat het doet, wel al uitgevogeld hoe ik de Replace code hierin verwerk.

Uiteraard ben ik ook verder gegaan en kwam ik ook tot de conclusies waar jij mee kwam, nl: Het gebruik van de klavier en de werking van de Shift.

-Mijn toetsenbord heeft geen klavier zodoende heb ik hier geen rekening mee gehouden. Ik heb deze meteen in de code meegenomen.

-De Shift toets had ik voordat jij er mee kwam al opgemerkt en op dezelfde wijze als jou meegenomen in de _KeyDown.

-Jij gebruikt leesbare constanten. Dat mag ook, maar zit daar dan behalve leesbaarheid verder nog verschil in?

Mijn code is nu als volgt:

Code:
Private Sub KeyBoard(Optional ByVal KeyCode As MSForms.ReturnInteger, Optional ByVal Shift As Integer)
    Dim KeyOK_1 As Integer
    Dim KeyOK_2 As Integer
    Dim KeyAll As Integer
    Dim Komma As Integer
    
    KeyOK_1 = KeyCode <> 8 And KeyCode <> 9 And KeyCode <> 13 'Alleen BACKSPACE, TAB en ENTER toestaan
    KeyOK_2 = KeyCode < 48 Or KeyCode > 57 And KeyCode < 96 Or KeyCode > 105 Or Shift = 1
    KeyOK_All = KeyOK_1 And KeyOK_2
    Komma = InStr(activecontrol.Value, ",")

    With activecontrol
        For i = 1 To 7
            If .Name = "TextBox" & i Then
                If KeyOK_All And KeyCode <> 39 Then KeyCode = 0
            End If
        Next

        For j = 8 To 11
            If .Name = "TextBox" & j Then
                If Komma Then 'Zoeken naar een komma
                    If KeyCode = 188 Then KeyCode = 0 'Wanneer komma aanwezig invoeren komma niet meer toestaan
                End If

                If Komma And Len(.Value) >= Komma + 2 Then 'Bij 2 cijfers achter de komma
                    If KeyOK_1 Then KeyCode = 0 'Verdere invoer niet meer toestaan dan behalve KeyOK_1
                End If

                If KeyOK_All And KeyCode <> 188 Then KeyCode = 0
            End If
        Next

        If .Name = "TextBox9" And CheckBox1 Or .Name = "TextBox11" And Not CheckBox1 Then
            If .Value <> vbNullString Then
                If KeyCode = 9 Or KeyCode = 13 Then Cb_Invoeren.Enabled = True
            End If
        End If
    End With

End Sub

Eventuele opmerkingen of aanpassingen mag je graag geven.
Over smaak valt niet te twisten, maar wel is dat het overwegen waard voor andere projecten. Dus nogmaals jouw advies is zeker niet weggegooid. Je kunt nooit alles weten en van elkaar kun je en blijf je leren.:thumb:
 
Laatst bewerkt:
Jouw wijze van bepalen actieve TextBox in onderstaande verwerkt, maar verder nog niet gebruikt. Dit omdat ik deze eerst eigen wil maken, maar toch nieuwsgierig ben of deze dan goed is gebruikt.

Code:
Private Sub KeyBoard(Optional ByVal KeyCode As MSForms.ReturnInteger, Optional ByVal Shift As Integer)
    Dim KeyOK_1 As Integer
    Dim KeyOK_2 As Integer
    Dim KeyAll As Integer
    Dim Komma As Integer
    
    KeyOK_1 = KeyCode <> 8 And KeyCode <> 9 And KeyCode <> 13
    KeyOK_2 = KeyCode < 48 Or KeyCode > 57 And KeyCode < 96 Or KeyCode > 105 Or Shift = 1
    KeyOK_All = KeyOK_1 And KeyOK_2
    Komma = InStr(activecontrol.Value, ",")

    With activecontrol
        i = CInt(Replace(.Name, "TextBox", ""))
    
        If i <= 7 Then
            If KeyOK_All And KeyCode <> 39 Then KeyCode = 0
        End If

        If i >= 8 Then
            If Komma Then 'Zoeken naar een komma
                If KeyCode = 188 Then KeyCode = 0 'Wanneer komma aanwezig invoeren komma niet meer toestaan
            End If

            If Komma And Len(.Value) >= Komma + 2 Then 'Bij 2 cijfers achter de komma
                If KeyOK_1 Then KeyCode = 0 'Verdere invoer niet meer toestaan dan behalve KeyOK_1
            End If

            If KeyOK_All And KeyCode <> 188 Then KeyCode = 0
        End If

        If i = 9 And CheckBox1 Or i = 11 And Not CheckBox1 Then
            If .Value <> vbNullString Then
                If KeyCode = 9 Or KeyCode = 13 Then Cb_Invoeren.Enabled = True
            End If
        End If
    End With

End Sub

Wat begrijp ik niet zal jij je denk ik afvragen.

i = CInt(Replace(.Name, "TextBox", ""))

Jij declareert "i" als integer en geeft deze als variabele: CInt(Replace(.Name, "TextBox", "")).
Vervolgens pak je de te zoeken string: ActiveControl.Name TextBox.
Voor zover volgens mij duidelijk. Echter klopt het dat je hem vervangt voor een lege string?? Want dat lijkt mij sterkt.
Ook vraag ik mij af, waar de opvolgende cijfers blijven achter TextBox. Ik zie enkel dat je deze terughaalt in de rest van de code met bijvoorbeeld: i <=7. Middels: "TextBox" & i, zie ik dit in 1 oogopslag. Echter daar is dan wel weer de For lus voor nodig.

Aanvulling:

Er valt volgens mij een 5 euro munt erg hard op mijn hoofd. Activecontrol.name bevat volledig: TextBox1. Wat jij doet met die code is dat je hier het gedeelte TextBox zoekt en deze verwijderd. Enkel het cijfer 1 blijft dan nog bestaan en dat cijfer wijs jij dan toe aan "i" en daar borduur je weer op verder met bijvoorbeeld: i <=7.

Als dit klopt dan begrijp ik de code en voer ik jouw inbreng meteen in. Dit omdat ik in de rest van het project deze nog niet hebt gebruikt dan wel dit zo is omgezet. Overigens kan Cint weggelaten worden al is het beter om "i" wel te declareren om fouten te voorkomen. Met andere woorden: i = Replace(.Name, "TextBox", "") zou mijn inzien, ook volstaan.
 
Laatst bewerkt:
Het kan ook simpel met:

Code:
Private Sub TextBox1_Change()
   If Not IsNumeric(TextBox1.Text) And Not TextBox1.Text = "" Then TextBox1.Text = Left(TextBox1.Text, Len(TextBox1.Text) - 1)
End Sub
 
Hoi MDN111,

Ik ben eens wezen stoeien met jouw code. Hoe jij hem stelde was voor AllowedForXX. Ik heb de code zelf anders gemaakt en met welke toetsaanslagen niet zijn toegestaan. Zo heb ik hem werkend gekregen. Het stukje met de komma laat ik voor nu achterwege. Daarin heb ik ook nog een aanpassing gemaakt om corrigeren mogelijk te maken. Dit kon eerst niet meer toen er eenmaal 2 cijfers achter de komma stonden. Hiervan moest er minimaal 1 worden verwijderd voordat ik een correctie kon doen. voor nu niet relevant. Deze wijze plaats ik wel even apart. Verder heb ik de toetsen uitgebreid daar ik nog tegen een aantal hiaten aanliep. De pijltoets naar links, , de pijltoets naar rechts en de END toets heb ik ook opgenomen in de variablen. Dit vanwege het feit dat deze nog wel eens makkelijk kunnen zijn bij invoeren en corrigeren van ingevoerde fouten.

De werkende code:

Code:
    Dim Key_NotOK_1 As Integer
    Dim Key_NotOK_2 As Integer
    Dim Key_NotOK_3 As Integer
    Dim Key_NotOK_123 As Integer

    Dim Komma As Integer
    Dim Punt As Integer
    
    Key_NotOK_1 = KeyCode < 48 Or KeyCode > 57 And KeyCode < 96 Or KeyCode > 105 Or Shift = 1
    Key_NotOK_2 = KeyCode <> 9 And KeyCode <> 13 And KeyCode <> 35 And KeyCode <> 39
    Key_NotOK_3 = KeyCode <> 8 And KeyCode <> 37
    Key_NotOK_123 = Key_NotOK_1 And Key_NotOK_2 And Key_NotOK_3
    
    Komma = InStr(activecontrol.Value, ",")
    Punt = InStr(activecontrol.Value, ".")
    
    With activecontrol
        i = Replace(.Name, "TextBox", "")
        
        If i >= 1 And i <= 7 Then
            If i = 1 Then
                Select Case .SelStart
                    Case Is = Punt
                        If Key_NotOK_1 And Key_NotOK_2 Then KeyCode = 0
                    Case Is > Punt
                        If Key_NotOK_123 Then KeyCode = 0
                    Case Is < Punt
                        KeyCode = 0
                        .SelStart = Len(.Value)
                End Select
            End If

Nu ben ik voor het uitproberen eens andersom gaan denken en juist met de toetsaanslagen die WEL zijn toegestaan. Echter dit krijg ik om de één of andere reden niet goed werkend. Ook de SHIFT =1 krijg ik nu niet uitgeschakeld. Vermoedelijk zit ik met de AND of OR verkeerd. Ik heb nu al verschillende zaken uitgeprobeerd maar het lukt mij telkens niet. Zie jij wat ik verkeerd doe? De code als die jij in je laatste post gebruikte werkt sowieso niet. Wel heb ik deze als voorbeeld genomen met andere namen voor de variabelen.

Dit is voor mij gewoon even een oefening. Ik vraag dus niet of de code simpeler of korter kan. De schoonheidsprijs zal voor de opzet van de code niet uitgereikt worden, maar voor mij is deze op deze wijze duidelijk en nog belangrijker werkend. Uiteraard mogen cruciale punten wel genoemd worden.

De niet werkende code:

Code:
    Dim Key_NotOK_1 As Integer
    Dim Key_NotOK_2 As Integer
    Dim Key_NotOK_3 As Integer
    Dim Key_NotOK_123 As Integer
    Dim Komma As Integer
    Dim Punt As Integer
    
    Key_OK_1 = (KeyCode >= 48 Or KeyCode <= 57 Or Shift = 1) Or (KeyCode >= 96 Or KeyCode <= 105)
    Key_OK_2 = KeyCode = 9 Or KeyCode = 13 Or KeyCode = 35 Or KeyCode = 39
    Key_OK_3 = KeyCode = 8 Or KeyCode = 37
    Key_OK_123 = Key_OK_1 Or Key_OK_2 Or Key_OK_3
    
    Komma = InStr(activecontrol.Value, ",")
    Punt = InStr(activecontrol.Value, ".")
    
    With activecontrol
        i = Replace(.Name, "TextBox", "")
        
        If i >= 1 And i <= 7 Then
            If i = 1 Then
                Select Case .SelStart
                    Case Is = Punt
                        If Not Key_OK_1 And Not Key_OK_2 Then KeyCode = 0
                    Case Is > Punt
                        If Not Key_OK_123 Then KeyCode = 0
                    Case Is < Punt
                        KeyCode = 0
                        .SelStart = Len(.Value)
                End Select
            End If

Wat ik wil bereiken is dat onderstaande code tegengesteld hetzelfde gaan doen als de bovenste.

Hoop dat jij of een ander mij dit kan aangeven waar ik fout ga.

Ter info:

8 = BACKSPACE
9= TAB
13= ENTER
35= END
37= PIJLTJE LINKS
39= PIJLTJE RECHTS
48-57= Getallen 0 - 9
96-105= Getallen 0-9 op het Numeriek Klavier
 
Laatst bewerkt:
Oke voor de netheid....... even de werkende code toch wat logischer en minder omslachtig gemaakt.

Code:
Private Sub KeyBoard(Optional ByVal KeyCode As MSForms.ReturnInteger, Optional ByVal Shift As Integer)
    Dim Key_NotOK_1 As Integer
    Dim Key_NotOK_2 As Integer
    Dim Key_NotOK_3 As Integer
    Dim Key_NotOK_123 As Integer
    Dim Komma As Integer
    Dim Punt As Integer
    
    Key_NotOK_1 = KeyCode < 48 Or KeyCode > 57 And KeyCode < 96 Or KeyCode > 105 Or Shift = 1
    Key_NotOK_2 = KeyCode <> 9 And KeyCode <> 13 And KeyCode <> 35 And KeyCode <> 39
    Key_NotOK_3 = KeyCode <> 8 And KeyCode <> 37
    Key_NotOK_123 = Key_NotOK_1 And Key_NotOK_2 And Key_NotOK_3
    
    Komma = InStr(activecontrol.Value, ",")
    Punt = InStr(activecontrol.Value, ".")
    
    With activecontrol
        i = Replace(.Name, "TextBox", "")
        
        If i >= 1 And i <= 7 Then
            If Key_NotOK_123 Then KeyCode = 0
            
            If i = 1 And .SelStart = Punt Or i = 4 And .SelStart = 2 Or i = 7 And .SelStart = 2 Then
                If Key_NotOK_1 And Key_NotOK_2 Then KeyCode = 0
            End If
            
            If i = 1 And .SelStart < Punt Or i = 4 And .SelStart < 2 Or i = 7 And .SelStart < 2 Then
                KeyCode = 0
                .SelStart = Len(.Value)
            End If
        End If
        
        If i >= 8 And i <= 11 Then
            If Key_NotOK_123 And KeyCode <> 188 Then KeyCode = 0
            
            If Komma And KeyCode = 188 Then KeyCode = 0
            
            If Komma And Len(.Value) >= Komma + 2 Then
                If .SelStart >= Komma And Key_NotOK_2 And Key_NotOK_3 Then KeyCode = 0
            End If
        End If

        If i = 9 And CheckBox1 Or i = 11 And Not CheckBox1 Then
            If .Value <> vbNullString Then
                If KeyCode = 9 Or KeyCode = 13 Then Cb_Invoeren.Enabled = True
            End If
        End If
    End With

End Sub

Toch blijft dezelfde vraag, voor oefening, hetzelfde hoe ik deze ook tegenovergesteld kan maken zoals geschreven in post 12.
 
Laatst bewerkt:
In antwoord op jouw onbehouwen 'werkte sowieso niet'...

Getallen invoeren met of zonder punt of komma.
Wijzigen met backspace.
 

Bijlagen

  • __werkt_wel.xlsb
    13,4 KB · Weergaven: 48
Onbehouwen??? Alle respect, maar de code doet precies wat het moet doen. Plussen, minnen en andere tekens zijn niet toegestaan, max 2 cijfers achter de komma en meer niet. Het werkt dus prima.

Als ik jouw stukje probeer dan kan ik in ieder geval een plus en een min invoeren. Daarnaast kunnen er ook meerdere posities achter de komma worden geplaatst alsmede meerdere punten achter elkaar.

Het is maar wat je wilt bereiken. Ik schakel alleen ook knoppen uit op het toetsenbord. Iets wat men aan mij heeft verzocht. Ik doe alleen maar wat mij is opgedragen.

Ik vind persoonlijk jouw bericht onbehouwen overkomen.

Ik laat het hierbij.
 
Laatst bewerkt:
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan