vb ที่ใช้ได้ vs ที่ใช้ไม่ได้ ช่วยเช็คด้วย ขอบคุณคร
กระทู้เก่าบอร์ด อ.Yeadram

 7,533   36
URL.หัวข้อ / URL
vb ที่ใช้ได้ vs ที่ใช้ไม่ได้ ช่วยเช็คด้วย ขอบคุณคร

ผมสร้างฟอร์มค้นหารายชื่อสมาชิกที่เิกิดในแต่ละเดือนนั้น โดยใช้วิซาร์ดสร้าง Option Group 13ปุ่ม ออกมาเป็น macro แล้ว convert เป็น vb ซึ่งใช้งานได้ดี ดังนี้
Private Sub SelectMonth_AfterUpdate()
On Error GoTo SelectMonth_AfterUpdate_Err

    With CodeContextObject
        If (.SelectMonth = 1) Then
             DoCmd.ApplyFilter "", "[BirthMonth] Like ""1""", ""       ' เลือก มค.
        End If
        If (.SelectMonth = 2) Then
             DoCmd.ApplyFilter "", "[BirthMonth] Like ""2""", ""        ' กพ
        End If
        If (.SelectMonth = 3) Then
             DoCmd.ApplyFilter "", "[BirthMonth] Like ""3""", ""        ' มีค
        End If
              ....
              ....
              ....
        If (.SelectMonth = 12) Then
            DoCmd.ApplyFilter "", "[BirthMonth] Like ""12""", ""        'ธค.
        End If
        If (.SelectMonth = 13) Then
            DoCmd.ShowAllRecords                                                'เลือกทั้งปี
        End If

        DoCmd.GoToControl "SelectMonth"
        Exit Sub
    End With

SelectMonth_AfterUpdate_Exit:
    Exit Sub

SelectMonth_AfterUpdate_Err:
    MsgBox Error$
    Resume SelectMonth_AfterUpdate_Exit

End Sub

แต่ผมอยากเขียน vb ออกมาเป็น do...case
จึงเอา vb ข้างต้นมาดัดแปลงเป็น
Private Sub SelectMonth_AfterUpdate()
    Select Case Month
        Case SelectMonth = 1
            [BirthMonth] = "1"
        Case SelectMonth = 2
            [BirthMonth] = "2"
        Case SelectMonth = 3
            [BirthMonth] = "3"
              ....
              ....
              ....
        Case SelectMonth = 12
            [BirthMonth] = "12"
        Case SelectMonth = 13
            DoCmd.ShowAllRecords
    End Select

SelectMonth_AfterUpdate_Exit:
    Exit Sub

SelectMonth_AfterUpdate_Err:
    MsgBox Error$
    Resume SelectMonth_AfterUpdate_Exit

End Sub
ปรากฏว่าเอาไปใช้งาน ไม่เกิดผลอะไรออกมาเลย
รบกวนอาจารย์ทั้งหลาย ช่วยดูให้หน่อยว่า ผมเขียนผิดตรงไหน
ขอบคุณล่วงหน้าครับ

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

1 @R13096
น่าจะเป็นอย่างนี้มากกว่า

with CodeContextObject
if .SelectMonth >=1 and .SelectMonth <= 12 then
     DoCmd.ApplyFilter "", "[BirthMonth] = """ & cstr(.SelectMonth) & """", ""
else
     DoCmd.ShowAllRecords
end If
end with
2 @R13115
โอ้โห อาจารย์
ผมเขียนเสียยาว
ของอาจารย์เขียนไม่กี่บรรทัด ใช้งานได้เลย นับถือจริงๆครับ

ขอถามอาจารย์ ดังนี้ครับ
1,with CodeContextObject ต้องใช้กับ Option Group เสมอ ถูกหรือเปล่าครับ?
2.ในฟอร์มนี้ ผมมี Text Box bound กับชื่อเดือน พอคลิกเลือกปุ่ม "มค" Text Box จะโชว์ "มกราคม" แต่พอกดปุ่ม"ทั้งปี(Select All)" ตัวText Box จะแสดงเดือน ม.ค.
อยากเรียนถามอาจารย์ว่า เราสามารถเขียนโค้ดให้ bound Text Box แสดงค่าเป็น "ทั้งปี" ได้ไหมครับ? (ผมลองหลายวิธีแล้วไม่สำเร็จ ลึกๆจึงคิดว่าไม่ได้ เพราะ bound ไปแล้ว)
ตอนนี้ ผมแก้ด้วยการสร้าง Text Box อีกตัวให้ค่า ="ทั้งปี" ขึ้นมาบังไว้ แล้วสั่งให้ Visible=true เมื่อกดปุ่ม"ทั้งปี"

งวดนี้ขอเรียนถามเท่านี้ก่อนครับ
3 @R13116
1. ไม่ถูก With ชื่ออ็อปเจ็ค มีไว้เพื่อให้เราสะดวกในการเขียนโปรแกรมโดยที่เราไม่ต้องเขียนมันซ้ำๆกันในทุกๆบรรทัด ถ้าเราไม่มี With เราก็ต้องเขียนเต็มๆเป็น CodeContextObject.SelectMonth ครับ แต่เราจะสั่ง With ซ้อน With ไม่ได้นะครับ

2. ทำยังไงเพื่อให้มันโชว์ชื่อเดือน บอกรายละเอียดมาด้วยครับ
4 @R13123
ขอบคุณครับ อ.สันติสุข ได้ความรู้เพิ่มอีกข้อ
อาจารย์ครับ ขอยกเลิกคำถามเก่า ขอถามใหม่ดังนี้ครับ
๑.โค้ด Select case ที่ผมเขียนข้างต้น ไม่ทำงาน เพราะเหตุอะไรครับ? (อาจารย์ตอบมา ผมจะได้เรียนรู้จากข้อผิดพลาดครับ)
๒.บน Form Header ผมมี Text box "BirthMonth: Month([Birthday])" ที่สร้างจากคิวรี
ที่ Form Footer มีOption Group ๑๓ปุ่ม ปุ่มที่๑-๑๒ ให้เลือกเดือน "มค-ธค"   ปุ่มที่๑๓ ให้เลือก"ทั้งปี(Show All Records)" แล้วให้Text box "BirthMonth: Month([Birthday])"บน Form Headerแสดงชื่อเดือนตามที่เลือก
แต่ปีหนึ่งมีแค่ ๑๒เดือน (มค-ธค) พอกดปุ่ม๑๓Text box "BirthMonth: Month([Birthday])" จะแสดงแค่ "มค"
ผมอยากให้ Text box นี้แสดงคำว่า"ทั้งปี"ออกมา ผมควรแก้ไขอย่างไรครับ?
๓.ถ้าผมไม่สร้างฟิลด์"BirthMonth: Month([Birthday])"ในคิวรี ผมสามารถสร้าง Text box บนForm Header แล้วให้แสดงชื่อเดือน+ทั้งปี ให้ตรงกับปุ่มที่กดเลือก จะทำได้ไหมครับ?
ไม่ทราบว่าผมเขียนอธิบายได้ชัดเจนดีหรือเปล่า?
รบกวนอาจารย์ช่วยสอนด้วยครับ
5 @R13127
1. ของเดิมคือ
If (.SelectMonth = 1) Then
     DoCmd.ApplyFilter "", "[BirthMonth] Like ""1""", ""       ' เลือก มค.
