Xin giúp đỡ về câu lệnh truy vấn sử dụng ADO đưa dữ liệu từ vào Excel (1 người xem)

  • Thread starter Thread starter KVP
  • Ngày gửi Ngày gửi
Liên hệ QC

Người dùng đang xem chủ đề này

KVP

Thành viên thường trực
Tham gia
7/7/07
Bài viết
218
Được thích
301
Nghề nghiệp
Cộng đồng
Em có 2 Sheets. 1 Sheet làm Report, 1 sheet Data chứa dữ liệu (File đính kèm). Hiện giờ em muốn dùng ADO để đưa dữ liệu từ Data vào report.
Em thường dùng phương thức CopyFromRecordset để lấy dữ liệu, thông thường nếu cấu trúc Data và report giống nhau thì không có gì để nói. Nhưng khi report thay đổi cấu trúc một chút thì phương thức này không còn đúng nữa.
Nếu copy từng Recordset thì phải đóng, mở Recordset giải khiến Code dài và phức tạp. Hiện em đang loay hoay với vấn đề này mà chưa có cách giải quyết.

Rất mong anh chị xem xét, giúp em phương pháp tối ưu nhất.
Xin cám ơn
 

File đính kèm

Em có 2 Sheets. 1 Sheet làm Report, 1 sheet Data chứa dữ liệu (File đính kèm). Hiện giờ em muốn dùng ADO để đưa dữ liệu từ Data vào report.
Em thường dùng phương thức CopyFromRecordset để lấy dữ liệu, thông thường nếu cấu trúc Data và report giống nhau thì không có gì để nói. Nhưng khi report thay đổi cấu trúc một chút thì phương thức này không còn đúng nữa.
Nếu copy từng Recordset thì phải đóng, mở Recordset giải khiến Code dài và phức tạp. Hiện em đang loay hoay với vấn đề này mà chưa có cách giải quyết.

Rất mong anh chị xem xét, giúp em phương pháp tối ưu nhất.
Xin cám ơn
Nếu cấu trúc Data có thay đổi thì thay đổi như thế nào? Có thay đổi tên trường hay không? Nếu không thì bạn vẫn có thể dùng phương thức CopyFromRecordset để lấy dữ liệu.
Cho mình hỏi code của bạn viết như thế nào vậy.
 
Cám ơn bạn
Mình gửi lại File kèm theo code của mình

Ở đây ý mình muốn nói: thông thường cột Mã giống như DATA có thứ tự từ 001-> 010, nhưng nếu Report cột mã thứ tự đó thay đổi, mất đi một số chỉ tiêu 003,005,009 thì khi Copyfromrecordset vào B2 sẽ cho ra toàn bộ dữ liệu của DATA.

Vậy phải thay thế phương thức này hoặc dùng bằng cách khác?
 

File đính kèm

Cám ơn bạn
Mình gửi lại File kèm theo code của mình

Ở đây ý mình muốn nói: thông thường cột Mã giống như DATA có thứ tự từ 001-> 010, nhưng nếu Report cột mã thứ tự đó thay đổi, mất đi một số chỉ tiêu 003,005,009 thì khi Copyfromrecordset vào B2 sẽ cho ra toàn bộ dữ liệu của DATA.

Vậy phải thay thế phương thức này hoặc dùng bằng cách khác?
Chưa hiểu ý KVP lắm, có phải sh report muốn ra kết quả cột B và C dạng như Vlookup từ Data?.
Thấy code trên chỉ lấy có 2 cột vào rec nên chưa hiểu ý đồ.
Tồi thì sẽ làm như sau
1/ Dùng ADO lấy toàn bộ data.
2/ Gán Rec -> Arr
3/ Duyệt cột 1 Report để lấy cột 2, 3
Mà hình như dùng ADO có dùng quạn hệ gì đó để chỉ lấy ra rec toàn bộ data theo tiêu chí report.
Tóm lại là yêu cầu cụ thể mới biết.
 
Dạ đúng như anh hiểu đó ah
Có điều dùng ADO để duyệt cột 1 report thì e chưa biết code thế nào . Code của em chỉ lấy được cả mảng dữ liệu của Data chứ không lấy được theo như yêu cầu giống Vlookup
 
