สมัครสมาชิก

แสดงกระทู้

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 - สันติสุข

หน้า: [1] 2 3 4 ... 10
1
ห้อง MS Access / : Else กับ ElseIf ให้ผลต่างกันอย่างไร
« เมื่อ: เมื่อวานนี้ เวลา 23:54:18 »
If เงื่อนไข Then
   ทำคำสั่งเมื่อเงื่อนไขเป็นจริง
Else
   ทำคำสั่งเมื่อเงื่อนไขไม่เป็นจริง
End If


If เงื่อนไขที่1 Then
   ทำคำสั่งเมื่อเงื่อนไขที่1เป็นจริง
ElseIf เงื่อนไขที่ 2 Then
   ทำคำสั่งเมื่อเงื่อนไขที่1ไม่เป็นจริง แต่เงื่อนไขที่2เป็นจริง
ElseIf เงื่อนไขที่ 3 Then
   ทำคำสั่งเมื่อเงื่อนไขที่1และ2ไม่เป็นจริง แต่เงื่อนไขที่3เป็นจริง
ElseIf ...
   ...
Else
   ทำคำสั่งเมื่อเงื่อนไขทั้งหมดข้างบนไม่เป็นจริง
End If

การใช้ ElseIf ทำให้ลดรูปการเขียนคำสั่งด้วย If ... Then ... Else ซ้อนกันให้สั้นลงและอ่านง่ายขึ้นเท่านั้นเองครับ ไม่งั้นเราก็ต้องเขียนเป็น

If เงื่อนไขที่1 Then
   ทำคำสั่งเมื่อเงื่อนไขที่1เป็นจริง
Else
   If เงื่อนไขที่ 2 Then
      ทำคำสั่งเมื่อเงื่อนไขที่1ไม่เป็นจริง แต่เงื่อนไขที่2เป็นจริง
   Else
      If เงื่อนไขที่ 3 Then
         ทำคำสั่งเมื่อเงื่อนไขที่1และ2ไม่เป็นจริง แต่เงื่อนไขที่3เป็นจริง
      Else
         If ... Then
            ...
         Else
            ทำคำสั่งเมื่อเงื่อนไขทั้งหมดข้างบนไม่เป็นจริง
         End If
      End If
   End If
End If
โพสต์นี้ได้รับคำขอบคุณจาก: มาลี

2
ในภาษา VBA  เครื่องหมาย double quote เป็น string delimeter เปิด/ปิดสำหรับค่าคงที่ของข้อความ (ในนี้ผมจะใช้สีแดงแล้วกัน) เช่น ค่าคงที่ของข้อความ AB ก็จะต้องสร้างเป็น "AB"   แต่ถ้าค่าคงที่ของข้อความต้องมี double quote อยู่ภายในอยู่ด้วย เช่น A"B  เราต้องใช้ double quote 2 ตัว   VBA จะรู้ว่าจริงๆแล้ว นี่เป็นตัวอักษร double quote เพียงตัวเดียว ไม่ใช่ delimiter  ดังนั้นเราก็ต้องสร้างเป็น "A""B" 


ส่วน string delimeter ในภาษา SQL จะใช้ได้ทั้ง double quote และ single quote  ดังนั้นเมื่อต้องการค่าคงที่ของข้อความ SELECT * FROM Output WHERE [Type] like 'AB' ลงในตัวแปรชื่อ SQL เราก็จะสร้างคำสั่งเป็น SQL = "SELECT * FROM Output WHERE [Type] like 'ABC'" หรือถ้าเราใช้ double quote แทน single quote คำสั่งก็จะกลายเป็น SQL = "SELECT * FROM Output WHERE [Type] like ""ABC"""


ส่วน & คือ operator ที่ใช้เชื่อมข้อความ 2 ข้อความเข้าด้วยกัน เช่น "A" & "B" ก็จะได้ค่าคงที่ของข้อความเป็น AB หรือ "A" & """B""" ก็จะได้เป็น A"B"
โพสต์นี้ได้รับคำขอบคุณจาก: ปิ่นณรงค์, aek, apirak

3
Object, Control, Textbox ต่างก็เป็น Data Type ใน Access   แต่ตัวแปรของ Object จะกว้างๆ เมื่อสร้างตัวแปรขึ้นมาด้วย Dim ตัวมันเองไม่มีคุณสมบัติอะไรอยู่เลย จนกว่ามันจะถูกกำหนดว่ามันคืออะไร เช่น จากรูป เมื่อกำหนดโดยคำสั่ง Set O = GetObject("C:\Data\DrugList.xls") กลไกของ Access ก็จะกำหนดให้ obj เป็น workbook ของ DrugList.xls ซึ่งหลังจากนี้เราก็สามารถเขียนโค้ดเพื่อเรียกใช้ property และ method ต่างๆที่ตัวโปรแกรม Excel มีให้กับ workbook ได้



