thang.phduy2
Thành viên mới

- Tham gia
- 20/1/21
- Bài viết
- 12
- Được thích
- 0
Tạo bảng cáo cáo giống pivot, chứ k phải insert pivot table.Sao bạn không Ghi lại Code của Pivot luôn
Theo ví dụ kết quảChào anh chị.
Em có thể xin code VBA có thể tạo báo cáo như sheet3 từ dữ liệu gốc ở sheet1. Hình thức báo cáo giống như pivot table.
Cảm ơn anh chị.
Sub ABC()
Dim sArr(), Res() As String, ResQt(), Dic As Object
Dim i&, k&, iR&, sRow&, iKey$
Set Dic = CreateObject("Scripting.Dictionary")
With Sheets("Sheet1")
sArr = .Range("A2", .Range("E" & Rows.Count).End(xlUp)).Value
End With
sRow = UBound(sArr)
ReDim Res(1 To sRow, 1 To 4)
ReDim ResQt(1 To sRow, 1 To 1)
For i = 1 To sRow
If sArr(i, 3) = 1 Then
iKey = sArr(i, 1) & "|" & sArr(i, 4)
If Not Dic.Exists(iKey) Then
k = k + 1
Dic.Add iKey, k
Res(k, 1) = sArr(i, 4)
Res(k, 2) = sArr(i, 5)
Res(k, 4) = sArr(i, 1)
End If
iR = Dic.Item(iKey)
ResQt(iR, 1) = ResQt(iR, 1) + 1
End If
Next i
With Sheets("Sheet3")
i = .Range("B" & Rows.Count).End(xlUp).Row
If i > 1 Then .Range("B2:E" & i).ClearContents
.Range("B2").Resize(k, 4) = Res
.Range("D2").Resize(k, 1) = ResQt
.Range("B2").Resize(k, 4).Sort .[E2], 1, .[B2], , 1
End With
End Sub
Chia theo cột E ở E3 và E11.Mình thấy phần Qty bạn điền tay đâu có đúng đâu nhỉ? Nó bằng 9 chứ sao bằng 7 được vậyView attachment 254270
Cảm ơn anh. Code chạy ngon lành.Theo ví dụ kết quả
Mã:Sub ABC() Dim sArr(), Res() As String, ResQt(), Dic As Object Dim i&, k&, iR&, sRow&, iKey$ Set Dic = CreateObject("Scripting.Dictionary") With Sheets("Sheet1") sArr = .Range("A2", .Range("E" & Rows.Count).End(xlUp)).Value End With sRow = UBound(sArr) ReDim Res(1 To sRow, 1 To 4) ReDim ResQt(1 To sRow, 1 To 1) For i = 1 To sRow If sArr(i, 3) = 1 Then iKey = sArr(i, 1) & "|" & sArr(i, 4) If Not Dic.Exists(iKey) Then k = k + 1 Dic.Add iKey, k Res(k, 1) = sArr(i, 4) Res(k, 2) = sArr(i, 5) Res(k, 4) = sArr(i, 1) End If iR = Dic.Item(iKey) ResQt(iR, 1) = ResQt(iR, 1) + 1 End If Next i With Sheets("Sheet3") i = .Range("B" & Rows.Count).End(xlUp).Row If i > 1 Then .Range("B2:E" & i).ClearContents .Range("B2").Resize(k, 4) = Res .Range("D2").Resize(k, 1) = ResQt .Range("B2").Resize(k, 4).Sort .[E2], 1, .[B2], , 1 End With End Sub
Thử bon chen với Bác @HieuCD , Bạn thử chạy 'Sub Tham_Khao_ForNext' bên dưới:Chào anh chị.
Em có thể xin code VBA có thể tạo báo cáo như sheet3 từ dữ liệu gốc ở sheet1. Hình thức báo cáo giống như pivot table.
Cảm ơn anh chị.
Option Explicit
Private Function KeyExists(aExists, sKey, j, k) As Boolean
For k = 1 To j
If aExists(k) = sKey Then
KeyExists = True
Exit For
End If
Next k
End Function
Sub Tham_Khao_ForNext()
Dim aExists, sKey As String, sArr(), Result()
Dim r As Long, i As Long, j As Long, k As Long
Dim shData As Worksheet, shKQ As Worksheet
Set shData = ThisWorkbook.Worksheets("Sheet1")
Set shKQ = ThisWorkbook.Worksheets("Sheet3")
r = shData.Range("A" & shData.Rows.Count).End(xlUp).Row
If r < 2 Then Exit Sub
shKQ.Range("A2").Resize(10000, 5).ClearContents
sArr = shData.Range("A1").Resize(r, 5).Value2
ReDim Result(1 To r, 1 To 5): ReDim aExists(1 To r)
For i = 1 To r
If sArr(i, 3) = 1 Then
sKey = sArr(i, 1) & "|" & sArr(i, 4)
If Not KeyExists(aExists, sKey, j, k) Then
aExists(k) = sKey
j = j + 1
Result(j, 1) = j
Result(j, 2) = sArr(i, 4)
Result(j, 3) = sArr(i, 5)
Result(j, 5) = sArr(i, 1)
End If
Result(k, 4) = Result(k, 4) + 1
End If
Next i
shKQ.Range("A2").Resize(j, 5) = Result
End Sub
Thêm cho bạn 1 cách dùng ADO:Chào anh chị.
Em có thể xin code VBA có thể tạo báo cáo như sheet3 từ dữ liệu gốc ở sheet1. Hình thức báo cáo giống như pivot table.
Cảm ơn anh chị.
Sub GopDL()
With CreateObject("ADODB.Recordset")
.Open "Select [article_no],[Size],sum(Qty),[Carton] from [Sheet1$] where [Carton] is not null Group By [article_no],[Size],[Carton] order by [Carton]", "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=Excel 12.0"
Sheet2.Range("G2").CopyFromRecordset .DataSource
End With
End Sub
Ta có thể thay thế đoạn truy vấn trên như sau:Thêm cho bạn 1 cách dùng ADO:
Mã:Sub GopDL() With CreateObject("ADODB.Recordset") .Open "Select [article_no],[Size],sum(Qty),[Carton] from [Sheet1$] where [Carton] is not null Group By [article_no],[Size],[Carton] order by [Carton]", "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=Excel 12.0" Sheet2.Range("G2").CopyFromRecordset .DataSource End With End Sub
Select [article_no],[Size],sum(Qty),[Carton]
From [Sheet1$]
Where [Carton] is not null
Group By [Carton],[article_no],[Size]
Ủa, nó khác gì vậy anh Hai Lúa, Ot thấy không sắp xếp theo [Carton] nữa ạTa có thể thay thế đoạn truy vấn trên như sau:
Mã:Select [article_no],[Size],sum(Qty),[Carton] From [Sheet1$] Where [Carton] is not null Group By [Carton],[article_no],[Size]
Khác chứ em, nếu ta ưu tiên cái nào Group trước thì nó sẽ sắp xếp trước theo thứ tự.Ủa, nó khác gì vậy anh Hai Lúa, Ot thấy không sắp xếp theo [Carton] nữa ạ
À ra vậy OT biết thêm chức năng Group By ạ,, cảm ơn Anh ạ.Khác chứ em, nếu ta ưu tiên cái nào Group trước thì nó sẽ sắp xếp trước theo thứ tự.
Dùng Sub tốc độ nhanh hơn FunctionThử bon chen với Bác @HieuCD , Bạn thử chạy 'Sub Tham_Khao_ForNext' bên dưới:
Mã:Option Explicit Private Function KeyExists(aExists, sKey, j, k) As Boolean For k = 1 To j If aExists(k) = sKey Then KeyExists = True Exit For End If Next k End Function Sub Tham_Khao_ForNext() Dim aExists, sKey As String, sArr(), Result() Dim r As Long, i As Long, j As Long, k As Long Dim shData As Worksheet, shKQ As Worksheet Set shData = ThisWorkbook.Worksheets("Sheet1") Set shKQ = ThisWorkbook.Worksheets("Sheet3") r = shData.Range("A" & shData.Rows.Count).End(xlUp).Row If r < 2 Then Exit Sub shKQ.Range("A2").Resize(10000, 5).ClearContents sArr = shData.Range("A1").Resize(r, 5).Value2 ReDim Result(1 To r, 1 To 5): ReDim aExists(1 To r) For i = 1 To r If sArr(i, 3) = 1 Then sKey = sArr(i, 1) & "|" & sArr(i, 4) If Not KeyExists(aExists, sKey, j, k) Then aExists(k) = sKey j = j + 1 Result(j, 1) = j Result(j, 2) = sArr(i, 4) Result(j, 3) = sArr(i, 5) Result(j, 5) = sArr(i, 1) End If Result(k, 4) = Result(k, 4) + 1 End If Next i shKQ.Range("A2").Resize(j, 5) = Result End Sub
Dạ, vâng Bác vậy con sửa luôn trong bộ sưu tập của con ạ, con cảm ơn Bác ạDùng Sub tốc độ nhanh hơn Function
Viết ào ào thế mà có biết nguyên lý hoạt động của Function KeyExists hay không vậy nhóc? Tại sao k cứ thế mà tăng 1?Thử bon chen với Bác @HieuCD , Bạn thử chạy 'Sub Tham_Khao_ForNext' bên dưới:
Mã:Option Explicit Private Function KeyExists(aExists, sKey, j, k) As Boolean For k = 1 To j If aExists(k) = sKey Then KeyExists = True Exit For End If Next k End Function
Chú vùi dập con cũng phải vừa phải thôi chúViết ào ào thế mà có biết nguyên lý hoạt động của Function KeyExists hay không vậy nhóc? Tại sao k cứ thế mà tăng 1?
Copy về chạy thì ra kết quả. Hiểu sai bét hoặc giải thích sai nguyên lýChú vùi dập con cũng phải vừa phải thôi chú
Không hiểu mà ra kết quả được, con làm gì mà may thế, k +1 là theo j+1 phải không chú Mỹ (hehe con cũng không chắc)
Vậy rút cục là sao chú Mỹ , con bổ sung thêm một cách gải thích nữa là k tăng là vì số key tăng ạ , key bao nhiêu thì k bấy nhiêu ạ.Copy về chạy thì ra kết quả. Hiểu sai bét hoặc giải thích sai nguyên lý
Quay về nguyên lý của For Next: Khi thoát ra thì counter bằng bi nhiuVậy rút cục là sao chú Mỹ , con bổ sung thêm một cách gải thích nữa là k tăng là vì số key tăng ạ , key bao nhiêu thì k bấy nhiêu ạ.
Khi thoát rồi thì có thể là nó = 0 ạQuay về nguyên lý của For Next: Khi thoát ra thì counter bằng bi nhiu