End If
หมายความว่าถ้า .SelectMonth เป็น 1 ให้ทำคำสั่งเพื่อกรองเอาเฉพาะเรคอร์ดบนหน้าจอที่ BirthMonth เป็น "1"

ของคุณเองเขียนใหม่เป็น
Select Case Month
หมายถึง ตรวจเช็คค่าของ Month ??? คุณเอา Month มาจากไหน ทำไมไม่เป็น CodeContextObject.SelectMonth

        Case SelectMonth = 1
            [BirthMonth] = "1"
หมายถึงกรณีที่ SelectMonth เป็น 1 ให้ BirthMonth มีค่าเป็น "1" ไม่ใช่ให้กรองเอาเรคอร์ดอย่างคำสั่งของเดิม และเนื่องจาก BirthMonth เป็นค่าที่อ่านได้อย่างเดียว จะเขียนหรือกำหนดค่าให้มันไม่ได้ เพราะมันมาจากค่าเดือนของฟิลด์ BirthDay ไม่ใช่เป็นฟิลด์ชื่อว่า BirthMonth จากในเทเบิลโดยตรง การกำหนดอย่างนี้จึงทำไม่ได้ แม้สมมุติว่ามีฟิลด์ชื่อ BirthMonth ในเทเบิลจริงๆก็ตาม แต่การกำหนดค่าให้มัน ก็คือการกำหนดค่าเข้าไปให้แก่ฟิลด์ในเทเบิลใหม่ ไม่ใช่เป็นการสั่งให้กรองเรคอร์ดอยู่ดี

2. ... ผมมี Text box "BirthMonth: Month([Birthday])" ที่สร้างจากคิวรี ...
เท็กซ์บ็อกซ์จะแสดงเลขเดือน (แต่ไม่เข้าใจว่าทำไมของคุณถึงออกมาเป็นชื่อเดือนแทน อาจมีอะไรที่คุณบอกผมไม่หมด) จากฟิลด์ BirthDay ของเรคอร์ดนั้นๆ ทีนี้พอเลือกปุ่มที่ 13 เรคอร์ดทั้งหมดก็แสดงออกมา BirthMonth จึงเป็นไปตามเดือนของ Birthday ของเรคอร์ดนั้นๆ ถ้าคุณลองเลื่อนไปที่เดือนอื่นๆที่ไม่ใช่เดือน 1 BirthMonth ก็จะไม่ใช่คำว่า ม.ค. อีกต่อไป ถ้าจะให้แสดงคำว่า "ทั้งปี" เราก็สร้างอีกเท็กซ์บ็อกซ์ที่มี ControlSource เป็น =Switch(Nz(SelectMonth,0) <= 0, "", Nz(SelectMonth,0) >= 1 and Nz(SelectMonth,0) <= 12, MonthName(SelectMonth,True), Nz(SelectMonth,0) = 13, "ทั้งปี")

(ฟังก์ชั่น Switch( ), Nz( ) และ MonthName( ) เป็นฟังก์ชั่นที่มีอยู่ใน VBA อยู่แล้ว ไปหาใน help file ดูครับว่ามันทำอะไร)




