Đánh giá chủ đề:
  • 0 Votes - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
[Hỏi] Mã Số Nhân Viên Tự Động Tăng
#1
Chào mọi người!
Em có soạn 1 đoạn code để khi nhấn nút "Thêm", Access sẽ tự động điền Mã Nhân Viên theo thứ tự tăng dần theo cú pháp: NV00001. Đoạn code như sau:
Mã:
Dim DB As DAO.Database
Dim rs As DAO.Recordset
Dim tt As Integer

Private Sub Them_Click()
   On Error GoTo Err_Them_Click
       
   DoCmd.GoToRecord , , acNewRec
Set DB = CurrentDb()
                   Set rs = DB.OpenRecordset("T_NhanVien", dbOpenDynaset)
                       tt = DCount("MaNV", "T_NhanVien")
                   For i = 1 To tt
                       rs.Edit
                       rs!MaNV = "NV" & Right("00000" & i, 5)
                       rs.Update
                       rs.MoveNext
                   Next
                       rs.Close
                       DB.Close

Exit_Them_Click:
       Exit Sub
Err_Them_Click:
       MsgBox Err.Description
       Resume Exit_Them_Click
End Sub

Nó trơ trơ, không chịu chạy. E không biết tại sao? Nhờ anh/chị xem giúp ạ!
Chữ ký của pherotao "Hạnh phúc ở đâu... biết tìm đâu,
Hồng trần là thế giới muôn màu,
Hội đủ nhân duyên... thời sinh quả,
Kết thúc... cũng là lúc bắt đầu".
Reply
Những người đã cảm ơn
#2
Bạn diễn giải thử từng dòng code bên trên của bạn xem bạn hiểu như thế nào nhé. Bắt đầu từ dòng Set rs = DB....
Chữ ký của ongke0711 If you BORN poor, it's not your mistake. But if you DIE poor, It's your mistake!
ღღღღღTài sản của ongke0711 (View All Items) ღღღღღ
Reply
Những người đã cảm ơn
#3
Cái này trên 4rum có rồi mà bạn, chịu khó search một chút nhé big green
Chữ ký của cpucloi Tôi chỉ biết mỗi một điều là những điều tôi biết được còn quá ít 021


ღღღღღTài sản của cpucloi (View All Items) ღღღღღ
Reply
Những người đã cảm ơn
#4
(22-12-17, 09:36 AM)ongke0711 Đã viết: Bạn diễn giải thử từng dòng code bên trên của bạn xem bạn hiểu như thế nào nhé. Bắt đầu từ dòng Set rs = DB....

Dim DB As DAO.Database
Dim rs As DAO.Recordset
Dim tt As Integer

Private Sub Them_Click()
   On Error GoTo Err_Them_Click
       
   DoCmd.GoToRecord , , acNewRec
Set DB = CurrentDb() 'Lấy (gán) CSDL hiện hành
                   Set rs = DB.OpenRecordset("T_NhanVien", dbOpenDynaset) 'Mở một đối tượng kiểu Dynaset ( tham chiếu đến recordset T_NhanVien)
                       tt = DCount("MaNV", "T_NhanVien") 'Đếm Mã Nhân Viên
                   For i = 1 To tt 'Cho i chạy từ 1 đến tt
                       rs.Edit
                       rs!MaNV = "NV" & Right("00000" & i, 5)
                       rs.Update
                       rs.MoveNext
                   Next
                       rs.Close
                       DB.Close

Exit_Them_Click:
       Exit Sub
Err_Them_Click:
       MsgBox Err.Description
       Resume Exit_Them_Click
End Sub

Nhờ anh hướng dẫn chỉ bảo thêm ạ!
Chữ ký của pherotao "Hạnh phúc ở đâu... biết tìm đâu,
Hồng trần là thế giới muôn màu,
Hội đủ nhân duyên... thời sinh quả,
Kết thúc... cũng là lúc bắt đầu".
Reply
Những người đã cảm ơn
#5
(22-12-17, 12:51 PM)pherotao Đã viết: ...
Set DB = CurrentDb() 'Lấy (gán) CSDL hiện hành
                   Set rs = DB.OpenRecordset("T_NhanVien", dbOpenDynaset) 'Mở một đối tượng kiểu Dynaset ( tham chiếu đến recordset T_NhanVien)
                       tt = DCount("MaNV", "T_NhanVien") 'Đếm Mã Nhân Viên
                   For i = 1 To tt 'Cho i chạy từ 1 đến tt
                       ..

007 007  Nói bạn diễn giải để xem bạn có hiểu code nó chạy như thế nào chứ đâu kêu bạn dịch ra tiếng Việt vòng lặp... 014 . Khi bạn hiểu cách code chạy sẽ tự thấy ra cái sai của code so với trường hợp của bạn.

