Mỗi tuần một chuyên đề

Đưa công thức đã định nghĩa vào tính toán trong query

  • Thread starter ahp
  • Ngày gửi
Khóa học Quản trị dòng tiền
paulsteigel

paulsteigel

Trung cấp
13/11/05
103
0
16
48
Hoà Bình
www.sfdp.net
:::::Khuyến cáo:::::
Hướng dẫn thực hiện dưới đây chỉ có ý nghĩa nếu chúng ta sử dụng tính toán phức hợp tức là không thể dùng các phép toán cột trong Query hay nói khác hơn sử dụng cùng công thức trong toàn cột.
Nếu bài toán là như vậy thì cách tốt nhất là sử dụng ngay phép toán công thức trong query hoặc có thể dùng cách duyệt lựa chọn các nhóm công thức giống nhau và triển khai phép toán trong query với vài vòng lặp thuật toán là xong. Tất nhiên, tốc độ sẽ nhanh hơn rất nhiều.

Với trường hợp bắt buộc phải tính kết quả vì sử dụng nhiều công thức khác nhau hoàn toàn thì cách sau đây có thể giải quyết được yêu cầu, tuy nhiên tốc độ thực hiện sẽ tương đối thấp và ít khả thi trong các bài toán đòi hỏi tính toán nhanh để hiển thị kết quả (vì cách này đỏi hỏi phải tương tác với dbEngine). Trong thực tế người ta thường thiết kế thành một chức năng riêng và không phải làm đi làm lại nhiều lần (tính xong thì cập nhật, lưu kết quả, lần tính tiếp theo chỉ áp dụng với dữ liệu phát sinh mới mà thôi). Nếu bạn muốn sử dụng theo hướng ưu tiên tốc độ thì tiếp cận ban đầu với việc truyền tham số trực tiếp qua hàm là cách nhanh nhất nhưng đổi lại phải viết hàm có nhiều tham số như bạn đã cụ thể hóa trong mấy bài trước. Đôi khi việc này cũng tỏ ra là hơi phiền toái đúng không? Về điểm này thì VB/VBA thua xa Fox, Php ...vv về cách sử dụng tên biến trong chuỗi xử lý.

Giải quyết ra sao thì đó là nhiệm vụ của các nhà phân tích thiết kế phần mềm. Trong phạm vi bài viết này, tôi mạn phép chỉ xin giới thiệu như là một cách tiếp cận cá nhân thôi (mang tính sự vụ rất cao hè hè).

:::::Trả lời câu hỏi của bài trên:::::
Thật sự khi xem thiết kế CSDL của bạn tôi thấy nhiều vấn đề lắm (nhất là bảng công thức), hơi rườm rà và không rõ ràng. Tuy nhiên, hy vọng bạn sẽ sửa được nó tốt hơn.
Tiếp theo là: Không nên cái gì cũng đưa vào Qry nguồn vì nếu nhiều trường quá thì dữ liệu sẽ chạy hơi bị ốm.
Cách của tôi chỉ mang tính đề mô thôi.
Nếu bạn muốn làm để có kết quả tốt, nhanh thì việc đầu tiên cần làm là:
1. Thiết kế thuật toán xử lý công thức để tìm ra các trường cần khai thác sau đó mới truy vấn giá trị.
2. Công thức cần làm dạng tôi đề nghị hoặc cách nào đó loại trừ lỗi mà tôi chỉ ra trong đoạn code demo.
Nếu làm được như vậy thì tốc độ sẽ cải thiện nhiều.
Bạn xem trong tập tin kèm theo nhé.
Trong đoạn code demo - cần chú ý chỗ này:
theFomular = Replace(theFomular, arrFld(i), Nz(rs.Fields(tmpFldName), 0))
Ngoài ra, ví dụ của tôi không chạy được là vì trong CSDL của bạn không đặt Reference tới DAO mà chỉ dùng ADO. Tôi đã sửa lại Code và bạn có thể tham khảo nhé.
Mã:
Option Compare Database

