สมัครสมาชิก

แสดงกระทู้

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - sjs

หน้า: [1] 2 3 4
1
ห้อง MS Access / : access 2003 to windows 10 64 bit
« เมื่อ: 04 พ.ย. 62 , 08:47:45 »
Control Panel > Region >Formate ต้องเป็น Thai (Thailand) Currnet language ต้องเป็น Thai (Thailand)

Option Compare Database
      Private Const LOCALE_SSHORTDATE = &H1F
      Private Const WM_SETTINGCHANGE = &H1A
      Private Const HWND_BROADCAST = &HFFFF&
#If VBA7 Then
      Private Declare PtrSafe Function SetLocaleInfo Lib "kernel32" Alias "SetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String) As Boolean
      Private Declare PtrSafe Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
      Private Declare PtrSafe Function GetSystemDefaultLCID Lib "kernel32" () As Long
#Else
      Private Declare Function SetLocaleInfo Lib "kernel32" Alias "SetLocaleInfoA" (ByVal Locale As Long, ByVal LCType As Long, ByVal lpLCData As String) As Boolean
      Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
      Private Declare Function GetSystemDefaultLCID Lib "kernel32" () As Long
#End If
     
Function setdate() 'ใช้เปลี่ยนรูปแบบวันที่
    Dim dwLCID As Long
            dwLCID = GetSystemDefaultLCID()
           
        If SetLocaleInfo(dwLCID, LOCALE_SSHORTDATE, "dd/MM/yyyy") = False Then
            MsgBox "รูปแบบวันที่ไม่ใช่ dd/MM/yyyy", vbCritical, "Error"
        End If
            PostMessage HWND_BROADCAST, WM_SETTINGCHANGE, 0, 0
End Function

กระทู้ถามว่าไงเนี๊ย   :shout: :shout: :shout:
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

2
ตามหลักการแล้ว อะไรที่ขึ้นกับคนนั้นและไม่มีทางเปลี่ยน ก็ให้ผูกกับเทเบิลที่มี Primary Key เป็น NationalID เช่น วันเกิด  แต่อะไรที่เปลี่ยนแปลงไปได้ เช่น ชื่อ นามสกุล ที่อยู่ เบอร์โทร ก็ต้องผูกกับเทเบิลที่มี Primary Key เป็น NationalID + NumberOfEdited  แต่เท่าที่ดู มีแค่ฟิลด์วันเกิดเท่านั้นที่ไม่เปลี่ยนแปลง ดังนั้นการจะแยกเป็นอีกเทเบิลที่มีแต่ฟิลด์ NationalID กับ BirthDate อาจจะดูไม่คุ้มกับการทำ ผมคิดว่าให้เทเบิล tbl_Contracter และ tbl_Address มี Primary Key เป็น NationalID + NumberOfEdited ไปเลยจะดีกว่า และคิดว่าเพิ่มฟิลด์ประเภท Boolean อีกฟิลด์ทั้งใน 2 เทเบิล เพื่อบอกว่า Edition ไหน เป็น Edition ปัจจุบันไปด้วย จะทำให้ตอนค้นหาข้อมูลปัจจุบันเพื่อนำมาใช้ในส่วนต่างๆ ไม่ยุ่งยากเมื่อเทียบกับการต้องหาว่า Edition ไหนเป็น Edition ล่าสุดโดยไม่มีฟิลด์ที่ว่า แต่ก็ต้องจัดการให้ดีๆว่า ในขณะใดขณะหนึ่งต้องมีเพียงเรคอร์ดเดียวเท่านั้นที่ฟิลด์ที่ว่ามีค่าเป็น True    ส่วนเทเบิลอื่นๆที่ต้องโยงมายัง 2 เทเบิลนี้ ก็ต้องเก็บทั้ง NationalID และ NumberOfEdited ไปด้วย ดังนั้น transaction ต่างๆก็จะอิงกับข้อมูลที่เป็นปัจจุบัน ณ เวลานั้นครับ
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

