Chuyên đề giải đáp những thắc mắc về code VBA

Liên hệ QC

maytinhvp01

Thành viên thường trực
Tham gia
27/7/13
Bài viết
390
Được thích
179
Mình muốn nhờ giải thich câu lệnh " If Ran.Cells(d, c) > max Then max = Ran.Cells(d, c) "
trong ví du:
Public Function LonNhat(Ran As Range)
Dim max As Double, v As Integer, d As Integer, c As Integer
max = Ran.Cells(1, 1)
For d = 1 To Ran.Rows.Count
For c = 1 To Ran.Columns.Count
If Ran.Cells(d, c) > max Then max = Ran.Cells(d, c)
Next c
Next d
v = Tim(max, Ran)
LonNhat = max
End Function
-------------------------------------------------------
[INFO1]Thông báo:
Vì topic này:
http://www.giaiphapexcel.com/forum/...ải-thích-các-code-đề-nghị-các-bạn-gửi-vào-đây
đã quá dài nên BQT đóng lại.
Nay tôi mở topic mới với cùng chủ đề: GIẢI THÍCH NHỮNG THẮC MẮC VỀ CODE
Các bạn nếu có nhu cầu giải thích code, vui lòng post tại đây nhé
NDU96081631

[/INFO1]
 
Chỉnh sửa lần cuối bởi điều hành viên:
Em đang tìm hiểu về Dictionary, xin nhờ các anh, chị giúp em cách gán Item của Dic xuống Sheet
Ở trong file đính kèm tính tổng doanh số của nhân viên ở các sheet. Em đã thử mấy cách mà không gán xuống được (chuẩn là em không biết cách gán), và cho em hỏi với trường hợp như file của em cách áp dụng Dic như nào sẽ tối ưu hơn
Em xin cám ơn!
Nó ra giá trị bằng không là đúng rồi còn gì.Ở đây câu lệnh này.Dic.Item(1) là lấy giá trị của item với Key = 1.Mà trong trường hợp này key =1 là giá không có nên nó bằng không.Nên dùng mảng ghi theo dữ liệu của dic thì ổn hơn.
 
Upvote 0
Đọc ở đâu không biết. Tài liệu rõ ràng, đầy đủ, chi tiết ở đây này.

Bài minh họa lọc trùng và tính tổng có sẵn luôn.


---
Item là Array thì làm vậy sao được.
Mã:
    For Each Sh In Worksheets
        If Sh.Name <> "TH" Then
            arr = Sh.Range("A2:C" & Sh.Cells(Rows.Count, "A").End(xlUp).Row).Value
            For i = 1 To UBound(arr, 1)
                If Not Dic.exists(CStr(arr(i, 1))) Then
                    Dic(CStr(arr(i, 1))) = Array(arr(i, 2), arr(i, 3))
                Else
                    Dic(CStr(arr(i, 1))) = Dic(CStr(arr(i, 1)))(1) + arr(i, 3)
                    'MsgBox Dic(CStr(arr(i, 1)))
                End If
            Next i
        End If
    Next Sh
    Worksheets("TH").Range("F1").Resize(Dic.Count, 3).ClearContents
    Worksheets("TH").Range("F1").Resize(Dic.Count, 1) = Application.Transpose(Dic.keys)
    Worksheets("TH").Range("G1").Resize(Dic.Count, 1) = Application.Transpose(Dic.Item(1))
 
Upvote 0
Đọc ở đâu không biết. Tài liệu rõ ràng, đầy đủ, chi tiết ở đây này.

Bài minh họa lọc trùng và tính tổng có sẵn luôn.


---
Item là Array thì làm vậy sao được.
Mã:
    For Each Sh In Worksheets
        If Sh.Name <> "TH" Then
            arr = Sh.Range("A2:C" & Sh.Cells(Rows.Count, "A").End(xlUp).Row).Value
            For i = 1 To UBound(arr, 1)
                If Not Dic.exists(CStr(arr(i, 1))) Then
                    Dic(CStr(arr(i, 1))) = Array(arr(i, 2), arr(i, 3))
                Else
                    Dic(CStr(arr(i, 1))) = Dic(CStr(arr(i, 1)))(1) + arr(i, 3)
                    'MsgBox Dic(CStr(arr(i, 1)))
                End If
            Next i
        End If
    Next Sh
    Worksheets("TH").Range("F1").Resize(Dic.Count, 3).ClearContents
    Worksheets("TH").Range("F1").Resize(Dic.Count, 1) = Application.Transpose(Dic.keys)
    Worksheets("TH").Range("G1").Resize(Dic.Count, 1) = Application.Transpose(Dic.Item(1))
