Thảo luận về bài: ADO căn bản "Kết nối truy vấn CSDL từ file Excel đến file Access."

Liên hệ QC
Đã test với rào # rồi. Nếu # thì nó sẽ chưa hiểu dd/mm/yyyy mà nó hiểu mm/dd/yyyy
Trong file gồm có các code.

Với dạng bài này, nếu dùng trực tiếp điều kiện thì code sẽ như vầy:

Mã:
Sub LayDuLieu02_1()
    On Error GoTo Loi
    Dim lsSQL As String: Dim rst As New ADODB.Recordset
    
    If cnn.State <> 1 Then Moketnoi
    
[COLOR=#0000cd][B]    lsSQL = "SELECT * FROM tblData " _
          & "WHERE [ORIGIN] = 'VIETNAM' " _
          & "AND [W_HDATE] >= #6/8/12# " _
          & "AND [W_HDATE] <= #7/20/12#;"
[/B] [/COLOR]   
    rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
    
    With Sheets("BC")
        .Cells.ClearContents
        .Range("A5").CopyFromRecordset rst
    End With
    
    rst.Close
    Set rst = Nothing
    cnn.Close
    Set cnn = Nothing
    Exit Sub
    
Loi:
    MsgBox Err.Description
End Sub

Tuy nhiên, tôi thích đưa dữ liệu gián tiếp hơn, bằng cách thông qua các INPUTBOX, nhằm đa dạng hóa điều kiện nhập vào:

Cũng giống như các Parameter của Access, tôi dùng InputBox (Nếu dùng trực tiếp trên Access thì không cần đặt InputBox làm gì, nhưng với ADO thì không làm sao cho nó hiển thị cái Parameter này nên phải dùng đến InputBox).

Mã:
Sub LayDuLieu02_2()
    On Error GoTo Loi
    Dim lsSQL As String: Dim rst As New ADODB.Recordset
    Dim IptXuatXu As String, IptfDate As Date, IpteDate As Date
    
[B][COLOR=#0000cd]    IptXuatXu = InputBox("ORIGIN", "INPUT ORIGIN")
    
    If IptXuatXu = "" Then Exit Sub
    
    IptfDate = InputBox("START DATE", "INPUT START DATE")
    
    IpteDate = InputBox("END DATE", "INPUT END DATE")
 [/COLOR][/B]   
    If cnn.State <> 1 Then Call Moketnoi
    
[COLOR=#800080]    lsSQL = "SELECT * FROM tblData " _
          & "WHERE [ORIGIN] LIKE [B]'[/B][/COLOR][B][COLOR=#ff0000]%[/COLOR][/B][COLOR=#800080][B]"[/B] & IptXuatXu & [B]"[/B][/COLOR][B][COLOR=#ff0000]%[/COLOR][/B][COLOR=#800080][B]'[/B] " _
          & "AND [W_HDATE] >= #" & Format(IptfDate, "m/d/yyyy") & "# " _
          & "AND [W_HDATE] <= #" & Format(IpteDate, "m/d/yyyy") & "#;"[/COLOR]
        
    rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
    
    With Sheets("BC")
      .Cells.ClearContents
      .Range("A5").CopyFromRecordset rst
    End With
    
    rst.Close
    Set rst = Nothing
    cnn.Close
    Set cnn = Nothing

Exit Sub

Loi:
    MsgBox Err.Description
End Sub

Khi các InputBox nhập ngày tháng, với năm hiện hành chúng ta chỉ cần điền [ngày/tháng] (theo kiểu mặc định của hệ thống nếu ngày trước tháng sau, hoặc ngược lại), nhưng nếu điều kiện không phải năm hiện hành thì ta điền đấy đủ [ngày/tháng/năm] (theo cấu trúc mặc định hệ thống).

VỚI SQL TRONG ACCESS CHỈ ĐƠN GIẢN NHƯ VẦY:

Mã:
SELECT *FROM tblData
WHERE [ORIGIN] LIKE [B]'[COLOR=#ff0000]*[/COLOR]'[/B] & [XUAT XU:] & [B]'[COLOR=#ff0000]*[/COLOR]'[/B]
AND [W_HDATE]>=[TU NGAY:] 
AND [W_HDATE]<=[DEN NGAY:];

Các bạn để ý thấy tôi sử dụng dấu phần trăm (%) và dấu sao (*), với 2 dấu này, với toán tử LIKE được xem như là dò tìm cụm từ nào đó trong toàn bộ điều kiện cần tìm.

VD: Cần tìm VIETNAM ta có thể gõ: VIE hoặc NAM hoặc IET v.v...

Tại sao lúc thì % lúc thì * , là vì với Access ta chỉ được dùng dấu * cho SQL thôi, còn với ADO thì ta phải dùng dấu % nó mới chạy đúng như ta mong đợi.
 
lsSQL = "SELECT * FROM tblData " _ & "WHERE [ORIGIN] LIKE '%" & IptXuatXu & "%' " _ & "AND [W_HDATE] >= #" & Format(IptfDate, "m/d/yyyy") & "# " _ & "AND [W_HDATE] <= #" & Format(IpteDate, "m/d/yyyy") & "#;"
khi thực hiện trong access đã chọn format theo kiểu"dd/mm/yyyy", nhưng trong Excel khi chọn format kiểu "dd/mm/yyyy" thì lại không select được vậy bác nghĩa?
 
lsSQL = "SELECT * FROM tblData " _ & "WHERE [ORIGIN] LIKE '%" & IptXuatXu & "%' " _ & "AND [W_HDATE] >= #" & Format(IptfDate, "m/d/yyyy") & "# " _ & "AND [W_HDATE] <= #" & Format(IpteDate, "m/d/yyyy") & "#;"
khi thực hiện trong access đã chọn format theo kiểu"dd/mm/yyyy", nhưng trong Excel khi chọn format kiểu "dd/mm/yyyy" thì lại không select được vậy bác nghĩa?


Nếu bạn dùng code đó, bạn gõ ngày tháng bình thường vào InputBox theo định dạng của hệ thống máy tính (Control Panel) của bạn. Ví dụ, tôi cài kiểu ngày tháng trong máy là dd/mm/yyyy thì tôi gõ trong InputBox là dd/mm/yyyy, còn tôi cài hệ thống là mm/dd/yyyy thì tôi gõ trong InputBox là mm/dd/yyyy.

Bạn phải nhập đúng theo kiểu ngày mà hệ thống máy tính của bạn đã cài đặt. Còn việc xử lý dữ liệu sẽ thuộc về code, không liên quan gì hết vì nó đã định dạng lại cho đúng chuẩn: Format(IpteDate, "m/d/yyyy")


Dù là trong Access, hay Excel thì cấu trúc về ngày tháng trong SQL cũng không thay đổi:

#M/D/YYYY#

Xem lại bại này: http://www.giaiphapexcel.com/forum/...ile-Excel-đến-file-Access&p=429179#post429179
 
Lần chỉnh sửa cuối:
Khi làm việc với dữ liệu ngày trong ADO, kinh nghiệm của tôi là nên dùng hàm DateSerial để chuyển định dạng ngày và đưa vào câu truy vấn.

Lê Văn Duyệt
 
Với Excel có thể làm điều tôi sắp trình bày bằng VBA dễ dàng. Nhưng với Access phải làm câu lệnh ADO thế nào?

Giả sử tôi có một Table NhanVien với 4 field: MaNV, TenNV, NoiLamViec, SoLuong

Tôi muốn đại loại như vầy:

SELECT MaNV, TenNV, Sum(SoLuong) AS TongSoLuong, [NoiLamViec] & " (" & [SoLuong] & ")" AS DienGiai
FROM NhanVien
GROUP BY MaNV, TenNV;


Ví dụ Nhân viên Y có mã XXX, làm việc tại 4 nơi (có 4 records cho mỗi nơi), tại A có số lượng là 4, B là 5, C là 6 và D là 7

Thì kết quả sẽ là:

MaNV: XXX
TenNV: YYY
TongSoLuong: 22
DienGiai: A (4), B (5), C (6), D (7)

Kết quả cột DienGiai thì phải làm thế nào? Xin được hướng dẫn.

Cảm ơn rất nhiều!

===================================

Đã post lại File ở bài này: http://www.giaiphapexcel.com/forum/...ile-Excel-đến-file-Access&p=431460#post431460
 
Lần chỉnh sửa cuối:
Cái này để cho HLMT. :)

Lê Văn Duyệt
 
Với Excel có thể làm điều tôi sắp trình bày bằng VBA dễ dàng. Nhưng với Access phải làm câu lệnh ADO thế nào?

Giả sử tôi có một Table NhanVien với 4 field: MaNV, TenNV, NoiLamViec, SoLuong

Tôi muốn đại loại như vầy:

SELECT MaNV, TenNV, Sum(SoLuong) AS TongSoLuong, [NoiLamViec] & " (" & [SoLuong] & ")" AS DienGiai
FROM NhanVien
GROUP BY MaNV, TenNV;


Ví dụ Nhân viên Y có mã XXX, làm việc tại 4 nơi (có 4 records cho mỗi nơi), tại A có số lượng là 4, B là 5, C là 6 và D là 7

Thì kết quả sẽ là:

MaNV: XXX
TenNV: YYY
TongSoLuong: 22
DienGiai: A (4), B (5), C (6), D (7)

Kết quả cột DienGiai thì phải làm thế nào? Xin được hướng dẫn.

Cảm ơn rất nhiều!
Không thể group được trong trường hợp này đâu anh.

SELECT NhanVien.MaNV, NhanVien.TenNV, NhanVien.SoLuong AS TongSoLuong, ([NoiLamViec]) & " (" & [TongSoLuong] & ")" AS DienGiai
FROM NhanVien;
Nếu muốn group thì tạo 1 cái Query nữa tham chiếu với query trên.
 
Nếu nối chuổi giống như anh thì nó ra kq là 70 dòng, sau khi group thì vẫn còn 70 dòng, chứng tỏ dữ liệu không có cái nào trùng.
Để đơn giản vấn đề, mình gửi lại file với 2 mã và 8 records. Nếu thực hiện xong thủ tục, kết quả mong muốn sẽ là:
MaNV ....|TenNV .....................|.TongSoLuong | DienGiai
HTN001 ..| Hoàng Trọng Nghĩa 01 | ........ 35 .......| Vị trí 1 (10), Vị trí 2 (12), Vị trí 3 (13)
HTN002 ..| Hoàng Trọng Nghĩa 02 | ........ 30 .......| Vị trí 1 (2), Vị trí 2 (4), Vị trí 3 (6), Vị trí 4 (8), Vị trí 5 (10)
 

File đính kèm

  • ThuNghiem.rar
    198.9 KB · Đọc: 74
Lần chỉnh sửa cuối:
Để đơn giản vấn đề, mình gửi lại file với 2 mã và 8 records. Nếu thực hiện xong thủ tục, kết quả mong muốn sẽ là:
MaNV ....|TenNV .....................|.TongSoLuong | DienGiai
HTN001 ..| Hoàng Trọng Nghĩa 01 | ........ 35 .......| Vị trí 1 (10), Vị trí 2 (12), Vị trí 3 (13)
HTN002 ..| Hoàng Trọng Nghĩa 02 | ........ 30 .......| Vị trí 1 (2), Vị trí 2 (4), Vị trí 3 (6), Vị trí 4 (8), Vị trí 5 (10)
Nếu Nghĩa là trên ex và dùng ADO thì sẽ làm thế nào.
A chỉ có thể lấy data = ADO sau đó xử lý arr thì có thể ra được.
Còn câu SQL mà có kq vậy thì thua.
Chờ Bác Duyệt, bác Mỹ và HL làm rồi học hỏi.
 
Để đơn giản vấn đề, mình gửi lại file với 2 mã và 8 records. Nếu thực hiện xong thủ tục, kết quả mong muốn sẽ là:
MaNV ....|TenNV .....................|.TongSoLuong | DienGiai
HTN001 ..| Hoàng Trọng Nghĩa 01 | ........ 35 .......| Vị trí 1 (10), Vị trí 2 (12), Vị trí 3 (13)
HTN002 ..| Hoàng Trọng Nghĩa 02 | ........ 30 .......| Vị trí 1 (2), Vị trí 2 (4), Vị trí 3 (6), Vị trí 4 (8), Vị trí 5 (10)

Sao anh không làm kết quả như hình bên dưới cho dể.

13.jpg
 
Nếu Nghĩa là trên ex và dùng ADO thì sẽ làm thế nào.
A chỉ có thể lấy data = ADO sau đó xử lý arr thì có thể ra được.
Còn câu SQL mà có kq vậy thì thua.
Chờ Bác Duyệt, bác Mỹ và HL làm rồi học hỏi.

Cái này với Excel thì chỉ là như vầy:

PHP:
Sub GroupSoLuong()
    Dim sArray, GroupArr, Tmp
    Dim h As Long, i As Long, r As Long
    Sheet1.Range("F2:I65536").Clear
    
    sArray = Range(Sheet1.[A2], Sheet1.[A65536].End(xlUp)).Resize(, 4).Value
    
    h = UBound(sArray, 1): r = 0
    
    ReDim GroupArr(1 To h, 1 To 4)
    With CreateObject("Scripting.Dictionary")
        For i = 1 To h
            Tmp = sArray(i, 1)
            If Not .Exists(Tmp) Then
                r = r + 1: .Add Tmp, r
                GroupArr(r, 1) = Tmp
                GroupArr(r, 2) = sArray(i, 2)
                GroupArr(r, 3) = sArray(i, 4)
                GroupArr(r, 4) = sArray(i, 3) & " (" & sArray(i, 4) & ")"
            Else
                GroupArr(.Item(Tmp), 3) = GroupArr(.Item(Tmp), 3) + sArray(i, 4)
                GroupArr(.Item(Tmp), 4) = GroupArr(.Item(Tmp), 4) & ", " & sArray(i, 3) & " (" & sArray(i, 4) & ")"
            End If
        Next
    End With
    Sheet1.Range("F2").Resize(r, 4).Value = GroupArr
End Sub
 

File đính kèm

  • Group.xls
    28 KB · Đọc: 47
Đây là bài toán nối chuỗi nhiều record vào 1 record. Dù làm trong access cũng phải viết code đọc từng record và nối lại.
 
Đây là bài toán nối chuỗi nhiều record vào 1 record. Dù làm trong access cũng phải viết code đọc từng record và nối lại.

Vì chỉ mới học Access một hoặc hai tháng nay, nên không biết ký rì về code của nó, vậy cho nên Sư phụ làm ơn hướng dẫn cho em bài này luôn đi ạ.

Xin cám ơn.
 
Vì chỉ mới học Access một hoặc hai tháng nay, nên không biết ký rì về code của nó, vậy cho nên Sư phụ làm ơn hướng dẫn cho em bài này luôn đi ạ.

Xin cám ơn.
Đã tìm được cách nối chuổi, nhưng cái khó ở chổ là cộng số lượng từng nơi làm việc vào chuổi.

14.jpg
 
Lần chỉnh sửa cuối:
Với bài toán dạng này, chúng ta có thể sử dụng một trong những tính năng ưu việt của Access là nhúng hàm người dùng vào câu lệnh truy vấn. Tuy nhiên, đổi lại, tốc độ sẽ rất kém.
Ta viết thêm một hàm

PHP:
Function FlattenQry(ID As String) As String
    Dim Sql As String
    Sql = "SELECT [NoiLamViec] & "" ("" & [SoLuong] & "")"" AS DienGiai FROM NhanVien WHERE MaNV='" & ID & "';"
    Dim Rcs As Object, cn As Connection
    Set Rcs = CurrentProject.AccessConnection.Execute(Sql)
    Sql = ""
    While Not Rcs.EOF
        Sql = Sql & ", " & Rcs.Fields(0)
        Rcs.MoveNext
    Wend
    FlattenQry = IIf(Sql = "", "", Mid(Sql, 3))
    Rcs.Close
End Function
Sau đó đưa vào Querry câu lệnh này


PHP:
SELECT NhanVien.MaNV, NhanVien.TenNV, FlattenQry([manv]) AS Expr1
FROM NhanVien
GROUP BY NhanVien.MaNV, NhanVien.TenNV, FlattenQry([manv]);
Thế là xong.
Các bác xem qua file đính kèm nhé.
Tuy nhiên, có điều tôi chưa rõ lắm đó là: có thể có trường hợp nhiều 1 nhân viên có cùng địa điểm nhưng số lượng khác nhau không? Nếu thế thì phải làm khác tí chút trong câu truy vấn đặt trong hàm.
 

File đính kèm

  • ThuNghiem.zip
    28 KB · Đọc: 55
Lần chỉnh sửa cuối:
Với bài toán dạng này, chúng ta có thể sử dụng một trong những tính năng ưu việt của Access là nhúng hàm người dùng vào câu lệnh truy vấn. Tuy nhiên, đổi lại, tốc độ sẽ rất kém.
Ta viết thêm một hàm

PHP:
Function FlattenQry(ID As String) As String
    Dim Sql As String
    Sql = "SELECT [NoiLamViec] & "" ("" & [SoLuong] & "")"" AS DienGiai FROM NhanVien WHERE MaNV='" & ID & "';"
    Dim Rcs As Object, cn As Connection
    Set Rcs = CurrentProject.AccessConnection.Execute(Sql)
    Sql = ""
    While Not Rcs.EOF
        Sql = Sql & ", " & Rcs.Fields(0)
        Rcs.MoveNext
    Wend
    FlattenQry = IIf(Sql = "", "", Mid(Sql, 3))
    Rcs.Close
End Function
Sau đó đưa vào Querry câu lệnh này


PHP:
SELECT NhanVien.MaNV, NhanVien.TenNV, FlattenQry([manv]) AS Expr1
FROM NhanVien
GROUP BY NhanVien.MaNV, NhanVien.TenNV, FlattenQry([manv]);
Thế là xong.
Các bác xem qua file đính kèm nhé.
Tuy nhiên, có điều tôi chưa rõ lắm đó là: có thể có trường hợp nhiều 1 nhân viên có cùng địa điểm nhưng số lượng khác nhau không? Nếu thế thì phải làm khác tí chút trong câu truy vấn đặt trong hàm.
Chưa được đâu nha bạn, ví dụ bạn thêm nv mới thì nó sẽ ra kết quả không group lại.

15.jpg

Hai Lúa thử open recordset, gán vào mảng, rồi xử lý mảng kết hợp Dic xem. (xử lý mảng ra kết quả, sau đó update query kết quả)

Em sẽ viết 1 hàm để gom nhóm dữ liệu theo yêu cầu đề bài.
 
Lần chỉnh sửa cuối:
Web KT
Back
Top Bottom