Đánh giá chủ đề:
  • 2 Votes - 4.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Thủ Thuật] Lưu vết chương trình khi nhập liệu
#21
Bác xem file đính kèm của e ạ

Mở file lên khi vào form frmLogin và đăng nhập (admin/admin; Nguyen Van A/1; Nguyen Van B/2)
Mình muốn khi đăng nhập vào bằng user nào đấy, các thao tác thêm, chỉnh sửa sẽ được Lưu Vết lại

Ví dụ:
1. Mở form frmSearchExample,
2. Double-click vào 1 thông tin trong Listbox,
3. Một form mới mở ra frmContactDetail
4. Mình sẽ cập nhật lại thông tin trong này sau đó nhấn Update --> lưu vết sẽ được lưu lại giá trị cũ là gì giá trị mới là gì, user nào đã làm vào bảng tblLuuVetChuongTrinh

Cảm ơn bác nhiều,


File đính kèm
.zip   HelpMe20062012.zip (Kích cỡ: 542.6 KB / Tải về: 65)
Chữ ký của uronmapu Cảm ơn cả nhà

Để học Access không nên ngại đặt câu hỏi


Uron
Reply
Những người đã cảm ơn
#22
(23-05-12, 04:29 PM)n2kp Đã viết: Xin chào cả nhà.
Tôi có viết một chương trình Access quản lý công việc trong phòng tại cơ quan. Tôi dùng phương pháp BackEnd và FrontEnd để chia sẻ dữ liệu trong mạng Lan, tổng số user khoảng 10 người. Chương trình chạy tốt và hiệu quả. Tuy nhiên có một vấn đề mà lâu nay tôi chưa tìm ra giải pháp tối ưu là làm sao biết được ai đã sửa dữ liệu trên form ngày giờ nào, và sửa như thế nào.
Tôi đã tìm kiếm nhiều giải pháp trên diễn đàn và đã áp dụng, tuy nhiên code rất dài, phức tạp, khó quản lý. Bởi tổng số record trong CSDL hơn 7000 records cùng với 10 users cùng làm việc hàng ngày, quản lý tốt CSDL là nhiệm vụ hàng đầu, hơn nữa trong phòng không phải ai cũng hiểu rõ vấn đề bảo vệ CSDL là quan trọng như thế nào.
Và thật không ngờ, không phải giải pháp cao siêu gì cả, rất đơn giản mà thật hiệu quả. Giờ đây, mỗi sáng tôi chỉ mở form theo dõi là có thể biết ai đã làm gì hôm qua, dữ liệu nào đã chỉnh sửa, giá trị cũ sang giá trị mới ra sao, không phải nhức đầu khi phải phân quyền cho từng user. Bây giờ ai cũng có thể chỉnh sửa dữ liệu và có trách nhiệm với việc thay đổi của mình.
Nói hơi dông dài để các bạn có thể hiểu rõ hơn vấn đề. Hôm nay tôi sẽ chia sẻ giải pháp của tôi với các bạn với mục đích là cùng nhau học hỏi. Biết đâu đây chưa phải là giải pháp tốt nhất. Rất mong sự chia sẻ từ diễn đàn.
I. MÔ TẢ CHƯƠNG TRÌNH
Khi mở chương trình sẽ có Form Đăng nhập như sau
[Hình: Dangnhap.jpg]
Sau khi đăng nhập đúng username và password, click button Đăng nhập sẽ mở ra Form Customers (lấy mẫu từ NorthWind Database của MS Office 2003)
[Hình: Customers.jpg]

Từ đây, bạn có thể sửa bất kỳ record nào, bất kỳ control nào trên form. Sau khi cập nhật dữ liệu xong, bạn đóng Form, thế thì xong.
Thế làm sao bạn có thể biết user nào đã cập nhật dữ liệu, cập nhật khi nào. Đây mới chính là vấn đề cần giải quyết. Chúng ta sẽ có một table tblLuuVetChuongTrinh ghi lại tất cả các hoạt động của user trên form này. Nào bạn hãy mở table tblLuuVetChuongTrinh, chúng ta sẽ có gì.

[Hình: LuuVetChuongTrinh.jpg]