- Đếm table T_NhanVien để xem đang có bao nhiêu NV, lấy số tổng. Sau đó duyệt toàn bộ T_NhanVien từ dòng đầu tiên...
Chữ ký của ongke0711 If you BORN poor, it's not your mistake. But if you DIE poor, It's your mistake!
ღღღღღTài sản của ongke0711 (View All Items) ღღღღღ
Reply
Những người đã cảm ơn pherotao
#6
Nó không chịu chạy hả bạn??
Bạn cho hàm 
For i = 1 to tt
'thân hàm
next i
Bạn không có cái chữ i thì nó chạy sao?

Bạn nên thử chạy kiểu Do While Loop đi cho nó thông mình :v
Chữ ký của duynamvnn1208 duynamvnn1208,gia nhập Thủ Thuật Access từ 25-06 -17.
Reply
Những người đã cảm ơn
#7
(22-12-17, 01:04 PM)ongke0711 Đã viết:
(22-12-17, 12:51 PM)pherotao Đã viết: ...
Set DB = CurrentDb() 'Lấy (gán) CSDL hiện hành
                   Set rs = DB.OpenRecordset("T_NhanVien", dbOpenDynaset) 'Mở một đối tượng kiểu Dynaset ( tham chiếu đến recordset T_NhanVien)
                       tt = DCount("MaNV", "T_NhanVien") 'Đếm Mã Nhân Viên
                   For i = 1 To tt 'Cho i chạy từ 1 đến tt
                       ..

007 007  Nói bạn diễn giải để xem bạn có hiểu code nó chạy như thế nào chứ đâu kêu bạn dịch ra tiếng Việt vòng lặp... 014 . Khi bạn hiểu cách code chạy sẽ tự thấy ra cái sai của code so với trường hợp của bạn.

- Đếm table T_NhanVien để xem đang có bao nhiêu NV, lấy số tổng. Sau đó duyệt toàn bộ T_NhanVien từ dòng đầu tiên...

Thật sự e chưa biết nó sai chỗ nào. Vì cũng code này nhưng là 1 chương trình e viết trước đó đã lâu (khoảng 2010, access 2003), nó hoạt động tốt. E đã kiểm tra trong References đã chọn lựa kỹ càng giống nhau, nhưng nó vẫn... sai???

A có thể giải thích thêm được không ạ!

Đây là T_NhanVien_2010 (e viết 2010): MaNV, TenNV; (tạm gọi DATA_2010)
và T_NhanVien_2017 (e đang viết): MaNV, TenNV; (Tạm gọi DATA_2017)

Sau đó, e thiết kế F_NhanVien, với phần Default Value của MaNV là: "MaNV" (ở cả 2 DATA), thiết kế nút "Thêm" để chạy code.
Sau đó, e copy cái code ở trên, nó không chạy. Cụ thể:
- code DATA_2010:
Mã:
Dim DB As DAO.Database
Dim rs As DAO.Recordset
Dim tt As Integer

Private Sub Them_Click()
On Error Resume Next
                       DoCmd.Requery
           
                   Set DB = CurrentDb()
                   Set rs = DB.OpenRecordset("T_NhanVien", dbOpenDynaset)
                       tt = DCount("MaNV", "T_NhanVien")
                   For i = 1 To tt
                       rs.Edit
                       rs!MaNV = "GD" & Right("00000" & i, 5)
                       rs.Update
                       rs.MoveNext
                   Next
                       rs.Close
                       DB.Close
                       
                           Ghi.Visible = False
                           Khong.Visible = False
                           DoCmd.GoToControl "Them"
                           
                     
End Sub

- và code DATA_2017:
Mã:
Dim DB As DAO.Database
Dim rs As DAO.Recordset
Dim tt As Integer

Private Sub Them_Click()
On Error Resume Next
                       DoCmd.Requery
           
                   Set DB = CurrentDb()
                   Set rs = DB.OpenRecordset("T_NhanVien", dbOpenDynaset)
                       tt = DCount("MaNV", "T_NhanVien")
                   For i = 1 To tt
                       rs.Edit
                       rs!MaNV = "VA" & Right("00000" & i, 5)
                       rs.Update
                       rs.MoveNext
                   Next
                       rs.Close
                       DB.Close
                       
                           Ghi.Visible = False
                           Khong.Visible = False
                           DoCmd.GoToControl "Them"
                           
                     
End Sub

Chỗ dòng: rs!MaNV = "VA" & Right("00000" & i, 5)  e chỉ sửa lại chữ "GD" thành "VA" mà nó không chịu chạy (DATA_2017). Nhưng nếu e sủa lại là "GD" thì nó chạy ok.