Function FormulaCal(InForm As String, TblName As String, KeyField As String, KeyValue As Long) As Double
    '==============================================
    ' Tham so dau vao:
    '   Inform: Cong thuc dau vao
    '   TblName: Ten bang chua du lieu
    '   KeyField: Ten truong khoa chua du lieu hien thoi
    '   KeyValue: Gia tri cua dong hien thoi
    '==============================================
    ' Tat nhien cach nay cu chuoi va ban can phai them reference cho DB vao DAO hoac ADODB (neu dung no thi sua lai cau
    ' truc truy van nhe. Va dac biet, toc do xu ly chac se rat rua.
    ' Nhung cung la mot cach thay the de giai quyet chuyen Query.
    
    Dim rs As New Recordset, i As Long, theFomular As String, prcFml As String, arrFld As Variant
    theFomular = InForm
    
    ' dung thu tuc de giai quyet viec xu ly vong lap se nhanh hon
    prcFml = BuildFieldList(InForm)
    If prcFml = "" Then GoTo Exit_Function
    arrFld = Split(prcFml, ",")
    
    ' Gio thiet ke Query cho tot
    ' Thuc hien Querry de lay gia tri truyen tham so cho cong thuc
    ' Cai nay danh cho ADO, cac ban tu giai thich tai sao toi lai dung prcFml trong doan code mo csdl sau
    ' Neu ban muon toc do xu ly nhanh hon thi can thiet phai thiet ke lai cach xay dung query nay
    rs.Open "Select " & prcFml & " from " & TblName & " where [" & KeyField & "] = " & KeyValue & ";", CurrentProject.Connection
    ' Cai nay danh cho DAO
    'Set rs = CurrentDb.OpenRecordset("Select " & prcFml & " from " & TblName & " where [" & KeyField & "] = " & KeyValue & ";")
    ' Duyet qua toan bo danh sach truong de giai quyet dut diem vu truyen tham so
    If rs.EOF Then GoTo Exit_Function
    
    For i = 0 To UBound(arrFld)
        ' Neu cac ban muon lam cho CSDL nghiem tuc thi can dua them dau [] vao cong thuc vi rat co the
        ' se xay ra lam lan khi thay the, chang han truong 1 la a, truong 2 la ab thi no thay the se sai.
        ' vi the ban nen dung cach sau day
        ' Neu dung cach tiep can duoi day thi trong cong thuc da phai co dau phan cach [] nhe
        ' chang han [a]+[c]+[d]
        ' lay ten field chinh thong
        tmpFldName = Mid(arrFld(i), 2, Len(arrFld(i)) - 2)
        ' gan vao cong thuc
        theFomular = Replace(theFomular, arrFld(i), Nz(rs.Fields(tmpFldName), 0))
    Next
    FormulaCal = Eval(theFomular)
Exit_Function:
    rs.Close
End Function

Private Function BuildFieldList(inFml As String) As String
    ' Minh khong dat bay loi, ban se phai tu xu ly van de nay nhe
    ' Ham nay de xay dung cac danh sach truong can xu ly dua tren cach dat ten truong trong dau []
    Dim prcTxt As String, lsField As String, fldName As String
    Dim stPos As Long, endPos As Long
    
    prcTxt = inFml
    ' Khoi dong tim dau mo truong de bat dau vong lap
    stPos = InStr(prcTxt, "[")
    
    While stPos > 0
        ' Lay vi tri hien thi dau dong ten truong
        endPos = InStr(prcTxt, "]")
        ' Lay ten truong
        fldName = Mid(prcTxt, stPos + 1, endPos - stPos - 1)
        ' ghi ten truong vao mot danh sach, ta dung dau phay thi sau nay co the xay dung luon query ma khong can lam gi them
        lsField = lsField & ",[" & fldName & "]"
        ' thu thuat de bo qua qua trinh tim dau dong va mo truong
        prcTxt = Replace(prcTxt, "[" & fldName & "]", "/" & fldName & "/")
        
        ' Lay vi tri hien thi dau mo ten truong/ tai sao phai dat o day chu yeu la nham tiet kiem thoi gian
        stPos = InStr(prcTxt, "[")
    Wend
    BuildFieldList = Mid(lsField, 2)
End Function
Chúc bạn thành công
 

Đính kèm

  • luong_vec.rar
    107.2 KB · Lượt xem: 134
Sửa lần cuối:
A

ahp

Guest
24/6/05
40
0
6
48
hanoi
to paulsteig

Em hỏi bác thêm tý nhé, khi em chuyển định dạng số sang 123.456.789.99 thì cái hàm Eval nó không thể thực thi khi field có định dạng thập phân. Bác xem hộ em với
 
paulsteigel

paulsteigel

Trung cấp
13/11/05
103
0
16
48
Hoà Bình
www.sfdp.net
Xin lỗi bạn vì lâu quá không vào WKT.
Lỗi này là do hàm chuyển đổi số từ ký tự sang số. Bạn thay hàm VAL bằng hàm CLng nhé.
Ngọc
 

Xem nhiều

Webketoan Zalo OA