Textbox ไม่หยุดรอให้ key ข้อมูล
กระทู้เก่าบอร์ด อ.Yeadram

 3,024   15
URL.หัวข้อ / URL
Textbox ไม่หยุดรอให้ key ข้อมูล

ขอความกรุณาช่วยดูให้หน่อยครับ

Private Sub Text29_LostFocus()
before_ent:
                 Me.Text29.SetFocus

     If Len(Text29) <> 4 Then GoTo incorrect
            For i = 1 To 4
     If IsNumeric(Mid(Text29, i, 1)) = False Then GoTo incorrect
            Next
        -
        -
        -
ในกรณีที่ตรวจสอบการ key ข้อมูลแล้วไม่ถูกต้อง ต้องการให้เคอร์เซอร์ไปรอการ key ใน Textbox (Text29) ที่ผมใช้ GoTo before_ent แต่มันไม่เป็นอย่างนั้น มันไม่หยุดรอการ key จึงกลายเป็นการไปติด loop ออกไม่ได้ครับ ผมอาจเขียน code ผิดก็ได้หรืออาจเข้าใจคุณสมบัติของ Textbox ผิดก็ได้ ช่วยแนะนำหน่อยครับ
        -
        -

incorrect:
        -
        -


End Sub

15 Reply in this Topic. Dispaly 1 pages and you are on page number 1

1 @R14405
ไม่ค่อยเข้าใจโค๊ดนะครับ แต่หากเข้าใจไม่ผิด น่าจะเป็นเรื่องที่เจอกันบ่อยๆครับ เป็นธรรมชาติของโปรแกรมจะอ่านคำสั่งไปเลยๆ โดยไม่สนว่าเหตุการณ์ได้ทำเสร็จแล้วหรือไม่ จึงมักเจอปัญหาเหตุการณ์ก่อนหน้ายังทำไม่เสร็จก็ไปติดที่การ Loop ทำให้คำสั่งก่อนหน้าไม่เกิดผล หากใช่ก็แก้ไขโดยการใช้ DoEvent ครับ
ลองดูครับ ใส่หลังคำสั่งที่เราอยากให้ทำก่อน เช่น
     Me.Text29.SetFocus

    DoEvents

     If Len(Text29) <> 4 Then GoTo incorrect
            For i = 1 To 4
     If IsNumeric(Mid(Text29, i, 1)) = False Then GoTo incorrect
            Next

หรืออาจใส่ใน Loop ในกรณีที่มีการ Loop นานๆ แต่อย่างให้ฟอร์มยังตอบสนองอยู่ ลองปรับใช้ดูครับ
2 @R14406
ผมคงจะตั้งคำถามไม่กระจ่างครับ คืออย่างนี้ครับ

ผมมี Form อยู่ 1 Form   บน Form มี Textbox หลาย Textbox ตัวอย่างที่ผมยกมาคือ Textbox ชื่อ Text29   รับข้อมูลเป็นตัวเลข 4 ตัว   ปัญหามีอยู่ว่า(ในกรณีที่ยกตัวอย่างมาถาม) เมื่อมีการ key ตัวหนังสือ หรือ ตัวเลขที่ไม่ตรงกับ ที่มีในตาราง จะมี MsgBox เตือนผู้ key ข้อมูล
**** ความต้องการคือ
เมื่อเกิดการเตือนจาก MsgBox ขึ้น ผู้ key คลิก OK แล้ว ต้องการให้ เคอร์เซอร์ ไปรอรับการ key ครั้งใหม่ที่ Textbox ชื่อ Text29 (ตัวเดิม) บน Form แต่ปัญหาที่ผมพบคือ เคอร์เซอร์ มันไม่หยุดรอรับการ key มันจะไปปรากฎที่ Textbox ตัวต่อไป ลองใช้ Me.Text29.SetFocus ก็ไม่หยุด   ...ผมลองใช้ GoTo before_ent กลายเป็นการติด loop ออกไม่ได้ เพราะเคอร์เซอร์ มันไม่หยุดรอรับการ key (ผมเข้าใจเอง) มันจึงเอาค่าที่ key ที่ผิดในครั้งแรกส่งไปตรวจสอบ วนเป็น loop ออกไม่ได้ ขึ้น MsgBox ตลอด   ทำได้แค่ คลิก OK ยังไม่รู้จะแก้ยังไงครับ
3 @R14408
? ใช่หรือเปล่า ?