E thật lòng không hiểu tại sao.
Chữ ký của pherotao "Hạnh phúc ở đâu... biết tìm đâu,
Hồng trần là thế giới muôn màu,
Hội đủ nhân duyên... thời sinh quả,
Kết thúc... cũng là lúc bắt đầu".
Reply
Những người đã cảm ơn
#8
* Xin tham gia 1 bài:
* Phải nói là bạn pherotao chưa biết khai thác thư viên DAO.
* Nhìn vào cái hàm và để ý từ câu hỏi của Ongke yêu câu bạn giải thích tôi có kêết luận như sau;
1. Chưa học bò mà lo học chạy.
2. Copy vô tội vạ mà chưa hiểu ý nghĩa câu hàm lỗi ở đâu
3. Không biết khai thác thư viện hàm DAO

* Cách khắc phục; Test lại table tại cột MaNV, xoá dòng buộc nhập dữ liệu đi hoăc tạo bằng tay table mới (không import hay copy từ data củ nhé)
* Góp ý về hàm cho gọn

Mã PHP:
Private Sub Them_Click()
Dim rs As DAO.Recordset
Dim i 
As Integer

Set rs 
CurrentDb.OpenRecordset("Select MaNV from T_NhanVien")

With rs
    
If .EOF False Then
        
.MoveFirst
        i 
0
        
Do Until .EOF
            i 
1
            
.Edit
            
.Fields("MaNV") = Format(i"VA00000")
            .Update
            
.MoveNext
        Loop
            Ghi
.Visible False
            Khong
.Visible False
            DoCmd
.GoToControl "Them"
    End If
    .Close
End With

Set rs 
Nothing
End Sub 
Chữ ký của maidinhdan * Để được hỗ trợ tốt nhất, nhấn vào link dưới đây để xem.
1. [Hướng dẫn] Kiểu file gửi lên để được giúp đỡ
2. [Hướng dẫn] Nội quy diễn đàn
3. [Hướng dẫn] Cách Đưa file và hình vào diễn đàn
4.[Hướng dẫn] Để xây dựng một ứng dụng hoàn hảo và lời cảm tạ
5. Cần tìm Demo hay ứng dụng sử dụng thanh tìm kiếm phía trên cùng, bên phải của diễn đàn.
* Nếu muốn cảm ơn, hãy nhấn nút thank, không cần viết thêm bài nào nửa.



ღღღღღTài sản của maidinhdan (View All Items) ღღღღღ
Reply
Những người đã cảm ơn advnamk , ongke0711 , pherotao
#9
(22-12-17, 11:09 PM)pherotao Đã viết: Chỗ dòng: rs!MaNV = "VA" & Right("00000" & i, 5)  e chỉ sửa lại chữ "GD" thành "VA" mà nó không chịu chạy (DATA_2017). Nhưng nếu e sủa lại là "GD" thì nó chạy ok.

E thật lòng không hiểu tại sao.

Tôi kêu bạn giải thích thử cách thức thực thi của từng dòng code để xem bạn hiểu đc bao nhiêu rồi mới giải thích để bạn hiểu rõ hơn.
Code bạn đang áp dụng nếu nó chạy được cũng sai rất nghiêm trọng vì đây là code cập nhật lại toàn bộ Mã nhân viên ngay từ dòng đầu tiên mỗi khi bạn nhấn tạo 1 nhân viên mới.
   rs.Edit
   ….
   rs.MoveNext  => di chuyển lần lượt đến hết toàn bộ Recordset trong table T_Nhanvien.
   rs.Update      => cập nhật dịnh dạng Mã NV mới (“VA0001”)