về bài hướng dẫn ở link này em đã làm theo và làm được, tuy nhiên em đang tìm hiểu thêm lên muốn thử về Array của Dic, em xin cám ơn các anh đã giúp đỡ
 
Upvote 0
về bài hướng dẫn ở link này em đã làm theo và làm được, tuy nhiên em đang tìm hiểu thêm lên muốn thử về Array của Dic, em xin cám ơn các anh đã giúp đỡ
Trợt lớt hết trơn rồi còn thử mốc xì gì.
Dic là một collection, làm quái gì có array mà gọi "Array của Dic".
 
Upvote 0
Em chào các Thầy Cô và Anh Chị
Em có đoạn code này mà không biết làm thế nào để đưa nó vào vòng lặp cho nó ngắn lại
Nhờ mọi người có thể chỉ giúp em với ạ
Em xin cám ơn nhiều
Mã:
     .Cells(r - 2, 12) = Empty
                .Cells(r - 1, 12) = Empty
                .Cells(r - 1, 6) = Empty
                .Cells(r, 7) = Empty
                .Cells(r + 1, 7) = Empty
                .Cells(r + 2, 7) = Empty
                .Cells(r + 3, 7) = Empty
                '----------------------
                .Cells(r - 2, 22) = Empty
                .Cells(r - 1, 22) = Empty
                .Cells(r - 1, 16) = Empty
                .Cells(r, 17) = Empty
                .Cells(r + 1, 17) = Empty
                .Cells(r + 2, 17) = Empty
                .Cells(r + 3, 17) = Empty
                '-----------------------
                .Cells(r + 4, 4) = Empty
                .Cells(r + 6, 4) = Empty
                .Cells(r + 8, 4) = Empty
                .Cells(r + 4, 9) = Empty
                .Cells(r + 6, 9) = Empty
                .Cells(r + 8, 9) = Empty
                '--------------------------
                .Cells(r + 4, 14) = Empty
                .Cells(r + 6, 14) = Empty
                .Cells(r + 8, 14) = Empty
                .Cells(r + 4, 19) = Empty
                .Cells(r + 6, 19) = Empty
                .Cells(r + 8, 19) = Empty
 
Upvote 0
.Cells(r + 4, 4) = Empty
.Cells(r + 6, 4) = Empty
.Cells(r + 8, 4) = Empty
.Cells(r + 4, 9) = Empty
.Cells(r + 6, 9) = Empty
.Cells(r + 8, 9) = Empty
'--------------------------
.Cells(r + 4, 14) = Empty
.Cells(r + 6, 14) = Empty
.Cells(r + 8, 14) = Empty
.Cells(r + 4, 19) = Empty
.Cells(r + 6, 19) = Empty
.Cells(r + 8, 19) = Empty

Dùng vòng lặp không phải chỉ để làm ngắn code. Đó là lối suy nghĩ của tay mơ.
Trong trường hợp code trên, thu vào vòng lặp sẽ cho thấy rõ hơn sự liên hệ giữa các cells đang làm việc, và sẽ dễ bảo trì code.

For r1 = r + 4 To r + 8 Step 2
For c1 = 4 To 19 Step 5
.Cells(r1, c1) = Empty
Next c1
Next r1
Mẹo đếm vòng lặp: vòng r1 có 3 lượt, vòng c1 có 4 lượt. 3x4 = 12 = số dòng trong code cũ. Vậy là code có nhiều hy vọng đúng.

Chú thích: code trên dùng cái With block dài quá, rất dễ bị sai sót, và rất khó cho việc copy/cut/paste thêm bớt code. Dùng thẳng tiền tố ShA, ShB, ... tốt hơn.
 