แต่อย่างไรก็ตาม ถ้าเรากำลังพิมพ์คำสั่งในบรรทัดต่อๆไปว่า O. เราก็จะยังไม่เห็นว่ามันมี property หรือ method อะไรโผล่ขึ้นมาทั้งๆที่ได้กำหนดไปแล้ว ไม่เหมือนตัวแปร C ซึ่งเป็นตัวแปรประเภท Control ที่จะมี listbox แสดง property และ method ออกมาให้เห็น นั่นเพราะว่า Access จะรู้ว่า O คืออะไรก็ต่อเมื่อโค้ดได้ทำงานแล้ว แต่ขณะที่เรากำลังเขียนโค้ดอยู่ใน Editor นั้น โค้ดยังไม่ได้ทำงาน (ยกเว้นว่าเรากำลังอยู่ในโหมด Debug) ดังนั้น Access จะไม่มีทางรู้เลยว่ามันคืออะไร ก็เลยไม่สามารถแสดง listbox นั้นออกมาให้เราเห็น

Object ต่างกับ Control และ Textbox ตรงที่สองตัวหลังนั้นเป็น object ที่อยู่ในตัว Access เองอยู่แล้ว มันย่อมรู้ดีอยู่แล้วว่ามี property และ method อะไรอยู่บ้างโดยไม่ต้องไปผูกว่า Control หรือ Textbox นี้คือตัว "อะไร" บนฟอร์ม/รายงานตัวนั้น (แต่การที่รู้อยู่แล้ว ไม่ได้หมายความว่าเราจะเรียกใช้ property และ method ก่อนการผูกกับ "อะไร", ด้วยคำสั่ง Set, โดยไม่เกิด error message เพราะมันขึ้นกับว่า property และ method นั้นๆเกี่ยวข้องกับ "อะไร" ที่ Access ต้องรู้ว่ามีอยู่จริงๆก่อนหรือไม่ เช่น ชื่อของ Control หรือ Textbox เป็นต้น)

สรุปว่าเราจะใช้ Object ก็ต่อเมื่อเราต้องการผูก Object นั้นกับ "อะไร" นอกตัว Access เพื่อใช้งาน "อะไร" ตัวนั้น

ส่วน Control ก็คือองค์ประกอบต่างๆบนฟอร์ม/รายงาน เช่น Textbox, Line, Section เป็นต้น มันมี property และ method รวมๆที่องค์ประกอบต่างๆมีเหมือนๆกัน ซึ่งก็มีไม่เท่าไหร่

สุดท้าย Textbox ก็เป็น Object ที่เฉพาะเจาะจงสำหรับเท็กซ์บ็อกซ์ไปเลย มี property และ method เฉพาะ Textbox เท่านั้นครับ เราไม่ค่อยกำหนดตัวแปรของ Textbox เท่าไหร่ เพราะมักอ้างถึง Textbox นั้นได้โดยตรงอยู่แล้ว
โพสต์นี้ได้รับคำขอบคุณจาก: mbbrid, Krathok-man

4
การกำหนด 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, Eik Q Sang

5
เพิ่มเติมหน่อยนะครับ ที่บอกไปครั้งก่อนว่า "ใน 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

6
ห้าม 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

7
ห้อง MS Access / : กำหนดช่วงวันที่
« เมื่อ: 24 พ.ค. 62 , 15:12:14 »
เดือน(วันที่ - 10) + 1 น่าจะให้ผลเดียวกันได้
โพสต์นี้ได้รับคำขอบคุณจาก: ปิ่นณรงค์

8
ผมไม่เคยใช้ MySQL นะครับ แต่ข้างล่างนี้เป็นหลักการ อาจพอช่วยได้

1. อาจเพราะไม่ได้สร้าง Primary Key ไว้ในเทเบิลบน MySQL

2. แต่ถ้าคิดว่าไม่ใช่ ก็ลองอ่าน https://www.thai-access.com/topic_post.asp?CategoryID=1&TopicID=4308

3. ถ้าปัญหาเกิดตอนแก้ไขข้อมูลโดยตรงผ่านหน้าต่างเทเบิล, คิวรี่ หรือฟอร์ม ถ้าเขียนโค้ดจำลองการแก้ไขได้ ก็เขียนดูตามลิงค์ที่ให้ แต่ถ้าไม่เขียน ก็ต้องค้นกูเกิลดูว่าเราจะสร้างและดู MySQL Log File ได้อย่างไร (หาด้วยคำ MySQL Log File) เพราะ Log File ที่ MySQL เก็บไว้ จะเก็บสิ่งต่างๆที่เกิดขึ้นกับฐานข้อมูลของมันเอง ผมเชื่อว่ามันจะเก็บข้อความของปัญหาที่เกิดขึ้นนี้ด้วยว่าเกิดจากอะไรกันแน่

4. อีกอย่างคือ คุณอาจย้ายฐานข้อมูลจาก Access ไป MySQL ไม่ถูกต้องหรือไม่ครบถ้วน ขาดอะไรบางอย่างไป ผมค้นเจอมาว่า MySQL มีโปรแกรมชื่อ MySQL Workbench ซึ่งหน้าที่อันหนึ่งของมันก็คือทำการย้ายฐานข้อมูลจาก Access ไปให้ ลองอ่านดูครับ https://dev.mysql.com/doc/workbench/en/wb-migration-database-access.html link
โพสต์นี้ได้รับคำขอบคุณจาก: chai, diehard4

