Hỏi giải pháp sao cho Code trở thành Code động có tính "co dãn" cùng bảng tính

Liên hệ QC

Dauthivan

Thành viên tiêu biểu
Tham gia
15/8/08
Bài viết
565
Được thích
326
Nhờ các thày và mọi người trên diễn đàn tận tình chỉ bảo, em đã bước đầu hiểu được các thuật toán VBA. Em làm thử nghiên cứu bài toán lọc vật tư trên diễn đàn có 1 số chỗ em chưa hiểu hết bản chất, em xin mạn phép được hỏi một chút ah, cụ thể: Đầu bài toán của em như sau:
DaubaiVT.png


Yêu cầu của bài toán để tổng hợp vật tư ra Sheet THVT bên cạnh, theo mẫu em xin post hình để mọi người dễ nhìn:


KetquaVT.png


Code của bài toán như sau:
PHP:
Sub TongVatTu()
    
Application.ScreenUpdating = False

''Loc lay vat tu
    Dim n As Long, m As Long
    m = S02.Range("C65000").End(xlUp).Row
    If m > 5 Then
        S02.Select
        Rows("6:" & m + 1).Select
        Selection.Delete Shift:=xlUp
    End If
    n = S01.Range("E65000").End(xlUp).Row
    For i = 6 To n
        If S01.Cells(i, 3) <> "công" And S01.Cells(i, 3) <> "ca" And S01.Cells(i, 3) <> "%" Then
            m = S02.Range("C65000").End(xlUp).Row
            DVT = S01.Cells(i, 3)
            If S01.Cells(i, 4) <> 0 Then
                S02.Cells(m + 1, 2) = S01.Cells(i, 2)
                S02.Cells(m + 1, 3) = DVT
                S02.Cells(m + 1, 7) = "=COUNTIF(R6C2:RC2,RC[-5])"
            End If
        End If
    Next
    
''Xoa Vat tu trung va sort theo ten vat tu
    m = S02.Range("G65000").End(xlUp).Row
    For i = m To 6 Step -1
        S02.Cells(i, 7).Select
        If S02.Cells(i, 7) > 1 Then
           Selection.EntireRow.Delete
        End If
    Next
    m = S02.Range("C65000").End(xlUp).Row
    Range("B6:C" & m).Select
    Selection.Sort Key1:=Range("B6"), Order1:=xlAscending, Header:=xlGuess, _
        OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
        DataOption1:=xlSortNormal

''Lay tong so luong vat tu va tien cua tung vat tu
    n = S01.Range("E65000").End(xlUp).Row
    m = S02.Range("C65000").End(xlUp).Row
    Columns("G:G").Select
    Selection.ClearContents
    For i = 6 To m
        S02.Cells(i, 1) = i - 5
        S02.Cells(i, 4) = "=SUMIF('Bang Du Toan'!R6C2:R" & n & "C2,RC[-2],'Bang Du Toan'!R6C5:R" & n & "C5)"
        S02.Cells(i, 4).Select
        Selection.NumberFormat = "#,##0.000"
        S02.Cells(i, 6) = "=ROUND(RC[-2]*RC[-1],0)"
    Next
    
    Application.ScreenUpdating = True
    
End Sub
Em có 1 số điều chưa rõ, xin được chỉ giúp:

1) Em hiểu đoạn Columns("G:G").Select; Selection.ClearContents là xoá toàn bộ cột G ở cả 2 Sheet, nhưng em thử Test bằng cách đánh số vào cột G của Sheet Bangdutoan thì nó không bị xoá khi chạy.

2) Em không biết mọi người khi đánh đoạn S02.Cells(i, 4) = "=SUMIF('Bang Du Toan'!R6C2:R" & n & "C2,RC[-2],'Bang Du Toan'!R6C5:R" & n & "C5)" chẳng hạn, có quay về màn hình excel nhờ trợ giúp viết cụm 'Bang Du Toan'! ...cho chính xác hay không? hay là cứ đánh thủ công bình thường như đánh Word (chứ không lấy tham chiếu trực tiếp từ Excel)