3
เว็บบอร์ดวันนี้มีการเพิ่มปุ่ม ตอบกระทู้ ให้กดกันง่ายขึ้นครับ(ข้างๆปุ่ม"อ้างถึง" :sweat:)
ปล.แผ่นป้ายช่วยลงไปกดกันสักหนึ่งทีพอครับ :love:
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

4
ห้อง MS Access / : เรียกข้อมูล Weekly
« เมื่อ: 27 ก.ย. 62 , 12:20:56 »
SELECT * FROM [ชื่อเทเบิล]
WHERE Format$([ชื่อฟิลด์วันนัดชำระ],"yyyymmww",2))=Format$(Date(),"yyyymmww",2)))
ORDER BY [ชื่อฟิลด์วันนัดชำระ]

กลับมาอ่านอีกที ชักเลอะเทอะเกินความจำเป็น  ไม่จำเป็นต้องเป็น yyyymmww แค่ yyyyww ก็พอแล้วครับ
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

5
Me("Refer") = RS("Refer")

แต่แนะนำให้เปลี่ยนชื่อเท็กซ์บ็อกซ์บนฟอร์มไปเป็นชื่ออื่นที่แตกต่างจากชื่อฟิลด์ดีกว่า อาจเป็น txtRefer ก็ได้ ก็จะเป็น Me("txtRefer") = RS("Refer")
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

6
โค้ดตัวอย่างนี้ เป็นการแปะค่าของฟิลด์ต่างๆในบรรทัดที่ต้องการ มาลงเป็นบรรทัดใหม่ในฟอร์ม/ซับฟอร์มเดียวกัน วิธีคือให้สร้าง Command Button เอาไว้ที่ไหนก็ได้สักที่บนบรรทัดของข้อมูล (สมมุติชื่อ btnCopy) เมื่อต้องการก็อปปี้ ก็แค่คลิกที่ปุ่มนี้

Private Sub btnCopy_Click()
    Dim RS As DAO.Recordset
   
    If Me.NewRecord Or Me.Dirty Then Exit Sub ' ถ้าคลิกปุ่มบนบรรทัดของรายการใหม่ หรือ บนบรรทัดที่รายการกำลังแก้ไขอยู่ ก็ไม่ต้องทำอะไร
   
    Set RS = Me.RecordsetClone    ' กำหนดตัวแปรสำหรับอ้างอิงข้อมูลของบรรทัดปัจจุบัน (บรรทัดที่เลือก)
    RS.Bookmark = Me.Bookmark  ' ให้ตัวแปรดังกล่าวชี้ไปเรคอร์ดเดียวกันกับบรรทัดปัจจุบัน
    DoCmd.GoToRecord , , acNewRec   ' กระโดดไปบรรทัดรายการใหม่
    Me("ชื่อคอนโทรลบนฟอร์ม") = RS("ชื่อฟิลด์ของคอนโทรลบนฟอร์ม") ' ต้องการก็อปปี้ฟิลด์อะไรบ้าง ก็เพิ่มบรรทัดตามจำนวนฟิลด์ที่ต้องการต่อลงไปได้เรื่อยๆ
   
    Set RS = Nothing
End Sub
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

7
การกำหนด Property ให้แก่คอนโทรลในบรรทัดของ Continuous Form จะมีผลกับคอนโทรลนั้นในทุกบรรทัดครับ แต่สำหรับการกำหนดคุณสมบัติในการแสดงบางอย่างเช่น สีพื้น, สีตัวอักษร. อักษรตัวหนา/ขีดเส้นใต้/ตัวเอียง, Enabled/Disabled สามารถใช้ Conditional Formatting ในการกำหนดเฉพาะคอนโทรลในบรรทัดนั้นๆตามเงื่อนไขให้เป็นไปอย่างอัตโนมัติได้ ดังนั้นอย่างแรกที่ต้องทำก็คือต้องหาก่อนว่าเงื่อนไขอะไรที่จะให้ Disabled   จากที่กำหนดมา ถ้าสมมุติว่าเมื่อเงื่อนไข cb_Status = "¨จบงาน" ก็ให้ Disabled ได้ ก็ให้ป้อน Conditional Formatting สำหรับคอนโทรลอื่นที่ต้องการเป็น (เช่น cb_DocEnvelope, txt_OrderID) [cb_Status] = "¨จบงาน" แล้วเลือกลักษณะคอนโทรลเป็น Disabled ครับ 