Private Sub Text29_LostFocus()

     If Len(Text29) <> 4 Then GoTo incorrect

     If Not IsNumeric(Text29) Then GoTo incorrect
        -
        -
    End If

incorrect:
    Me.Text29.SetFocus


End Sub
4 @R14409
ทำไมไม่เขียนโค้ดใน Text29_BeforeUpdate event เพราะสามารถกำหนดค่า Cancel อากิวเมนท์ ให้เป็น True ซึ่งจะทำให้ไม่หลุดออกจากเท็กซ์บ็อกซ์นั้น ??? ลองค้นหาเวปนี้ด้วยคำว่า BeforeUpdate ดูครับ
5 @R14410
งั้นปัญหาของคุณไม่ใช่การ Setfocus หรอกครับ ต่อให้คุณ Setfocus ได้ แต่ข้อมูลก็ถูกบันทึกไปแล้วอยู่ดี อยู่ที่การ Cancel อย่างที่ อ.สันติสุข บอกแหละครับ
และหากข้อมูลทั้ง 4 ตัวเป็นตัวเลขทั้งหมด คุณก็ไม่ต้อง Loop ที่ละตัวหรอกครับใช้ IsNumeric อย่าง อ.PichaiTC เขียนได้เลย เช่น

Private Sub Text29_BeforeUpdate(Cancel As Integer)
    If Len(Me.Text1) <> 4 Or Not IsNumeric(Me.Text1) Then
        MsgBox "...."
        Cancel = True
    End If
End Sub

ลองปรับดูนะครับ
6 @R14411
แก้ไข
Text1 เป็น Text29
7 @R14413
ขอบคุณมากๆ นะครับ ท่าน อ.ทุกท่าน ที่กรุณาให้คำแนะนำ ผมเอาไปประยุกต์ใช้งานได้ตามความต้องการแล้วครับ
8 @R14415
จากตัวอย่างของคุณ TTT

Private Sub Text29_BeforeUpdate(Cancel As Integer)
    If Len(Me.Text29) <> 4 Or Not IsNumeric(Me.Text29) Then
        MsgBox "...."
        Cancel = True
    End If
--->   พอได้ข้อมูลจาก Text29 นำไปตรวจสอบกับข้อมูลในตาราง แล้วข้อมูลที่ได้มาไม่มีในตาราง ต้องการให้ เคอร์เซอร์กลับไปที่ Textbox "Text29" เพื่อให้ป้อนข้อมูลใหม่ ผมลองใช้ Me.Text29.SetFocus มันไม่ได้ครับ มันเตือนว่าต้องบันทึกข้อมูลก่อน มีวิธีไหนบ้างครับที่จะทำให้ขบวนการที่เราต้องการ..เสร็จก่อนจึงจะ End Sub

End Sub
9 @R14418
คำถามคือ ทำไม่คุณไม่ตรวจสอบให้เสร็จใน Event ของ Before Update เลยหละครับ เช่น

Private Sub Text29_BeforeUpdate(Cancel As Integer)
    If Len(Me.Text29) <> 4 Or Not IsNumeric(Me.Text29) Then
        MsgBox "...."
        Cancel = True
    ElseIf isnull(Dlookup("ชื่อฟิลด์...", "ชื่อตารางที่ตรวจสอบ", "[ชื่อฟิลด์] = '" & Text29 & "'")) Then
            Cancel = True
        end if
    End If
End Sub

อะไรประมาณนี้ครับ คือตรวจสอบให้จบที่เหตุการณ์เดียวไปเลยครับ ง่ายกว่า

