Excel my love_1
Thành viên thường trực
- Tham gia
- 12/11/19
- Bài viết
- 330
- Được thích
- 183
Bạn thử đoạn code này xem sao. Kết quả đang để ở dòng A20 để so sánh.Từ vùng dữ liệu A1:E11, em muốn dồn dữ liệu về 1 dòng theo tên nhà cung cấp cột A
Chi tiết như hình ảnh minh họa
View attachment 269694
Và xem file đính kèm nhé!
Chúc cả nhà ngày vui
Sub XYZ()
Dim i&, k&, t&, R&
Dim Arr(), KQ()
Dim Sh As Worksheet
Dim Dic As Object
Set Sh = Sheet3
Arr = Sh.Range("A2:E11").Value ' nếu dữ liệu nhiều hơn thì phải tìm dòng cuối và khi đó Arr=Sh.range("A2:E"& dongcuoi).value
R = UBound(Arr)
Set Dic = CreateObject("Scripting.Dictionary")
ReDim KQ(1 To R, 1 To 3)
For i = 1 To R
Keys = Arr(i, 1)
If Not Dic.Exists(Keys) Then
t = t + 1
Dic.Add (Keys), t
KQ(t, 1) = Keys
KQ(t, 2) = "Ngày " & Arr(i, 2) & Sh.[C1] & " " & Arr(i, 3) & " " & Sh.[D1] & " " & Arr(i, 4) & " -" & Sh.[E1] & " " & Arr(i, 5)
KQ(t, 3) = Arr(i, 4)
Else
k = Dic.Item(Keys)
KQ(k, 2) = KQ(k, 2) & Chr(10) & "Ngày " & Arr(i, 2) & Sh.[C1] & " " & Arr(i, 3) & " " & Sh.[D1] & " " & Arr(i, 4) & " -" & Sh.[E1] & " " & Arr(i, 5)
KQ(k, 3) = KQ(k, 3) + Arr(i, 4)
End If
Next
If t Then
Sh.Cells(20, 1).Resize(R + 10, 3).ClearContents
Sh.Cells(20, 1).Resize(R + 10, 3) = KQ
End If
Set Dic = Nothing
End Sub
Module nào có dòng Option Explicit trên cùng, sẽ bị lỗi biến KeysSh.Cells(20, 1).Resize(R + 10, 3) = KQ
Nếu dữ liệu đã sắp xếp như trong cột A, cũng không cần tới Dictionary.Sh.Cells(20, 1).Resize(t, 3) = KQ
Cảm ơn Anh đã chỉ giáo. Tôi sẽ rút kinh nghiệm. Đưa những Cái Sh.[C1]... vào thành biến (ngay=Sh.[C1].....) thì code sẽ nhẹ hơn,và dễ kiểm tra hơn....Module nào có dòng Option Explicit trên cùng, sẽ bị lỗi biến Keys
ReDim KQ(1 To R, 1 To 3)
............................................
Kết quả sẽ có những dòng #N/A.
Gán xuống sheet như thế này là đủ:
Nếu dữ liệu đã sắp xếp như trong cột A, cũng không cần tới Dictionary.
Mấy cái Sh.[C1], ... nếu dữ liệu 10.000 dòng sẽ phải tìm trong sheet 10.000 lần.
Cảm ơn bạn đã giúp đỡ, thật tuyệt vời.Bạn thử đoạn code này xem sao. Kết quả đang để ở dòng A20 để so sánh.
Mã:Sub XYZ() Dim i&, k&, t&, R& Dim Arr(), KQ() Dim Sh As Worksheet Dim Dic As Object Set Sh = Sheet3 Arr = Sh.Range("A2:E11").Value ' nếu dữ liệu nhiều hơn thì phải tìm dòng cuối và khi đó Arr=Sh.range("A2:E"& dongcuoi).value R = UBound(Arr) Set Dic = CreateObject("Scripting.Dictionary") ReDim KQ(1 To R, 1 To 3) For i = 1 To R Keys = Arr(i, 1) If Not Dic.Exists(Keys) Then t = t + 1 Dic.Add (Keys), t KQ(t, 1) = Keys KQ(t, 2) = "Ngày " & Arr(i, 2) & Sh.[C1] & " " & Arr(i, 3) & " " & Sh.[D1] & " " & Arr(i, 4) & " -" & Sh.[E1] & " " & Arr(i, 5) KQ(t, 3) = Arr(i, 4) Else k = Dic.Item(Keys) KQ(k, 2) = KQ(k, 2) & Chr(10) & "Ngày " & Arr(i, 2) & Sh.[C1] & " " & Arr(i, 3) & " " & Sh.[D1] & " " & Arr(i, 4) & " -" & Sh.[E1] & " " & Arr(i, 5) KQ(k, 3) = KQ(k, 3) + Arr(i, 4) End If Next If t Then Sh.Cells(20, 1).Resize(R + 10, 3).ClearContents Sh.Cells(20, 1).Resize(R + 10, 3) = KQ End If Set Dic = Nothing End Sub
Bạn vào Tools, Options của VBE, check vào ô chọn như trong hình.Máy tôi khi chèn modul vào nó không có dòng Option Exlicit, mà tôi không biết cài đặt thế nào được. Nếu có thể Anh giúp tôi với.
Bài của em được Anh Ba Tê ngó tới là em thấy vui rồi! Em cảm ơn anh nhéBạn vào Tools, Options của VBE, check vào ô chọn như trong hình.
Sau này, khi bạn Insert 1 Module, nó sẽ tự động có dòng Option Explicit trên đầu Module.
Bạn dùng bảng dữ liệu và bảng Kết quả chung 1 sheet, với code như của bạn thì chạy Sub nhiều lần sẽ thành "từa lưa" hết, do biến lastrow của bạn sau mỗi lần chạy sẽ không còn là 523 dòng nữa.Cảm ơn bạn đã giúp đỡ, thật tuyệt vời.
Nhưng ở các dòng Kết quả, trong ô gộp dữ liệu phần số tiền bị mất dấu phân cách thập phân bạn à (như trong ảnh mình gửi)
Dữ liệu chạy lớn hơn thì có bị làm sao không bạn. Ví dụ mình gửi tiếp file này dữ liệu là 523 dòng. File gửi kèm
Thử code này coiCảm ơn bạn đã giúp đỡ, thật tuyệt vời.
Nhưng ở các dòng Kết quả, trong ô gộp dữ liệu phần số tiền bị mất dấu phân cách thập phân bạn à (như trong ảnh mình gửi)
Dữ liệu chạy lớn hơn thì có bị làm sao không bạn. Ví dụ mình gửi tiếp file này dữ liệu là 523 dòng. File gửi kèm
Sub ABC()
Dim sArr(), iRow&, Res(), i&, Dic As Object, K&, KK&
Set Dic = CreateObject("Scripting.dictionary")
With Sheets("Data")
iRow = .Range("A" & Rows.Count).End(3).Row
sArr = .Range("A1:E" & iRow).Value
End With
ReDim Res(1 To UBound(sArr, 1), 1 To 3)
For i = 2 To UBound(sArr, 1)
If Dic.exists(sArr(i, 1)) = False Then
K = K + 1
Dic.Add (sArr(i, 1)), K
Res(K, 1) = sArr(i, 1)
Res(K, 2) = sArr(1, 2) & sArr(i, 2) & sArr(1, 3) & sArr(i, 3) & sArr(1, 4) & Format(sArr(i, 4), "0,00#") & sArr(1, 5) & sArr(i, 5)
Res(K, 3) = Format(sArr(i, 4), "0,00#")
Else
KK = Dic.Item(sArr(i, 1))
Res(KK, 2) = Res(KK, 2) & vbCrLf & sArr(1, 2) & sArr(i, 2) & sArr(1, 3) & sArr(i, 3) & sArr(1, 4) & Format(sArr(i, 4), "0,00#") & sArr(1, 5) & sArr(i, 5)
Res(KK, 3) = Format(Res(KK, 3) + sArr(i, 4),"0,00#")
End If
Next
With Sheets("KQ")
If K Then
.Range("A2:C1000").Clear
.Range("A2").Resize(K, 3).Value = Res
.Range("A2").Resize(K, 3).Borders.LineStyle = 1
End If
End With
End Sub
Cảm ơn anh Ba Tê , kết quả thật tuyệt vờiBạn dùng bảng dữ liệu và bảng Kết quả chung 1 sheet, với code như của bạn thì chạy Sub nhiều lần sẽ thành "từa lưa" hết, do biến lastrow của bạn sau mỗi lần chạy sẽ không còn là 523 dòng nữa.
Nên cho kết quả vào 1 sheet khác, không động chạm vào sheet dữ liệu.
Sửa lại Code trong file cho bạn.
Cảm ơn bạn , mình tham khảo cách của bạn cũng rất hay.Thử code này coi
Thêm 1 sheet chứa kết quả nếu data nhiều
Mã:Sub ABC() Dim sArr(), iRow&, Res(), i&, Dic As Object, K&, KK& Set Dic = CreateObject("Scripting.dictionary") With Sheets("Data") iRow = .Range("A" & Rows.Count).End(3).Row sArr = .Range("A1:E" & iRow).Value End With ReDim Res(1 To UBound(sArr, 1), 1 To 3) For i = 2 To UBound(sArr, 1) If Dic.exists(sArr(i, 1)) = False Then K = K + 1 Dic.Add (sArr(i, 1)), K Res(K, 1) = sArr(i, 1) Res(K, 2) = sArr(1, 2) & sArr(i, 2) & sArr(1, 3) & sArr(i, 3) & sArr(1, 4) & Format(sArr(i, 4), "0,00#") & sArr(1, 5) & sArr(i, 5) Res(K, 3) = Format(sArr(i, 4), "0,00#") Else KK = Dic.Item(sArr(i, 1)) Res(KK, 2) = Res(KK, 2) & vbCrLf & sArr(1, 2) & sArr(i, 2) & sArr(1, 3) & sArr(i, 3) & sArr(1, 4) & Format(sArr(i, 4), "0,00#") & sArr(1, 5) & sArr(i, 5) Res(KK, 3) = Format(Res(KK, 3) + sArr(i, 4),"0,00#") End If Next With Sheets("KQ") If K Then .Range("A2:C1000").Clear .Range("A2").Resize(K, 3).Value = Res .Range("A2").Resize(K, 3).Borders.LineStyle = 1 End If End With End Sub