Nhờ hướng dẫn (gợi ý) giải quyết vấn đề bằng VBA

Liên hệ QC
Hoàn toàn có thể lấy được Thầy à, ở trên là em lấy toàn bộ bảng, nếu Thầy muốn lấy cột nào thì chỉ Select cột đó là OK
Ví dụ:

Dùng GroupBy (Cột NCC):

Mã:
lsSQL = "select [NCC] from [ThongTin$] group by [NCC]"

Dùng distinct (Cột TEN_NCC):

Mã:
lsSQL = "select distinct [TEN_NCC] from [ThongTin$]"

* Thầy muốn cột nào thì chọn tiêu đề của cột đó, muốn chon hết thì thay = dấu sao "*"
Ah, hổng phải vậy!
Ý tôi là vẫn lấy toàn bộ bảng tính nhưng chỉ Unique 1 cột thôi, các cột khác sẽ "ăn theo" ---> code trên là Unique tất tần tật mà
(Hôm này mới biết select * là cái gì! Cứ tưởng * là dấu nhân...)
 
Ah, hổng phải vậy!
Ý tôi là vẫn lấy toàn bộ bảng tính nhưng chỉ Unique 1 cột thôi, các cột khác sẽ "ăn theo" ---> code trên là Unique tất tần tật mà
(Hôm này mới biết select * là cái gì! Cứ tưởng * là dấu nhân...)
Phải chịu cực select cột thôi Thầy à.
*/ Ta tiếp tục nhé, với dữ liệu ở sheet Data, ta dùng GroupBy như trên để tổng hợp dữ liệu theo mã hàng, kết quả cho ra là sheet Temp.
 

File đính kèm

Em đang "tầm sư học đạo" và mới tập tọe học về ADO, tham gia trả lời trong topic này còn có nhiều điều cần phải học hỏi. Các bác nào thấy sai thì sửa giùm em để em tiến bộ hơn ạ:
Em cảm ơn ạ!


Mã:
Private Sub CommandButton3_Click()
Dim arrValue As Variant
Dim lsSQL As String: Dim rst As New ADODB.Recordset
If cnn.State = 1 Then cnn.Close
Moketnoi
lsSQL = "SELECT [NCC], [Ten_NCC], Sum([so tien]) AS [Tong Tien] " & _
"FROM [data$] " & _
"GROUP BY [NCC], [Ten_NCC];"
rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
Sheets("Temp").Range("A2").CopyFromRecordset rst
rst.Close
Set rst = Nothing
cnn.Close
Set cnn = Nothing
Sheet4.Select
End Sub
 

File đính kèm

Lần chỉnh sửa cuối:
Em đang "tầm sư học đạo" và mới tập tọe học về ADO, tham gia trả lời trong topic này còn có nhiều điều cần phải học hỏi. Các bác nào thấy sai thì sửa giùm em để em tiến bộ hơn ạ:
Em cảm ơn ạ!


Mã:
Private Sub CommandButton3_Click()
Dim arrValue As Variant
Dim lsSQL As String: Dim rst As New ADODB.Recordset
If cnn.State = 1 Then cnn.Close
Moketnoi
lsSQL = "SELECT [NCC], [Ten_NCC], Sum([so tien]) AS [Tong Tien] " & _
"FROM [data$] " & _
"GROUP BY [NCC], [Ten_NCC];"
rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
Sheets("Temp").Range("A2").CopyFromRecordset rst
rst.Close
Set rst = Nothing
cnn.Close
Set cnn = Nothing
Sheet4.Select
End Sub
Với trường hợp trên, nếu chỉ cần lọc theo NCC thôi, kg cần theo Ten_NCC thì sửa code thế nào.
Còn có cần thiết Sum([so tien]) AS [Tong Tien]?
Tôi bỏ mà cũng chạy.
Cám ơn XuanNguyen nhiều, đúng là cao thủ ADO, chắc cũng siêu Acc.
To: HLMT
Nếu thuật toán ADO trên so với dùng Dic để lấy DM duy nhất và tính tổng thì cái nào nhanh hơn?
 
Lần chỉnh sửa cuối:
Em đang "tầm sư học đạo" và mới tập tọe học về ADO, tham gia trả lời trong topic này còn có nhiều điều cần phải học hỏi. Các bác nào thấy sai thì sửa giùm em để em tiến bộ hơn ạ:
Em cảm ơn ạ!


Mã:
Private Sub CommandButton3_Click()
Dim arrValue As Variant
Dim lsSQL As String: Dim rst As New ADODB.Recordset
If cnn.State = 1 Then cnn.Close
Moketnoi
lsSQL = "SELECT [NCC], [Ten_NCC], Sum([so tien]) AS [Tong Tien] " & _
"FROM [data$] " & _
"GROUP BY [NCC], [Ten_NCC];"
rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
Sheets("Temp").Range("A2").CopyFromRecordset rst
rst.Close
Set rst = Nothing
cnn.Close
Set cnn = Nothing
Sheet4.Select
End Sub
Đúng theo yêu cầu đề bài, XN vừa làm thơ hay vừa viết code giỏi.