Dạ đúng như anh hiểu đó ah
Có điều dùng ADO để duyệt cột 1 report thì e chưa biết code thế nào . Code của em chỉ lấy được cả mảng dữ liệu của Data chứ không lấy được theo như yêu cầu giống Vlookup
Vậy thì viết tiếp 1 code dạng vlookup nhé. Và cũng xử lý từ rec trên theo đúng tinh thần ADO.
 
Anh cho em một ví dụ đc ko
 
Cám ơn bạn
Mình gửi lại File kèm theo code của mình

Ở đây ý mình muốn nói: thông thường cột Mã giống như DATA có thứ tự từ 001-> 010, nhưng nếu Report cột mã thứ tự đó thay đổi, mất đi một số chỉ tiêu 003,005,009 thì khi Copyfromrecordset vào B2 sẽ cho ra toàn bộ dữ liệu của DATA.

Vậy phải thay thế phương thức này hoặc dùng bằng cách khác?
Theo mình nghĩ là phải đóng và mở record nhiều lần bằng cách là duyệt qua từng cell dữ liệu sheet Report từ A2:A8 để làm điều kiện lọc. Kết quả tương tứng sẽ cho ra tại 2 cột kế bên.
 
Vậy nếu Report >> 8 dòng thì có khả thi ko anh?
 
Anh cho em một ví dụ đc ko
KVP dùng thử code này nhé, có dùng Dic đế lấy danh mục mã duy nhất.
PHP:
Sub Button1_Click()
Dim strPath As String, mySQL_Dr As String
Dim Cnn As New ADODB.Connection
Dim Rcs As New ADODB.Recordset
Dim iR&, iC&, nR&, sMa$, endr&
Dim recArr(), sArr, rArr, ArrKQ
Dim Dic As Object
Set Dic = CreateObject("Scripting.Dictionary")
'-------------------------------------------------------------------------
'Tuy chon Loai BC combobox phu hop SQL text sau menh de Where
strPath = ThisWorkbook.FullName
Set Cnn = New ADODB.Connection
'Tao Ket noi voi file du lieu nguon:
Cnn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & strPath & _
                            ";Persist Security Info=False; Extended Properties=Excel 8.0;"
'---------------------------------------------------------------------------
mySQL_Dr = " SELECT Ma, F01,F02  FROM [DATA$] "
Rcs.Open mySQL_Dr, Cnn, adOpenKeyset, adLockOptimistic
'---------------------------------------------------------------------------
With Sheets("Report")
  endr = .Cells(65000, 1).End(xlUp).Row
  .Range("B2:C100").ClearContents
  'gan ma cua rport thanh rArr
  rArr = .Range("A2:A" & endr).Value
End With
'Convert Rec to RecArr va chuyen ngang thanh doc và lay ma duy nhat
recArr = Rcs.GetRows
ReDim sArr(1 To UBound(recArr, 2) + 1, 1 To UBound(recArr) + 1)
For iR = 0 To UBound(recArr, 2)
  sMa = CStr(recArr(0, iR))
  Dic.Add sMa, iR + 1
  For iC = 0 To UBound(recArr, 1)
   sArr(iR + 1, iC + 1) = recArr(iC, iR)
  Next iC
Next iR
'Duyet qua report va lay ket qua
ReDim ArrKQ(1 To UBound(rArr), 1 To 2)
For iR = 1 To UBound(rArr)
  If Len(rArr(iR, 1)) > 0 Then
    sMa = CStr(rArr(iR, 1))
    nR = Dic.Item(sMa)
    For iC = 1 To 2
      ArrKQ(iR, iC) = sArr(nR, iC + 1)
    Next iC
  End If
Next iR
'Gan vao sh
With Sheets("Report")
  .[B2].Resize(UBound(rArr), 2) = ArrKQ
End With
'Refresh lai hai bien cnEx va Rcs:
Rcs.Close: Set Rcs = Nothing
Cnn.Close: Set Cnn = Nothing
Set Dic = Nothing
Erase recArr(), sArr, rArr, ArrKQ
End Sub
 
