tanthuc > 07-10-12, 03:04 PM
(29-06-12, 11:48 AM)lehongduc Đã viết: Rất mong các Bạn tham gia trao đổi về chuyên đề này. Các Bạn có thể trao đổi về:
1. Nội dung bài viết, đúng, sai?
2. Những giải pháp khác của Bạn xung quanh vấn đề chúng ta đang bàn
3. Những thắc mắc phát sinh khi chạy file ứng dụng minh họa
Và những vấn đề có liên quan khác.
Thú thật, một mình độc thoại thấy cũng hơi vắng thiếu.
Mong các Bạn nhiệt tình tham gia trao đổi.
bangnguyencong > 06-11-12, 12:45 AM
bangnguyencong > 30-11-12, 12:39 PM
Minh Tiên > 02-09-13, 11:44 AM
nguyenthanvu > 12-02-14, 03:38 PM
paulsteigel > 13-02-14, 09:37 AM
(30-11-12, 12:39 PM)bangnguyencong Đã viết: ....
Tất cả đều trong tầm tay. Nhưng khó một cái là kết nối SQL và internet.
...
lehongduc > 15-07-14, 11:10 AM
Trích dẫn:Function BuildSQLWhere(blnPriorWhere As Boolean, strPriorWhere As String, strValue As String, strDbFieldName As String) As StringCác Bạn chú ý đoạn code trên có dòng ghi:
On Error GoTo HandleError
Dim strWhere As String
If blnPriorWhere Then
'add to the existing where clause
strWhere = strPriorWhere & " AND "
Else
'create the where clause for the first time
strWhere = " WHERE "
End If
If strDbFieldName = "Ngaysinh" Then
strWhere = strWhere & strDbFieldName & " = '" & Format$(strValue, "dd-mmm-yy") & "' "
Else
'build where clause using LIKE so will find both exact
'matches and those that start with value input by user
If strDbFieldName = "Gioitinh" Then
strWhere = strWhere & strDbFieldName & " = " & PadQuotes(strValue) & " "
Else
strWhere = strWhere & strDbFieldName & " LIKE N'%" & PadQuotes(strValue) & "%' "
End If
End If
blnPriorWhere = True
'return where clause
BuildSQLWhere = strWhere
Exit Function
HandleError:
GeneralErrorHandler Err.Number, Err.Description, DB_QUANLY, "BuildSQLWhere"
Exit Function
End Function
Trích dẫn:strWhere = strWhere & strDbFieldName & " LIKE N'%" & PadQuotes(strValue) & "%' "Đây là điều kiện lọc dữ liệu để tìm. Ta chú ý 2 dấu % đặt ở 2 đầu trong dòng trên có ý nghĩa "dữ liệu cần tìm bắt đầu và kết thúc bằng gì cũng được miễn là có sự hiện diện của từ được cung cấp bởi biến strValue là được".
Trích dẫn:Sub LoadInvoiceInfoToForm(SoCtuSt, Optional NoSetSourceRecForSubForm)
Dim sqlSt As String, SQLrec As ADODB.Recordset
Dim KHrec As ADODB.Recordset
Dim tblName As String, MSKH, vIdKH As Long
‘Xác định nguồn dữ liệu chứa thông tin của chứng từ cần nạp
tblName = "tblctunx"
If IsNull(SoCtuSt) Then Exit Sub
sqlSt = "SELECT * FROM " & GetSchemaTable(tblName) & "." & tblName
sqlSt = sqlSt & " WHERE soctu ='" & SoCtuSt & "'"
Set SQLrec = ProcessRecordset(sqlSt)
'Nếu chứng từ hiện hữu, cho ghi thông tin chi tiết của chứng từ lên các ô dữ liệu tương ứng của Form
If SQLrec.RecordCount > 0 Then
Set objKhachHang = New clsDanhba
With Me
.txtId = SQLrec!id
.txtNgay = SQLrec!Ngay
.cmbNghiepvu = SQLrec!MSNV
.txtTsuat = SQLrec!tsuatvat
.txtNguoiGiaodich = SQLrec!NguoiGiaodich
MSKH = SQLrec!MSKH
sqlSt = "SELECT * FROM " & GetSchemaTable("tblDanhsach") & ".tblDanhsach"
sqlSt = sqlSt & " WHERE MSKH = '" & MSKH & "'"
Set KHrec = ProcessRecordset(sqlSt)
objKhachHang.PopulatePropertiesFromRecordset KHrec
.cmbKhachhang.RowSourceType = "Value List"
.cmbKhachhang.RowSource = objKhachHang.HoChulot & ";" & objKhachHang.MaKhachHang
.cmbKhachhang = objKhachHang.MaKhachHang
.txtDiachi = objKhachHang.Diachi
.txtPhone = objKhachHang.Dtvp
.txtMasoThue = objKhachHang.Msthue
KHrec.Close
Set KHrec = Nothing
' Và nạp nguồn dữ liệu chi tiết các mặt hàng phát sinh cho Subform
If IsMissing(NoSetSourceRecForSubForm) Then SetSourceRecForSubForm Me, "frmCtuNXCT"
End With
End If
'
SQLrec.Close
Set SQLrec = Nothing
End Sub
Trích dẫn:Sub SetSourceRecForSubForm(mForm As Form, sForm As String)
Dim sqlSt As String
Dim SQLrec As ADODB.Recordset
Dim tblName As String
Dim vSoCtu, stChema As String
‘
vSoCtu = mForm!cmbSoCtu
‘Xác định nguồn dữ liệu chứa thông tin chi tiết hàng hoá phát sinh của chứng từ cần nạp
If Not IsNull(vSoCtu) Then
tblName = "tblctunxct"
stChema = GetSchemaTable(tblName)
sqlSt = "SELECT " & stChema & ".tbldmhanghoa.tenhanghoa, " & stChema & ".tblctunxct.*"
sqlSt = sqlSt & " FROM " & stChema & ".tbldmhanghoa INNER JOIN " & stChema & ".tblctunxct"
sqlSt = sqlSt & " ON " & stChema & ".tbldmhanghoa.mahang=" & stChema & ".tblctunxct.mahang"
sqlSt = sqlSt & " WHERE " & stChema & ".tblctunxct.soctu = '" & vSoCtu & "'"
Set SQLrec = ProcessRecordset(sqlSt)
Set mForm(sForm).Form.Recordset = SQLrec
‘Nạp thông tin chi tiết lên các ô dữ liệu tương ứng trên SubForm
With mForm(sForm).Form
.Requery
!txtId.ControlSource = "id"
!txtMahang.ControlSource = "mahang"
!txtTenHanghoa.ControlSource = "tenhanghoa"
!txtCapDvt.ControlSource = "dvt"
!txtDvt.ControlSource = "=IIF(not isnull(dvt),flookup('kihieu','tbldonvitinh','cap=' & [dvt]),'')"
!txtSoluong.ControlSource = "soluong"
!txtDongia.ControlSource = "dongia"
!chkCKTL.ControlSource = "lacktyle"
!txtMucCK.ControlSource = "mucck"
End With
SQLrec.Close
Set SQLrec = Nothing
End If
End Sub
Trích dẫn:Private Sub cmbSoCtu_AfterUpdate()
Dim vSoCtu
ClearInputCTHH ‘Xoá trống các ô nhập chi tiết hàng hoá
vSoCtu = Trim(Me.cmbSoCtu.Text)
LoadInvoiceInfoToForm vSoCtu ‘Nạp thông tin chứng từ đã chọn lên MainForm và SubForm
End Sub
Trích dẫn:Sub SaveToInvoiceDetailFromForm(Optional InVoiceDetailId)Ở đây chúng ta chú ý: có 2 trường hợp cần phân biệt là nhập mới và hiệu chỉnh thông tin đang có.
'Luu thong tin tren form vao tblctunxCT
'UpdateInvoiceDetail
On Error GoTo HandleError
Dim sqlSt As String, tblName As String
Dim vId
Dim MucCK As Double, CKTL As Byte
Call OpenMyConnection
tblName = "tblctunxct"
With Me
vId = Me.txtDetailId
MucCK = Nz(.txtMucCK)
If IsNull(.chkCKTL) Then
CKTL = 0
Else
If .chkCKTL.Value = True Then
CKTL = 1
Else
CKTL = 0
End If
End If
‘Phân biệt là trường hợp nhập mới hay hiệu chỉnh lại dữ liệu đã có.
If Not IsNull(vId) Then
sqlSt = "UPDATE " & GetSchemaTable(tblName) & "." & tblName & " SET "
sqlSt = sqlSt & " soctu ='" & Trim(.cmbSoCtu) & "',"
sqlSt = sqlSt & " mahang ='" & .cmbMSHH & "',"
sqlSt = sqlSt & " dvt =" & .cmbDvt & ","
sqlSt = sqlSt & " soluong =" & .txtSoluong & ","
sqlSt = sqlSt & " dongia =" & .txtDongia & ","
sqlSt = sqlSt & " lacktyle =" & CKTL & ","
sqlSt = sqlSt & " mucck =" & MucCK
sqlSt = sqlSt & " WHERE ("
sqlSt = sqlSt & " soctu='" & Trim(Me.cmbSoCtu) & "'"
sqlSt = sqlSt & " AND id=" & InVoiceDetailId
sqlSt = sqlSt & ")"
Else
sqlSt = "INSERT INTO " & GetSchemaTable(tblName) & "." & tblName
sqlSt = sqlSt & "(soctu, mahang, dvt, soluong, dongia, lacktyle, mucck)"
sqlSt = sqlSt & " VALUES ("
sqlSt = sqlSt & " '" & Trim(.cmbSoCtu) & "',"
sqlSt = sqlSt & " '" & .cmbMSHH & "',"
sqlSt = sqlSt & " " & .cmbDvt & ","
sqlSt = sqlSt & " " & .txtSoluong & ","
sqlSt = sqlSt & " " & .txtDongia & ","
sqlSt = sqlSt & " " & CKTL & ","
sqlSt = sqlSt & " " & Nz(MucCK)
sqlSt = sqlSt & ")"
End If
End With
MyConn.Execute sqlSt
Call CloseMyConnection ‘Dùng xong rồi thì đóng lại cho đỡ tốn tài nguyên và khỏi gặp xung đột dữ liệu đó các Bạn.
HandleError:
If Err > 0 Then
GeneralErrorHandler Err.Number, Err.Description, NhapXuat_FORM, "SaveToInvoiceDetailFromForm"
Exit Sub
End If
End Sub
Trích dẫn:Dim vHoi As Long, sqlSt As String, tblName As String+ Đối với thông tin chung của chứng từ: cũng tương tự như trên, ta hiệu chỉnh thông tin tại các ô tương ứng; và cũng phân biệt 2 trường hợp: nhập mới và hiệu chỉnh thông tin đang có. Việc ghi lại các thông tin đã cập nhật vào bảng dữ liệu ghi chứng từ phát sinh được thực hiện bằng thủ tục SaveToInvoiceFromForm
Dim DetailId
DetailId = Me.txtDetailId
If Not IsNull(DetailId) Then
vHoi = Eval("msgbox('" & "Ban vua ra lenh cho xoa dong ghi mat hang nay" & vbCrLf & "Co phai Ban chac chan muon Xoa hay khong?" & "@" & "Bam YES de xoa, bam NO de huy bo lenh nay" & "@" & "',36,'Xoa chi tiet hang hoa')")
If vHoi = vbYes Then
tblName = "tblctunxct"
sqlSt = "DELETE " & GetSchemaTable(tblName) & "." & tblName
sqlSt = sqlSt & " WHERE Id =" & DetailId
'
Call OpenDbConnection
ExecuteSQLCommand sqlSt
Call CloseDbConnection
'Xoá xong thì cho cập nhật lại nội dung hiển thị trên SubForm
SetSourceRecForSubForm Me, "frmCtuNXCT"
End If
End If
Trích dẫn:Sub SaveToInvoiceFromForm(Optional InvoiceId, Optional NoLoadInfo)Trong thủ tục trên ta chú ý đoạn
'Luu thong tin tren form vao tblctunx
'UpdateOrInsert:
'+ True: Luu thong tin thay doi vao mau tin dang hien huu
'+ Flase: Them mau tin moi
'InvoiceId: so chung tu
'
On Error GoTo HandleError
Dim sqlSt As String, tblName As String
Dim vId
Call OpenMyConnection
tblName = "tblctunx"
With Me
vId = Me.txtId
If Not IsNull(vId) Then
If IsNull(InvoiceId) Then Exit Sub
sqlSt = "UPDATE " & GetSchemaTable(tblName) & "." & tblName & " SET "
sqlSt = sqlSt & " soctu ='" & .cmbSoCtu & "',"
sqlSt = sqlSt & " ngay ='" & Format$(.txtNgay, "dd-mmm-yy") & "',"
sqlSt = sqlSt & " msnv ='" & .cmbNghiepvu & "',"
sqlSt = sqlSt & " mskh ='" & .cmbKhachhang & "'"
If Not IsNull(.txtNguoiGiaodich) Then sqlSt = sqlSt & ", nguoigiaodich ='" & .txtNguoiGiaodich & "'"
If Not IsNull(.txtTsuat) Then sqlSt = sqlSt & ", tsuatvat =" & .txtTsuat
sqlSt = sqlSt & " WHERE ("
sqlSt = sqlSt & " soctu='" & InvoiceId & "'"
sqlSt = sqlSt & ")"
Else
If IsNull(.cmbSoCtu) Then Exit Sub
sqlSt = "INSERT INTO " & GetSchemaTable(tblName) & "." & tblName
sqlSt = sqlSt & "(soctu, ngay, msnv, mskh"
If Not IsNull(.txtNguoiGiaodich) Then sqlSt = sqlSt & ", nguoigiaodich"
If Not IsNull(.txtTsuat) Then sqlSt = sqlSt & ", tsuatvat"
sqlSt = sqlSt & ")"
sqlSt = sqlSt & " VALUES ("
sqlSt = sqlSt & " '" & .cmbSoCtu & "',"
sqlSt = sqlSt & " '" & Format$(.txtNgay, "dd-mmm-yy") & "',"
sqlSt = sqlSt & " '" & .cmbNghiepvu & "',"
sqlSt = sqlSt & " '" & .cmbKhachhang & "'"
If Not IsNull(.txtNguoiGiaodich) Then sqlSt = sqlSt & ", '" & .txtNguoiGiaodich & "'"
If Not IsNull(.txtTsuat) Then sqlSt = sqlSt & ", " & .txtTsuat
sqlSt = sqlSt & ")"
End If
End With
MyConn.Execute sqlSt
‘Lưu xong thì cho cập nhật lại các thông tin đã lưu lên Form.
If IsMissing(NoLoadInfo) Then
LoadInvoiceInfoToForm Me.cmbSoCtu
Else
LoadInvoiceInfoToForm Me.cmbSoCtu, True
End If
Call CloseMyConnection ‘Mở ra xài xong thì đóng lại
HandleError:
If Err > 0 Then
GeneralErrorHandler Err.Number, Err.Description, NhapXuat_FORM, "SaveToInvoiceFromForm"
Exit Sub
End If
End Sub
Trích dẫn:If IsMissing(NoLoadInfo) ThenCho Lưu xong thì cho cập nhật lại các thông tin đã lưu lên Form. Cái này cần để ghi bổ sung những thông tin chỉ phát sinh khi dữ liệu được ghi vào bảng dữ liệu, chẳng hạn như chỉ số Id tự động của bản ghi, hoặc các giá trị tính toán cần thiết khác.
LoadInvoiceInfoToForm Me.cmbSoCtu
Else
LoadInvoiceInfoToForm Me.cmbSoCtu, True
End If
Trích dẫn:If Not IsNull(.txtNguoiGiaodich) Then sqlSt = sqlSt & ", '" & .txtNguoiGiaodich & "'"Ở đây tôi xác định các chi tiết: Người trực tiếp giao dịch, thuế suất VAT là những chi tiết thông tin không phải lúc nào cũng bắt buộc phải có khi lập chứng từ nên đã dự liệu bằng các statement IF... THEN ...
If Not IsNull(.txtTsuat) Then sqlSt = sqlSt & ", " & .txtTsuat
lehongduc > 18-07-14, 07:37 AM
quanghoasla > 14-10-14, 02:31 PM
(05-07-12, 02:14 PM)Noname Đã viết:(05-07-12, 12:27 PM)lehongduc Đã viết: Chào các Bạn,Bài viết rất hay và câu nói rất chí lý! Mình thấy nhiều bạn cứ cố nhét thật nhiều VBA vào để có vẻ 'pro', nhưng thật ra chỉ vài câu query là giải quyết được vấn đề.Mình từng thấy 1 chương trình kế toán chỉ có code đọc số thành chữ là dùng VBA, còn lại toàn query và macro và "10 năm vẫn chạy tốt". Và cũng đúng như bạn phân tích, unbound đúng là xử lý tốt hơn Bound, nhưng các bạn cần cân nhắc hiệu quả kinh tế khi dùng nó!
Hôm nay, xin trao đổi với các Bạn về Bound Form và UnBound Form
1. Bound Form là gì?
Bound Form là 1 form được gán Record Source xác định,
............
2. UnBound Form là gì?
Ngược với Bound Form, UnBound Form là form không gắn với 1 nguồn dữ liệu xác định nào cả.
.....
3. Vậy, nên áp dụng Bound Form hay UnBound Form? Cái nào ưu việt hơn?
Câu trả lời ở đây là: lựa chọn phải tùy vào mục đích ta áp dụng để làm gì và trong hoàn cảnh cụ thể như thế nào?
Nếu chỉ với dữ liệu chạy cục bộ, chỉ có một người sử dụng trong cùng 1 thời gian và quy mô dữ liệu không lớn lắm thì lựa chọn áp dung Bound Form sẽ tốt hơn, vì dễ dàng và nhanh chóng.
Cái nào ưu việt hơn? cái nào giúp ta đạt được mục đích với chi phí ít nhất (tiền bạc, thời gian, công sức) là cái ưu việt hơn. Ở đây chúng ta cần suy niệm nguyên tắc của tiền nhân là “đừng bao giờ mổ gà bằng dao mổ trâu và ngược lại.”
quanghoasla > 14-10-14, 02:58 PM
(09-07-12, 01:22 PM)lehongduc Đã viết: Chào các Bạn,
Về việc kết nối với dữ liệu nguồn qua mạng máy tính tôi thấy cũng cần trao đổi thêm về việc tổ chức dữ liệu sao cho việc kết nối dữ liệu được thuận lợi và hiệu quả nhất.
Theo tôi thấy (có thể các Bạn sẽ thấy khác): Trong thực tế, không phải lúc nào chúng ta cũng cần lấy dữ liệu xuống bằng cách kết nối với dữ liệu nguồn đặt tại server; có những nguồn dữ liệu có tính ổn định nhất định (không bị thay đổi thường xuyên) ta có thể cho trích xuất với phạm vi giới hạn nhất định và cho lưu xuống máy client (máy khách cần kết nối vào server), sau đó ta sẽ cho nạp nguồn dữ liệu từ dữ liệu đã được trích xuất này. Làm như vậy ta vừa cải thiện được tốc độ truy xuất dữ liệu, vừa giảm được tải không cần thiết cho cả server và client.
Các Bạn thử xem xét tình huống sau đây nhé:
Với doanh nghiệp bán hàng trên phạm vi rộng, có ứng dụng chạy trên client kết nối đến dữ liệu nguồn ở server, ứng dụng này dành cho các nhân viên thị trường sử dụng trên các laptop để thực hiện nhiệm vụ "Tìm kiếm khách mua hàng và lập đơn đặt hàng theo bảng giá ấn định chung". Mỗi nhân viên thị trường đều được phân công phụ trách một phạm vi địa lý nhất định.
Như vậy, ta có thể cho trích xuất các nguồn dữ liệu sau lưu xuống máy client để ứng dụng client sử dụng trực tiếp, không cần phải lấy từ server thông qua kết nối qua mạng:
+ Danh sách khách hàng trong phạm vi địa lý đã phân công cho từng nhân viên;
+ Danh mục hàng hoá (có bảng giá) cũng trong giới hạn cần thiết.
Đồng thời với đó, ta sẽ có các thủ tục thích hợp để cho đồng bộ dữ liệu đang lưu tạm trên các máy Client với dữ liệu gốc trên server. Việc đồng bộ dữ liệu này sẽ được thực hiện tại thời điểm thích hợp (trong ngày hoặc trong tuần) hoặc khi có sự kiện thay đổi dữ liệu xảy ra (như đơn giá được người có thẩm quyền cập nhật mới, ...).
Các Bạn có thấy điều gì không ổn trong đề nghị trên của tôi không? Xin vui lòng góp ý trao đổi thêm.