To: HLMT
Nếu thuật toán ADO trên so với dùng Dic để lấy DM duy nhất và tính tổng thì cái nào nhanh hơn?
Cái này em chưa thử, ở đây em muối nói về ADO thôi anh ạ.

*./ Cũng dữ liệu là sheet Data, yêu cầu lọc và tổng hợp dữ liệu với cột NCC là "XN", Kết quả đưa ra ở sheet Temp.
 
Lần chỉnh sửa cuối:
Đúng theo yêu cầu đề bài, XN vừa làm thơ hay vừa viết code giỏi.

*./ Cũng dữ liệu là sheet Data, yêu cầu lọc và tổng hợp dữ liệu với cột NCC là "XN", Kết quả đưa ra ở sheet Temp.
Cho góp vui. tham khảo ADO hay ghê, nhớ đề tài này lâu rồi nay mới xem lại. Quên tuốt.
PHP:
Sub LocADO_02()
Dim sTxT$
Dim arrValue As Variant
sTxT = "XN"
Dim lsSQL As String: Dim rst As New ADODB.Recordset
  If cnn.State = 1 Then cnn.Close
    Moketnoi
    lsSQL = "SELECT [NCC],  [Ten_NCC], [sotien] FROM [data$]"
    lsSQL = lsSQL & "where [NCC]  like '" & sTxT & "'"
    rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
    arrValue = rst.GetRows()
  With Sheet4
    .[A2].Resize(rst.RecordCount, 3) = Application.Transpose(arrValue)
  End With
 rst.Close
 Set rst = Nothing
 cnn.Close
 Set cnn = Nothing
Erase arrValue
End Sub
 
Với trường hợp trên, nếu chỉ cần lọc theo NCC thôi, kg cần theo Ten_NCC thì sửa code thế nào.
Còn có cần thiết Sum([so tien]) AS [Tong Tien]?
Tôi bỏ mà cũng chạy.
Cám ơn XuanNguyen nhiều, đúng là cao thủ ADO, chắc cũng siêu Acc.
To: HLMT
Nếu thuật toán ADO trên so với dùng Dic để lấy DM duy nhất và tính tổng thì cái nào nhanh hơn?


Hic, em hỏng phải cao thủ hay thấp thủ đâu, em phải cảm ơn GPE nhiều lắm lắm, em học được kiến thức mọi mặt, có nhiều bạn tốt, có nhiều "sư phụ", có nhiều người để mà...thương mến, hihi.
Mà em là dân HR anh ạ...

AS [Tong Tien] Không cần cũng được, cái này là gán tên cột [SumOfso tien] thành [Tong Tien], nhưng sau này mình muốn lấy tên cột?
Còn anh cần mã NCC thôi thì bỏ cái [TEN_NCC] đi
lsSQL = "SELECT [NCC], Sum([so tien]) AS [Tong Tien] "
Phần Group By chỉ cần
"GROUP BY [NCC];"
là đủ
 
Hic, em hỏng phải cao thủ hay thấp thủ đâu, em phải cảm ơn GPE nhiều lắm lắm, em học được kiến thức mọi mặt, có nhiều bạn tốt, có nhiều "sư phụ", có nhiều người để mà...thương mến, hihi.
Mà em là dân HR anh ạ...

AS [Tong Tien] Không cần cũng được, cái này là gán tên cột [SumOfso tien] thành [Tong Tien], nhưng sau này mình muốn lấy tên cột?
Còn anh cần mã NCC thôi thì bỏ cái [TEN_NCC] đi
lsSQL = "SELECT [NCC], Sum([so tien]) AS [Tong Tien] "
Phần Group By chỉ cần
"GROUP BY [NCC];"
là đủ
Bây giờ nâng cao lên nhé, vẫn dùng ADO.
Từ sh data liệt kê sang sh TMP theo từng NCC và preview (xem trước).
Nếu theo thuật toán từng làm thì như sau:
1/ Lấy DM NCC
2/ Duyệt qua NCC để lấy Data.
Kg biết ADO sẽ làm thế nào. Có thể vận dụng để InPhieuLuong.
 
Bây giờ nâng cao lên nhé, vẫn dùng ADO.
Từ sh data liệt kê sang sh TMP theo từng NCC và preview (xem trước).
Nếu theo thuật toán từng làm thì như sau:
1/ Lấy DM NCC
2/ Duyệt qua NCC để lấy Data.
Kg biết ADO sẽ làm thế nào. Có thể vận dụng để InPhieuLuong.
Hoàn toàn có thể được anh à: Lấy dữ liệu duy nhất của cột NCC đưa vào mãng, duyệt qua từng nhà cung cấp để làm điều kiện lọc.