>>> 8 dòng anh ạ. Thực chất là em muốn biết thuật toán. Ở ví dụ này em đưa dữ liệu là Excel cho đơn giản, ứng dụng của em là lấy dữ liệu từ Access, Excel chỉ dùng làm report nên không Vlookup đc. Muốn vậy em phải đưa data ra một sheets tạm rồi mới Vlookup.
Report thì không cố định bao giờ cả, nên em muốn tìm giải pháp tốt nhất cho ứng dụng của mình bằng ADO

Cám ơn anh Thunghi nhiều, code chạy ngon lành, em chỉnh sửa một chút cho phù hợp với ứng dụng của mình là OK
 
Lần chỉnh sửa cuối:
>>> 8 dòng anh ạ. Thực chất là em muốn biết thuật toán. Ở ví dụ này em đưa dữ liệu là Excel cho đơn giản, ứng dụng của em là lấy dữ liệu từ Access, Excel chỉ dùng làm report nên không Vlookup đc. Muốn vậy em phải đưa data ra một sheets tạm rồi mới Vlookup.
Report thì không cố định bao giờ cả, nên em muốn tìm giải pháp tốt nhất cho ứng dụng của mình bằng ADO

Cám ơn anh Thunghi nhiều, code chạy ngon lành, em chỉnh sửa một chút cho phù hợp với ứng dụng của mình là OK
Anh ThuNghi can thiệp thô bạo vào nó quá, làm mất "mùi" ADO hết, với lại khi có dữ liệu trùng, trống, hoặc nếu như mã ở sheet Report có mà sheet Data không có sẽ gây lỗi. Ta có thể dùng Query truy vấn với 2 bảng này bình thường giống như bên Access vậy. Bạn thử xem sao nhé.
 
Nếu dùng Query với CSDL acess, report excel mà kết hợp thì em chưa thấy bao giờ.
Giả sử e đưa data ra một sheets tạm rồi truy vấn, câu lệnh SQL liệu có giống Acess không anh. Anh có thể cho ví dụ dc không ạh?
Nhưng dùng được đơn thuần SQL thì vẫn là giải pháp chuẩn ADO nhất
 
Lần chỉnh sửa cuối:
Nếu dùng Query với CSDL acess, report excel mà kết hợp thì em chưa thấy bao giờ.
Giả sử e đưa data ra một sheets tạm rồi truy vấn, câu lệnh SQL liệu có giống Acess không anh. Anh có thể cho ví dụ dc không ạh?
Nhưng dùng được đơn thuần SQL thì vẫn là giải pháp chuẩn ADO nhất
Bạn thử đoạn truy vấn như sau:

mySQL_Dr = "SELECT [Report$].[Ma], [Data$].[F01], [Data$].[F02] " & _
"FROM [Report$] LEFT JOIN [Data$] ON [Report$].[Ma] = [Data$].[Ma] "

Tham khảo thêm file đính kèm nhé.
 

File đính kèm

Quá tuyệt vời.
Nhưng nếu như em đề cập, không đưa Data ra sheets tạm mà để nguyên trong access thì không LEFT JOIN được anh ạh
 
Quá tuyệt vời.
Nhưng nếu như em đề cập, không đưa Data ra sheets tạm mà để nguyên trong access thì không LEFT JOIN được anh ạh
Vẫn được bạn à, truy vấn được hết. Nếu không dùng LEFT JOIN thì nó không thể hiện dữ liệu nếu như bảng kia không có dữ liệu. Bạn thử test nhé.
 
Lần chỉnh sửa cuối:
Test kỹ lại File của anh, nếu report có cấu trúc khác data (cách dòng) thì dữ liệu cũng không hiển thị.

Nếu đưa data vào Access như File đính kèm thì rõ ràng phép nối INNER JOIN một sheets với một Table mdb là không thể. Anh có thể xem lại dùm em một chút dc không?
 

File đính kèm

Test kỹ lại File của anh, nếu report có cấu trúc khác data (cách dòng) thì dữ liệu cũng không hiển thị.