แต่หากคุณสงสัยเรื่อง SetFocus ว่านั้นเป็นปัญหา อธิบายดังนี้นะครับว่า หากผมเข้าใจไม่ผิด มันเป็นการกดเปลี่ยนฟิลด์ เช่นการกดปุ่ม Tab Enter หรือการคลิ๊กเมาส์ ไปยังอีกฟิลด์เพื่อให้เหตุการณ์ในฟิลด์ Text29 ทำงาน เสร็จแล้วเมื่อมันไม่ตรงตามเงื่อนไขคุณก็สั่งให้มัน SetFocus กลับไปที่ฟิลด์ Text29 ถามว่าคำสั่งทำตามนั้นหรือไม่ ตอบว่าทำครับ หากคุณสั่งเกตุดีๆ แต่มันยังมีเหตุการณ์หลังจากคำสั่ง SetFocus ของคุณอยู่ คือการกดปุ่ม ไม่ว่าจะเป็น Tab Enter หรือคลิ๊กเมาส์ ของคุณนั้นเอง ซึ่งโปรแกรมจะถือว่านั้นเป็นเหตุการณ์ต่อจากคำสั่งคุณ ดังนั้นหลังการ SetFocus ที่ Text29 แล้ว มันจึงต่อด้วยการย้ายไปยัง Textbox ตัวอื่นที่คุณคลิ๊ก หรือกด Tab หรือ Enter อะไรก็ไม่ทราบได้ (งงเหมือนกัน) นั่นเอง แต่หากอยากแก้แค่นี้จริงๆ แบบกำปั้นทุบดิน ที่ผมคิดได้ตอนนี้คือประมาณนี้ครับ

Dim TT As String
TT = Me.CurrentRecord
MsgBox "................."
SendKeys "{F5}", True
DoCmd.GoToRecord , , acGoTo, dd
Me.Text29.SetFocus

ประมาณว่า Reset ฟอร์มใหม่แล้วค่อยกลับไป SetFocus ที่เรคคอร์ดเดิม ลองดูแล้วกันครับ
ปล. คิดว่าคุณต้องลองเรียบเรียงโค๊ดดูใหม่ให้ดี ไม่งั้นคุณอาจต้องมาเขียนแก้นั่นดักตรงนี้ เกินความจำเป็นนะครับ
10 @R14419
แก้ไข (อีกแล้ว พิมพ์เองจากจินตนาการ เลย งง เอง)
If Len(Me.Text29) <> 4 Or Not IsNumeric(Me.Text29) Then
    Dim TT As String
    TT = Me.CurrentRecord
    MsgBox "................."
    SendKeys "{F5}", True
    DoCmd.GoToRecord , , acGoTo, TT
    Me.Text29.SetFocus
end sub
11 @R14427
ขอบคุณมากครับ คุณ TTT ผมใช้แนวการตรวจสอบ(ตามที่คุณบอก)ให้เสร็จก่อน ถ้าข้อมูลไม่ถูกต้อง ก็ไม่สามารถออกจาก Textbox บน Form นี้ได้ ถ้าข้อมูล(รหัสลูกค้าถูกต้อง) จะแสดงชื่อลูกค้าบน Textbox (Text37) บน Form ด้วยครับ ใช้งานได้ดีเลยครับ...แต่มีปัญหาอยู่ว่า สมมุติว่า เมื่อผู้ใช้งาน..เปิด Form นี้เพื่อป้อนข้อมูล แล้วเกิดเปลี่ยนใจ ต้องการยกเลิกการทำงาน จะออกจาก Textbox นี้ได้อย่างไรครับ ผมลองแล้ว มันไม่ยอมให้ออกเลยครับ

Private Sub Text29_BeforeUpdate(Cancel As Integer)
     If Len(Me.Text29) <> 4 Or Not IsNumeric(Me.Text29) Then
        MsgBox "ป้อนเฉพาะตัวเลข 4 ตัว"
        Cancel = True
     ElseIf Me.Text29 = IsNull(DLookup("Customer_ID", "Table4", "Customer_ID = Forms!frmTable1_InsertData!Text29")) Then
        MsgBox "รหัสผิด.. โปรดตรวจสอบใหม่"
        Cancel = True
     End If
        Text37 = DLookup("Customer_Name", "Table4", "Customer_ID=FORMS!frmTable1_InsertData!Text29")
    