Mã:
Private Sub cmdXem_Click()
On Error GoTo Loi
    Dim lsSQL As String, arr As Variant
    Dim r, c As Integer
    Dim rst As New ADODB.Recordset
    Unload NHAPLIEU
    If cnn.State = 1 Then cnn.Close
    Moketnoi
    With rst
        lsSQL = "SELECT distinct [NCC] from [data$]"
        .Open lsSQL, cnn, adOpenStatic, adLockReadOnly
        arr = .GetRows()
        .Close
        For c = LBound(arr, 2) To UBound(arr, 2)
            For r = LBound(arr, 1) To UBound(arr, 1)
                Sheet4.Range("A2:D65000").ClearContents
                lsSQL = "SELECT [ngay],[ncc],[Ten_Ncc],[so tien] " & _
                        "from [data$] " & _
                        "where [NCC] like'" & arr(r, c) & "'"
                        
                .Open lsSQL, cnn, adOpenStatic, adLockReadOnly
                 Sheet4.Range("A2").CopyFromRecordset rst
                .Close
                Sheet4.PrintPreview
            Next
        Next
    End With
    Set rst = Nothing
    Exit Sub
Loi:
    MsgBox Err.Description
    
End Sub
 

File đính kèm

Ta tiếp tục nhé:
Cũng dữ liệu ở bài #29 làm sao ta lọc ra dữ liệu của mã HLMT (Bao gồm cả HLMT,HLMT1...) và ngày phát sinh từ ngày 01/07/2012 đến ngày 14/07/2012.
 