3) Ý này em mượn bài này để hỏi chung cho mọi bài, tức là tình trạng Code không liên hệ gì với Bảng excel khi bảng Excel bị thêm bớt dòng cột ( ví dụ nếu chèn hoặc xoá bớt dòng ở 1 trong 2 Sheet trên) thì Tổng hợp sẽ không đúng nữa? Vậy có cách nào cho Code trở thành "Code động", kiểu như khai biến mảng động ý ah?

4) Em không hiểu tại sao Code chưa hoàn thiện ở điểm gì mà nếu em xoá phần kết quả vừa chạy ra (SheetTHVT) thì em phải ấn Click Code chạy phải 2 lần nó mới được?
 

File đính kèm

  • Loc Vat tu.xls
    54.5 KB · Đọc: 33
Lần chỉnh sửa cuối:
Trả lời:
1. Columns("G:G").Select; Selection.ClearContents là xoá toàn bộ cột G ở cả 2 Sheet

Sai.
Code đặt ở Module, nên Column("G:G") không có tên sheet kèm theo tức là nói đến sheet hiện hành. Sheet hiện hành là sheet TH, nên chỉ cột G của sheet TH bị xoá.

2. Khi gõ code liên quan đến tên sheet thì sao?

Trong cửa sổ VBA cũng có liệt kê sheet và tên sheet, tội gì chạy đi chạy về?

3. Code động:

Có 1 số cách trong đó cách hay nhất là thủ tục (sub) có tham số truyền. Ngoài ra có nhiều cách như:
- Dùng Name
- Dùng UsedRange
- Dùng inputbox để lấy vùng cần tính toán.
- ...

4. Tại sao xoá kêt quả thì phải chạy code 2 lần

trong code có đoạn:

PHP:
    If m > 5 Then
        S02.Select
        Rows("6:" & m + 1).Select
        Selection.Delete Shift:=xlUp
    End If

Nếu m>5 thì mới chọn (select) sheet TH, m <= 5 thì không select sheet.
Xoá hết rồi thì m = 5, sheet TH không được chọn. Sheet chưa được chọn mà chọn ô hoặc vùng của sheet đó thì lỗi.
Khi xảy ra lỗi, stop code thì đã có 1 mớ được ghi vào sheet TH, m trở nên >5. Chạy lần 2 không lỗi nữa.
 
Lần chỉnh sửa cuối:
Upvote 0
Trả lời:

2. Khi gõ code liên quan đến tên sheet thì sao?

Trong cửa sổ VBA cũng có liệt kê sheet và tên sheet, tội gì chạy đi chạy về?

3. Code động:

Có 1 số cách trong đó cách hay nhất là thủ tục (sub) có tham số truyền. Ngoài ra có nhiều cách như:
- Dùng Name
- Dùng UsedRange
- Dùng inputbox để lấy vùng cần tính toán.
- ...

Ý em muốn nói khi gõ đoạn S02.Cells(i, 4) = "=SUMIF('Bang Du Toan'!R6C2:R" & n & "C2,RC[-2],'Bang Du Toan'!R6C5:R" & n & "C5)" chẳng hạn thì ta cứ gõ thủ công toàn bộ như bình thường? hay có tận dụng được cái gì có sẵn trên màn hình không ah?

Có 1 số cách trong đó cách hay nhất là thủ tục (sub) có tham số truyền như thày nói ở trên, liệu nó có làm nặng file, làm quá trình tính toán chậm không ah? Em sợ cái name trong Excel tính chậm lắm, dữ liệu em lại nhiều.

(Vì em mới tập chưa hình dung hết, mong thày và mọi người chỉ hộ em với ah)
 