Nếu đưa data vào Access như File đính kèm thì rõ ràng phép nối INNER JOIN một sheets với một Table mdb là không thể. Anh có thể xem lại dùm em một chút dc không?
Kết nối vào CSDL Access , mà CSDL Access chỉ có bảng Data, không có bảng Report, nên gây lỗi. Hình như không thể ghép 2 kết nối riêng lẽ vào 1. Để thực hiện yêu cầu của bạn thì bạn phải tạo bảng Report trong CSDL Access rồi đưa dữ liệu ĐK vào bảng đó, xong rồi truy vấn, khi đạt kết quả ta xóa hết dữ liệu trong bảng Report đó đi. Bạn thử theo cách này xem nhé.
Xin lỗi mình chưa test theo ý này. Nhưng chắc bạn làm được.
Thân
 
Code của a ThuNghi chỉ cần thêm bẫy lỗi khéo một chút là đáp ứng được yêu cầu.
Tuy hơi phức tạp nhưng gọn gàng hơn nếu dùng ADO phải đưa dữ liệu ra, vô.

Cám ơn các anh nhiều
 
Test kỹ lại File của anh, nếu report có cấu trúc khác data (cách dòng) thì dữ liệu cũng không hiển thị.
Hiển thị chứ bạn, điều này tôi đảm bảo với bạn, nếu như mã bên sheet Data và mã bên sheet Report có tương ứng.
File của bạn không ra là đúng vì sheet Report bạn ghi mã 0050, 0030 mã này không có tồn tại bên sheet Data nên nó không ra là đúng.
Ta nên loại bỏ dòng trống thừa khi lấy kq nhé bạn.
 
Lần chỉnh sửa cuối:
Code của a ThuNghi chỉ cần thêm bẫy lỗi khéo một chút là đáp ứng được yêu cầu.
Tuy hơi phức tạp nhưng gọn gàng hơn nếu dùng ADO phải đưa dữ liệu ra, vô.

Cám ơn các anh nhiều
Nếu không muốn đưa vào, đưa ra thì bạn có thể đưa vào 1 phát = Update Query. Vừa nhanh, vừa gọn, lại vừa dể hiểu.
 
Hiển thị chứ bạn, điều này tôi đảm bảo với bạn, nếu như mã bên sheet Data và mã bên sheet Report có tương ứng.
File của bạn không ra là đúng vì sheet Report bạn ghi mã 0050, 0030 mã này không có tồn tại bên sheet Data nên nó không ra là đúng.
Ta nên loại bỏ dòng trống thừa khi lấy kq nhé bạn.
Theo tôi thì nếu sử dụng ADO thì nên dùng để lấy Data thôi, lấy xong rồi mà muốn Report trên Ex thì xử lý trên Ex cho khỏe.
Chớ ai lại dùng ADO chuyển report sang Acc rồi từ Data kết hợp Join để tạo ra 1 report và lấy chuyển qua Ex. Phức tạp quá.
Còn vấn đề code của mình nếu bẫy lỗi khi report kg có mã thì dễ mà. Code chỉ phức tạp ở chuyển từ ngang qua dọc, còn kg chả có gì, kg cần dùng Dic cũng OK. Thêm vòng lặp theo hướng xử lý Arr cũng nhanh.
PHP:
If nR then...
end if
Đàng nào cũng phải.
1/ Dùng Ado lấy Data -> rec
2/ Convert Rec sang Arr
3/ Convert Arr ngang sang dọc (transpose) kết hợp luôn lấy số dòng hiển thị mã (nR=Dic.Item)
5/ Duyệt lại Report, nếu tìm ra nR thì gán cột còn lại, còn kg thì thôi.
Code dùng arr của mình báo lỗi do
1/ Data có A06 là trùng
Vậy phải thêm
PHP:
If Not Dic.Exists(sMa) Then
    Dic.Add sMa, iR + 1
  End If
2/ Những mã kg có trong Data thì thêm
PHP:
If nR Then
      For iC = 1 To 2
        ArrKQ(iR, iC) = sArr(nR, iC + 1)
      Next iC
    Else
      ArrKQ(iR, 1) = "Nothing"
    End If
 