6 @R13139
ขอบคุณครับ อาจารย์
คำอธิบายของอาจารย์เคลียมากครับ
ผมเข้าใจผิดมาตลอดว่า do...case (แปลตามภาษาอังกฤษ คือ "ให้ทำ..ในกรณี" มาตลอด) เป็นการสั่งให้ฟังค์ชั่น/โปรแกรมทำงานในเงื่อนไขที่เรากำหนด
เพราะ (ในฟอร์มของผม)
SelectMonth เป็นชื่อของ Option Group
สำหรับ Month ผมเขียนผิดจริงๆด้วย ที่ถูกคือ BirthMonth: Month([Birthday]) ผมสร้างเป็นฟิวด์ไว้ตรวจสอบดูการเลือกใน Option Group
ส่วน Text box ผมก็เขียนผิดอีก ที่ถูกคือ BirthMonthName: Format([Birthday],"mmmm") ผมวางต่อจาก Label: "คนที่เกิดเดือน.." ผมกะแล้วว่า Text box นี้คงเป็นอ่านอย่างเดียว เพราะผมลองหลายทีแล้ว ไม่สามารถเปลี่ยนค่าของมันได้
ผมจำไปศึกษาต่อตามที่อาจารย์แนะนำครับ
่ขอบคุณอีกครั้งครับ

7 @R13182
เรียน อ.สันติสุข
เอาโค้ดของอาจารย์ไปใช้แล้ว ยังมีคำถามต้องการให้อาจารย์แนะนำ ดังนี้ครับ
1.พอกดปุ่ม 13 ขึ้น error ไม่แสดง "ทั้งหมด" ออกมาครับ ไม่ทราบว่า ต้องแก้ตรงไหนครับ? (ผมลองผิดลองถูกไปหลายวิธี แต่ยังแก้ไม่ตก)
2.ชื่อเดือน MonthName() ออกมาเป็นตัวย่อ (ม.ค. ก.พ.--) ของเดิมผม format "mmmm" ไม่ทราบว่าต้องแก้ตรงไหนให้ออกมาเป็นตัวเต็ม (มกราคม กุมภาพันธ์--) ครับ
รบกวนอาจารย์อีกครั้งครับ
8 @R13184
1. ในระบบคอมพิวเตอร์ใดๆ ถ้ามีอะไร error เกิดขึ้น สิ่งสำคัญคือต้องบอกว่า error อะไร รหัสอะไร ข้อความอะไร บอกโดยละเอียดครับ ไม่งั้นได้แต่เดา เสียเวลาครับ   ยังไงก็ตาม ตรวจสอบให้ดีๆว่าจำนวนเครื่องหมายคอมม่า (,) ใส่ครบทุกๆตำแหน่ง ให้ก๊อปปี้เอา ControlSource property ของเท็กซบ็อกซ์นี้มาให้ดูหน่อยครับ ก๊อปปี้มานะครับ อย่าพิมพ์ใหม่ จะได้เห็นว่ามีตัวอักษรตรงไหนผิดหรือเปล่า

2. เปลี่ยนจาก MonthName(SelectMonth,True) ให้เป็น MonthName(SelectMonth,False) ครับ
9 @R13193
ขอบคุณครับอาจารย์
1.ทีแรกเปิด help MonthName() แต่ไม่ได้อ่านให้ละเอียดว่า default is False ซึ่งหมายความว่าเป็นชื่อเต็ม ตอนนี้แก้เรียบร้อยแล้วครับ ขอบคุณครับ
2.error ที่เกิด ไม่ใช่ Run time error ครับ เป็น error ปรากฎในช่อง Text box นั้นเลย ผมก็อปสูตรมาให้อาจารย์ดูแล้วครับ รบกวนอาจารย์ช่วยดูด้วยครับ
=Switch(Nz([SelectMonth],0)<=0,"",Nz([SelectMonth],0)>=1 And Nz([SelectMonth],0)<=12,MonthName([SelectMonth],False),Nz([SelectMonth],-1)=13,"ทั้งปี")

3.ในกระทู้T02811 ผมเรียนถาม อ.yeadram ให้ช่วยแนะนำว่า ผมจะเอาที่อยู่(ที่ไม่มีถนน มีเพียงอำเภอกับจังหวัด)มาแสดงได้อย่างไร?
ผมเลยถือโอกาสเรียนถาม อ.สันติสุขว่า ถ้าผมดัดแปลโค้ดนี้ไปใช้เป็น
=Switch(Nz([Tanon],0)<="",Me![cmbTanon].[AmPhur]=[AmPhur] And Me![cmbTanon].[JungWat]=[JungWat],Nz([Tanon],0)<>"",Me![cmbTanon].[Tanon]=[Tanon] And Me![cmbTanon].[AmPhur]=[AmPhur] And Me![cmbTanon].[JungWat]=[JungWat])
โดยส่วนแรกให้แสดงออกมาเป็นทำนอง "116/15 ซ.จรัญฯ 13 ถ.(ไม่มีดาต้า) ต.วัดท่าพระ อ.บางกอกใหญ่ จ.กทม "จะได้ไหมครับ?
ขอบคุณครับ
10 @R13194
2. Nz([SelectMonth],-1)=13     ต้องเป็นศูนย์ครับ ไม่ใช่ -1