Giờ đây ta đã biết user nào sửa control nào, giá trị cũ qua giá trị mới, ngày giờ cụ thể. Bạn chỉ cần tạo một form lọc những giá trị cần biết để quản lý tốt hơn CSDL của mình.

II. GIẢI QUYẾT VẤN ĐỀ

Trong CSDL mẫu này, bạn hãy import 1table Customers và 1 form Customers từ NorthWind Database, bỏ đi tất cả code trong AfterUpdate của từng Control và Form của Customers Form nguyên gốc.
1. Tạo table tblUsers có cấu trúc như sau:
[Hình: cautructblusers.jpg]
2. Nhập tên user và password của từng user
[Hình: dulieutbluser.jpg]
3. Tạo table tblLuuVetChuongTrinh có cấu trúc như sau:
[Hình: tblluvetchuongtrinh.jpg]

4. Tạo 5 biến toàn cục (Global) trong standard module
Option Compare Database
Public GvarUserName As String
Public varOldValue As String
Public varNewValue As String
Public varControlName As String
Public varFormName As String

Các biến toàn cục này có ý nghĩa thế nào chắc không cần giải thích các bạn nhỉ Tongue_smile

Khi form Đăng nhập mở lên, user chọn username từ combo box và gõ password, sau đó click button Đăng nhập, nếu chọn đúng tất cả sẽ mở form Customers, đồng thời sẽ gán biến toàn cục GvarUsernName = UserName.

Đây là đoạn code kiểm tra khi click vào button đăng nhập (OnClick)

Private Sub cmdDangNhap_Click()
Dim varPassword As String
' Doan code khong cho Control cbUserName trong hay rong
If IsNull(Me.cbUserName) Or Me.cbUserName = "" Then
MsgBox "Please select Username!", vbCritical, "Require Data"
Me.cbUserName.SetFocus
Exit Sub
End If
' Doan code khong cho Control txtPassword trong hay rong
If IsNull(Me.txtPassword) Or Me.txtPassword = "" Then
MsgBox "Please enter Password!", vbCritical, "Require Data"
Me.txtPassword.SetFocus
Exit Sub
End If

varPassword = DLookup("Password", "tblUser", "Username ='" & Me.cbUserName & "'")
If Me.txtPassword = varPassword Then
GvarUserName = Me.cbUserName
DoCmd.Close acForm, Me.Name
DoCmd.OpenForm "Customers"
Else
MsgBox "Incorect Password. Please contact the Administrator.", vbCritical, "Cannot access the Database"
Me.txtPassword.SetFocus
Exit Sub
End If
End Sub


Sau khi form Customers mở lên, user sửa đổi dữ liệu thì sẽ có một hàm lưu lại các thay đổi đó, đồng thời ghi các thay đổi đó vào table tblLuuVetChuongTrinh. Chúng ta đã có 5 biến toàn cục (global) đã định nghĩa ở trên, vấn đề là chúng ta sẽ gán giá trị cho các biến như thế nào. Ở đây với sự kiện AfterUpdate cho từng control trên form chúng ta sẽ gọi một Function có tên GoiHamLuuVetChuongTrinh. Đây chính là cái quan trọng nhất của chương trình, không cao siêu, không phức tạp, cực kỳ đơn giản. Function GoiHamLuuVetChuongTrinh được tôi viết như sau:

Function GoiHamLuuVetChuongTrinh()
If IsNull(Screen.ActiveControl.OldValue) Then
varOldValue = ""
Else
varOldValue = Screen.ActiveControl.OldValue
End If
If IsNull(Screen.ActiveControl.Value) Then
varNewValue = ""
Else
varNewValue = Screen.ActiveControl.Value
End If
varControlName = Screen.ActiveControl.Name
varFormName = Screen.ActiveForm.Name
Call CapNhatLuuVet(GvarUserName, varOldValue, varNewValue, varControlName, varFormName)
End Function


Hàm này sẽ gán từng giá trị cho các biến toàn cục ở trên, ngữ pháp câu lệnh đơn giản, tuy nhiên theo tôi kỹ thuật dùng Screen.ActiveControl đã biến những việc phức tạp trở nên cực kỳ đơn giản. Kỹ thuật này không cần biết Control đó tên gì, giá trị bao nhiêu mà chỉ đơn giản là Screen.ActiveControl.