Vậy cái lỗi nghiêm trọng là gì?
- Mã NV phải cố định và bất biến sau khi đã tạo (Primary Key) vì nó có liên quan đến các table khác. Các báo cáo thu tiền, bán hàng v.v.. đã có phát sinh cho mã Nv nào đó và bây giờ bạn sửa mã NV lại hết thì nó sai tùm lum tùm la. Lấy ví dụ như table T_HoaDonNX: khi bạn đã tạo 1 hóa đơn NX có tên nhân viên nhập là “VA0003”. Sau đó vì lý do gì đó bạn thấy mã nhân viên VA0002 bị tạo sai nên bạn Delete nó, sau đó tạo lại ==> chạy code trên thì nó sẽ cập nhật lại tất cả mã NV và nhân viên “VA0003” sẽ thành “VA0002” ==> thông tin của nhân viên “VA0003” thành mã của người kế tiếp =>dữ liệu đã phát sinh của “VA0003” đã lưu trong table “Hóa đơn NX” đã không còn đúng với nhân viên đã nhập liệu nữa rồi (đã bị đổi thành VA0002). Đây là trường hợp bạn đổi số thứ tứ và 2 ký tự đầu như “VA” vẫn giữ nguyên nên vô tình Access không báo lỗi. Nếu như bạn đổi từ “VA” thành “DG” thì Access sẽ báo lỗi vì Mã NV “VA003” đã có phát sinh dữ liệu liên quan đến bảng khác, bạn không thể thay đổi nó -> code của bạn chỉ chạy cập nhật được các NV nào chưa có phát sinh giao dịch gì thôi. 
- Nếu trong table nhân viên bạn đã thiết lập quan hệ với table hóa đơn NV có thêm tùy chọn "Cascade Update Related Fields" thì Access cũng sẽ cho bạn cập nhật nhưng hóa ra cũng sai dữ liệu lưu trữ rồi. Mã nv còn nguyên "VA0003" nhưng là mã của người khác rồi.

Bạn áp dụng hàm DCount() để đếm số nhân viên rồi tạo số thứ tự cho nó là đúng nhưng bạn để ý trong code của các bạn đã hướng dẫn trên diễn đàn còn kèm thêm nhưng dòng code để bẫy lỗi và code bạn đã không có nó => sai tè le.
- Tạo số tt là tạo cho dòng mới nhất khi bấm nút Thêm chứ không phải tạo lại toàn bộ Mã NV (như code bạn đang làm).
- Khi dùng Dcount() để lấy số tt nó có một cái lỗi là: sẽ tạo trùng số tt nếu đã có phát sinh delete mã NV. 
Ví dụ cho dễ hiểu: 
- Bạn đã tạo mã cho 5 nhân viên NV001 - NV005.
- Vì lý do sai gì đó bạn xóa đi 1 nhân viên NV003.
- Khi dùng DCount() nó sẽ đếm ra còn có 4 nhân viên, từ đó nó sẽ tạo ra số tt kế tiếp là 5 -> tạo mã nv: "NV" + stt = NV005 ==> trùng mã nhân viên 005 đã tồn tại.

Code để bẫy lỗi này:
1. Thường người ta dùng DMax() để lấy số tt cao nhất trong bảng rồi +1 để tạo số tt mới.
2. Nếu muốn dùng Dcount() thì sau khi lấy số tt rồi sẽ duyệt trong Recordset có tồn tại không, nếu không thì sử dụng nó, nếu có thì stt+1 rồi duyệt tiếp (dùng vòng lặp) đến khi không có số trùng lắp thì sử dụng số đó làm số tt mới.
Chữ ký của ongke0711 If you BORN poor, it's not your mistake. But if you DIE poor, It's your mistake!
ღღღღღTài sản của ongke0711 (View All Items) ღღღღღ
Reply
Những người đã cảm ơn maidinhdan , pherotao
#10
Rất cảm ơn anh Ongke0711 đã chỉ dẫn tận tình. E đọc và nghiền ngẫm bài trả lời của a lắm. Ngày hôm qua e đã suy nghĩ nhiều và dùng hàm DMax để làm mã số đó rồi. Và đạt như ý mình muốn. Rất cảm ơn mọi người trên diễn đàn này đã tận tình chỉ dẫn, đặc biệt là anh Ongke0711 đây.

Chúc mọi người trong diễn đàn đêm Giáng sinh tràn đầy an lành - hạnh phúc!
Chữ ký của pherotao "Hạnh phúc ở đâu... biết tìm đâu,
Hồng trần là thế giới muôn màu,
Hội đủ nhân duyên... thời sinh quả,
Kết thúc... cũng là lúc bắt đầu".
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
  Function check các biến chưa đóng mrsiro 0 102 13-10-18, 05:44 PM
Bài mới nhất: mrsiro
  Gửi tin nhắn SMS bằng Access lmthu 9 2,041 23-07-18, 07:09 PM
Bài mới nhất: tt1212
  [Hỏi] Căn Chỉnh Form Tự Động pherotao 9 1,107 21-12-17, 11:38 PM
Bài mới nhất: ongke0711
  [Thủ Thuật] Thiết lập tự động Windows Regional ngày/tháng, định dạng tiền, số ongke0711 1 624 16-11-17, 02:42 PM
Bài mới nhất: vuthaiha90
  [Hỏi] Mã Số Hóa Đơn Tăng Dần theo Ngày - Tháng - Năm pherotao 17 1,997 11-11-17, 09:15 PM
Bài mới nhất: pherotao

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ơ| PMA Nha Trang| Gỗ Acrylic Không Đường Line