Upvote 0
1. Tận dụng cái có sẵn trên màn hình:
Chả có sẵn. Đọc và gõ lại. Khi đọc gõ lại sai vài lần, tự nhiên thấy sự cần thiết phải đặt tên sheet ngắn, không dấu và không có khoảng trắng. Lợi cả 2 đường.
Hoặc: Không có sẵn thì tạo ra cho có: Trong cửa sổ Immediate gõ ?sheet1.name rồi enter, nó sẽ cho tên sheet, để đó để dành, khi cần thì copy nó.

2. Sub có tham số truyền:
Code nhanh chậm ở thuật toán, ở thủ thuật, và ở cả xảo thuật, chứ có tham số hay không không ảnh hưởng. Code có tham số lại còn tiện lợi ở chỗ 1 code có thể dùng cho nhiều lần cho nhiều vùng dữ liệu khác nhau, chỉ cần gọi nó với tham số này, nó chạy với tham số này, gọi nó với tham số kia, nó chạy với tham số kia. Thí dụ như file bài này, cách 3 và 4 là sub có tham số truyền: http://www.giaiphapexcel.com/forum/showthread.php?60044-Hỏi-công-thức-mảng-kiểm-tra-bằng-ấn-F9-hàm-mảng-VBA-làm-cách-nào-để-biết-kết-quả&p=371533#post371533

3. Name cũng là 1 range, Name động thì Range động. Dù Name là range Nhưng từ Name đưa vào mảng để xử lý thì làm sao mà chậm được?
 
Lần chỉnh sửa cuối:
Upvote 0
Ý em muốn nói khi gõ đoạn S02.Cells(i, 4) = "=SUMIF('Bang Du Toan'!R6C2:R" & n & "C2,RC[-2],'Bang Du Toan'!R6C5:R" & n & "C5)" chẳng hạn thì ta cứ gõ thủ công toàn bộ như bình thường? hay có tận dụng được cái gì có sẵn trên màn hình không ah?

Bạn có thể gõ công thức bên Excel trong khi ghi macro để lấy code, sau đó copy bỏ vào code đang viết sửa lại địa chỉ cho nó "động".
 
Upvote 0
Em xin trích dẫn 1 số đoạn Code nhỏ mà em muốn hỏi, xin được mọi người giúp cho:

PHP:
''Xoa Vat tu trung va sort theo ten vat tu
    m = S02.Range("G65000").End(xlUp).Row
    For i = m To 6 Step -1
        S02.Cells(i, 7).Select
        If S02.Cells(i, 7) > 1 Then
           Selection.EntireRow.Delete
        End If
    Next
    m = S02.Range("C65000").End(xlUp).Row
    Range("B6:C" & m).Select
    Selection.Sort Key1:=Range("B6"), Order1:=xlAscending, Header:=xlGuess, _
        OrderCustom:=1, MatchCase:=False, Orientation:=xlTopToBottom, _
        DataOption1:=xlSortNormal

Em thắc mắc là một biến có thể định nghĩa nhiều lần khác nhau trong một Sub, cụ thể ở đây ban đầu m = S02.Range("G65000").End(xlUp).Row, sau đó lại là m = S02.Range("C65000").End(xlUp).Row. Tức là khai báo đầu tiên nó có tác dụng từ dòng đó trở đi cho đến khi được thay thế bởi việc khai báo mới.
-------------------------------------

PHP:
 m = S02.Range("G65000").End(xlUp).Row
    For i = m To 6 Step -1
        S02.Cells(i, 7).Select
        If S02.Cells(i, 7) > 1 Then
           Selection.EntireRow.Delete
        End If
    Next

Em nghĩ tại sao đã có dòng If S02.Cells(i, 7) > 1 Then, tức là đã chọn làm việc ở S02 rồi tại sao trước đó lại phải có thêm dòng S02.Cells(i, 7).Select (có cảm giác như thừa?).
---------------------------------
PHP:
For i = 6 To n
        If S01.Cells(i, 3) <> "công" And S01.Cells(i, 3) <> "ca" And S01.Cells(i, 3) <> "%" Then
            m = S02.Range("C65000").End(xlUp).Row
            DVT = S01.Cells(i, 3)
            If S01.Cells(i, 4) <> 0 Then
                S02.Cells(m + 1, 2) = S01.Cells(i, 2)
                S02.Cells(m + 1, 3) = DVT
                S02.Cells(m + 1, 7) = "=COUNTIF(R6C2:RC2,RC[-5])"
            End If