Function CapNhatLuuVet sẽ add các biến toàn cục vào tblLuuVetChuongTrinh.

Function CapNhatLuuVet(fUserName, fOldValue, fNewValue, fControlName, fFormName)
Dim db As Database
Dim rst As Recordset
Set db = CurrentDb
Set rst = db.OpenRecordset("tblLuuVetChuongTrinh")
rst.AddNew
rst!TenUser = fUserName
rst!GiaTriCu = fOldValue
rst!GiatriMoi = fNewValue
rst!TenControl = fControlName
rst!TenForm = fFormName
rst!NgayCapNhat = Date
rst!GioCapNhat = Time()
rst.Update
rst.Close
Set rst = Nothing
Set db = Nothing
End Function



Sau khi đã có 2 function quan trọng trên, bạn vào từng control một trên form Customers chon sự kiện AfterUpdate và gõ (hoặc copy) chỉ một dòng lệnh sau:

Call GoiHamLuuVetChuongTrinh


Thế là xong, riêng tôi đã cất đi gánh nặng khi phải suy nghĩ về cách phân quyền cho từng user (ai được sửa cái gì, ai không được sửa cái gì, làm sao theo dõi . . .) khi áp dụng kỹ thuật này. Mỗi người đều có một phương pháp riêng để giải quyết các vấn đề trong công việc, sao cho ĐƠN GIẢN, NHANH CHÓNG, HIỆU QUẢ. Rất mong những ý kiến đóng góp của tất cả các bạn ở diễn đàn thuthuataccess.com và hy vọng các bạn có một giải pháp tốt hơn cho vấn đề này.
Tôi đã làm theo hương dẫn của bạn nhưng khi chay thì chương trình báo lỗi: user-defined type not defined.
và dong dưới hiện lên màu vàng:
Function CapNhatLuuVet(fUserName, fOldValue, fNewValue, fControlName, fFormName)
Xin cho mình biết nguyên nhân của nó là gì
Chữ ký của buitheduy Xin chào, mình là buitheduy, Tham gia http://thuthuataccess.com/forum từ ngày 21-09 -12.
Reply
Những người đã cảm ơn
#23
(31-05-12, 02:53 PM)n2kp Đã viết:
(29-05-12, 05:40 PM)connguoi123 Đã viết: Trong trường hợp mình muốn trong bảng tblLuuvetchuongtrinh có nêu rõ được cả bản ghi nào được user tác động kô ( để biết người sử dụng tác động vào record nào - Ví dụ số hóa đơn nào chẳng hạn )? Vậy phải làm như nào, mong các bạn chỉ giáo thêm, tôi thấy cái này hay và tiện lợi quá. Cám ơn rất nhiều.

Chào bạn,
Bạn có thể thêm một trường (vd:IDHoadon) vào tblLuuvetchuong trình và trong Function CapNhatLuuVet bạn thêm một tham số IDhoadon, lúc đó Function CapNhatLuuVet chi tiết sẽ như thế này:
Function CapNhatLuuVet(IDhoadon, fUserName, fOldValue, fNewValue, fControlName, fFormName)
Dim db As Database
Dim rst As Recordset
Set db = CurrentDb
Set rst = db.OpenRecordset("tblLuuVetChuongTrinh")
rst.AddNew
rst!IDhoadon = IDhoadon
rst!TenUser = fUserName
rst!GiaTriCu = fOldValue
rst!GiatriMoi = fNewValue
rst!TenControl = fControlName
rst!TenForm = fFormName
rst!NgayCapNhat = Date
rst!GioCapNhat = Time()
rst.Update
rst.Close
Set rst = Nothing
Set db = Nothing
End Function

Thân chào.