ส่วนโค้ดที่ให้มา ก็มีแค่นี้เท่านั้น

Private Sub Command27_Click()
    Me.txt_DateClose = Now()
    Me.cb_Status = "¨จบงาน"
End Sub
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

8
เพิ่มเติมหน่อยนะครับ ที่บอกไปครั้งก่อนว่า "ใน BeforeUpdate event จะไม่ยอมให้เราแก้ไขค่าในเท็กซ์บ็อกซ์ของตัวมันเอง" หมายถึงจะเกิด runtime error ขึ้น แต่ถ้าเราอยากข้าม error นี้ไป ก็ทำแบบเถื่อนๆคือใส่ On Error Resume Next ตามโค้ดที่แก้ไขข้างล่างนี้ก็ได้

Private Sub TxITEM_ฺBeforeUpdate(Cancel As Integer)
  If Me.TxItem.Text = "" Then
  ElseIf DCount("Item", "QrItem") > 0 Then
  Else
      MsgBox "Item ¹ÕéäÁèÁÕã¹ÃкºËÃ×ÍÂѧäÁèä´éà¾ÔèÁà¢éÒä»ã¹Ãкº", vbOKOnly, "Warning!"
      Cancel = True
      On Error Resume Next
      Me.TxItem.Text = ""

  End If
End Sub

หมายเหตุ : สังเกตให้ดีว่าเราต้องอ้าง TxtItem.Text นะครับ ไม่ใช่ TxtItem เฉยๆ
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

9
ห้าม set focus กลับไปที่ตัวเองครับ การทดสอบว่าเงื่อนไขไหนไม่ผ่านและจะให้ยังคงอยู่ที่เท็กซ์บ็อกซ์เดิม เราต้องทำที่ BeforeUpdate event  และเราจะกำหนดพารามิเตอร์ Cancel เป็น True เพื่อให้ Access หยุดเพียงแค่ event นี้ ดังนั้นจึงไม่ต้องกำหนด .SetFocus เพิ่มเติม แต่เนื่องจากใน BeforeUpdate event จะไม่ยอมให้เราแก้ไขค่าในเท็กซ์บ็อกซ์ของตัวมันเองเช่นกัน จึงไม่สามารถกำหนดค่า Null กลับไปได้ วิธีที่พอทำได้คือ กำหนดให้ตัวอักษรทั้งหมดในเท็กซ์บ็อกซ์ถูกเลือก ดังนั้นผู้ใช้ก็สามารถป้อนค่าใหม่ทับของเดิมไปได้ทันทีครับ

โค้ดคุณก็จะมีแค่นี้ครับ

Private Sub TxITEM_ฺBeforeUpdate(Cancel As Integer)
  If Me.TxItem.Text = "" Then
  ElseIf DCount("Item", "QrItem") > 0 Then
  Else
      MsgBox "Item ¹ÕéäÁèÁÕã¹ÃкºËÃ×ÍÂѧäÁèä´éà¾ÔèÁà¢éÒä»ã¹Ãкº", vbOKOnly, "Warning!"
      Cancel = True
      Me.TxItem.SelStart = 0
      Me.TxItem.SelLength = Len(Me.TxItem.Text)
  End If
End Sub


โพสต์นี้ได้รับคำขอบคุณจาก: sjs

10
สนับสนุนการบ่นอีกเสียงครับ

บางคำถามอ่านแล้วได้แต่ถอนใจ
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

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

