1
ห้อง MS Access / : VBA ป้องกันการลบข้อมูลบาง record แบบมีเงื่อนไข
« เมื่อ: 12 ก.ย. 67 , 16:09:35 »
ถามเองตอบเอง ได้แล้วครับ
me.AllowDeletions=False
me.AllowDeletions=False
โพสต์นี้ได้รับคำขอบคุณจาก: UnKnown
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.
จะพยามอธิบายให้เข้าใจนะครับ เผื่อเป็นประโยชน์กับท่านอื่นๆด้วยขอบคุณมากนะครับ เดี๋ยวผมลองศึกษาดูจากคำแนะนำนะครับ
- ฟังก์ชั่นนี้เป็นการเปลี่ยนพาธของ Linked Table ที่มีอยู่แล้วในไฟล์เดิม ดังนั้นจะใช้ได้ต่อเมื่อมีการทำ Linked Table ในไฟล์ MS Access อยู่ก่อนแล้ว
- โดยฟังก์ชั่นนี้จะยึดชื่อตารางที่มีอยู่เดิมในการเปลี่ยนพาธตามที่กำหนดเท่านั้น ไม่ใช่เป็นการลิ้งค์พาธชื่อตารางใหม่
- สร้างฟังก์ชั่นขึ้นใหม่ดังนี้:โค๊ด: [Select]Public Function ChangeLinkedMDB()
Dim DB As DAO.Database
Dim TD As DAO.TableDef
On Error GoTo Err_Handler
Set DB = CurrentDb
'---หากไม่ต้องการลูป ต้องการแค่ชื่อตารางเป้าหมายเพียงชื่อเดียว-----------------------------------------
'Set TD = DB.TableDefs("ชื่อตารางเป้าหมาย")
'If (TD.Attributes And dbAttachedTable) = dbAttachedTable Then
'TD.Connect = ";DATABASE=" & CurrentProject.Path & "\1.accdb"
'TD.Connect = ";DATABASE=" & CurrentProject.Path & "\1.accdb" & ";pwd=1234"
'หากไฟล์มี password
'TD.RefreshLink
'End If
'--------------------------------------------------------------------------------------
For Each TD In DB.TableDefs
If (TD.Attributes And dbAttachedTable) = dbAttachedTable Then
TD.Connect = ";DATABASE=" & CurrentProject.Path & "\1.accdb" '1.accbd ชื่อไฟล์ Back End เป้าหมาย
'TD.Connect = ";DATABASE=" & CurrentProject.Path & "\1.accdb" & ";pwd=1234"
'หากไฟล์มี password
TD.RefreshLink
End If
Next TD
Exit_Handler:
DB.Close: Set DB = Nothing
Exit Function
Err_Handler:
Select Case Err.Number
Case 3024&, 3044&
MsgBox "ไม่พบไฟล์ในพาธที่กำหนด", , "พาธไฟล์ผิดพลาด"
Case 3011&
MsgBox "ไม่พบชื่อตารางเป้าหมายในไฟล์ที่กำหนด", , "ชื่อตารางผิดพลาด"
End Select
End Function
* ส่วนเสริมฟังก์ชั่นสำหรับการอ่านค่าลิ้งค์ของตารางก่อน หากไม่ตรงกับที่อยู่ปัจจุบันค่อยใช้ฟังก์ชั่นเปลี่ยน โปรแกรมจะได้ไม่ต้องเปลี่ยนลิ้งค์ทุกครั้งที่เปิดไฟล์โค๊ด: [Select]Private Function GetLinkedDBName(TableName As String) As String
Dim db As DAO.Database
Dim Ret As String
On Error GoTo DBNameErr
Set db = CurrentDb() 'Set db = DAO.OpenDatabase("PathFileName", False, False, ";pwd=Password")
Ret = db.TableDefs(TableName).Connect
GetLinkedDBName = Right(Ret, Len(Ret) - (InStr(1, Ret, "DATABASE=") + 8))
db.Close: Set db = Nothing
Exit Function
DBNameErr:
GetLinkedDBName = 0
db.Close: Set db = Nothing
End Function
- การใช้งานฟังก์ชั่นร่วมกันโค๊ด: [Select]Public Function iStartup()
If GetLinkedDBName("Table1") <> CurrentProject.Path & "\1.accdb" Then
ChangeLinkedMDB
End If
'DoCmd.OpenForm "ชื่อฟอร์ม" 'หากต้องการเปิดฟอร์มเป้าหมายอัตโนมัติ
End Function
<การใช้งาน>
- เนื่องจากการเปลี่ยนพาธลิ้งค์เทเบิ้ล ต้องทำก่อนการเรียก ตาราง คิวรี่ ฟอร์ม หรือ รายงาน ดังนั้นจึงต้องเรียกตั้งแต่ตอนเปิดไฟล์ MS Access
1. เลือกเมนูหัวข้อ Create > Macro
2. เลือกหัวข้อคำสั่ง RunCode
3. ใส่คำสั่ง iStartup() ลงในช่องว่าง
4. เซฟ Macro เป็นชื่อ Autoexec เท่านั้น (หากมีชื่อนี้อยู่แล้ว ให้ไปเพิ่มคำสั่งใหม่ที่ Macro Autoexec แทน)
<อธิบาย>
- For each TD .... ก็เป็นการวนลูป โดยกำหนด object variable TD ให้เป็นทีละเทเบิลในฐานข้อมูล
- TD.Attributes จะให้ค่าเท่ากับ dbAttachedTable เมื่อเทเบิลนั้นเป็น Linked Table ที่ลิงค์มาจากฐานข้อมูลประเภท Access ด้วยกันเอง (พวก .accdb, .mdb, .mda) แต่ถ้าลิ้งค์มาจาก ODBC จะให้เป็นค่า dbAttachedODBC โดยปกติคิดว่า 99.99% เราสามารถทดสอบด้วยคำสั่ง If TD.Attributes = dbAttachedTable then ได้โดยตรง แต่เนื่องจาก .Attributes อาจมีค่าเกิดจากการรวมหลายๆ option เข้าด้วยกัน ด้วย logical OR (แต่ก็ไม่ทราบเหมือนกันว่ามันจะรวมกับ option อื่นอย่างไรได้บ้าง) ดังนั้นเพื่อให้แน่ใจเต็ม 100% เวลาจะทดสอบกรองเอาเพื่อดูว่ามีค่าของ dbAttachedTable อยู่ในส่วนผสมนั้นหรือไม่ ก็ต้องทดสอบด้วย logical AND (ตรงนี้คิดว่าหลายๆท่านก็คงจะทราบดีอยู่แล้ว) คำสั่ง If ที่เขียนให้ดูเลยออกมาเป็นอย่างนั้น
- TD.Connect ก็เป็นการกำหนดชื่อพาธและไฟล์ที่จะลิ้งค์เข้ามา เนื่องจากเราลิงค์มาจากเทเบิลต้นทางที่ชื่อเดิมเสมอ (ชื่อเดียวกันกับที่เราลิงค์มาครั้งแรก) ดังนั้นจึงไม่ต้องบอกมันอีกว่ามาจากเทเบิลชื่ออะไร
- TD.RefreshLink เป็นการสั่งให้ทำการอ่านค่าใหม่ทั้งหมด
- DB.Close: Set DB = Nothing สั่งให้ปิด Database และยกเลิกการเซ็ท DB
<หมายเหตุ>
* การใช้ฟังก์ชั่นนี้ ต้องมีการสร้าง Link Table ของเดิมอยู่ก่อนแล้ว ลักษณะของฟังก์ชั่นจะเป็นการแก้ไขพาธของ Link Table ใหม่ให้เท่านั้น ไม่ใช่การสร้าง Link Table ขึ้นมาใหม่ แต่หากต้องการทำลิ้งค์ตารางขึ้นมาใหม่จากไฟล์ MS Access ภายนอกให
* หากไฟล์ข้อมูลที่ทำการลิ้งค์มีการตั้งรหัสผ่านไว้ จะทำให้การเปลี่ยนลิ้งค์ช้ากว่าปกติ
ลองทำความเข้าใจและปรับใช้ดูนะครับ
ใช้ Nas synology เป็นตัวเก็บ database ของ access แนวเหมือนเป็น BackEnd ส่วนวิธีเชื่อมต่อ VPN ตามคลิบก็แนะนำให้ใช้ OpenVPN ลองตั้งค่าใช้งานดูครับขอบคุณนะครับ เดี๋ยวลองทำดูก่อน ได้เรื่องยังไงจะมาอัพเดทครับ
ใส่โค้ดว่าได้แล้วครับ ขอบคุณมากครับ
DoEvents
แล้วลองเปลี่ยนโค้ด เซฟดูครับว่าได้ไหม
DoEvents
DoCmd.save acForm, "Merchandiser Key Update"
ลองดูตัวอย่างนี้นะครับ น่าจะโอเคสุดละได้เลยครับ ขอบคุณมากๆเลยนะครับคุณปิ่นณรงค์ (คุณ Newbies เดิมหรือเปล่าครับ)
บน Moduleโค๊ด: [Select]Public Function RowNum(frm As Form) As Variant
On Error GoTo Err_RowNum
With frm.RecordsetClone
.Bookmark = frm.Bookmark
RowNum = .AbsolutePosition + 1
End With
Exit_RowNum:
Exit Function
Err_RowNum:
If Err.Number <> 3021& Then
Debug.Print "RowNum() error " & Err.Number & " - " & Err.Description
End If
RowNum = Null
Resume Exit_RowNum
End Function
ที่ textbox ชื่อ NO ใส่ =RowNum([Form])
ตัวอย่างด้านล่าง
ที่ Event: On mouse up ให้ใส่ Code นี้เข้าไปครับตามที่อาจารย์แนะนำ ผมลองทำดูแล้วก็ทำงานตามที่อาจารย์บอกครับ แต่ก็ยังไม่ได้ตรงตามจุดประสงค์ของผม แต่ไม่เป็นไรครับผมคงไม่ไป protectหรือ hide อะไรมากมายแล้วครับ
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Me.ชื่อฟิลด์ที่ต้องการซ่อน.ColumnHidden = False Then
Me.ชื่อฟิลด์ที่ต้อกงารซ่อน.ColumnHidden = True
End If
End Sub
Unhide ได้แป๊บเดียว(ประมาณ 1-2 วินาที) ก็จะกลับไปซ่อนใหม่ทันที
ถ้ามีหลายฟิลด์ก็เหนื่อยหน่อยนะ
อ้อ! ใช้ได้เฉพาะ Datasheet View เท่านั้นนะครับ