Chào bạn, bạn chỉ giúp mình cách lấy recordid mà active object thuộc về. Cám ơn bạn trước![/font]
Chữ ký của ppdung.public Xin chào, mình là ppdung.public, Tham gia http://thuthuataccess.com/forum từ ngày 04-03 -14.
Reply
Những người đã cảm ơn
#24
(31-05-12, 02:53 PM)n2kp Đã viết:
(29-05-12, 05:40 PM)connguoi123 Đã viết: Trong trường hợp mình muốn trong bảng tblLuuvetchuongtrinh có nêu rõ được cả bản ghi nào được user tác động kô ( để biết người sử dụng tác động vào record nào - Ví dụ số hóa đơn nào chẳng hạn )? Vậy phải làm như nào, mong các bạn chỉ giáo thêm, tôi thấy cái này hay và tiện lợi quá. Cám ơn rất nhiều.

Chào bạn,
Bạn có thể thêm một trường (vd:IDHoadon) vào tblLuuvetchuong trình và trong Function CapNhatLuuVet bạn thêm một tham số IDhoadon, lúc đó Function CapNhatLuuVet chi tiết sẽ như thế này:
Function CapNhatLuuVet(IDhoadon, fUserName, fOldValue, fNewValue, fControlName, fFormName)
Dim db As Database
Dim rst As Recordset
Set db = CurrentDb
Set rst = db.OpenRecordset("tblLuuVetChuongTrinh")
rst.AddNew
rst!IDhoadon = IDhoadon
rst!TenUser = fUserName
rst!GiaTriCu = fOldValue
rst!GiatriMoi = fNewValue
rst!TenControl = fControlName
rst!TenForm = fFormName
rst!NgayCapNhat = Date
rst!GioCapNhat = Time()
rst.Update
rst.Close
Set rst = Nothing
Set db = Nothing
End Function

Thân chào.

Noname cho mình hỏi còn hàm GoiHamLuuVetChuongTrinh thì ta lấy tên table được chỉnh sửa phải thêm lệnh Screen.ActiveControl như thế nào ?
Chữ ký của winer531 Xin chào, mình là winer531, Tham gia http://thuthuataccess.com/forum từ ngày 22-11 -13.
Reply
Những người đã cảm ơn
#25
Bài viết rất hay.
Đây là file mẫu để mọi người khỏi mất thời gian.
File access 2007-2013 accdb.
http://www.mediafire.com/download/ch4wx0...LuuVet.rar
Chữ ký của changkhoonline77 Xin chào, mình là changkhoonline77, Tham gia http://thuthuataccess.com/forum từ ngày 25-06 -12.
Reply
Những người đã cảm ơn
#26
Chào các bạn,

Mình đã làm theo hướng dẫn trên của n2kp

Tuy nhiên chương trình không update giá trị cũ và mới.

Không biết mình đã làm sai ở khâu nào.

Các bạn xem file đính kèm và sửa giúp mình.
http://www.mediafire.com/download/1cp9eg...a/test.zip

Thanks,
Tâm
Reply
Những người đã cảm ơn
#27
(14-07-14, 01:16 PM)btamsgn Đã viết: Chào các bạn,

Mình đã làm theo hướng dẫn trên của n2kp

Tuy nhiên chương trình không update giá trị cũ và mới.

Không biết mình đã làm sai ở khâu nào.

Các bạn xem file đính kèm và sửa giúp mình.
http://www.mediafire.com/download/1cp9eg...a/test.zip

Thanks,
Tâm
Không biết bạn làm được chưa nhưng file download bị lỗi rồi.
Chữ ký của changkhoonline77 Xin chào, mình là changkhoonline77, Tham gia http://thuthuataccess.com/forum từ ngày 25-06 -12.
Reply
Những người đã cảm ơn
#28
nếu form có nút lưu với bỏ qua thì sao bạn.
Nếu như của bạn hướng dẫn thì sau khi thay đổi nội dung trong control thì ngay lập tức dc thêm vào tblluuvetchuongtrinh.
Nhưng yêu cầu đặt ra là khi ấn nút lưu trên form thì mới xác nhận là đã thay đổi khi đó mới thêm vào tblluuvetchuongtrinh.
Còn nếu ấn bỏ qua thì xem như chưa thay đổi gì hết.
Chữ ký của mrsiro Xin chào, mình là mrsiro, Tham gia http://thuthuataccess.com/forum từ ngày 05-12 -14.
Reply
Những người đã cảm ơn
#29
Xin chào mọi người mình làm giống bạn đã chạy ok trên file acc bình thường  nhưng khi mình cho table tblLuuVetChuongTrinh lên sql rồi mình link table tới sql  nó báo lỗi ở phần code 
Function CapNhatLuuVet(fUserName, fOldValue, fNewValue, fControlName, fFormName)

