Access căn bản(???)

  • Thread starter khuenguyen.tran
  • Ngày gửi
K

khuenguyen.tran

Thành viên sơ cấp
3/12/05
40
0
0
37
HCM
#1
Bên Excel, em thấy nhiều bài rất căn bản dành cho các Mem mới học hỏi, em nghĩ các bác bên Access cũng nên dành chút ít kiến thức, kinh nghiệm của mình trao đổi với các Mem mới về cách viết SQL này, cách thiết lập quan hệ trong CSDL này, không phải chỉ như kiến thức trong sách đâu, mà là những kinh nghiệm thực tế, những thủ thuật Access...Chẳng lẽ Box Access chỉ dành cho các bác trao đổi những vấn đề cao siêu quá, bọn Mem mới tụi em không sao hiểu nổi ?
 
T

trunghungtan

Thành viên sơ cấp
30/11/05
3
0
0
35
Vinh
#2
Đâu có. Như thế là bạn nhùm rùi. Bạn có post lên đi. Tôi sẽ trả lời tất
 
L

Longlv

Thành viên sơ cấp
21/10/05
44
1
8
41
Hanoi
#3
Các bác làm ơn cho hỏi làm sao Format được trường AutoNumber.
VD: NK00001, NK00002, .....
trường này có thể tự động bắt đầu từ 01 khi hết tháng không?
Cảm ơn các bác.
 
Secret_grasses

Secret_grasses

Thành viên sơ cấp
#4
Longlv nói:
Các bác làm ơn cho hỏi làm sao Format được trường AutoNumber.
VD: NK00001, NK00002, .....
trường này có thể tự động bắt đầu từ 01 khi hết tháng không?
Cảm ơn các bác.
Bạn định dạng như thế này: "NK0000"#
Nếu muốn tự động thì bạn tạo module tăng mã. Để bữa nào rảnh mình sẽ gửi đoạn module đó cho bạn.
 
L

Longlv

Thành viên sơ cấp
21/10/05
44
1
8
41
Hanoi
#5
Cảm ơn bạn Secret_grasses. Nếu có thể bạn gửi cho mình module đó nhé email của mình long_levan21@yahoo.com.

Thanks a lot
 
K

khuenguyen.tran

Thành viên sơ cấp
3/12/05
40
0
0
37
HCM
#6
Mình thấy đâu cần Module tăng mã hả bạn ? Vì nó là Autonumber nên tự động tăng mà, bạn có thể giải thích rõ hơn không ? Nếu được, bạn gởi cho mình với, bạn gởi vào khuenguyen.tran@gmail.com nhé, cám ơn bạn nhiều
 
paulsteigel

paulsteigel

