Osaako kukaan neuvoa:
Minulla on esimerkiksi TextBoxeja Txt_luku_1, Txt_luku_2, ... Txt_luku_n ja aliohjelmia esimerkiksi Txt_luku1_Change jne.
jokainen xxx_Change -tapahtuma lukee ko. TextBoxin arvon yleiseen muuttujaan ja samainen xxx_Change -tapahtuma käynnistää aliohjelman SubLuvunTarkistus jossa tarkistetaan että annettu merkkijono (yleisen muuttujan arvo) on numero eikä se sisällä esim. kirjaimia. Tämän jälkeen palataan xxx_Change -koodiin jossa ko. TextBox tyhjennetään jos merkkijono ei ollut kelvollinen ja tehdään muitakin temppuja jotka ovat täysin samanlaisia jokaisen TextBoxin kohdalla.
Voinko mitenkään siirtää myös tuon TextBoxin nimen tms. julkisessa muuttujassa aliohjelmaan SubLuvunTarkistus että voisin välttyä kirjoittamasta samanlaista koodia useaan kertaan?
Minulla on esimerkiksi TextBoxeja Txt_luku_1, Txt_luku_2, ... Txt_luku_n ja aliohjelmia esimerkiksi Txt_luku1_Change jne.
jokainen xxx_Change -tapahtuma lukee ko. TextBoxin arvon yleiseen muuttujaan ja samainen xxx_Change -tapahtuma käynnistää aliohjelman SubLuvunTarkistus jossa tarkistetaan että annettu merkkijono (yleisen muuttujan arvo) on numero eikä se sisällä esim. kirjaimia. Tämän jälkeen palataan xxx_Change -koodiin jossa ko. TextBox tyhjennetään jos merkkijono ei ollut kelvollinen ja tehdään muitakin temppuja jotka ovat täysin samanlaisia jokaisen TextBoxin kohdalla.
Voinko mitenkään siirtää myös tuon TextBoxin nimen tms. julkisessa muuttujassa aliohjelmaan SubLuvunTarkistus että voisin välttyä kirjoittamasta samanlaista koodia useaan kertaan?
Vastaukset 15
Vanhimmat
Jos ymmärsin oikein niin pitääkö sinun kirjoittaa jokaiseen textboxiin koodi, esim?:
Private Sub Txt_luku_1_Change
Luku=Txt_luku_1.Txt
LuvunTarkistus
End Sub
Private Sub Txt_luku_2_Change
Luku=Txt_luku_2.Txt
LuvunTarkistus
End Sub
.
.
.
jne.
Onko tuo nyt niin hankalaa jollei textboxeja ole kymmenittäin?
Olethan tietysti määritellyt muuttujan "Luku" moduulin yläosan määrittelyosassa jolloin muuttuja on moduulikohtainen ja pysyvä.
vaan pikemminkin näin:
Private Sub Txt_luku_1_Change
Luku=Txt_luku_1.Txt
Call LuvunTarkistus
Temppu 1 TextBoxin 1 luvulle
Temppu 2 TextBoxin 1 luvulle
...
Temppu n TextBoxin 1 luvulle
End Sub
Private Sub Txt_luku_2_Change
Luku=Txt_luku_2.Txt
Call LuvunTarkistus
Temppu 1 TextBoxin 2 luvulle
Temppu 2 TextBoxin 2 luvulle
...
Temppu n TextBoxin 2 luvulle
End Sub
eli "samanlaisia" koodirivejä on yli kymmenen ja Textboxejakin on yli kymmenen...
Luku on nimenomaan määritetty julkiseksi, eli Public Luku as Integer, muuten ei toimi.
Haluat siis välittää muuttujan "Luku" arvon proseduureille LuvunTarkistus. Mitä nämä "Temppu 1...n" on? Jos ne on käskyrivejä niin sisällytä ne proseduurin "LuvunTarkistus".
Muuttujan "Luku" arvon voit välittää proseduurille "LuvunTarkistus" vaikkapa näin:
Private Sub Txt_luku_1_Change
Luku=Txt_luku_1.Txt
Call LuvunTarkistus Luku 'P.S Call käskyä ei tarvita
.
.
.
Sub LuvunTarkistus(Dim TämänSubinLuku as Var)
'Varianttina koska ei tiedetä onko "Luku" tekstia vai luku
.
.
.
Kirjoitit:
>Luku on nimenomaan määritetty julkiseksi, eli Public Luku as Integer, muuten ei toimi.<
Ohjelma kaatuu heti jos "Luku" on määritelty Integer ja TextBox:iin kirjoitetaan tekstiä.
Haluaisinkin sisällyttää nuo käskyrivit proseduuriin "Luvun tarkistus". Ongelma on nyt siinä, Että en tuolla "Luvun tarkistuksessa" enää tiedä mistä ComboBoxixta arvo on peräisin ennen kuin palaan sieltä takaisin ko. proseduuria kutsuneeseen proseduuriin. Alla esimerkkinä parin proseduurin koodi (Txt_Luku_n -proseduureja on tällä hetkellä 10 kappaletta ja "LuvunTarkistusta" kutsutaan monesta muustakin kohtaa):
Public Toiminto As String, Luku As String
Private Sub Txt_Luku_1_Change()
Luku = Txt_Luku_1.Value
Toiminto = "PituusTarkistus"
Call LuvunTarkistus
If Luku = "0" Or Luku = "" Then
Txt_Luku_1.Value = ""
Exit Sub
Else
Txt_Luku_1.Value = Luku
End If
Luku = Empty
Toiminto = "AktivoiSarakkeet"
Call AktivoiSarakkeet
Call LaskePituudet
Txt_Luku_1.SetFocus
Call LaskeVirta
Call LaskeJännite
End Sub
Sub LuvunTarkistus()
Dim Ohjeteksti As String
Select Case Toiminto
Case "Virta"
Ohjeteksti = "Virta voi olla vain positiivinen luku välillä 1...99."
Case "Pituustarkistus"
Ohjeteksti = "Pituus voi olla vain positiivinen luku välillä 1...9999."
Case "Teho"
Ohjeteksti = "Teho voi olla vain positiivinen luku välillä 1...999."
Case Else
End Select
If IsNumeric(Luku) Then
If Luku = 0 Then MsgBox Ohjeteksti, 48, "Syöttämäsi merkkijono ei kelpaa ! ! !"
Else
If Luku Empty Then
Luku = ""
MsgBox Ohjeteksti, 48, "Syöttämäsi merkkijono ei kelpaa ! ! !"
End If
End If
End Sub
Haluaisin siis tuolla "LuvunTarkistuksessa" tietää sen että Luku on juuri tällä kertaa peräisin TextBoxixta Txt_Luku_1, tai Txt_Luku_2 tai Cbo_Arvo_8 siten että tuo Txt_Luku_1 olisi vaikka muuttujan "LähdeCombo" -arvo ja voisin kirjoittaa vaikkapa näin:
LähdeCombo.Value = ""
Nyt ei onnistu vaan joudun aina palaamaan alunperin "luvunTarkistusta" kutsuneeseen proseduuriin jossa teen tietyt temput.
PS. kirjoitin aluksi väärin, "Luku" on tosiaan Integer.
Välitä proseduuriin LuvunTarkistus myös tieto mistä comboboxista tieto on. Esim
Private Sub Txt_Luku_1_Change()
Dim Luku as Variant
Luku = Txt_Luku_1.Value
Toiminto = "PituusTarkistus"
Call LuvunTarkistus Luku, 1 'Luku 1 tarkoitaa että se on tullut juuri tästä proseduurista
.
.
.
Sub LuvunTarkistus (Luku as Variant, TxNro as integer)
.
.
.
Ennen kaikkea muuttuja "Luku" pitää määritella varianttina!
Kaunis kiitos sinulle, hienoa oppia jotain uutta. Tein näin:
Private Sub Txt_Luku_1_Change()
LuvunTarkistus Luku, 1
End Sub
Private Sub Txt_Luku_2_Change()
LuvunTarkistus Luku, 2
End Sub
LuvunTarkistus (Lähde as Variant)
Dim Kenttä As Variant
Kenttä = Array(Empty, Txt_Luku_1, Txt_Luku_2)
If Kenttä(Lähde).Value = "0" Then
koodia
koodia
.
.
koodia
End Sub
sulla on kutsussa 2 argumenttiä
LuvunTarkistus Luku, 1
ja kutsu proseduurissa vain 1
LuvunTarkistus (Lähde as Variant)
Tosiaan, kopioin koodin vahingossa jostakin testailukoodista (en ole kovin hyvä ohjelmoimaan, täytyy aina välillä kokeilemalla koodata. Toimiva kutsu menee siis näin:
Private Sub Txt_Luku_1_Change()
LuvunTarkistus 1
End Sub
Private Sub Txt_Luku_2_Change()
LuvunTarkistus 2
End Sub
Nyt tein näin:
Private Sub Txtbox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
NumeronSyöttö 1, KeyAscii
End Sub
Private Sub Txtbox2_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
NumeronSyöttö 2, KeyAscii
End Sub
Sub NumeronSyöttö(Lähde As Variant, KeyAscii As MSForms.ReturnInteger)
Dim Syöttökenttä As Variant
Syöttökenttä = Array(Empty, Txtbox1, Txtbox2)
If Syöttökenttä(Lähde).Value = Empty And KeyAscii = Asc("0") Then KeyAscii = 0
Select Case KeyAscii
Case Asc("0") To Asc("9")
Case Else
KeyAscii = 0
End Select
End Sub
mutta voisiko tehdä jollakin tavalla tähän tapaan:
Private Sub Txtbox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger, ByJotakinMuuta1 As JotakinMuuta2)
NumeronSyöttö KeyAscii, ArgumenttiTxtboxNimi
End Sub
Private Sub Txtbox2_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger, ByJotakinMuuta1 As JotakinMuuta2)
NumeronSyöttö KeyAscii, ArgumenttiTxtboxNimi
End Sub
Sub NumeronSyöttö(KeyAscii As MSForms.ReturnInteger, JotakinMuuta1 As JotakinMuuta2)
If JotakinMuuta1.Value = Empty And KeyAscii = Asc("0") Then KeyAscii = 0
Select Case KeyAscii
Case Asc("0") To Asc("9")
Case Else
KeyAscii = 0
End Select
End Sub
Voiko myös TxtBoxin nimen viedä argumenttina toiseen proseduuriin noiden "JotakinMuuta" avulla?
Kyllä sun selvityksesi on aika sekava, mutta jos nyt välttämättä sitä nimeä sinne haluat niin OK...
kirjoita
TextBox1 Tagin(ominaisuudet) arvoksi TextBox1
TextBox2 Tagin(ominaisuudet) arvoksi TextBox2 jne...
sitten koodissa käytät
Me.Controls.Item(0).Tag textbox 1
Me.Controls.Item(1).Tag textbox 2 jne...
olettaen ,että olet lisännyt niitä "oikeassa järjestyksessä"
esim.
Sub NumeronSyöttö(KeyAscii As MSForms.ReturnInteger, Nimi As String)
MsgBox "tulit " & Nimi & " tekstiruudusta"
Select Case KeyAscii
Case Asc("0") To Asc("9")
Case Else
KeyAscii = 0
End Select
End Sub
Private Sub Textbox1_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
NumeronSyöttö KeyAscii, Me.Controls.Item(0).Tag
End Sub
Private Sub Textbox2_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
NumeronSyöttö KeyAscii, Me.Controls.Item(1).Tag
End Sub
selvittikös tää nyt mitään sulle?
@Kunde
Ja ymmärrän mitä olen vailla.
Käyttöliittymässäni on hieman yli kaksikymmentä TextBoxia, joihin sallitaan syötettäväksi vain numeroita, ja vielä siten että nollaa ei hyväksytä ensimmäiseksi numeroksi.
Myös jos TextBoxissa on vaikkapa luku "10" ja joku keksii maalata tästä numeron "1" ja painaa sitten "0", olisi lopputuloksena "00" siitä huolimatta että nollaa ei hyväksytä ensimmäisenä numerona. Tämän takia siinä tapauksessa että TextBoxin arvo on "0" tai "00" tai "000" jne., Ko. TextBoxin sisältö tyhjennetään.
Nyt koodissani selvitän sen, minkä TextBoxin arvoa tarkastellaan tuon Muuttuja=Array(jne.jne.)
avulla, mutta olisihan se kätevää jos sen saisi selville ilman tuota Array-juttua koska esimerkiksi tällainen rivi:
Syöttökenttä = Array(Empty, Pituus_0_1, Pituus_0_2, Pituus_0_3, Pituus_0_4, Pituus_1_1, Pituus_1_2, Pituus_1_3, Pituus_1_4, Txt_P1_1, _
Txt_P1_2, Txt_P1_3, Txt_P1_04, Pituus_04_1, Pituus_04_2, Pituus_04_3, Pituus_04_4, Txt_P04_1, Txt_P04_2, Txt_P04_3, Txt_P04_4)
on mielestäni aika sekava ja TextBoxeja lisätessä tulee helposti virheitä.
Kiitän kauniisti avustasi ja pyydän anteeksi että olen vasta aloittelija eivätkä kaikki termit yms. ole minulle tuttuja.
Private Sub TextBox1_Change()
tarkasta Me.OLEObjects("TextBox1")
End Sub
Private Sub TextBox2_Change()
tarkasta Me.OLEObjects("TextBox2")
End Sub
Sub tarkasta(ByRef mika As OLEObject)
If Val(mika.Object) > 5 Then mika.Object = ""
End Sub
vaikuttaa mielenkiintoiselta, täytyypä kokeilla. Kiitos :)
Hieman toisenlainen lähestymistapa
Tietämättä tarkemmin projektiasi, niin voit varmistaa, että tekstiruutuun ei voi syöttää kuin numeerista tietoa ja esim. pilkun tutkimalla mitä näppäintä on painettu.
Itselläni on allaoleva koodi käytössä monissa CNC ohjelmissa, kun pitää varmistaa, että kenttään voi syöttää vain lukuja
Private Sub TxtLeveys_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
If InStr(1, TxtLeveys.Text, ",") > 0 And KeyAscii = Asc(",") Then ' tarkistetaan ettei kirjoiteta 2 pilkkua
' muuta pilkku pisteeksi jos käytät desimaalierottimena pistettä
KeyAscii = 0
Exit Sub
End If
Select Case KeyAscii
Case Asc("0") To Asc("9"), Asc(",") ' tässä voit valita mitä merkkejä voidaan syöttää
Case Else
KeyAscii = 0
End Select
End Sub
lisäksi käytössäsi on myös IsNumeric funktio, jota voisi käyttää esm. AfterUpdate tapahtumassa
Mielenkiintoinen koodi sinulla, kiitoksia paljon.
PS. Lisätietoja projektistani näät otsikon "Juuri Niin" alta.