3. ก่อนอื่นต้องบอกว่าผมไม่ได้อ่านทั้งหมดของคำถามนั้นนะครับ ยังไม่มีเวลา เลยหยิบเฉพาะ 2 คำตอบสุดท้ายมาพิจารณา โค้ดที่ได้ควรเป็นอย่างนี้

Private Sub cmbTanon_AfterUpdate()
On Error GoTo cmbTanon_Err
       
    MsgBox Nz(Me.cmbTanon) & " " & Nz(Me.cmbAmPhur) & " " & Nz(Me.cmbJungWat)

    If Nz(Me.cmbTanon) Then
        Me.RecordsetClone.FindFirst "JungWat = '" & Me.cmbJungWat & "' and AmPhur = '" & Me.cmbAmPhur & "' "
        Me.Bookmark = Me.RecordsetClone.Bookmark
    Else
        Me.RecordsetClone.FindFirst "JungWat = '" & Me.cmbJungWat & "' and AmPhur = '" & Me.cmbAmPhur & "' and Tanon = '" & Me.cmbTanon & "' "
        Me.Bookmark = Me.RecordsetClone.Bookmark
    End If
    
cmbTanon_Exit:
    Exit Sub

ขอเพิ่มเติมว่า
- คุณใช้เครื่องหมาย [ ] เมื่อจำเป็นเช่น ชื่อฟิลด์หรือคอลโทรลมีช่องว่างอยู่ในชื่อ

- ให้ใช้ . แทน ! ได้แล้ว เพราะมีข้อดีกว่าในแง่เขียนโปรแกรม (มีเวลาแล้วจะบอกอีกที)

- การที่คุณเขียน Me![cmbTanon].[AmPhur] แสดงว่ายังไม่เข้าถึงวิธีการการอ้างอิง การเขียนลักษณะนี้ หมายถึงต้องการอ้างอิงถึง object หรือ property หรือ method ที่อยู่ในส่วนสุดท้าย แต่ Amphur ไม่ใช่ทั้งสามอย่างของคอนโทรล cmbTanon (ซึ่งมันเป็นอ๊อปเจ็ค ถ้าจะเขียนให้เต็มยศ ก็ต้องเขียนว่า "คอนโทรลอ๊อปเจ็ค") ดังนั้นเขียนอย่างนี้ก็จะเกิด error อย่างใดอย่างหนึ่งแน่นอน