Lần chỉnh sửa cuối:
Theo tôi thì nếu sử dụng ADO thì nên dùng để lấy Data thôi, lấy xong rồi mà muốn Report trên Ex thì xử lý trên Ex cho khỏe.
Chớ ai lại dùng ADO chuyển report sang Acc rồi từ Data kết hợp Join để tạo ra 1 report và lấy chuyển qua Ex. Phức tạp quá.
Còn vấn đề code của mình nếu bẫy lỗi khi report kg có mã thì dễ mà. Code chỉ phức tạp ở chuyển từ ngang qua dọc, còn kg chả có gì, kg cần dùng Dic cũng OK. Thêm vòng lặp theo hướng xử lý Arr cũng nhanh.
PHP:
If nR then...
end if
Đàng nào cũng phải.
1/ Dùng Ado lấy Data -> rec
2/ Convert Rec sang Arr
3/ Convert Arr ngang sang dọc (transpose) kết hợp luôn lấy số dòng hiển thị mã (nR=Dic.Item)
5/ Duyệt lại Report, nếu tìm ra nR thì gán cột còn lại, còn kg thì thôi.
Em làm cái Update Query luôn, anh xem coi nó rất đơn giản.
Cái này em kết nối với CSDl Access, rồi update trực tiếp vào sheet Report, không qua 1 bảng trung gian nào.
Mã:
Sub HLMT_ADO()
Dim Cn As New ADODB.Connection
With Cn
    .Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.Path & "\DB.mdb"


        sSQL = "UPDATE [Data] a " _
                & "INNER JOIN " _
                & "[Excel 8.0;HDR=YES;IMEX=2;DATABASE=" & ThisWorkbook.FullName & "].[Report$] b  " _
                & "ON a.ma=b.ma " _
                & "SET b.f01=a.f01, b.f02=a.f02"
        [B2:C100].ClearContents
    .Execute sSQL
    .Close
End With
Set Cn = Nothing


End Sub
 

File đính kèm

Em làm cái Update Query luôn, anh xem coi nó rất đơn giản.
Cái này em kết nối với CSDl Access, rồi update trực tiếp vào sheet Report, không qua 1 bảng trung gian nào.
Mã:
Sub HLMT_ADO()
Dim Cn As New ADODB.Connection
With Cn
    .Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.Path & "\DB.mdb"


        sSQL = "UPDATE [Data] a " _
                & "INNER JOIN " _
                & "[Excel 8.0;HDR=YES;IMEX=2;DATABASE=" & ThisWorkbook.FullName & "].[Report$] b  " _
                & "ON a.ma=b.ma " _
                & "SET b.f01=a.f01, b.f02=a.f02"
        [B2:C100].ClearContents
    .Execute sSQL
    .Close
End With
Set Cn = Nothing


End Sub
Quá hay ADO kết hợp cả tbl acc và sh của Ex, đang học hỏi nhưng hơi khó.
HLMT cho hỏi thử câu nào là gán vào sh Report vậy
PHP:
.Execute sSQL
Và nếu gán vào dòng 100 thay ví A 1 thì sửa thế nào
Cám ơn.
 
Lần chỉnh sửa cuối:
Quả thật là E cũng không ngờ và chưa thâý sự kết hợp này bao giờ (cả Google luôn). Code gọn lỏn àh
Lúc trước cũng đã học hỏi anh được một chiêu trong ADO giờ lại được chiêu nữa.
Như vậy là E sử dụng 2 phương án cho tình huống này. ADO và Dic. cho nó chắc và ổn định.
 
Lần chỉnh sửa cuối:
Quá hay ADO kết hợp cả tbl acc và sh của Ex, đang học hỏi nhưng hơi khó.
HLMT cho hỏi thử câu nào là gán vào sh Report vậy
PHP:
.Execute sSQL
Và nếu gán vào dòng 100 thay ví A 1 thì sửa thế nào
Cám ơn.

Theo Em, Code này không copy từ Rec mà update và Range name định sẵn của report. Nếu muốn gán vào dòng 100 thì chỉ có di chuyển cả name theo địa chỉ tương ứng hoặc Update song copy lại thôi à.
 