End Sub
12 @R14430
เพิ่ม เงื่อนไขนี้เข้าไปครับ And Not IsNull(Me.Text29) เป็นเงื่อนไขหากเปลี่ยนใจก็ลบค่าใน Text29 ออกให้หมด ก็สามารถย้าย Focus ได้ครับ

If Len(Me.Text29) <> 4 Or Not IsNumeric(Me.Text29) And Not IsNull(Me.Text29) Then
...
ElseIf Me.Text29 = IsNull(DLookup("Customer_ID", "Table4", "Customer_ID = Forms!frmTable1_InsertData!Text29")) And Not IsNull(Me.Text29) Then

จริงๆหากเป็นการเพิ่มเรคคอร์ดใหม่ ไม่ใช่การแก้ไขเรคคอร์ด ผู้ใช้ใส่ข้อมูลไปแล้ว ตามปกติ ผมเข้าใจว่าโปรแกรมจะบันทึกเป็นเรคคอร์ดใหม่เลยนะครับ ฉนั้นหากต้องการยกเลิกเรคคอร์ดใหม่อาจต้องใช้คำสั่ง
Me.Undo หรือ กดปุ่ม Esc หรือ sendkeys "{esc}" อะไรประมาณนี้ด้วยนะครับ ลองปรับใช้ดู พอดีวันนี้ผมอยู่ข้างนอกไม่มี MS Access ให้ลอง
13 @R14432
ในกรณีที่ผมเขียนนี้นะครับก่อนการบันทึก record ต้องตรวจสอบข้อมูลใน Textbox บน Form ทั้งหมดก่อนว่ามีการใส่ข้อมูล ห้ามว่าง จึงจะบันทึกได้ครับ
14 @R14433
- แล้วประเด็นคืออะไร
"แต่มีปัญหาอยู่ว่า สมมุติว่า เมื่อผู้ใช้งาน..เปิด Form นี้เพื่อป้อนข้อมูล แล้วเกิดเปลี่ยนใจ ต้องการยกเลิกการทำงาน จะออกจาก Textbox นี้ได้อย่างไรครับ ผมลองแล้ว มันไม่ยอมให้ออกเลยครับ"

- ตามเงื่อนไขที่เพิ่มไป ก็ไม่บันทึกก็ถูกแล้ว ก็ให้เป็นค่าว่างก่อน แล้วยกเลิก กด Esc ก็ได้

"ในกรณีที่ผมเขียนนี้นะครับก่อนการบันทึก record ต้องตรวจสอบข้อมูลใน Textbox บน Form ทั้งหมดก่อนว่ามีการใส่ข้อมูล ห้ามว่าง จึงจะบันทึกได้ครับ"

- ก็ในเมื่อคุณต้องการยกเลิก แล้วคุณจะตรวจสอบห้ามว่าง จึงจะบันทึก อะไร จะสื่ออะไรครับ ขออีกที ผมงงเลย ตกลงต้องการบันทึก หรือ ยกเลิกได้
15 @R14448
OK แล้วครับ ทำงานได้ตามความต้องการแล้วครับ   ต้องขอขอบคุณ คุณ TTT มากเลยนะครับที่กรุณาสละเวลาชี้แนะ ให้ความรู้แก่ผู้ที่เพิ่งเริ่มต้นอย่างผม และอีกหลายท่านที่เข้ามาค้นคว้าหาความรู้ที่ Web นี้ และขอขอบคุณทุกท่านที่สละเวลาเข้ามาให้ความรู้ด้วยครับ
@ ประกาศใช้งานเว็บบอร์ดใหม่ => บอร์ดเรียนรู้ Access สำหรับคนไทย
แล้วจะใส่ลิ้งอ้างอิงมาที่โพสต์เก่านี้หรือไม่ก็ตามสะดวกครับ
Time: 0.3547s