Khi em chuyển font cho các Sheet đầu vào thì bản thân các chữ (công,ca..)trong giữa Code và trên màn hình excel không trùng nhau, điều này dẫn đến KQ chạy sai? vậy em phải làm sao khắc phục tình trạng này ah?
 
Upvote 0
(1)
Em thắc mắc là một biến có thể định nghĩa nhiều lần khác nhau trong một Sub, cụ thể ở đây ban đầu
m
= S02.Range("G65000").End(xlUp).Row
,
sau đó lại là m = S02.Range("C65000").End(xlUp).Row.

Tức là khai báo đầu tiên nó có tác dụng từ dòng đó trở đi cho đến khi được thay thế bởi việc khai báo mới.

(1) biến không được định nghĩa nhiều lần! Nhưng vấn đề của bạn đó không fải là định nghĩa nhiều lần;
Đó là gán cho biến nhiều giá trị khác nhau trong suốt chu trình;

Bạn hãy xem ngay câu lệnh sau:

Mã:
 Dim GPE
 
 Set GPE= Range("A9:B35")
'. . . . . . . '
 GPE=[B13].value +  91
'. . . . . . . '
GPE = GPE - 2

Các câu lệnh này có lúc báo lỗi, lúc không. Điều này có lúc tùy thuộc vô GPE trước đó chứa gì trong nớ!

(2) Cảm giác không đánh lừa bạn!

(3)Bạn Hữu Thắng BĐ đã giúp bạn hiểu sơ bộ về vấn đề này rồi mà!
Bạn có thể tìm đọc thêm các bài viết về tiếng Việt trong VBA;
Mình chỉ bạn cách khác đơn giản, nhưng fí fạm tài nguyên hơn: Đó là cách đưa các từ như 'Công', 'Tổng' hay 'Tổng cộng' vô Name & ới nó ra xài khi cần.

Mong giúp bạn ít nhiều!
 
Upvote 0
(1)
(3)Bạn Hữu Thắng BĐ đã giúp bạn hiểu sơ bộ về vấn đề này rồi mà!
Bạn có thể tìm đọc thêm các bài viết về tiếng Việt trong VBA;
Mình chỉ bạn cách khác đơn giản, nhưng fí fạm tài nguyên hơn: Đó là cách đưa các từ như 'Công', 'Tổng' hay 'Tổng cộng' vô Name & ới nó ra xài khi cần.

Mong giúp bạn ít nhiều!

Vâng hướng giải quyết của bài này thì mọi người cũng đã đề cập rồi, nhưng em chưa biết các bước cụ thể của nó như thế nào. Xin được hướng dẫn chi tiết giúp.
 
Upvote 0
Bác Chanh đã trả lời hết rồi, nhưng nói thêm về 2 và 3:

2. Các câu lệnh Select có nghĩa là đánh vào sheet, chạy qua chạy lại giữa các sheet và giữa các cell, điều này làm giảm tốc độ. Do đó, không dùng hoặc hạn chế dùng phương thức select. Bù lại, mọi tác động vào Range phải ghi rõ tên sheet, nếu không code sẽ đánh vào sheet hiện hành.
Thí dụ thay vì select 1 vùng rồi sort:

S02.Select
Range
("B6:C" & m).Select
Selection
.Sort Key1:=Range("B6"), ...

Ta làm thẳng:

S02.Range("B6:C" & m).Sort Key1:=S02.Range("B6"), ...

3. Tạo 1 Name = 1 giá trị cụ thể đâu có khó? Gọi nó bằng VBA cũng lại càng dễ

a. Gọi Name để gán giá trị xuống ô:

Cách 1: Tạo 1 Name Cong = "Tổng cộng"