- ค่าที่เราเห็นว่างๆในฟิลด์หรือในคอนโทรลหรือในตัวแปร มีความเป็นไปได้อยู่ 3 อย่างคือ มีช่องว่างแฝงอยู่ เช่น " " หรือเป็น zero length string คือ "" (อันนี้จะขัดสามัญสำนึกเสียหน่อย เพราะถือว่ามีข้อความอยู่ในนั้น แต่ความยาวเป็นศูนย์) และสุดท้ายคือ Null ซึ่งหมายถึงว่ายังไม่มีค่า/ข้อความใดๆกำหนดมาให้เลย กรณีเป็นค่าตัวเลข จะมีเฉพาะมีค่า (-1,9,322,0,23.4566) กับ Null เท่านั้น ดังนั้นการทดสอบข้อมูล คุณจึงต้องรู้ว่าประเภทข้อมูล (data type) ที่บรรจุอยู่นั้น มันเป็น numeric หรือ string(text) เพราะแม้ว่าเราเห็น 1 แต่มันอาจเป็นค่า 1 (numeric) หรืออาจเป็น "1" (string) ก็ได้   ดังนั้นถ้าเราไม่รู้ประเภทข้อมูล การทดสอบอาจจะไม่ครอบคลุม ทำให้ได้ผลลัพธ์ที่ผิดไป ฟังก์ชั่น Nz( ) มีไว้เพื่อช่วยให้การทดสอบนี้ง่ายขึ้น ลองอ่านและทดสอบดูนะครับ
11 @R13204
ขอบคุณครับ อาจารย์
2.ทำตามที่อาจารย์บอกแล้ว ยัง error เหมือนเดิมครับ เป็นerror ใน Text Box ไม่ไ้ด้ขึ้น dialog เตื่อน Run Time Error ครับ
ผมก็อปโค้ดมาให้อาจารย์ดูอีกครั้งครับ
ใน Text Box :
=Switch(Nz([SelectMonth],0)<=0,"",Nz([SelectMonth],0)>=1 And Nz([SelectMonth],0)<=12,MonthName([SelectMonth],False),Nz([SelectMonth],0)=13,"ทั้งปี")
ใน Option Group :
Private Sub SelectMonth_AfterUpdate()
MsgBox Me.SelectMonth
With CodeContextObject
If .SelectMonth >= 1 And .SelectMonth <= 12 Then
     DoCmd.ApplyFilter "", "[BirthMonth] = """ & CStr(.SelectMonth) & """", ""
Else
     .SelectMonth = 13
     DoCmd.ShowAllRecords
End If
End With
End Sub

3.กำลังจะถามอาจารย์เรื่องความแตกต่างระหว่าง . กับ !อยู่พอดี ส่วนตัวที่อาจารย์เขียน if .SelectMonth >=1 .... มีค่าเท่ากับ if Me.SelectMonth >=1 หรือเปล่าครับ?
ขอเรียนอาจารย์ว่า Tanon เป็น string(text) ""ครับ
cmbTanon มี 3 column Tanon.AmPhur.JungWat
เมื่อ Tanon=string(text) "" เครื่องจึงไม่แสดงข้อมูลออกมา บอกว่า "Syntex error in string in expression"
พอเอาโค้ดของอาจารย์ไปใส่แทนที่ คราวนี้ error เป็น "Type mismatch" ครับ

ขอรบกวนอาจารย์อีกครั้งครับ
ขอบคุณครับ
12 @R13206
(ไม่แน่ใจว่าเกิดอะไรขึ้น โพสข้อความยาวๆแล้วเกิดปัญหา
Microsoft VBScript runtime error '800a0005' Invalid procedure call or argument: 'Mid' /functions/functions_filters.asp, line 37

ผมเลยต้องแยกโพสทีละส่วนๆนะครับ)

2. =Switch(Nz([SelectMonth],0)<=0,"",Nz([SelectMonth],0)>=1 And Nz([SelectMonth],0)<=12,MonthName([SelectMonth],False),Nz([SelectMonth],0)=13,"ทั้งปี")

ผมลองสร้างฟอร์มเพื่อจำลองการทำงานของคำสั่งนี้แล้วก็เจอว่ามัน Error เหมือนกัน กว่าจะเจอว่ามันผิดที่ไหน ก็ใช้เวลาไปพอสมควรทีเดียว ปัญหาคือว่า ฟังก์ชั่น Switch( ) จะทำการหาค่าของทุกนิพจน์ในฟังก์ชั่น แม้ว่าจะมีเพียงนิพจน์เดียวที่เข้าเงื่อนไขก็ตาม นั่นคือ เมื่อ SelectMonth เป็น 13 นิพจน์ MonthName([SelectMonth],False) ก็จะถูกหาค่าด้วยเช่นกัน ดังนั้นการส่งเดือนที่ 13 เข้าไปฟังก์ชั่นนี้ ก็ทำให้เกิด #Error แน่นอน นี่คือสาเหตุครับ

ก็ต้องใช้วิธีอื่นแสดงแทน ซึ่งมีหลายวิธี หนึ่งในนั้นก็คือลบโค้ดจาก ControlSource property ที่เกิดปัญหา แล้วย้ายเข้ามาใน SelectMonth_AfterUpdate event procedure แทน

Private Sub SelectMonth_AfterUpdate()
Dim M    as Integer
M = Nz(Me.SelectMonth, 0)
MsgBox M
With CodeContextObject
If M >= 1 And M <= 12 Then
     Me.ชื่อเท็กซ์บ็อกซ์ = MonthName(M, False)
     DoCmd.ApplyFilter "", "[BirthMonth] = '" & CStr(M) & "' ", ""
Else
     Me.ชื่อเท็กซ์บ็อกซ์ = "ทั้งปี"
     DoCmd.ShowAllRecords
End If
End With
End Sub


และไปกำหนด Lock property ของเท็กซ์บ็อกซ์นั้นให้เป็น True หรือ Yes
13 @R13207
3. ตามโค้ด
With CodeContextObject
If .SelectMonth >= 1 And .SelectMonth <= 12 Then


If .SelectMonth จะหมายถึง CodeContextObject.SelectMonth ไม่ใช่ Me.SelectMonth แต่ว่ามันแตกต่างกันแค่ไหน อันนี้ผมยังไม่ทราบเพราะไม่เคยใช้ Access 2007 (หรือสูงกว่าสักที) ครับ

นอกเรื่องนิดนึง ส่วนที่เขียนว่า "cmbTanon มี 3 column Tanon.AmPhur.JungWat" ตรงนี้อย่าใช้ . ครับ เพราะมันเป็นสัญญลักษณ์เพื่ออ้างถึง object หรือ method หรือ property เขียนแบบนี้แล้วคนอ่านจะสับสน คุณอาจเขียนว่า "Tanonm, AmPhur และ JungWat" ยังจะอ่านได้เข้าใจกว่า

เข้าเรื่องเดิม ถ้าเกิด Type Mismatch แปลว่า data type ของ JungWat และ/หรือ AmPhur เป็น numeric ใช่ไหม ถ้าใช่ เราก็ไม่ต้องมี string delimeter ซึ่งในที่นี้ก็คือ ' (single quote) โค้ดก็จะเป็น

Me.RecordsetClone.FindFirst "JungWat = " & Me.cmbJungWat & " and AmPhur = " & Me.cmbAmPhur & " "    จริงๆแล้ว & " "   ตัดออกไปได้ แต่ผมเขียนเพื่อให้เปรียบเทียบกับโค้ดเดิมได้ชัดๆ    ส่วนอีกบรรทัดก็ทำเช่นเดียวกัน
14 @R13220
ขอบคุณครับ อาจารย์
ปิดคดีข้อ 2 ไปเรียบร้อยแล้วครับ
ขอบคุณอาจารย์จริงๆ ที่อุตส่าห์จำลองแบบขึ้นมา
ปัญหายากๆ แบบนี้ กลับกลายมาเป็นบทเรียนที่ดีของอาจารย์ และของผมด้วย
การเขียน Sub หรือ Function เมื่อไรต้องใช้ตัวแปร? (อย่าง Dim M    as Integer)
อย่างกรณีของผมนี้ รู้แน่ว่า M คือ SelectMonth เราใช้ตรงๆแบบนั้นไม่ดีหรือครับ?

อาจารย์ครับ ยังปิดคดี ข้อ 3ไม่ลงครับ
ผมลบ ' กับ &" "ออกไปแล้ว พอ run ดู เกิด message box ขึ้นมาว่า "The Microsoft Office Access database engine does not recognize 'นครปฐม(ด้าต้าในฟิวด์ JungWat)' as a valid field name or expression"
ทั้งๆที่ cmbJungWat, cmbAmPhur ก่อนหน้า cmbTanon นี้ ก็ขึ้น นครปฐม มาเรียบร้อยดี

ต่อไปนี้ ไม่ใช่คำถามครับ แค่เรียนให้อาจารย์ทราบ
- ผมใส่ [] เพราะอ่านในหนังสือ เขาแนะให้ใส่ ก็เลยใส่เรื่อยมา แต่เห็นแล้วครับ วิธีของอาจารย์สะดวกกว่ามาก
- ผมเพิ่มเข้าใจว่า "_" หมายถึง string '_' หมายถึง number และ "'_'" หมายถึง string กับ number รวมกัน ผมเข้าใจถูกไหมครับ?
เดิมผมเขียน "'_'" เพราะเข้าใจว่า '_'เป็นชื่อของ object หรือ control อย่าง FindFirst "JungWat = "' & Me.cmbJungWat & '"
-ที่ผมเขียน Tanon.AmPhur.JungWat เพราะตั้งใจจะให้เข้าใจว่าเป็น value ของ ComboBox ครับ (แต่เข้าใจที่อาจารย์ทักท้วงแล้วครับ จะไม่เขียนอย่างนี้อีก)
เดิมทีคิดว่า จะเขียน
    If Me.cmbTanon = "" Or IsNull(Me.cmbTanon) Then
        Me.RecordsetClone.FindFirst JungWat = Me.cmbTanon.Value(1) = " " AND Me.cmbTanon.Value(2) = AmPhur AND Me.cmbTanon.Value(3) = JungWat ครับ เลยเขียนเป็น Tanon.AmPhur.JungWat ไม่คิดว่ากลับทำให้สับสนมากขึ้น ขอโทษครับ

"valid field name or expression" หมายถึงอะไรครับ? (ชื่อเจาะจง-คำอธิบายเฉาพะ?)
รบกวนอาจารย์ช่วยอีกครั้งครับ
ขอบคุณล่วงหน้าครับ

15 @R13224
- กรณีนี้ผมใช้ตัวแปรก็เพื่อแค่ทำให้มันอ่านง่ายๆ สั้นๆ ไม่รกหูรกตา เท่านั้นเองครับ

- ปัญหาข้อ 3 ช่วยเอาโค้ดที่คุณแก้ไขแล้วมาให้ดูอีกที และ cmbJungWat, cmbAmPur และ cmbTanon แต่ละคอลโทรลมีกี่คอลัมน์ คอลัมน์ไหนคือรหัส คอลัมน์ไหนคือชื่อ ช่วยบอกด้วยครับ

- ตกลงฟิลด์ JungWat, AmPur และ Tanon มีประเภทข้อมูลเป็น numeric (เช่น AutoNumber, Integer, Long, Single, Decimal เป็นต้น) หรือเป็น string(text) กันแน่

- ถ้าชื่อต่างๆในระบบของคุณมีช่องว่างในชื่อ คุณจำเป็นต้องใส่ [ ] แต่ถ้าไม่มีก็ไม่จำเป็น ยกเว้นบางทีระบบมันใส่ [ ] ให้คุณเองโดยอัตโนมัติ

- ผมเพิ่มเข้าใจว่า "_" หมายถึง string '_' หมายถึง number และ "'_'" หมายถึง string กับ number รวมกัน ผมเข้าใจถูกไหมครับ?
คำตอบคือ ผิดครับ     เมื่อใดก็ตามที่มี single quote ( ' ) หรือ double quote ( " ) ครอบข้อความหรือตัวเลขเอาไว้ ข้อความหรือตัวเลขนั้นจะถือว่าเป็น string(text) เสมอ และในทางกลับกัน เมื่อใดคุณต้องการเขียน/สร้างค่าคงที่ที่เป็น string(text) คุณต้องมีสัญญลักษณ์ข้างต้นครอบไว้เช่นกัน   ส่วน numeric ไม่ต้องมีสัญญลักษณ์ใดๆครอบ

.FindFirst ต้องการอากิวเมนท์ตัวต่อมาเป็น string(text) สำหรับเจาะจงเงื่อนไขว่าจะหาเรคอร์ดอะไร (ลองอ่านดูใน help file) เช่น สมมุติว่ากรณีนี้ จังหวัดเก็บเป็นรหัส มีประเภทข้อมูลเป็น string(text) คำสั่งที่เราต้องการจริงๆก็คือ Me.RecordsetClone.FindFirst "JungWat = '01'" แต่ '01' เก็บอยู่ใน cmbJungWat ดังนั้นเราจึงต้องสร้างคำสั่งเป็น Me.RecordsetClone.FindFirst "JungWat = '" & cmbJungWat & "'"   แต่ถ้าคุณเขียนว่า Me.RecordsetClone.FindFirst "JungWat = 'cmbJungWat'" มันจะหาจังหวัดที่มีค่าเท่ากับคำว่า 'cmbJungWat' ไม่ใช่หาค่าจากคอลโทรล cmbJungWat แล้วนำมาใส่ใน string(text) อีกที อธิบายอย่างนี้ไม่ทราบว่าพอจะเข้าใจหรือไม่

- Me.RecordsetClone.FindFirst JungWat = Me.cmbTanon.Value(1) = " " AND Me.cmbTanon.Value(2) = AmPhur AND Me.cmbTanon.Value(3) = JungWat ถ้าคำสั่งของคุณเขียนตามนี้ทุกตัวอักษร รับรองได้เลยว่ามันทำงานไม่ได้ครับ แค่คอมไพล์ก็ไม่ผ่านแล้ว เพราะมั่วไปหมด เพราะอย่างที่ผมว่าไว้ว่าอากิวเมนท์ตัวแรกของ .FindFirst คือ string(text) แต่ของคุณคือ JungWat มันลอยๆ ไม่ใช่ทั้ง string(text) ไม่ใช่ทั้ง numeric มันจึงพยายามหาว่า JungWat คืออะไร ตัวแปรหรือเปล่า ? ก็ไม่ใช่    ค่าคงที่หรือเปล่า ? ก็ไม่ใช่    คอนโทรลบนฟอร์มหรือเปล่า ? ก็ไม่ใช่   ในเมื่อไม่มีอะไรใช่ มันก็ยอมแพ้หล่ะครับ จึงเกิด "valid field name or expression" ครับ   ส่วนอื่นๆตามหลังของคำสั่งนี้ยังไม่ต้องพูดถึงนะครับ ผิดแน่ๆ เอาไว้แก้ส่วนแรกให้ได้ก่อนแล้วค่อยว่ากันต่อ

จะเห็นว่าผมเน้นเรื่อง data type มาก ต้องเข้าใจ data type และการเขียน data type ประเภทต่างๆในโค้ด คุณถึงจะไปต่อได้
16 @R13225
ขอบคุณครับ อาจารย์
จะไปลองทำดู/ศึกษาดู แล้วแจ้งผลให้อาจารย์ทราบต่อไป
ขอบคุณครับ
17 @R13231
อาจารย์ครับ ยังไม่สำเร็จครับ
ผมยกรายละเอียดมาให้อาจารย์พิจารณาดังนี้
Query: qryVisit มี field JungWat, AmPhur, Tanon, ทั้ง 3 field นี้เป็น Text มี field DL, Address, PagerMobiTel เป็น RecordSet
Form: Main Form ชื่อ mfmVisit มี Sub Form sfmVisit
Main Form มี
cmbJungWat (SELECT DISTINCTROW qryVisit.JungWat FROM qryVisit GROUP BY qryVisit.JungWat ORDER BY qryVisit.JungWat; )
Private Sub cmbJungWat_AfterUpdate()
On Error GoTo cmbJungWat_Err
    
    DoCmd.SetProperty "cmbAmPhur", acPropertyEnabled, "JungWat Like '" & cmbJungWat & "'"
    DoCmd.Requery "cmbAmPhur"
    DoCmd.SetProperty "cmbAmPhur", acPropertyEnabled, "-1"
    DoCmd.GoToControl "cmbAmPhur"
    Exit Sub

cmbJungWat_Exit:
    Exit Sub

cmbJungWat_Err:
    MsgBox Error$
    Resume cmbJungWat_Exit
End Sub

cmbAmPhur (SELECT DISTINCT qryVisit.AmPhur, qryVisit.JungWat FROM qryVisit GROUP BY qryVisit.AmPhur, qryVisit.JungWat, qryVisit.Tanon HAVING (((qryVisit.JungWat)=[Forms]![mfmVisit]![cmbJungWat])) ORDER BY qryVisit.AmPhur; )
Private Sub cmbAmPhur_AfterUpdate()
On Error GoTo cmbAmPhur_Err
    
    DoCmd.SetProperty "cmbTanon", acPropertyEnabled, "JungWat Like '" & cmbJungWat & "' AND Amphur Like '" & cmbAmPhur & "'"
    DoCmd.Requery "cmbTanon"
    DoCmd.SetProperty "cmbTanon", acPropertyEnabled, "-1"
    DoCmd.GoToControl "cmbTanon"
       
cmbAmPhur_Exit:
    Exit Sub

cmbAmPhur_Err:
    MsgBox Error$
    Resume cmbAmPhur_Exit
End Sub

cmbTanon(SELECT DISTINCT qryVisit.Tanon, qryVisit.AmPhur, qryVisit.JungWat FROM qryVisit GROUP BY qryVisit.Tanon, qryVisit.AmPhur, qryVisit.JungWat HAVING (((qryVisit.AmPhur)=Forms!mfmVisit!cmbAmphur) And ((qryVisit.JungWat)=Forms!mfmVisit!cmbJungWat)) ORDER BY qryVisit.Tanon; )
Private Sub cmbTanon_AfterUpdate()
On Error GoTo cmbTanon_Err
    
    Me.RecordsetClone.FindFirst "[Tanon] = '" & Me![cmbTanon] & "'"
    Me.Bookmark = Me.RecordsetClone.Bookmark

cmbTanon_Exit:
    Exit Sub

cmbTanon_Err:
    MsgBox Error$
    Resume cmbTanon_Exit

End Sub

Sub Form: sfmVisit มี field DL, Address, PagerMobiTel เป็น RecordSet

Main Form กับ Sub Form link กันด้วย field JungWat, AmPhur, Tanon

การใช้งาน
เช่น เลือก cmbJungWat เป็น "ชลบุรี" จะได้ cmbAmPhur เป็น "บ้านบึง/ชลบุรี" "พานทอง/ชลบุรี" "เมือง/ชลบุรี" "หนองใหญ่/ชลบุรี" ตามลำดับ
พอเลือก "เมือง/ชลบุรี" cmbTanon จะขึ้น "สุรชัย/หนองใหญ่/ชลบุรี" พอเลือก "สุรชัย/หนองใหญ่/ชลบุรี" Sub Form จะแสดงผลออกมา
588/236 ซ. ถ.สุรชัย ต.มะขามหย่ง อ.เมือง จ.ชลบุรี 20000

ปัญหาคือ ถ้า cmbTanon มี Tanon เป็นข้อมูล "" เมื่อไร Sub Form จะไม่แสดงข้อมูลออกมา
เช่น เลือก cmbTanon เป็น "หนองใหญ่/ชลบุรี" จะได้ "ถนน""/หนองใหญ่/ชลบุรี" พอเลือก "ถนน""/หนองใหญ่/ชลบุรี" แล้ว Sub Form ไม่แสดงผลอะไรออกมาเลย
ผมอยากให้เอาข้อมูลที่มีอยู่จริงในคิวรี/ตาราง คือ 670/330 ม.2 ซ. ถ. ต.หนองใหญ่ อ.หนองใหญ่ จ.ชลบุรี 20190 มาแสดงใน Sub Form ครับ

เหลือขั้นตอนสุดท้ายนี้ ก็จะปิดคดีนี้แล้วครับ รบกวนอาจารย์ช่วยอีกสักครั้ง
ขอบคุณครับ

18 @R13235
คงไว้ค่ำๆผมถึงมาตอบให้นะครับ ตอนนี้ยังไม่มีเวลา
19 @R13240
ขอบคุณครับ
รออยู่ครับ อาจารย์
20 @R13248
DoCmd.SetProperty "cmbAmPhur", acPropertyEnabled, "JungWat Like '" & cmbJungWat & "'"

DoCmd.SetProperty "cmbTanon", acPropertyEnabled, "JungWat Like '" & cmbJungWat & "' AND Amphur Like '" & cmbAmPhur & "'"


ก่อนอื่น... สังเกตุเห็นสองบันทัดที่ผมไม่รู้จัก เพราะผมไม่เคยใช้ Access 2007/2010 แต่เท่าที่อ่านดูจาก help file มันควรเป็นค่า True/False ไม่ใช่นิพจน์ของ string รวมทั้งคำสั่ง SELECT มันก็ดูแปลกๆ แต่ยังไงถ้ามันทำงานได้ ก็ขอข้ามจุดนี้ไปก่อน

ผมงงๆว่าทำไมเมื่อ cmbTanon ไม่เป็น "" แล้ว subform ยังถึงทำงานได้ เพราะถ้ามันทำงานได้ อาจสันนิษฐานได้ว่า mainform เชื่อมกับ subform ด้วยฟิลด์ใน linked master/child fields property กันอยู่ ส่วนโค้ดของ Private Sub cmbTanon_AfterUpdate() มันไม่น่าจะทำงานอะไรได้ถูกต้องเลยเพราะเป็นการค้นหาใน mainform ไม่ใช่ subform !!!

อย่างงั้นผมจะถือว่ามันเชื่อมกันด้วย linked master/child fields แล้วกันนะครับ แต่เพราะมันไม่มีความสามารถจัดการเชื่อมระหว่าง NULL หรือ Zero-Length ของค่าบน main form และ sub form ได้ นี่เลยทำให้มันไม่แสดงเมื่อคุณไม่มีถนน ดังนั้นต้องลบ linked master/child fields ออก แล้วเปลี่ยนไปกำหนด RecordSource property ของ subform ให้ตรงตามเงื่อนไขด้วยโค้ดของเราเองแทน

Private Sub cmbTanon_AfterUpdate()
On Error GoTo cmbTanon_Err
    Me.ชื่อของ subform control.form.recordsource = "select * from qryVisit where JungWat = '" & cmbJungWat & "' and AmPur = '" & cmbAmPur & "' and Nz(Tanon,'') = '" & Nz(cmbTanon,'') & "'"
cmbTanon_Exit:
    Exit Sub

cmbTanon_Err:
    MsgBox Error$
    Resume cmbTanon_Exit
End Sub

ลองดูครับ ถ้าไม่ถูกต้องยังไงก็ช่วยบอกเพิ่มด้วยว่าคุณใช้ linked master/child fields เชื่อมข้อมูลระหว่าง mainform และ subform ใช่หรือไม่ และมีค่าเป็นอะไร
@ ประกาศใช้งานเว็บบอร์ดใหม่ => บอร์ดเรียนรู้ Access สำหรับคนไทย
แล้วจะใส่ลิ้งอ้างอิงมาที่โพสต์เก่านี้หรือไม่ก็ตามสะดวกครับ
Time: 0.2591s