PHP:
arrValue = rst.GetRows()
HK ơi, cho a hỏi, khi lấy từ recordset sang ArrValue, thì có thông số nào từ GetRows để cho ta biết tên Field (tên cột) cụ thể như NCC.
Thay vì
FieldName=rst(i).name (i=1,2,... số field.
Có thể dùng
FieldName=ArrValue(.....)
Nghĩa là Rec lấy luôn tên tiêu đề khi gán sang Arr.
Cám ơn.
 
PHP:
arrValue = rst.GetRows()
HK ơi, cho a hỏi, khi lấy từ recordset sang ArrValue, thì có thông số nào từ GetRows để cho ta biết tên Field (tên cột) cụ thể như NCC.
Thay vì
FieldName=rst(i).name (i=1,2,... số field.
Có thể dùng
FieldName=ArrValue(.....)
Nghĩa là Rec lấy luôn tên tiêu đề khi gán sang Arr.
Cám ơn.
Anh thử dùng vòng lặp duyệt qua tên trường rồi đưa tên trường đó vào mãng.
 
Ta tiếp tục nhé:
Cũng dữ liệu ở bài #29 làm sao ta lọc ra dữ liệu của mã HLMT (Bao gồm cả HLMT,HLMT1...) và ngày phát sinh từ ngày 01/07/2012 đến ngày 14/07/2012.
Anh dùng between thì được nhưng triển khai sang Ngay<=eDate and >=fDate thì báo lỗi.
Nhờ HL xem giúp.
PHP:
Sub LocADO_03()
Dim iR&, iC&
Dim sTxT$
Dim fDate$: fDate = "01/07/2012"
Dim eDate$: eDate = "14/07/2012"
Dim sArr, rArr
sTxT = "HLMT"
Dim lsSQL As String: Dim rst As New ADODB.Recordset
If cnn.State = 1 Then cnn.Close
Moketnoi
lsSQL = "SELECT [NCC],  [Ten_NCC], [sotien] FROM [data$]"
lsSQL = lsSQL & "where left([NCC],4)  like '" & sTxT & "'"
'lsSQL = lsSQL & "and [Ngay] >=" & fDate & " "
'lsSQL = lsSQL & "and [Ngay] <=" & eDate & " "
lsSQL = lsSQL & "and [Ngay] BETWEEN #01/07/2012# and #14/07/2012#"
rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
sArr = rst.GetRows()
If rst.RecordCount Then
  ReDim rArr(1 To UBound(sArr, 2) + 1, 1 To UBound(sArr) + 1)
  For iR = 0 To UBound(sArr, 2)
    For iC = 0 To UBound(sArr)
      rArr(iR + 1, iC + 1) = sArr(iC, iR)
    Next iC
  Next iR
Else
  Exit Sub
End If
With Sheet4
  .[A2].Resize(1000, 3).ClearContents
  .[A2].Resize(rst.RecordCount, 3) = rArr
End With
rst.Close: Set rst = Nothing
cnn.Close: Set cnn = Nothing
Erase sArr, rArr
End Sub
 
đúng rồi anh à, phần sotien anh tham chiếu bị sai: phải là [so tien]
 
đúng rồi anh à, phần sotien anh tham chiếu bị sai: phải là [so tien]
Không phải vậy. Đã sử field name sotien rồi.
Muốn thay thế dòng between mà cứ báo lỗi EOF...
HL test giúp. Bỏ dòng between và thay dòng and >....
PHP:
Sub LocADO_03()
Dim iR&, iC&
Dim sTxT$
Dim fDate$: fDate = "01/07/2012"
Dim eDate$: eDate = "14/07/2012"
Dim sArr, rArr
sTxT = "HLMT"
Dim lsSQL As String: Dim rst As New ADODB.Recordset
If cnn.State = 1 Then cnn.Close
Moketnoi
lsSQL = "SELECT [NCC],  [Ten_NCC], [sotien] FROM [data$]"
lsSQL = lsSQL & "where left([NCC],4)  like '" & sTxT & "'"
lsSQL = lsSQL & "and [Ngay] >=" & fDate & " "
lsSQL = lsSQL & "and [Ngay] <=" & eDate & " "
rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
sArr = rst.GetRows()
If rst.RecordCount Then
  ReDim rArr(1 To UBound(sArr, 2) + 1, 1 To UBound(sArr) + 1)
  For iR = 0 To UBound(sArr, 2)
    For iC = 0 To UBound(sArr)
      rArr(iR + 1, iC + 1) = sArr(iC, iR)
    Next iC
  Next iR
Else
  Exit Sub
End If
With Sheet4
  .[A2].Resize(1000, 3).ClearContents
  .[A2].Resize(rst.RecordCount, 3) = rArr
End With
rst.Close: Set rst = Nothing
cnn.Close: Set cnn = Nothing
ErasesArr, rArr
End Sub
Hình như nó sai ở chỗ kiểu ngày mà chưa tìm ra.
 
Lần chỉnh sửa cuối:
Không phải vậy. Đã sử field name sotien rồi.
Muốn thay thế dòng between mà cứ báo lỗi EOF...
HL test giúp. Bỏ dòng between và thay dòng and >....
PHP:
Sub LocADO_03()
Dim iR&, iC&
Dim sTxT$
Dim fDate$: fDate = "01/07/2012"
Dim eDate$: eDate = "14/07/2012"
Dim sArr, rArr
sTxT = "HLMT"
Dim lsSQL As String: Dim rst As New ADODB.Recordset
If cnn.State = 1 Then cnn.Close
Moketnoi
lsSQL = "SELECT [NCC],  [Ten_NCC], [sotien] FROM [data$]"
lsSQL = lsSQL & "where left([NCC],4)  like '" & sTxT & "'"
lsSQL = lsSQL & "and [Ngay] >=" & fDate & " "
lsSQL = lsSQL & "and [Ngay] <=" & eDate & " "
rst.Open lsSQL, cnn, adOpenStatic, adLockReadOnly
sArr = rst.GetRows()
If rst.RecordCount Then
  ReDim rArr(1 To UBound(sArr, 2) + 1, 1 To UBound(sArr) + 1)
  For iR = 0 To UBound(sArr, 2)
    For iC = 0 To UBound(sArr)
      rArr(iR + 1, iC + 1) = sArr(iC, iR)
    Next iC
  Next iR
Else
  Exit Sub
End If
With Sheet4
  .[A2].Resize(1000, 3).ClearContents
  .[A2].Resize(rst.RecordCount, 3) = rArr
End With
rst.Close: Set rst = Nothing
cnn.Close: Set cnn = Nothing
ErasesArr, rArr
End Sub


Cho em "bon chen" tý ạ.

Anh cho thêm dấu # vào điều kiện ngày:

lsSQL = lsSQL & "and [Ngay] >=#" & fDate & "#"
lsSQL = lsSQL & "and [Ngay] <=#" & eDate & "#"
 
Cho em "bon chen" tý ạ.

Anh cho thêm dấu # vào điều kiện ngày:

lsSQL = lsSQL & "and [Ngay] >=#" & fDate & "#"
lsSQL = lsSQL & "and [Ngay] <=#" & eDate & "#"
XN nhanh tay thiệt, chưa kịp trả lời là đã có đáp án.

Ta tiếp tục:
*./ Cũng dữ liệu trên làm sao ta lấy được 2 số tiền là cao nhất.
 
Cho em "bon chen" tý ạ.

Anh cho thêm dấu # vào điều kiện ngày:

lsSQL = lsSQL & "and [Ngay] >=#" & fDate & "#"
lsSQL = lsSQL & "and [Ngay] <=#" & eDate & "#"
Cám ơn Xuân nhiều. OK rồi.
Cái vụ SQL này nhức đầu mấy cái dấu,vì kg qua bài bản nên làm kg bài bản.
Muốn làm để triển khai cho dễ.
 
Web KT

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

Back
Top Bottom