Upvote 0
.Cells(r + 4, 4) = Empty
.Cells(r + 6, 4) = Empty
.Cells(r + 8, 4) = Empty
.Cells(r + 4, 9) = Empty
.Cells(r + 6, 9) = Empty
.Cells(r + 8, 9) = Empty
'--------------------------
.Cells(r + 4, 14) = Empty
.Cells(r + 6, 14) = Empty
.Cells(r + 8, 14) = Empty
.Cells(r + 4, 19) = Empty
.Cells(r + 6, 19) = Empty
.Cells(r + 8, 19) = Empty

Dùng vòng lặp không phải chỉ để làm ngắn code. Đó là lối suy nghĩ của tay mơ.
Trong trường hợp code trên, thu vào vòng lặp sẽ cho thấy rõ hơn sự liên hệ giữa các cells đang làm việc, và sẽ dễ bảo trì code.

For r1 = r + 4 To r + 8 Step 2
For c1 = 4 To 19 Step 5
.Cells(r1, c1) = Empty
Next c1
Next r1
Mẹo đếm vòng lặp: vòng r1 có 3 lượt, vòng c1 có 4 lượt. 3x4 = 12 = số dòng trong code cũ. Vậy là code có nhiều hy vọng đúng.

Chú thích: code trên dùng cái With block dài quá, rất dễ bị sai sót, và rất khó cho việc copy/cut/paste thêm bớt code. Dùng thẳng tiền tố ShA, ShB, ... tốt hơn.
Cám ơn chú rất nhiều. Tại viết code nó dài lê thê. Ngồi coi mãi mà không tìm ra điểm nào để đưa nó vào vòng lặp
Cho con hỏi. "Tay mơ" là thế nào chú?
Hihi. cám ơn chú rất nhiều. Để con thử ạ
------------------------------------------
Cám ơn chú đã gơi ý .
Ngồi test thấy nó ra bị thiếu. Quay lại đọc bài thì thấy chú ghi chú 1 nửa đoạn cho vào vòng lặp
Còn 1 nửa còn lại quên béng mất bảo sao thấy nó không xoá hết.
Cho con hỏi thêm chút nữa ạ. Nếu thao tác empty thế kia thì cũng có thể dùng Cleacontents những vùng được xác định phải không chú?
 
Lần chỉnh sửa cuối:
Upvote 0
Mẹo đếm vòng lặp: vòng r1 có 3 lượt, vòng c1 có 4 lượt. 3x4 = 12 = số dòng trong code cũ. Vậy là code có nhiều hy vọng đúng.
Cảm ơn chú 1 lần nữa. Sau khi ngồi đọc code của chú. Cũng tìm ra cách đưa nó vào vòng lặp
Nhưng có vẻ số dòng code cũng không ngắn hơn là bao. Hihi
Tương lai sau khi phát sinh sự cố chắc ngồi đọc lại chẳng hiểu tại sao đặt biết kiểu ấy mất.
Mã:
                For r1 = r - 2 To r - 1 Step 1
                    For c1 = 12 To 22 Step 10
                        .Cells(r1, c1) = Empty
                    Next
                Next
                For c1 = 6 To 16 Step 10
                    .Cells(r - 1, c1) = Empty
                Next
                For r1 = r To r + 3
                    For c1 = 7 To 17 Step 10
                        .Cells(r1, c1) = Empty
                    Next
                Next
                For r1 = r + 4 To r + 8 Step 2
                    For c1 = 4 To 19 Step 5
                        .Cells(r1, c1) = Empty
                    Next c1
                Next r1
Chắc cứ viết tường minh ra có lẽ tránh hậu hoạ sau này đọc không hiểu mất.
Xin cám ơn chú nhiều ạ
 
Upvote 0
Cám ơn chú rất nhiều. Tại viết code nó dài lê thê. Ngồi coi mãi mà không tìm ra điểm nào để đưa nó vào vòng lặp
Cho con hỏi. "Tay mơ" là thế nào chú?
Hihi. cám ơn chú rất nhiều. Để con thử ạ
"Tay mơ" sẽ cố gắng nhét chúng hết vào một block vòng lặp. Nhưng không có khái niệm "nhóm" chúng theo loại dòng cho nên sẽ bí.

