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

Thảo luận trong 'Ứng dụng Access' bắt đầu bởi khuenguyen.tran, 5 Tháng mười hai 2005.

10,451 lượt xem

  1. khuenguyen.tran

    khuenguyen.tran Thành viên sơ cấp

    Bài viết:
    40
    Đã được thích:
    0
    Nơi ở:
    HCM
    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 ?
     
    #1
  2. trunghungtan

    trunghungtan Thành viên sơ cấp

    Bài viết:
    3
    Đã được thích:
    0
    Nơi ở:
    Vinh
    Đâ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
     
    #2
  3. Longlv

    Longlv Thành viên hoạt động

    Bài viết:
    44
    Đã được thích:
    1
    Nơi ở:
    Hanoi
    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.
     
    #3
  4. Secret_grasses

    Secret_grasses Thành viên hoạt động

    Bài viết:
    317
    Đã được thích:
    3
    Nơi ở:
    Ngôi nhà nhỏ trên thảo nguyên.
    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.
     
    #4
  5. Longlv

    Longlv Thành viên hoạt động

    Bài viết:
    44
    Đã được thích:
    1
    Nơi ở:
    Hanoi
    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
     
    #5
  6. khuenguyen.tran

    khuenguyen.tran Thành viên sơ cấp

    Bài viết:
    40
    Đã được thích:
    0
    Nơi ở:
    HCM
    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
     
    #6
  7. paulsteigel

    paulsteigel Thành viên thân thiết

    Bài viết:
    103
    Đã được thích:
    0
    Nơi ở:
    Hoà Bình
    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.
     
    Last edited: 8 Tháng mười hai 2005
    #7
  8. Longlv

    Longlv Thành viên hoạt động

    Bài viết:
    44
    Đã được thích:
    1
    Nơi ở:
    Hanoi
    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.
     
    #8
  9. khuenguyen.tran

    khuenguyen.tran Thành viên sơ cấp

    Bài viết:
    40
    Đã được thích:
    0
    Nơi ở:
    HCM
    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 ?
     
    #9
  10. mysterious_girl

    mysterious_girl Thành viên sơ cấp

    Bài viết:
    358
    Đã được thích:
    1
    Nơi ở:
    ...close to you...
    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.
     
    #10
  11. paulsteigel

    paulsteigel Thành viên thân thiết

    Bài viết:
    103
    Đã được thích:
    0
    Nơi ở:
    Hoà Bình
    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
     
    Last edited: 8 Tháng mười hai 2005
    #11
  12. Longlv

    Longlv Thành viên hoạt động

    Bài viết:
    44
    Đã được thích:
    1
    Nơi ở:
    Hanoi
    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?
     
    #12
  13. paulsteigel

    paulsteigel Thành viên thân thiết

    Bài viết:
    103
    Đã được thích:
    0
    Nơi ở:
    Hoà Bình
    Để 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é
     
    Last edited: 14 Tháng mười hai 2005
    #13
  14. Longlv

    Longlv Thành viên hoạt động

    Bài viết:
    44
    Đã được thích:
    1
    Nơi ở:
    Hanoi
    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:
     
    #14
  15. HongViet

    HongViet Thành viên thân thiết

    Bài viết:
    286
    Đã được thích:
    10
    Nơi ở:
    Đà nẵng
    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!
     
    #15
  16. paulsteigel

    paulsteigel Thành viên thân thiết

    Bài viết:
    103
    Đã được thích:
    0
    Nơi ở:
    Hoà Bình
    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ư.
     
    #16
  17. Secret_grasses

    Secret_grasses Thành viên hoạt động

    Bài viết:
    317
    Đã được thích:
    3
    Nơi ở:
    Ngôi nhà nhỏ trên thảo nguyên.
    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é!
     
    #17
  18. HongViet

    HongViet Thành viên thân thiết

    Bài viết:
    286
    Đã được thích:
    10
    Nơi ở:
    Đà nẵng
    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:
     
    Last edited: 15 Tháng mười hai 2005
    #18
  19. mysterious_girl

    mysterious_girl Thành viên sơ cấp

    Bài viết:
    358
    Đã được thích:
    1
    Nơi ở:
    ...close to you...
    Mình đồng ý với bạn Hồng việt ở chổ này.

    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.
     
    #19
  20. Longlv

    Longlv Thành viên hoạt động

    Bài viết:
    44
    Đã được thích:
    1
    Nơi ở:
    Hanoi
    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:
     
    #20

Chia sẻ trang này