9
เนื่องจาก Message Box ไม่อนุญาตให้โค้ดบรรทัดต่อไปทำงาน จนกว่าจะปิดกล่องข้อความที่แสดงไป ดังนั้นเราจึงต้องไปใช้อย่างอื่นทำหน้าที่แสดงข้อความแทน เช่น สร้างฟอร์มเพื่อทำหน้าที่เป็น Message Box, แสดงข้อความบน Textbox หรือ Command Button ภายในฟอร์มของตัวของเขาเองครับ ส่วนตัวผมเอง ผมหาพื้นที่สักส่วนนึงบนฟอร์มแล้วสร้าง Textbox เพื่อแสดงข้อความครับ ง่ายดี พอทำงานเสร็จ จะ Invisible มันไปด้วยก็ได้ หรือจะเคลียร์ข้อความใน Textbox ทิ้งก็ได้ ตย.เช่น

    Dim oFSO As Object
    Dim strDestination As String
    strDestination = "\\server\"
    DBEngine.Idle
    Set oFSO = CreateObject("Scripting.FileSystemObject")
   
    Me.[ชื่อ Textbox].Visible = True
    Me.[ชื่อ Textbox] = "ข้อความ"

    oFSO.CopyFile CurrentProject.Path & "Data1.accdb", strDestination   
    Set oFSO = Nothing
   
    Me.[ชื่อ Textbox].Visible = False
    Me.[ชื่อ Textbox] = ""

    MsgBox ("สำรองข้อมูลเสร็จแล้ว"), vbOKOnly + vbInformation, "Process Completed"

แต่ถ้าต้องการสร้างเป็นฟอร์มแทน Message Box ก็ไปสร้างฟอร์มโดยกำหนด Property ของฟอร์มเป็นค่าเหล่านี้
Pop up เป็น Yes
Scroll bars เป็น Neither
Record Selector เป็น No
Navigation Button เป็น No
Auto Resize เป็น Yes
Auto Center เป็น Yes
Border Style เป็น Thin หรือจะเป็น None ก็ได้ ลองดูเอาแบบที่ชอบครับ
Control เป็น None
แล้วก็สร้าง Textbox เพื่อไว้แสดงข้อความ พอจะใช้งาน ก็เพียงเปิดฟอร์มนี้ ใส่ข้อความลง Textbox แล้วปิดเมื่อทำงานเสร็จ เท่านี้เองครับ

โพสต์นี้ได้รับคำขอบคุณจาก: มาลี, diehard4, apirak

10
อ่านแล้ว งง คำถาม แต่ งง ไปอีก ทำไมอาจารย์เก่งจัง
เดาได้ด้วยว่าเค้าถามอะไร

:question: พูดแล้วผมเองก็อยากรู้เลยว่าคำถามไหน ยังพอจำโพสนั้นได้ไหมครับ
โพสต์นี้ได้รับคำขอบคุณจาก: apirak

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

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

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

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

13
ต้องป้องกันตั้งแต่การป้อนครับ โดยกำหนดรูปแบบการป้อนใน Input Mask ของเท็กซ์บ็อกซ์นั้นๆ เช่น ป้อนได้ไม่เกิน 5 หลักและไม่มีทศนิยม ก็กำหนดเป็น 99,999  ส่วนการแสดง ปกติผมจะเลือก Format เป็น Standard และใส่จำนวนทศนิยมที่ต้องการในช่อง Decimal Places
โพสต์นี้ได้รับคำขอบคุณจาก: Kanxay Vnv

14
เชื่อว่า Price จริงๆแล้วไม่ได้เป็น 83 ครับ  น่าจะเป็น 82.50  แต่ format ของ Price บนหน้าฟอร์ม คงจะเป็นประเภทที่แสดงเป็นจำนวนเต็ม  ในการแสดง Access เลยปัดเศษขึ้นเป็น 83 แทนครับ
โพสต์นี้ได้รับคำขอบคุณจาก: Kanxay Vnv

15
น่าจะเพราะตกเครื่องหมาย quote ไป ลองแก้เป็น =DLookup("D1", "DATA", "[D2] = '"& Mid([textbox1],4,4) & "'")
โพสต์นี้ได้รับคำขอบคุณจาก: yot

16
ถ้าจะเขียนในลักษณะเดียวกับที่คุณมาลีเขียนมา ก็เขียนเป็น Forms!Main!Text2 = Text1

แต่โดยปกติผมจะเขียนเป็น Me.Parent!Text2 = Me.Text1 ครับ โดยที่ Parent หมายถึงเมนฟอร์มของฟอร์มปัจจุบันที่โค้ดเราอาศัยอยู่  (Me) ซึ่งตอนนี้เราอยู่ที่ซับฟอร์ม
โพสต์นี้ได้รับคำขอบคุณจาก: Un, มาลี

หน้า: [1] 2 3 4 ... 10