Đây là code 1 block. Dùng Union để nhóm:
For r1 = r - 2 To r + 8
Select Case r1 - r
Case -2
Union(.Cells(r1, 12), .Cells(r1 - 2, 22)) = Empty
Case -1
Union(.Cells(r1, 12), .Cells(r1, 22), .Cells(r1, 6), .Cells(r1, 16)) = Empty
Case 0 To 3
Union(.Cells(r1, 7), .Cells(r1, 17)) = Empty
Case 4, 6, 8
Union(.Cells(r1, 4), .Cells(r1, 9), .Cells(r1, 14), .Cells(r1, 19)) = Empty
End Select
Next r1
 
Lần chỉnh sửa cuối:
Upvote 0
"Tay mơ" sẽ cố gắng nhét chúng hết vào một block vòng lặp. Nhưng không có khái niệm "nhóm" chúng theo loại dòng cho nên sẽ bí.

Đây là code 1 block. Dùng Union để nhóm:
For r1 = r - 2 To r + 8
Select Case r1
Case r - 2
Union(.Cells(r1, 12), .Cells(r1 - 2, 22)) = Empty
Case r - 1
Union(.Cells(r1, 12), .Cells(r1, 22), .Cells(r1, 6), .Cells(r1, 16)) = Empty
Case r To r+3
Union(.Cells(r1, 7), .Cells(r1, 17)) = Empty
Case 4, 6, 8
Union(.Cells(r1, 4), .Cells(r1, 9), .Cells(r1, 14), .Cells(r1, 19)) = Empty
End Select
Next r1
Cám ơn chú. Chắc kiểu này con viết rõ ràng ra cho lành mạnh. Chứ viết thế kia nếu đúng mà không hiểu được nó, không kiểm soát được nó, Chắc mai mốt có vấn đề gì đó chắc lại chữ thầy giả thầy. Thậm chí không biết là sai chỗ nào ế.
Cám ơn chú 1 lần nữa. Chắc chắn sẽ ngồi đọc cho vỡ lẽ cái đoạn kia ạ
 
Upvote 0
Em chào các Thầy Cô và Anh Chị
Em có đoạn code này mà không biết làm thế nào để đưa nó vào vòng lặp cho nó ngắn lại
Nhờ mọi người có thể chỉ giúp em với ạ
Em xin cám ơn nhiều
Mã:
     .Cells(r - 2, 12) = Empty
                .Cells(r - 1, 12) = Empty
                .Cells(r - 1, 6) = Empty
                .Cells(r, 7) = Empty
                .Cells(r + 1, 7) = Empty
                .Cells(r + 2, 7) = Empty
                .Cells(r + 3, 7) = Empty
                '----------------------
                .Cells(r - 2, 22) = Empty
                .Cells(r - 1, 22) = Empty
                .Cells(r - 1, 16) = Empty
                .Cells(r, 17) = Empty
                .Cells(r + 1, 17) = Empty
                .Cells(r + 2, 17) = Empty
                .Cells(r + 3, 17) = Empty
                '-----------------------
                .Cells(r + 4, 4) = Empty
                .Cells(r + 6, 4) = Empty
                .Cells(r + 8, 4) = Empty
                .Cells(r + 4, 9) = Empty
                .Cells(r + 6, 9) = Empty
                .Cells(r + 8, 9) = Empty
                '--------------------------
                .Cells(r + 4, 14) = Empty
                .Cells(r + 6, 14) = Empty
                .Cells(r + 8, 14) = Empty
                .Cells(r + 4, 19) = Empty
                .Cells(r + 6, 19) = Empty
                .Cells(r + 8, 19) = Empty
Dùng 2 mảng liệt kê dòng và cột
Mã:
  Dim rng As Range, sRow, aCol, k&
  '....
  arow = Array(-2, -1, -1, 0, 1, 2, 3, -2, -1, -1, 0, 1, 2, 3, 4, 6, 8, 4, 6, 8, 6, 8, 4, 6, 8)
  aCol = Array(12, 12, 6, 7, 7, 7, 7, 22, 22, 16, 17, 17, 17, 17, 4, 4, 4, 9, 9, 9, 14, 14, 14, 19, 19, 19)
  Set rng = .Cells(r + arow(0), aCol(0))
  For k = 1 To UBound(arow)
    Set rng = Union(rng, .Cells(r + arow(k), aCol(k)))
  Next k
  rng = Empty
  Set rng = Nothing
 