Sẳn đề tài này về ADO, cho tôi hỏi, giữa 2 thủ tục dưới đây, thủ tục nào cũng cho ra kết quả đúng và thời gian cũng như nhau, vậy chúng ta nên dùng cấu trúc nào để tối ưu nhất:

Thủ tục 1:

PHP:
            sSQL = "SELECT Sum(NgayPhep) " _
                 & "FROM TB_LuongThucTe " _
                 & "WHERE KyLuong Like '%2012' AND MaTinhLuong = 'TM00001' " _
                 & "GROUP BY MaTinhLuong"

Thủ tục 2:

PHP:
            sSQL = "SELECT Sum(NgayPhep) " _
                 & "FROM TB_LuongThucTe " _
                 & "WHERE KyLuong Like '%2012' " _
                 & "GROUP BY MaTinhLuong " _
                 & "HAVING MaTinhLuong = 'TM00001'"
 
Theo Em, Code này không copy từ Rec mà update và Range name định sẵn của report. Nếu muốn gán vào dòng 100 thì chỉ có di chuyển cả name theo địa chỉ tương ứng hoặc Update song copy lại thôi à.

Câu lệnh SQL là Update, đích là recordset trên sheet của Excel, vậy recordset Excel nằm đâu, Update vào đó.
Tuy nhiên, nếu "Report" là record set lấy từ sheet name, đương nhiên là bắt đầu từ A1
Nếu A100 hoặc chỗ khác, thì phải đặt Name và recordset lấy từ Range Name, thay vì sheet name
 
Lần chỉnh sửa cuối:
Câu lệnh SQL là Update, đích là recordset trên sheet của Excel, vậy recordset Excel nằm đâu, Update vào đó.
Tuy nhiên, nếu "Report" là record set lấy từ sheet name, đương nhiên là bắt đầu từ A1
Nếu A100 hoặc chỗ khác, thì phải đặt Name và recordset lấy từ Range Name, thay vì sheet name

Anh có thể cho em 1 ví dụ nho nhỏ được không anh ?
 
Bạn xem trong File đính kèm, xin phép mượn code của Anh HLMT
Ở đây mình đặt Name có tên RangeName
 

File đính kèm

Lần chỉnh sửa cuối:
Chỉ có 1 câu giải thích nho nhỏ: http://www.giaiphapexcel.com/forum/...ase-cho-công-việc-kế-toán&p=365750#post365750

ADO có thể lấy dữ liệu từ các bảng (table), không phải chỉ lấy từ tên sheet.
Nếu 1 sheet chỉ chứa 1 bảng, ta có thể dùng tên sheet làm tên table, và ADO hiểu. Nếu thêm $ thì càng tốt thí dụ [Data$]
Nếu 1 sheet chứa nhiều table như sheet DM (3 bảng danh mục), ta sẽ đặt name cho từng vùng, name đó trở thành tên table
 
Sẳn đề tài này về ADO, cho tôi hỏi, giữa 2 thủ tục dưới đây, thủ tục nào cũng cho ra kết quả đúng và thời gian cũng như nhau, vậy chúng ta nên dùng cấu trúc nào để tối ưu nhất:

Thủ tục 1:

PHP:
            sSQL = "SELECT Sum(NgayPhep) " _
                 & "FROM TB_LuongThucTe " _
                 & "WHERE KyLuong Like '%2012' AND MaTinhLuong = 'TM00001' " _
                 & "GROUP BY MaTinhLuong"

Thủ tục 2:

PHP:
            sSQL = "SELECT Sum(NgayPhep) " _
                 & "FROM TB_LuongThucTe " _
                 & "WHERE KyLuong Like '%2012' " _
                 & "GROUP BY MaTinhLuong " _
                 & "HAVING MaTinhLuong = 'TM00001'"
Cả 2 cách này đều được. Tuy nhiên cái thủ tục 2 nếu dùng Having thì phải như sau:

Mã:
sSQL = "SELECT Sum(NgayPhep) " _
                 & "FROM TB_LuongThucTe " _
                 & "GROUP BY MaTinhLuong " _
                 & "HAVING MaTinhLuong = 'TM00001' and KyLuong Like '%2012'"