Sau đó gán:

Sheet1.[A1] = "=Cong"

Cách 2: Tạo Name "Cong" = $A$1 với A1 gõ sẵn "Tổng cộng"
Sau đó gán:

Sheet1.[A1] = Range("Cong")


b. Gán Range của Name vào mảng:

Tạo 1 name Rng là 1 vùng nào đó của sheet1, Name dộng cũng được.Sau đó dùng lệnh sau:
Dim Arr
Arr = Range("Rng").Value

Đó là code trong module, code của sheet thì phải ghi rõ Sheet1.Range("Rng"), nhất là đứng sheet này gọi Rng của sheet kia.
 
Lần chỉnh sửa cuối:
Upvote 0
Bác Chanh đã trả lời hết rồi, nhưng nói thêm về 2 và 3:

2. Các câu lệnh Select có nghĩa là đánh vào sheet, chạy qua chạy lại giữa các sheet và giữa các cell, điều này làm giảm tốc độ. Do đó, không dùng hoặc hạn chế dùng phương thức select. Bù lại, mọi tác động vào Range phải ghi rõ tên sheet, nếu không code sẽ đánh vào sheet hiện hành.

Em cũng nghĩ thế nhưng nếu cụ thể bài này em thay đoạn:
PHP:
'Xoa Vat tu trung va sort theo ten vat tu
    m = S02.Range("G65000").End(xlUp).Row
    For i = m To 6 Step -1
        S02.Cells(i, 7).Select
        If S02.Cells(i, 7) > 1 Then
           Selection.EntireRow.Delete
        End If
    Next
Sau khi xóa đi dòng mà em nghĩ là thừa, nó trở thành:
PHP:
'Xoa Vat tu trung va sort theo ten vat tu
    m = S02.Range("G65000").End(xlUp).Row
    For i = m To 6 Step -1
                If S02.Cells(i, 7) > 1 Then
           Selection.EntireRow.Delete
        End If
    Next

Lập tức khi chạy màn hình để trắng (không ra kết quả ah).
 
Upvote 0
Xoá bỏ Câu lệnh Select, thì làm gì còn Selection như ý muốn mà xoá dòng? Không có tên sheet, thì selection là selection của sheet hiện hành. Chạy hết vòng lặp nó không xoá phứt sheet hiện hành mới là lạ.
Đã nhắc đi nhắc lại là đánh đập range phải có tên sheet!

If S02.Cells(i, 7) > 1 Then
Selection
.EntireRow.Delete
End
If


sửa thành

If
S02.Cells(i, 7) > 1 Then
S02.Cells(i, 7).EntireRow.Delete

Vui lòng đọc kỹ từng câu từng chữ tôi viết ở trên, và làm theo. Nếu làm theo mà vẫn sai, tôi chịu sai và nhận lỗi. Chứ không đọc kỹ, làm theo không đúng phải sửa từng câu như vầy thì khó tiến bộ lắm.

Ở trên tôi đã thí dụ 1 đoạn code sort không cần select, cũng bỏ chữ selection y như vầy, mà không áp dụng.
 
Lần chỉnh sửa cuối:
Upvote 0
Em vấn thắc mắc trong bài này, đoạn code:
PHP:
Sub TongVatTu()
    
Application.ScreenUpdating = False

''Loc lay vat tu
    Dim n As Long, m As Long
    m = S02.Range("C65000").End(xlUp).Row
    If m > 5 Then
        S02.Select
        Rows("6:" & m + 1).Select
        Selection.Delete Shift:=xlUp
    End If
    n = S01.Range("E65000").End(xlUp).Row
    For i = 6 To n
        If S01.Cells(i, 3) <> "công" And S01.Cells(i, 3) <> "ca" And S01.Cells(i, 3) <> "%" Then
            m = S02.Range("C65000").End(xlUp).Row
            DVT = S01.Cells(i, 3)
            If S01.Cells(i, 4) <> 0 Then
                S02.Cells(m + 1, 2) = S01.Cells(i, 2)
                S02.Cells(m + 1, 3) = DVT
                S02.Cells(m + 1, 7) = "=COUNTIF(R6C2:RC2,RC[-5])"
            End If
        End If
    Next