Upvote 0
Dùng 2 mảng liệt kê dòng và cột
Mã:
  Dim rng As Range, sRow, aCol, k&
  '....
  arow = Array(-2, -1, -1, 0, 1, 2, 3, -2, -1, -1, 0, 1, 2, 3, 4, 6, 8, 4, 6, 8, 6, 8, 4, 6, 8)
  aCol = Array(12, 12, 6, 7, 7, 7, 7, 22, 22, 16, 17, 17, 17, 17, 4, 4, 4, 9, 9, 9, 14, 14, 14, 19, 19, 19)
  Set rng = .Cells(r + arow(0), aCol(0))
  For k = 1 To UBound(arow)
    Set rng = Union(rng, .Cells(r + arow(k), aCol(k)))
  Next k
  rng = Empty
  Set rng = Nothing
Cám ơn thầy nhiều ạ.
 
Upvote 0
Nhờ a/c viết giùm code để sheets tổng hợp làm được nhanh hơn
Bài đã được tự động gộp:

Nhờ a/c viết giúp code để tổng hợp nhiều sheets lại thành 1 sheets tổng hợp
 
Lần chỉnh sửa cuối:
Upvote 0
Tác giả bài trên chẳng biết muốn gì mà đăng hỏi câu ấy tùm lum hết.
 
Upvote 0
em là người mới, mong anh chị giúp đỡ nhiều.
em có 1 file muốn nhờ anh chị viết code VBA giúp em.
em cần tự động giãn dòng khi giá trị đấy xuất hiện lần đầu tiên ở cột AI.
trước đấy em cũng có thử viết code nhưng không ra được kết quả như mong muốn.
em cảm ơn anh chị nhiều
 

File đính kèm

Upvote 0
PHP:
Sub ZanDong()
 Dim WF As Object, Rng As Range, Cls As Range
 Dim J As Long, Rws As Long, W
 Const MaX_ As Integer = 35:         Const Min_ As Integer = 23

 Set WF = Application.WorksheetFunction
 Rws = [AI10].End(xlDown).Row
 For J = 9 To Rws
    W = W + 1
    Set Rng = [AI9].Resize(W)
    If WF.CountIf(Rng, Cells(J, "AI").Value) = 1 Then
        Rows(J & ":" & J).RowHeight = MaX_
    Else
        Rows(J & ":" & J).RowHeight = Min_
    End If
 Next J
End Sub
 
Upvote 0
PHP:
Sub ZanDong()
 Dim WF As Object, Rng As Range, Cls As Range
 Dim J As Long, Rws As Long, W
 Const MaX_ As Integer = 35:         Const Min_ As Integer = 23

 Set WF = Application.WorksheetFunction
 Rws = [AI10].End(xlDown).Row
 For J = 9 To Rws
    W = W + 1
    Set Rng = [AI9].Resize(W)
    If WF.CountIf(Rng, Cells(J, "AI").Value) = 1 Then
        Rows(J & ":" & J).RowHeight = MaX_
    Else
        Rows(J & ":" & J).RowHeight = Min_
    End If
 Next J
End Sub
Đọc ngược từ dưới lên trên, và dùng hàm Match để tìm. Nếu hàm Match cho vị trí ứng với dòng hiện tại thì đó là lần xuất hiện đầu tiên.
Dù sao thì Match cũng nhanh hơn CountIf một chút.
 
Upvote 0
PHP:
Sub ZanDong()
 Dim WF As Object, Rng As Range, Cls As Range
 Dim J As Long, Rws As Long, W
 Const MaX_ As Integer = 35:         Const Min_ As Integer = 23

 Set WF = Application.WorksheetFunction
 Rws = [AI10].End(xlDown).Row
 For J = 9 To Rws
    W = W + 1
    Set Rng = [AI9].Resize(W)
    If WF.CountIf(Rng, Cells(J, "AI").Value) = 1 Then
        Rows(J & ":" & J).RowHeight = MaX_
    Else
        Rows(J & ":" & J).RowHeight = Min_
    End If
 Next J
End Sub
Application.WorksheetFunction thường giúp code ngắn gọn nhưng nếu dùng nhiều có thể làm chậm code.
Bài nầy dữ liệu được sắp xếp nên chỉ cần so sánh với ô trên nếu khác là thỏa điều kiện giãn dòng
 
Upvote 0
Web KT

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

Back
Top Bottom