Dim DB As DAO.Database
Dim rst As DAO.Recordset
Set DB = CurrentDb
Set rst = DB.OpenRecordset("tblLuuVetChuongTrinh", dbOpenSnapshot)
rst.AddNew   báo lỗi
rst!TenUser = fUserName
rst!GiaTriCu = fOldValue
rst!GiatriMoi = fNewValue
rst!TenControl = fControlName
rst!TenForm = fFormName
rst!NgayCapNhat = Date
rst!GioCapNhat = time()
rst.Update
rst.Close
Set rst = Nothing
Set DB = Nothing
End Function

mong bạn chỉnh sửa giúp mình Cảm ơn bạn rất nhiều 
khongventoan@gmail.com
Chữ ký của kiengxuong Xin chào, mình là kiengxuong, Tham gia http://thuthuataccess.com/forum từ ngày 05-06 -15.
Reply
Những người đã cảm ơn
#30
(22-06-15, 06:12 PM)kiengxuong Đã viết: Xin chào mọi người mình làm giống bạn đã chạy ok trên file acc bình thường  nhưng khi mình cho table tblLuuVetChuongTrinh lên sql rồi mình link table tới sql  nó báo lỗi ở phần code 
Function CapNhatLuuVet(fUserName, fOldValue, fNewValue, fControlName, fFormName)

Dim DB As DAO.Database
Dim rst As DAO.Recordset
Set DB = CurrentDb
Set rst = DB.OpenRecordset("tblLuuVetChuongTrinh", dbOpenSnapshot)
rst.AddNew   báo lỗi
rst!TenUser = fUserName
rst!GiaTriCu = fOldValue
rst!GiatriMoi = fNewValue
rst!TenControl = fControlName
rst!TenForm = fFormName
rst!NgayCapNhat = Date
rst!GioCapNhat = time()
rst.Update
rst.Close
Set rst = Nothing
Set DB = Nothing
End Function

mong bạn chỉnh sửa giúp mình Cảm ơn bạn rất nhiều 
khongventoan@gmail.com

Nó báo lỗi gì vậy bạn?
Đối với table dạng link, nếu bạn muốn thêm xóa sửa thì truyền đối số là dbOpenDynaset
Nếu chỉ muốn truy vấn (như dlookup) thì dùng dbOpenSnapshot sẽ cải thiện tốc độ.
Chữ ký của Noname 020
ღღღღღTài sản của Noname (View All Items) ღღღღღ
Reply
Những người đã cảm ơn


Có thể liên quan đến chủ đề
Chủ đề: Tác giả Trả lời: Xem: Bài mới nhất
  Tránh xung đột dữ liệu trong access quocdung9999 16 1,692 23-11-16, 11:13 AM
Bài mới nhất: quocdung9999
  [Thủ Thuật] Tạo thanh tiến trình trên Form (Progress bar) khi xử lý dữ liệu ongke0711 18 1,500 21-10-16, 10:17 PM
Bài mới nhất: ongke0711
  [Hỏi] Quá trình thực hiện một lệnh với CSDL dinh_trong_hoa 1 174 02-08-16, 04:06 PM
Bài mới nhất: ongke0711
Photo Hướng dẫn tính tôn kho từ một bảng chi tiết nhập xuất tt1212 8 399 17-06-16, 04:47 PM
Bài mới nhất: tt1212
  Sử dụng Class Module và Kết nối dữ liệu SQL SERVER trong Access VBA lehongduc 42 17,037 12-06-16, 12:28 PM
Bài mới nhất: lehongduc

Chuyển nhanh:


User(s) browsing this thread: 1 Guest(s)
Diễn Đàn Thơ Văn Thi Ẩm Lâu|Nhà Hàng Sông Thơ