.....
End Sub

Tại dòng lệnh: S02.Cells(m + 1, 2) = S01.Cells(i, 2) tại sao lại thế được, trong khi m cố định, i thay đổi?
 
Upvote 0
Bài này của bạn nếu giải quyết bằng Array + Dictionary mới là cách tốt nhất
Code như sau:
PHP:
Sub TongHop()
  Dim sArray, Arr(), lR As Long, n As Long
  Dim tmp1 As String, tmp2 As String, tmp3 As Double
  sArray = S01.Range("A6:E1000").Value
  ReDim Arr(1 To UBound(sArray, 1), 1 To 4)
  With CreateObject("Scripting.Dictionary")
    For lR = 1 To UBound(sArray, 1)
      If sArray(lR, 2) <> "" Then
        If sArray(lR, 1) = "" Then
          If sArray(lR, 3) <> "công" And sArray(lR, 3) <> "ca" And sArray(lR, 3) <> "%" Then
            tmp1 = sArray(lR, 2)
            tmp2 = sArray(lR, 3)
            tmp3 = sArray(lR, 5)
            If Not .Exists(tmp1) Then ''<-- chổ này xét sự tồn tại để lấy Item duy nhất
              n = n + 1
              .Add tmp1, n
              Arr(n, 1) = n
              Arr(n, 2) = tmp1
              Arr(n, 3) = tmp2
              Arr(n, 4) = tmp3
            Else
              Arr(.Item(tmp1), 4) = Arr(.Item(tmp1), 4) + tmp3 ''<-- Nếu có Item trùng thì sẽ cộng dồn
            End If
          End If
        End If
      End If
    Next
    If n Then ''<-- Nếu n > 0 thì chứng tỏ các điều kiện thiết lập ở trên đã thỏa mản, ta mới tiến hành gán mảng xuống sheet
      S02.Range("A6:F1000").ClearContents
      S02.Range("A6").Resize(n, 4).Value = Arr
    End If
  End With
End Sub
Trong các bài toán liên quan đến lọc duy nhất thì tôi cho rằng dùng Dictionary là tốt nhất vì:
- Tốc độ rất cao
- Độ chính xác gần như tuyệt đối
- Code đơn giản nhất
Nếu bạn đồng ý với phương pháp này thì chúng ta sẽ bàn tiếp
 
Upvote 0
Bài này của bạn nếu giải quyết bằng Array + Dictionary mới là cách tốt nhất

Trong các bài toán liên quan đến lọc duy nhất thì tôi cho rằng dùng Dictionary là tốt nhất vì:
- Tốc độ rất cao
- Độ chính xác gần như tuyệt đối
- Code đơn giản nhất
Nếu bạn đồng ý với phương pháp này thì chúng ta sẽ bàn tiếp
Em cũng đã nghe về tính ưu việt của Dictionary, em sẽ tích cực tìm hiểu về cái này (hiện em chưa biết về nó), em xin hỏi cách này khi tổng hợp khối lượng tại cột D của SheetTHVT nó có hiện ra được công thức Sumif như cách kia không ah?

Nếu được, mong mọi người giúp cho em với.
 
Upvote 0
Em cũng đã nghe về tính ưu việt của Dictionary, em sẽ tích cực tìm hiểu về cái này (hiện em chưa biết về nó), em xin hỏi cách này khi tổng hợp khối lượng tại cột D của SheetTHVT nó có hiện ra được công thức Sumif như cách kia không ah?