Thành viên thân thiết
13/11/05
103
0
16
42
Hoà Bình
www.sfdp.net
#7
Mình xin được giới thiệu bổ sung về biện pháp của bạn "Grasses" nhé!
Bạn khuenguyen.tran có đề cập như thế này "Mình thấy đâu cần Module tăng mã hả bạn ? Vì nó là Autonumber nên tự động tăng mà, bạn có thể giải thích rõ hơn không ? Nếu được, bạn gởi cho mình với, bạn gởi vào khuenguyen.tran@gmail.com nhé, cám ơn bạn nhiều"
Trường kiểu Autonumber là trường đánh số tăng tự động kiểu số vì thế bạn không thể đưa kiểu khoá NK0001 tự động tăng được, nếu muốn làm thế bạn chỉ có 2 cách:
1. Vẫn để trường là kiểu autonumber song khi truy xuất xử lý dữ liệu bạn dùng đến các lệnh format để gắn thêm chuỗi NK vào dữ liệu đầu ra, kiểu này đôi lúc cũng phức tạp lắm vì bạn có thể vô tình quên mất ở đâu đó thủ tục xử lý dữ liệu.
2. Bạn thiết lập trường kiểu ký tự với độ dài tối đa phải được tính trước (ví dụ là 10 thì sẽ hiển thị được số có 8 chữ số và cụm NK). Với cách này thì không thể tự động đánh số được mà bạn phải thiết kế thuật toán để thực hiện việc tăng dần số đếm.
Đại loại thuật toán đó phải làm việc dạng như thế này:
+ Tìm số cực đại có trong CSDL - để làm việc naỳ bạn cần dùng đến hàm Mid để lấy phần số của chuỗi và hàm val để đổi chuỗi thành số
Ví dụ chuỗi là NK00123 thì dùng hàm như sau mid("NK00123,2) kết quả nhận được là 123.
Để tìm số cực đại, bạn có thể dùng truy vấn SQL. ví dụ
Select Max(Mid([KeyField],2)) from [Tenbang];
Với câu truy vấn trên bạn hãy dự đoán các kết quả có thể xảy ra nhé - quan trọng lắm đấy - vì nếu không có thể có lỗi.
Bạn có thể thử viết thủ tục và kiểm tra xem.
+ Sau khi lấy được số cực đại, bạn có thể tự động gán thêm 1 để tăng thêm vào kết quả và tiếp tục dùng hàm format để gắn thêm giá trị cho chuỗi kết quả. ví dụ
Dim MyKey as long, RetStr as string
MyKey=1
RetStr="NK" & format(Mykey,"000000")
(Kết quả sẽ là NK000001)
Bạn hãy thử tự mình viết đoạn chương trình trên xem nào.
 
Sửa lần cuối:
L

Longlv

Thành viên sơ cấp
21/10/05
44
1
8
41
Hanoi
#8
Về phần viết mã thì quả thật mình không biết gì, bạn paulsteigel có thể hướng dẫn chi tiết hơn một chút được không. VD đây là running number của phiếu NK, mình muốn mỗi tháng số phiếu này lại quay lại từ số 01.

T1 /2005 : NK00001, NK00002, ...... NK00030
T2 /2005 : NK00001, NK00002, ...... NK00048
.....

Cảm ơn các bạn nhiều.
 
K

khuenguyen.tran

Thành viên sơ cấp
3/12/05
40
0
0
37
HCM
#9
Bọn chúng em đều biết ít lắm về Access, nên vào đây để học hỏi, mà sao lục tung cả cái Box này ra, chẳng thấy ai thắc mắc những cái sơ sơ thôi để mình được nghe giải đáp với trình độ thấp thấp dễ hiểu một chút, chẳng lẽ Box Access này toàn bài khó không à, ngay cái bài giải đáp của bác Paulsteigel, em cũng tự nhận thấy là mình kém cỏi lắm, không làm được, bác à. Bác có cách nào giúp bọn em không ?
 
M

mysterious_girl

Thành viên sơ cấp
#10
khuenguyen.tran nói:
Bọn chúng em đều biết ít lắm về Access, nên vào đây để học hỏi, mà sao lục tung cả cái Box này ra, chẳng thấy ai thắc mắc những cái sơ sơ thôi để mình được nghe giải đáp với trình độ thấp thấp dễ hiểu một chút, chẳng lẽ Box Access này toàn bài khó không à, ngay cái bài giải đáp của bác Paulsteigel, em cũng tự nhận thấy là mình kém cỏi lắm, không làm được, bác à. Bác có cách nào giúp bọn em không ?
Bạn ơi, box Access mới được thành lập mà. Bạn có gì ko hiểu thì cứ đặt câu hỏi. Mọi người sẽ trả lời cho bạn.
 
paulsteigel

paulsteigel

Thành viên thân thiết
13/11/05
103
0
16
42
Hoà Bình
www.sfdp.net
#11
Bạn có thể dùng thử đoạn mã sau nhé
Mình xin lỗi vì các đoạn comment - hihi không dấu
Sub Test()
Debug.Print GetOrder("tbl_Solution", "Heading", , "C:\ts.mdb")
End Sub

Function GetOrder(MyTable As String, MyKeyField As String, Optional MyCriteria As String = "", Optional dbPath As String) As String
' Ham phai de o kieu string - vi ban dat kieu ma la string ma
' MyTable la ten bang can xac dinh ma
' MyKeyField la ten cot can xac dinh danh so tu dong
' MyCriteria la Dieu kien truy van
' Truoc khi dung ham nay, ban can dat tham chieu den bo thu vien DAO 3.xx nhe
' Ham nay chi su dung duoc neu ban dat kieu dinh dang the nhap kho la dong kieu
' Vi du NK#####, PNK######..
' O day toi su dung mot doan thu tuc de tim phan bat dau cua ma ky tu
' Ham RetInitialChar()
Dim rs As Recordset, db As Database
Dim iCond As String, i As Long, iQry As String
'Dim Currentdb As Database 'neu ban o trong access thi thoi - con trong VB thi phai bo comment dong nay nhe

' Lay doan ma danh so
iCond = RetInitialChar(MyTable, MyKeyField, dbPath)
Set db = IIf(dbPath = "", Currentdb, OpenDatabase(dbPath))
' Bay gio mo bang va tim doi tuong lon nhat
iQry = "Select Max(Mid([" & MyKeyField & "]," & Len(iCond) + 1 & ")) as MyField " & _
"from " & MyTable & IIf(MyCriteria = "", ";", " Where " & MyCriteria & ";")
Debug.Print iQry
Set rs = db.OpenRecordset(iQry)
' Tat nhien SQL tren hoi phuc tap mot chut nhung co the giai thich the nay
'Max(Val(Mid([" & MyKeyField & "],Len(" & iCond & ")+1)) de tra lai phan so lon nhat co trong bang
'IIf(MyCriteria = "", ";", "Where " & MyCriteria & ";")) De dua cau dieu kien neu chuoi myCriteria <>0
On Error Resume Next
i = Val(rs.Fields(0))
If Err.Number <> 0 Then
' Co loi - chac la khong co doi tuong nao - tat nhien ban can phai chac chan
' la minh khong co loi trong cau dieu kien
iCond = iCond & Format(1, "000000")
Err.Clear
Else
iCond = iCond & Format(i + 1, "000000")
End If
rs.Close
If dbPath = "" Then Set db = Nothing Else db.Close
GetOrder = iCond
End Function

Private Function RetInitialChar(ByVal MyTable As String, ByVal MyKeyField As String, Optional dbPath As String) As String
' Ham se mo CSDL va tim ma phieu mac dinh, neu khong tim thay
' ham se tu dong gan ma mac dinh la "NK#####"
Dim rs As Recordset, db As Database
Dim MyKey As String, i As Long
'Dim Currentdb As Database 'neu ban o trong access thi thoi - con trong VB thi phai bo comment dong nay nhe
' Mo co so du lieu nhe/ neu bien dbpath khong duoc chi ra - db se duoc gan cho currentdb
' day la doi tuong mac dinh chi den csdl hien thoi cua Access

Set db = IIf(dbPath = "", Currentdb, OpenDatabase(dbPath))
' Mo bang lam viec nhe
Set rs = db.OpenRecordset("Select [" & MyKeyField & "] From [" & MyTable & "];")
On Error Resume Next
MyKey = rs.Fields(0)

For i = 1 To Len(MyKey)
' Kiem tra xem ky tu dang duyet co phai la so hay khong
If InStr("0123456789", Mid(MyKey, i, 1)) <> 0 Then
' Lay doan dau cua ma the va thoat khoi vong lap
MyKey = Left(MyKey, i - 1)
Exit For
End If
Next
' Neu co loi xay ra, chuong trinh se xu ly ngay thu tuc nay
If Err.Number <> 0 Then
' Co loi nao do .. co the la khong co ban ghi nao
MyKey = "NK"
Err.Clear
End If
' Dong doi tuong recordset truoc khi thoat
rs.Close
If dbPath = "" Then Set db = Nothing Else db.Close
' Tra ve gia tri va thoat ra
RetInitialChar = MyKey
End Function
 
Sửa lần cuối:
L

Longlv

Thành viên sơ cấp
21/10/05
44
1
8
41
Hanoi
#12
Cảm ơn bạn paulsteigel nhiều. Mình đã chạy thử đoạn mã của bạn theo kiểu step info (F8) thì số running tăng lên nhưng nó lại không gán kết quả vào Table. Bạn có thể chỉ cho mình cách gán kết quả vào table được không?
 
paulsteigel

paulsteigel

Thành viên thân thiết
13/11/05
103
0
16
42
Hoà Bình
www.sfdp.net
#13
Để có thể gán kết quả vào bản ghi, bạn cần nắm được các khái niệm này đã nhé:
1. Cách làm việc với đối tượng DAO hoặc ADODB - tuỳ theo cái nào bạn thích
2. Cách cập nhật một bản ghi với các đối tượng đó.
Tôi xin trình bày cụ thể:
1. Với DAO (Data Access Object)
+ Bạn cần đặt tham chiếu đến bộ thư viện DAO (hiện tại là 3.6 thì phải)
+ Khai báo các thủ tục kết nối. Ví dụ:
Dim Db as Database
Dim Rs as Recordset
' Mở CSDL
Set db=Opendatabase("Đường dẫn đến CSDL")
' Mở bảng
Set rs=db.Openrecordset("Select * from tenbang where Thang=xx and Nam =xxxx;")
2.Và bắt đầu làm việc cập nhật hoặc sửa đồi
If rs.Eof then
rs.addnew' để thêm mới
else
rs.Edit ' để sửa
end if
' và thực hiện gán ở dây
rs.Fields("TheCT")=GetOrder("tbl_Solution", "Heading", , "C:\ts.mdb")
' Kết thúc bằng lệnh
rs.Update
'========================
Với ADODB cũng tạm có thể coi như trên nhưng bạn cần biết cách viết thủ tục kết nối...
[Nay viết thêm đoạn kết nối dùng ADODB]
Access từ 2000 trở lên khi bạn bắt đầu một CSDL mới, tham chiếu mặc định đến Dự án (DA) (CSDL) của bạn là Microsoft ActiveX Data Object 2.xx
Cái này chính là thư viện hỗ trợ ADODB, nếu bạn không muốn phải dùng đến DAO thì cứ để nguyên nhé.
Ngoài ra các đối tượng cơ bản của một DA Access là
+ CurrentDb chỉ đến kiểu đối tượng đại diện cho CSDL hiện thời đang mở trong cửa sổ Access.
+ CurrentProject chỉ đến dự án của CSDL hiện thời.
Nếu quan sát một chút ta có thể thấy cái Currentdb giống như đối tượng Database trong DAO đấy. Còn khi tìm các thuộc tính của CurrentProject bạn sẽ thấy một cái tên là Connection ... à là thế
Vậy bạn có thể tạo kết nối thế này:
' Này thì khai báo hihi - bạn nhớ là phải có từ khoá new nếu không bạn lại phải khởi tạo lại biến đó bằng lệnh set .. = new recordset
Dim Rs As New Recordset
Dim oCon As New Connection
Dim iQry As String
' Đây là gán kết nối
Set oCon = CurrentProject.Connection
' Chuỗi truy vấn nhé
iQry1 = "Select * from tbl_vanban;"
' và mở bảng nào
Rs.Open iQry1, oCon, adOpenStatic, adLockPessimistic
Các bạn có thể tham khảo trong bản viết lại cái csdl của bác Haitam mà tôi đã gởi trước đây nhé ... cũng có một số ví dụ có thể tham khảo.
'========================
Nay kính thư nhé
 
Sửa lần cuối:
L

Longlv

Thành viên sơ cấp
21/10/05
44
1
8
41
Hanoi
#14
Thanks for helping

Cám ơn bạn Paulsteigel nhiều nhé. Chúc box Access và Kế toán ngày càng phát triển hơn nữa:dzo:
 
HongViet

HongViet

Thành viên thân thiết
10/11/05
286
10
18
Đà nẵng
#15
To Paulsteigel

Đoạn mã của bạn thật là chiến! Nhờ bạn bớt chút thời gian cho nhận xét về cách làm của tôi như sau, nha!:
Ở form nhập liệu tôi thêm 1 control có tên là SoKeTiep & gán hàm tự tạo như sau:
Function TaoMa(SoTT) As String
Dim CSDL As Database, Bang As Recordset
Dim MaxSo as Long, Chu As String
Set CSDL = CurrentDB()
Set Bang = CSDL.OpenRecordset("Table1",DB_OPEN_TABLE)
Bang.MoveFirst
'Tìm Số Cực Đại Hiện Hành:
Do Until Bang.EOF
Chu = Mid( Bang!Ma;2)
If Int(Chu) > MaxSo then MaxSo = Int(Chu)
Bang.Movenext
Loop
Bang.Close: Set Bang=Nothing
TaoMa=MaxSo
End Function
Khi cần nhập STT kế tiếp thì nghía vô cái control SoKeTiep ấy mà tham khảo; chẵng hạn nó đang là 999 thì ta nhập NX1000
Xin lỗi trước nếu bạn thấy phiền lòng!
 
paulsteigel

paulsteigel

Thành viên thân thiết
13/11/05
103
0
16
42
Hoà Bình
www.sfdp.net
#16
HongViet nói:
Xin lỗi trước nếu bạn thấy phiền lòng!
Có gì đâu bạn Hồng Việt... Ai cũng đều phải học mà hihi.
Cách tiếp cận của bạn rất hay, đơn giản và dễ hiểu và quan trọng hơn, không phải dùng đao búa quá nhiều.
Tuy nhiên tôi muốn giải thích một chút:
Giữa đoạn mã của bạn Hồng Việt và đoạn mã mà tôi đã đăng có 2 sự khác biệt cơ bản:
1. Tốc độ - tốc độ duyệt qua bản ghi tuần tự chậm hơn nhiều so với tốc độ truy vấn SQL.
2. Tính đa dạng của mã số
Thuật toán của bạn Việt sẽ giải quyết được các mã bất kỳ có chuỗi 2 ký tự bắt đầu của mã kho, nhưng nếu có 3,4 hoặc nhiều hoặc ít hơn thì bạn lại phải viết lại dòng: Chu=Mid( Bang!Ma;2).
Và tiếp nữa, người dùng sẽ cảm thấy hơi phức tạp khi sử dụng chương trình vì họ phải có thêm động tác.
Trong viết mã chương trình, người ta hay tránh điều này - vì tất cả chúng ta đều muốn có thể sử dụng lại được những thủ tục ta đã viết ra từ trước.
Và dòng này chính là đoạn thủ tục RetInitialChar mà tôi đã đưa ra....
Tất nhiên đoạn mã này có thể cần phải sửa chữa tiếp vì tôi chưa hoàn chỉnh cấu trúc mà.
Tuy vậy, cũng phải nói là bạn Hồng Việt sẽ luôn có những cách giải quyết nhanh đối với nhiều vấn đề (Nhanh nhẹn - sáng tạo) - đây có lẽ là đức tính quan trọng nhất đối với một lập trình viên Amateur.
Trong các bài tới tôi sẽ đưa ra một số ví dụ nhỏ về SQL để các bạn tham khảo nhé.
Nay kính thư.
 
Secret_grasses

Secret_grasses

Thành viên sơ cấp
#17
Cám ơn anh Paulsteigel đã trả lời giúp em.

To longlv: Sorry bạn nhé. Vì đã hứa mà chưa thực hiện được với bạn. Dữ liệu của mình đã bị mất. Mình đang trong thời gian khôi phục lại dữ liệu của mình.Thông cảm cho mình nhé!
 
HongViet

HongViet

Thành viên thân thiết
10/11/05
286
10
18
Đà nẵng
#18
Longlv nói:
VD đây là phiếu NK, mình muốn mỗi tháng số phiếu này lại quay lại từ số 01. T1 /2005 : NK00001, NK00002, ...... NK00030
........................T2 /2005 : NK00001, NK00002, ...... NK00048.
Cho mình hỏi tẹo: Tại sao hết tháng bạn phải quay lại vậy?, Bạn không sợ bị trùng lắp, sau này khi tìm kiếm sẽ khó lắm nha?! Theo mình bạn lãng phí kí tự 'K' (Nhà nước ta đang chống lãng phí mà!). Theo thiển ý bạn nên dùng thay vô đó là kí tự biểu thị 12 tháng: 1,2,3........9,A,B,C (Bạn thấy NTN, được nha?!);
Còn nữa, mỗi tháng bạn có bao nhiêu phiếu? 10^5! Vị chi mỗi ngày bạn có khoảng (10^4)/3 = 3.400 phiếu. Vậy bạn chỉ cần dùng 1 kí tự và thêm 4 ký số nữa có dạng A9999 là thừa sức biểu diễn (vì độ dự trữ của bạn tự nhiên tăng thêm gần 2 lần). Có điều A là kí tự (và kí số) biểu thị 31 ngày trong tháng theo chiều tăng dần!:lol:
 
Sửa lần cuối:
M

mysterious_girl

Thành viên sơ cấp
#19
HongViet nói:
Cho mình hỏi tẹo: Tại sao hết tháng bạn phải quay lại vậy?, Bạn không sợ bị trùng lắp, sau này khi tìm kiếm sẽ khó lắm nha?!
Mình đồng ý với bạn Hồng việt ở chổ này.

Theo mình bạn lãng phí kí tự 'K' (Nhà nước ta đang chống lãng phí mà!). Theo thiển ý bạn nên dùng thay vô đó là kí tự biểu thị 12 tháng: 1,2,3........9,A,B,C (Bạn thấy NTN, được nha?!);
Còn nữa, mỗi tháng bạn có bao nhiêu phiếu? 10^5! Vị chi mỗi ngày bạn có khoảng 10^4/3 = 3.400 phiếu. Vậy bạn chỉ cần dùng 1 kí tự và thêm 4 ký số nữa có dạng A9999 là thừa sức biểu diễn (vì độ dự trữ của bạn tự nhiên tăng thêm gần 2 lần). Có điều A là kí tự (và kí số) biểu thị 31 ngày trong tháng theo chiều tăng dần!:lol:
Bạn ơi, hai ký tự đầu "NK" nghĩa là "Nhập kho".(Phải ko longlv nhỉ?)

Theo mình thì bạn nên đặt là: "NK0501001" nghĩa là phiếu nhập kho năm 2005 tháng 1, phiếu số 1.
 
L

Longlv

Thành viên sơ cấp
21/10/05
44
1
8
41
Hanoi
#20
Xin cảm ơn các bạn paulsteigel, hongviet, green_field, Secret_grasses... đã nhiệt tình giúp đỡ. Mình chỉ biết chút ít về Access nên nhiều cũng không hiểu được hết các bài viết trên box này, hy vọng trong thời gian tới sẽ học hỏi được nhiều hơn từ các bạn.
Vấn đề đặt tên tài liệu, mình muốn số running quay lại từ 01 để đơn giản hơn cho việc thống kê số lượng phiếu nhập kho, phiếu xuất kho,... trong tháng. Ý kiến của các bạn HongViet và green_field về việc đưa năm, tháng phát sinh tài liệu vào số tài liệu là rất hay mình xin tiếp thu.
Một lần nữa xin chân thành cảm ơn tất cả các bạn. Chúc các bạn có nhiều sức khỏe, Webketoan lớn mạnh hơn nữa.

Thân. :two:
 

Thành viên trực tuyến

  • huonghvtc89
  • tridung290798
  • lenam1960
  • kophaithach2
  • thuongdan
  • daongocnam0603
  • xediengiatot
  • minhminhCIC5
  • Huongtb205

Xem nhiều