ดังนั้น เพื่อเพิ่มความสมบูรณ์ของคำถาม มันก็มีหลายวิธี แต่หลายๆวิธีคงวุ่นวายไป ก็เลยคิดว่าก่อนระบบจะรับโพส อยากให้มี message box แสดงข้อความ "เขียนถามให้ผู้ตอบเข้าใจ..." ตามข้อความเตือนสีแดงๆที่อยู่บนหัวเพจอีกที และอาจมีข้อความอื่นเพิ่มเติมเพื่อเน้นว่าเขาแน่ใจไหมว่าได้อธิบายละเอียดแล้ว ถ้าเขาไม่ยืนยัน ก็ให้เขากลับไปแก้ข้อความ แต่ถ้าเขากดยืนยัน ก็ค่อยโพสจริงๆอีกที

ถามยาว โอกาสได้รับคำตอบเร็วมีสูง -- ถามสั้น โอกาสน้อยลง -- ถามสั้นมากๆ ยากที่จะมีโอกาส
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

12
นำไปใช้ การลงข้อมูล ชื่อ - ที่อยู่ลูกค้า ครับ

ไฟล์ตัวอย่างใช้ Combo box หลายตัว โดยทุกตัวมีความหมายเหมือนกันเพียงแค่เมื่อเลือกแล้วส่งค่ากลับไปยัง Combo box อื่นๆ เอาไปศึกษาแนวทางการนำไปใช้ดูครับ :yuush:
โค๊ด: [Select]
Private Sub Cus_ID_Click()
        Cus_Tax_ID.Value = Cus_ID.Column(9)
        Cus_Name.Value = Cus_ID.Column(1)
        Cus_addess.Value = Cus_ID.Column(2) & "  " & Cus_ID.Column(3) & Cus_ID.Column(4) & "  " & Cus_ID.Column(5) & "  " & Cus_ID.Column(6) & Cus_ID.Column(7) & "  " & Cus_ID.Column(8) '& "."
End Sub
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

13
นำไปใช้ การลงข้อมูล ชื่อ - ที่อยู่ลูกค้า ครับ 
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

14
Combobox นิยมใช้ในการเลือกรายการหรือเลือกจากตัวเลือกที่สร้างขึ้นมามากกว่าจะใช้การ ใส่ตัวเลขนะครับ
แต่ถ้าใส่ตัวเลือก จาก ID แล้ว แสดงส่วนของ Detail ก็ว่าไปอย่าง
ถ้าเป็นการใส่ตัวเลขก็ใช้ textbox ก็ได้ เลยสงสัยว่าการนำไปใช้ๆทำอะไรครับ

เช่น
โค๊ด: [Select]
Private Sub Combo_Box_1_AfterUpdate()
If Not IsNull(Me.Combo_Box_1) Then
Me.Combo_Box_2 = Me.Combo_Box_1
Me.Combo_Box_3 = Me.Combo_Box_1
End If
End Sub



โพสต์นี้ได้รับคำขอบคุณจาก: sjs

15
ไม่เคยทำกับเรคอร์ดจำนวนมากอย่างนี้ ได้แค่ออกแนวคิดให้ แต่จะทำได้ผลจริงหรือไม่ อันนี้ไม่ทราบนะครับ วิธีคือต้องหาทางสร้างคิวรี่เพื่อให้ได้เรคอร์ดทีละล้านเรคอร์ดก่อน แล้วใช้ CopyFromRecordset method ของ Range object จาก Excel object https://docs.microsoft.com/en-us/office/vba/api/excel.range.copyfromrecordset link เพื่อดึงข้อมูลจำนวนมากเข้าชีท แล้วก็เปิดชีทใหม่ วนทำกับคิวรี่ตัวต่อไปจนหมดครับ
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

16
กดปุ่ม [CTRL] + ['] จะเป็นการเรียกข้อมูลก่อนหน้ามาใส่ (ไม่รู้ว่าช่วยแก้ปัญหาได้ป่าวนะครับ)
โพสต์นี้ได้รับคำขอบคุณจาก: sjs

หน้า: [1] 2 3 4