Nếu được, mong mọi người giúp cho em với.
Bạn muốn SUMIF hay bất cứ công thức gì thì cứ việc viết vào
Riêng Dictionary nó chỉ có 1 nhiệm vụ duy nhất là phát hiện dữ liệu trùng hay không mà thôi
Vì thế, nếu bạn để ý trong code tôi viết sẽ thấy rằng:
- Dictionary dùng để phát hiện sự tồn tại của 1 phần từ (phương thức Exists)
- Nếu chưa tồn tại, ta Add vào (phương thức Add)
- Nếu có tồn tại, ta làm cái gì khác tùy ý (code trong trên thì khi phát hiện tồn tại, tôi cộng dồn)
- Vậy Dictionary trong code chỉ là "món" phụ ---> Mọi dữ liệu đều được cho vào biến Arr (khi các điều kiện đã thỏa)
Ngoài ra xin nói thêm:
- Nếu đã dùng code thì tuyệt đối không nên có bất cứ công thức nào (chẳng lẽ bạn không tin độ chính xác của code?)
- Nếu dùng đến công thức, thôi thì ta làm bằng tay cho khỏe (Advanced Filter kết hợp SUMIF chẳng hạn)
- Với dữ liệu sau khi xuất ra mà cở vài ngàn dòng thì công thức sẽ làm chậm bảng tính
===> Vài góp ý nhỏ, bạn tự quyết định đi.. nhưng xin nhớ rằng: không nên dùng lộn xộn code + công thức
 
Upvote 0
Tại dòng lệnh: S02.Cells(m + 1, 2) = S01.Cells(i, 2) tại sao lại thế được, trong khi m cố định, i thay đổi?

Câu này chưa hỏi tại đây, nên trả lời (ẹc ẹc)

1. m được xác định bằng dòng cuối chứa dữ liệu (m = S02.Range("C65000").End(xlUp).Row)
(vụ này trong topic này chưa nói, nhưng hình như đã giải thích bên kia)

2. câu lệnh xác định dòng cuối đặt trong vòng lặp, vậy mỗi vòng lặp i sẽ xác định lại m 1 lần. Mà mỗi vòng lặp i lại ghi thêm dữ liệu vào 1 dòng, vậy dòng cuối đã thay đổi.

(Hic, vụ này mà làm theo Cò già, nhấn F8 kết hợp với Locals Windows cũng thấy m thay đổi, mà không làm)
 
Lần chỉnh sửa cuối:
Upvote 0
Bạn muốn SUMIF hay bất cứ công thức gì thì cứ việc viết vào