Còn nếu dùng where thì theo cái thủ tục 1 của anh.

Xin nói thêm khi nào dùng where và khi nào dùng having trong Query gom nhóm: Theo kinh nghiệm non kém của em thì cú pháp như sau

1./ Where:

Mã:
Select .......
          From ........
         [COLOR=#ff0000] Where[/COLOR] .......
          Group by......

2./ Having:

Mã:
Select .......
          From ........
         [COLOR=#FF0000] [/COLOR]Group by......
          [COLOR=#ff0000]Having [/COLOR].......

Nói túm lại Having là điều kiện lọc phải đứng sau Group by, ngược lại Where là điều kiện lọc phải đứng trước Group by.
 
Cả 2 cách này đều được. Tuy nhiên cái thủ tục 2 nếu dùng Having thì phải như sau:

Còn nếu dùng where thì theo cái thủ tục 1 của anh.
PHP:
sSQL = "SELECT Sum(NgayPhep) " _
                 & "FROM TB_LuongThucTe " _
                 & "WHERE Sum(NgayPhep)> 2  and KyLuong Like '%2012' AND MaTinhLuong = 'TM00001' " _
                 & "GROUP BY MaTinhLuong"
Theo như mới google thì cú pháp having có ứng dụng riêng <> where.
Với code trên nếu muốn select sum(ngayphep) where sum(ngayphep) > 2 thì kg được mà phải dùng having.
mà phải dùng
PHP:
sSQL = "SELECT Sum(NgayPhep) " _
                 & "FROM TB_LuongThucTe " _
                 & "WHERE KyLuong Like '%2012' AND MaTinhLuong = 'TM00001' " _
                 & "GROUP BY MaTinhLuong having Sum(NgayPhep)> 2"
Với select mà có điều kiện sum ... thì kg thể gán ở where mà phải having.
Do chưa có bài để test nên chỉ phác họa.
Mấy điều này học từ file kế toán của Bác Mỹ làm = ADO lấu rồi => nghiệm ra nên chả biết giải nghĩa thế nào.
 
Anh thử
Nói túm lại Having là điều kiện lọc phải đứng sau Group by, ngược lại Where là điều kiện lọc phải đứng trước Group by.

Em nghĩ sẽ được đó anh.
 
Với select mà có điều kiện sum ... thì kg thể gán ở where mà phải having.
Do chưa có bài để test nên chỉ phác họa.
Mấy điều này học từ file kế toán của Bác Mỹ làm = ADO lấu rồi => nghiệm ra nên chả biết giải nghĩa thế nào.
Về vấn đề này cadafi có giải thích 1 lần rất ngắn gọn mà rất hay, tiếc là không tìm lại được bài ấy:
Đại khái là:
câu lệnh where sẽ lọc và trích xuất trước khi tính toán
having lọc và trích xuất sau khi tính toán

(nhớ không chắc lắm nhen, để hỏi lại cadafi)
 
Em làm cái Update Query luôn, anh xem coi nó rất đơn giản.
Cái này em kết nối với CSDl Access, rồi update trực tiếp vào sheet Report, không qua 1 bảng trung gian nào.
Mã:
Sub HLMT_ADO()
Dim Cn As New ADODB.Connection
With Cn
    .Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & ThisWorkbook.Path & "\DB.mdb"


        sSQL = "UPDATE [Data] a " _
                & "INNER JOIN " _
                & "[Excel 8.0;HDR=YES;IMEX=2;DATABASE=" & ThisWorkbook.FullName & "].[Report$] b  " _
                & "ON a.ma=b.ma " _
                & "SET b.f01=a.f01, b.f02=a.f02"
        [B2:C100].ClearContents
    .Execute sSQL
    .Close
End With
Set Cn = Nothing


End Sub
Với cấu trúc này ta có thể update dữ liệu ngược lại từ file Excel của sheet report sang file access có bảng là data một cách rất dể dàng.
Ta chỉ cần thay a thành b của dòng "SET b.f01=a.f01, b.f02=a.f02" là được.
 

Bài viết mới nhất

Back
Top Bottom