Nói thêm về việc đặt công thức trong code cho bạn tham khảo
Ta sẽ thay đoạn này:
Mã:
If Not .Exists(tmp1) Then
  n = n + 1
  .Add tmp1, n
  Arr(n, 1) = n
  Arr(n, 2) = tmp1
  Arr(n, 3) = tmp2
  [COLOR=#ff0000][B]Arr(n, 4) = tmp3[/B][/COLOR]
Else
  [COLOR=#ff0000][B]Arr(.Item(tmp1), 4) = Arr(.Item(tmp1), 4) + tmp3[/B][/COLOR]
End If
Thành thế này:
Mã:
If Not .Exists(tmp1) Then
  n = n + 1
  .Add tmp1, n
  Arr(n, 1) = n
  Arr(n, 2) = tmp1
  Arr(n, 3) = tmp2
  [COLOR=#ff0000][B]Arr(n, 4) = "=SUMIF('Bang Du Toan'!R6C2:R1000C2,RC[-2],'Bang Du Toan'!R6C5:R1000C5)"[/B][/COLOR]
End If
Màu đỏ là những chổ thay đổi
(nói thật, tôi chẳng khoái cái vụ chèn công thức vào code này tí nào....)
 
Upvote 0
Câu này chưa hỏi tại đây, nên trả lời (ẹc ẹc)

(Hic, vụ này mà làm theo Cò già, nhấn F8 kết hợp với Locals Windows cũng thấy m thay đổi, mà không làm)

Bây giờ thì em đã hiểu và làm được rồi.
----------------------

Bạn muốn SUMIF hay bất cứ công thức gì thì cứ việc viết vào
Riêng Dictionary nó chỉ có 1 nhiệm vụ duy nhất là phát hiện dữ liệu trùng hay không mà thôi
Vì thế, nếu bạn để ý trong code tôi viết sẽ thấy rằng:
- Dictionary dùng để phát hiện sự tồn tại của 1 phần từ (phương thức Exists)
- Nếu chưa tồn tại, ta Add vào (phương thức Add)
- Nếu có tồn tại, ta làm cái gì khác tùy ý (code trong trên thì khi phát hiện tồn tại, tôi cộng dồn)
- Vậy Dictionary trong code chỉ là "món" phụ ---> Mọi dữ liệu đều được cho vào biến Arr (khi các điều kiện đã thỏa)
Ngoài ra xin nói thêm:
- Nếu đã dùng code thì tuyệt đối không nên có bất cứ công thức nào (chẳng lẽ bạn không tin độ chính xác của code?)
- Nếu dùng đến công thức, thôi thì ta làm bằng tay cho khỏe (Advanced Filter kết hợp SUMIF chẳng hạn)
- Với dữ liệu sau khi xuất ra mà cở vài ngàn dòng thì công thức sẽ làm chậm bảng tính
===> Vài góp ý nhỏ, bạn tự quyết định đi.. nhưng xin nhớ rằng: không nên dùng lộn xộn code + công thức

Chắc chắn Code dùng là chính xác 100%, ví dụ này em hỏi chủ yếu để em nghiên cứu thuật toán là chủ yếu; em đang cần hiểu, giải quyết những cái đơn giản trước đã (giai đoạn này em thử nghịch lung tung để tìm hiểu, biết càng nhiều càng tốt thày ah).

Cảm ơn các thày và mọi người đã giúp đỡ em rất nhiều, những độc chiêu của các thày em sẽ nghiên cứu sau khi em làm thuần thục những vấn đề đơn giản nhất đã (đúng như thày đoán em đang cần học For...next...tức những bài toán rõ ràng về mặt câu lệnh, em sẽ dễ dàng nắm bắt đầu tiên hơn).

Khổ cho em, Sếp lúc nào cũng ngồi bên cạnh, tuy không biết nhiều về Excel nhưng rất hay chỉ đạo, thích kết quả nhanh nhưng đòi hỏi sếp phải kiểm tra được (qua mấy hàm thông dụng Sum, sumif...cỡ hàm Vlookup không cho dùng vì không sếp không quản lý được). Nếu em làm Code ra số ngay có khi lại bảo em làm thế chắc gì tin được (không có cơ sở kiểm tra). Đây là lý do chính khiến em hay dùng lẫn lộn cả Code và công thức Excel thày ah.
 
Lần chỉnh sửa cuối:
Upvote 0
Làm sao kiểm tra nhanh biết được Code sai ở đâu?

Em giả sử Code có đoạn bị sai, thì đối với 1 đoạn rất dài thì mình có thủ thuật gì để phát hiện nhanh ra chỗ sai. VBA có hỗ trợ gì về việc này không ah?

Em không hiểu vệt màu nâu có đánh mũi tên ở hình dưới dùng để làm gì?

Caigivay.jpg
 
Lần chỉnh sửa cuối:
Upvote 0
Em giả sử Code có đoạn bị sai, thì đối với 1 đoạn rất dài thì mình có thủ thuật gì để phát hiện nhanh ra chỗ sai. VBA có hỗ trợ gì về việc này không ah?

Em không hiểu vệt màu nâu có đánh mũi tên ở hình dưới dùng để làm gì?

Caigivay.jpg

Theo tôi biết thì dòng màu nâu là do người dùng đánh dấu. Đánh dấu bằng cách click vào lề bên trái của dòng lệnh. Khi code có dòng đánh dấu, thì macro sẽ chạy cho đến dòng trên dòng đánh dấu đầu tiên sẽ dừng lại và hiện thông báo.
Cái này chắc dùng để test code.
 
Upvote 0
Web KT
Back
Top Bottom