Người mới học VBA, gặp khó khăn: Cú pháp, lý luận, thuật toán trong VBA thì vào đây cùng học!

Liên hệ QC

Cô Bé Dễ Thương

Thành viên thường trực
Tham gia
30/9/16
Bài viết
223
Được thích
48
Giới tính
Nữ
Các bạn cùng giống vấn đề như mình, xin hãy chỉ post bài tóm lược và trọng tâm nhất có thể (ngán nhất nhưng phải trọng tâm, xin cảm ơn)
Xin phép ban điều hành GPE cho cháu lập chủ đề này! Khi học VBA cháu thấy khó tìm và không tự nghĩ ra được cú pháp và lý luận dùng trong lập trình VBA.
Chăm đọc code cũng chỉ tìm hiểu được cú pháp và lý luận trong code nhưng đa phần là 50-50 không tìm thấy và nghĩ ra được. Vấn đề này quả là khó với người mới học code.
Mong chủ đề này được các bậc tiền bối chỉ dạy cho cháu(em) để có chút vốn để mày mò học code. Xin cảm ơn tất cả thật nhiều ạ!
(các bạn cùng giồng vấn đề như mình xin hãy post bài theo kiểu như mình ở dưới)
PHP:
Xin mở đầu bằng câu hỏi mà cháu(em) tìm kiếm mãi không thấy để bắt chước:
===================================================
Dim Rng1 as Range, Rng2 as Range, Rng4 as Range, Rng5 as Range
Dim rg as Range ,Rng as Range
===================================================
Cháu muốn gộp các bảng dữ liệu có cùng cấu trúc: Rng1, Rng2 , Rng3, Rng4, Rng5 thành 1 bảng. Mục đích để có thể dùng biến rg dùng vòng lặp For Each
duyệt từ Rng1 rồi đến Rng2 rồi đến Rng3 rồi đến Rng4 rồi đến Rng5. Hậu quả là phải viết ra 5 Sud để duyệt từng cái 1,nếu không gộp được các
Rng1,Rng2,Rng3,Rng4,Rng5 thành 1 bảng.
For Each rg In (Tất cả Rng1 và Rng2  và Rng3  và Rng4 và Rng5).Rows
................................................
Next rg
===================================================
Vậy cú pháp để cho biến rg duyệt "Tất cả các Rng1 và Rng2  và Rng3  và Rng4 và Rng5" trong một vòng lặp này là gì ạ?[CODE]
 
Lần chỉnh sửa cuối:
Được nhờ chú @ptm0412(mong chú phê vài dòng giúp cháu ạ) và các bác mới được đến đây ạ!
Bài dưới đây hiện có 3 cách giải với Dictionary:
1. Key tao ra ở từng bảng có giá trị duy nhất.Nghĩa là có 6 bảng thì có 6 Sub. Sau đó thêm một Sub nữa để ghép các cột kết quả lại với nhau. Đồng nghĩa với viêc dùng tới 7 Sub và 6 cột phụ
2. Gộp tất cả các bảng lại thành 1 bảng duy nhất. Sau đó mới tạo Key. Cách này phải dùng tới 2 Sub và trên Sheets phải thêm dữ liệu 1 bảng
3. Dùng chỉ 1 Sub và không phát sinh cột phụ.Cách 3 hiện chịu thua và cầu cứu sự giúp đỡ của các thầy!
(Hình minh họa cách 2 và code gộp bảng cách 2, và file đính kèm đã hoàn thành 2 cách)
View attachment 255205
Gôp bảng theo cách nhà quê, nông dân, chân đất mắt toét này của em thì xác định tay to hơn chân. Nhưng nom cũng được!
PHP:
Sub ghep_bang()
Dim Rng As Range, RArr()
Dim Rng1 As Range, Rng2 As Range, Rng3 As Range, _
Rng4 As Range, Rng5 As Range, Rng6 As Range
LR1 = Application.WorksheetFunction.CountA(Sheet3.Range("F:F")) - 2
lR2 = Application.WorksheetFunction.CountA(Sheet3.Range("j:j")) - 2
lR3 = Application.WorksheetFunction.CountA(Sheet3.Range("n:n")) - 2
lR4 = Application.WorksheetFunction.CountA(Sheet3.Range("r:r")) - 2
lR5 = Application.WorksheetFunction.CountA(Sheet3.Range("v:v")) - 2
lR6 = Application.WorksheetFunction.CountA(Sheet3.Range("z:z")) - 2

Set Rng1 = Sheet3.Range("F10:H" & LR1 + 9)
Set Rng2 = Sheet3.Range("j10:l" & lR2 + 9)
Set Rng3 = Sheet3.Range("n10:p" & lR3 + 9)
Set Rng4 = Sheet3.Range("r10:t" & lR4 + 9)
Set Rng5 = Sheet3.Range("v10:x" & lR5 + 9)
Set Rng6 = Sheet3.Range("z10:ab" & lR6 + 9)
For i = 1 To LR1 + lR2 + lR3 + lR4 + lR5 + lR6
Set Rng_TT = Sheet3.Range("ad" & i + 9)
Set Rng_Name = Sheet3.Range("ae" & i + 9)
Set Rng_Mon = Sheet3.Range("af" & i + 9)
Rng_TT.Value = i
    If (i <= LR1) Then
            Rng_Name.Value = Rng1.Cells(i, 2)
            Rng_Mon.Value = Rng1.Cells(i, 3)
    End If
    If (i > LR1 And i <= LR1 + lR2) Then
            Rng_Name.Value = Rng2.Cells(i - LR1, 2)
            Rng_Mon.Value = Rng2.Cells(i - LR1, 3)
    End If
    If (i > LR1 + lR2 And i <= LR1 + lR2 + lR3) Then
            Rng_Name.Value = Rng3.Cells(i - LR1 - lR2, 2)
            Rng_Mon.Value = Rng4.Cells(i - LR1 - lR2, 3)
    End If
    If (i > LR1 + lR2 + lR3 And i <= LR1 + lR2 + lR3 + lR4) Then
            Rng_Name.Value = Rng4.Cells(i - LR1 - lR2 - lR3, 2)
            Rng_Mon.Value = Rng4.Cells(i - LR1 - lR2 - lR3, 3)
    End If
    If (i > LR1 + lR2 + lR3 + lR4 And i <= LR1 + lR2 + lR3 + lR4 + lR5) Then
            Rng_Name.Value = Rng5.Cells(i - LR1 - lR2 - lR3 - lR4, 2)
            Rng_Mon.Value = Rng5.Cells(i - LR1 - lR2 - lR3 - lR4, 3)
    End If
    If (i > LR1 + lR2 + lR3 + lR4 + lR5 And i <= LR1 + lR2 + lR3 + lR4 + lR5 + lR6) Then
            Rng_Name.Value = Rng6.Cells(i - LR1 - lR2 - lR3 - lR4 - lR5, 2)
            Rng_Mon.Value = Rng6.Cells(i - LR1 - lR2 - lR3 - lR4 - lR5, 3)
    End If
Next i
End Sub
Hình như bạn ghiền Dic hay sao ấy chứ, Cách 3 của bạn là tập hợp lại tất cả các bảng chứ không phải loại trùng (vì tất nhiên dạy cấp khác nhau thì thầy cô có thể trùng tên nhưng chắc chắn phải là 2 người khác nhau - Ông A dạy cấp 1 khác ông A dạy cấp 2). Mà đã không loại trùng thì không nhất thiết phải dùng dic trong trường hợp này.
Vòng lặp for là đủ:
Mã:
Option Explicit
Sub Cach3()
Dim I As Long, J As Long, K As Long, Lr As Long
Dim U1 As Long, U2 As Long
Dim sArr(), dArr()
With Sheets("Cach3")
    Lr = .Range("F10:AB1000").Find("*", , xlValues, , xlByRows, xlPrevious).Row
    sArr = .Range("F10:AC" & Lr).Value
    U1 = UBound(sArr, 1): U2 = UBound(sArr, 2)
    ReDim dArr(1 To U1 * U2 / 4, 1 To 3)
    For I = 2 To U2 Step 4 ' cot
        For J = 1 To U1 'dong
            If sArr(J, I) <> "" Then
                    K = K + 1
                    dArr(K, 1) = K
                    dArr(K, 2) = sArr(J, I)
                    dArr(K, 3) = sArr(J, I + 1)
            End If
        Next
    Next
    .Range("B10").Resize(10000, UBound(dArr, 2)).ClearContents
    .Range("B10").Resize(K, UBound(dArr, 2)) = dArr
End With
End Sub
 
Upvote 0
Hình như bạn ghiền Dic hay sao ấy chứ, Cách 3 của bạn là tập hợp lại tất cả các bảng chứ không phải loại trùng (vì tất nhiên dạy cấp khác nhau thì thầy cô có thể trùng tên nhưng chắc chắn phải là 2 người khác nhau - Ông A dạy cấp 1 khác ông A dạy cấp 2). Mà đã không loại trùng thì không nhất thiết phải dùng dic trong trường hợp này.
Vòng lặp for là đủ
Dạ. Em nghiện VBA rồi ạ!
Cách của bác có kiến thức mảng liên quan đến bài đang làm, em thích lắm! Ứng dụng được nhiều!
PHP:
With Sheets("Cach3")
    Lr = .Range("F10:AB1000").Find("*", , xlValues, , xlByRows, xlPrevious).Row
    sArr = .Range("F10:AC" & Lr).Value
    U1 = UBound(sArr, 1): U2 = UBound(sArr, 2)
    ReDim dArr(1 To U1 * U2 / 4, 1 To 3) 'Không biêt sao bác lại chia cho 4 chỗ này, xin chỉ giúp ạ?
Nhưng hiện với Dict em còn vướng chỗ cách 3 bài #17,Bác thạo Dict nếu có thời gian bác thử xem sao?
Tài nguyên diễn đàn nhiều quá! Em không tìm thấy chủ đề tương tự cách 3 bài #17 để bắt chước. Còn nghĩ ra thì chưa đủ khả năng ạ
 
Lần chỉnh sửa cuối:
Upvote 0
A. Không biêt sao bác lại chia cho 4 chỗ này, xin chỉ giúp ạ?
B. Cách 2. Gộp tất cả các bảng lại thành 1 bảng duy nhất. Sau đó mới tạo Key. Cách này phải dùng tới 2 Sub và trên Sheets phải thêm dữ liệu 1 bảng
C. Cách 3 ...

A. Code bài 21 là cách không chính thống lắm (hơi tà đạo và lợi dụng cấu trúc dữ liệu, không tổng quát):
- Tìm dòng cuối bằng cách tìm * ByRow: Nếu dữ liệu rời rạc và/ khác sheet thì không dùng được
- Chia 4 vì cứ mỗi bảng chiếm 4 cột, tổng cột x tổng dòng chia 4 = số dòng 1 cột (và là số dòng lớn nhất xác định được khi Find. Nếu dữ liệu rời rạc thì cũng không làm được
Tốt nhất người mới học đừng làm kiểu không chính thống.
B. Cách 2: Ý tưởng thì hay nhưng làm thì dở.
1. Sub ghep_bang
- Hạn chế dùng Application.WorsheetFunction nếu có cách khác thuần VBA. Ngay cả dùng hàm Excel trên sheet mà CountA nguyên cột là đã đáng đánh đòn rồi, lại còn trừ 2, làm sao biết chắc là trừ 2 khi bắt đầu từ dòng 10? 9 dòng trên ai bảo đảm là luôn luôn chỉ có 2 ô chứa dữ liệu? Tại sao việc đơn giản là end(xlUp).Row thì lại không làm?
- Định nghĩa Rng_TT làm gì rồi không xài?
- Tại sao không dùng mảng 3 cột hoặc 2 cột, mà lại dùng Range và 3 Range? Nếu dùng mảng thì thậm chí vòng lặp tạo Dict không cần gán xuống sheet và đọc trực tiếp trên mảng.
- Khi đã có 5 khoảng đếm và dùng If để tách ra các khoảng khác nhau, thì phải biết cấu trúc If có tính năng loại trừ dần dần, không ai làm 5 cái If và If kiểu a >=X2 and a <=X3 cả. Cách đúng là:
Mã:
If a <X1 Then
   ..
ElseIf a< X2 Then
  ...
ElseIf a < X3 Then
  ...
Else
   ...
End If
Hoặc dùng cấu trúc Select Case
Mã:
Select Case a
Case Is < X1
  ..
Case Is < X2
...
Case Else
End Select
2. Sub dict_thayday()
- Dữ liệu đã duy nhất chưa mà không đặt điều kiện, cứ thế add tất tần tật vào Dict? Nếu 1 thầy dạy 2 môn cho nhiều lớp thì sao? Như lão chết tiệt dạy cho 2 con nhãi cháu gọi bằng chú môn VBA, dạy 3 anh chàng khác môn vẽ biểu đồ, dạy 15 anh chị nọ về Power query, ...
- item có mỗi một phần tử mà cũng xài Array(Sample(I, 3)) là sao? Chưa nói việc cứ đặt tên biến là Sample! Sample là mẫu để thực hiện cái gì khác mà? Cơ bản đặt tên biến mà không biết nữa!
- Nói về SData: Nếu tên thầy có trong Dict thì điền môn dạy (trả lương), còn thầy không có môn dạy thì bỏ trống không trả lương à? Rồi nếu thầy có môn dạy (có trong Dict) mà không có trong danh sách cột B cũng mặc kệ? Đây là do đề bài không rõ ràng, dữ liệu không rõ ràng, yê ucầu không rõ ràng
C. Cách 3
Thôi đừng nói cách 3 cho mệt. Ở trên đã "may quá" với Union ở bài 3, dạ vâng với Array(rng1, rng2, ...) ở bài 15 mà không thử làm theo cái nào.

TB
Việc lớn nhất:
Tự ra cái đề để tự làm thì cũng phải đặt cái đề cho hợp lý,
- yêu cầu ở ngành nghề nào, của ông bộ trưởng nào đòi mà có 1 danh sách giáo viên chưa biết dạy môn gì phải lập trình để điền môn?
- Tên có thể trùng bất cứ ngành nghề nào, luôn luôn phải có mã. Đặt đề bài thì phải từ dữ liệu hợp lý (có thực) và đúng chuẩn (có mã), và yêu cầu ra báo cáo không phải là 1 báo cáo ngu ngơ cho 1 ông sếp ngu ngơ.
 
Upvote 0
Union các Range có cột bằng nhau, nhưng khác số dòng thì có Union đc không. Vì cháu dùng Union trường hợp này là để tạo ra vùng có dữ liệu không trùng lặp (Dictionary). Sau đó mới tạo Key cho Dict nhưng Union rồi mà nó lại hiểu có 1 Range đầu tiên.
Nhiều người, và cả bạn, có thói quen rất xấu là chỉ dùng ảnh và nước bọt nên người khác muốn giúp nhưng không hiểu ý. Nếu đính kèm code thì dễ rồi. Chỉ cần nhìn vào code ai cũng thấy code làm gì rồi.

Do bạn không có code nên tôi đoán mò là vấn đề ở chỗ là bạn chưa hiểu rõ đối tượng RANGE.

Thường thì bạn chọn một vùng hình chữ nhật có ít nhất 1 ô (cell). Nhiều khi bạn hiện InputBox để người ta có thể chọn nhiều vùng TÁCH RỜI NHAU như AD10:AF38, B10: D19. Như vậy Range trong trường hợp tổng quát là một tập hợp 1 hoặc nhiều vùng LIỀN HÌNH CHỮ NHẬT. Mỗi vùng như thế có thể có 1 hoặc nhiều cell và đeo huy hiệu (được gọi là) AREA. Trong vd. ở trên thì nếu
Mã:
Set Sample = Union(Sheet3.Range("AD10:AF38"), Sheet3.Range("B10:D19"))
thì Sample có 2 AREA. AREA 1 là Sheet3.Range("AD10:AF38") và có 29 dòng, AREA 2 là Sheet3.Range("B10: D19") có 10 dòng. Trong trường hợp như thế thì vd.
Mã:
For i = 1 To Sample.Rows.Count
...
Next i
code chỉ duyệt AREA 1 là Sheet3.Range("AD10:AF38"). Tôi đoán mò là bạn gặp vấn đề do duyệt Range kiểu này.

Trong trường hợp tổng quát thì tùy vào nhu cầu mà có 2 cách duyệt vùng
1. Nhu cầu cần duyệt từng dòng của Range.
Phải duyệt từng AREA và trong mỗi AREA (là vùng liền hình chữ nhật) duyệt từng dòng.
Mã:
Dim i As Long, hichic As Range, vung As Range

Set hichic = Union(Sheet3.Range("AD10:AF15"), Sheet3.Range("B10:D19"))
For Each vung In hichic.Areas
    Debug.Print vung.Address
    For i = 1 To vung.Rows.Count
        Debug.Print vung(i, 2)
    Next i
Next vung

hoặc

Dim i As Long, a As Long, hichic As Range

Set hichic = Union(Sheet3.Range("AD10:AF15"), Sheet3.Range("B10:D19"))
For a = 1 To hichic.Areas.Count
    With hichic.Areas(a)
        Debug.Print .Address
        For i = 1 To .Rows.Count
            Debug.Print .Cells(i, 2)
        Next i
    End With
Next a

2. Nhu cầu cần duyệt từng ô (cell).
Thì duyệt trong 1 vòng lặp vd.
Mã:
Set hichic = Union(Sheet3.Range("AD10:AF15"), Sheet3.Range("B10:D19"))
For Each cell_ In hichic
    Debug.Print cell_.Address
Next

Trong trường hợp tổng quát số AREA của đối tượng hichic là hichic.Areas.Count. AREA 1, tức Sheet3.Range("AD10:AF38"), là hichic.Areas(1), AREA 2 là hichic.Areas(2)
 
Lần chỉnh sửa cuối:
Upvote 0
Mình bảo này, chỗ nào bạn cần chèn code khi post bài lên GPE bạn làm như sau:
CODE=php
Nội dung gì cũng được
/CODE
Nhớ thêm dấu [ ] bọc lấy 2 từ màu đỏ là được nhé
Làm thế các thầy dễ nhìn hơn. Ở đây comment với mình cho vui!
(Hóng cách 3 bài #17)
Vâng, lần sau mình sẽ chú ý hơn ạ ^^~
Bài đã được tự động gộp:

......................................................................................................
Xin thầy hướng dẫn cách sửa cho đúng ạ. Em mới học, thật sự là ko biết gì ạ huhu.... Mong thầy thông cảm cho em kiến thức nông cạn :please:
 
Upvote 0
C. Cách 3
Thôi đừng nói cách 3 cho mệt. Ở trên đã "may quá" với Union ở bài 3, dạ vâng với Array(rng1, rng2, ...) ở bài 15 mà không thử làm theo cái nào.
Cách 4:
- Toàn bộ dùng mảng
Bước 1: Do dữ liệu trên cùng sheet nên tạo 1 mảng là các cột đầu của các bảng dữ liệu: ColumnArr = Array(6, 10, 14, 18, 24, 30)
Bước 2: Dùng vòng lặp 6 vòng, mỗi vòng:
- Lấy dữ liệu 1 khối vào mảng
- Duyệt dữ liệu mảng, add vào Dict, tính SL bán (dữ liệu mới cho chuẩn, không làm dữ liệu và báo cáo ngu ngơ)
Bước 3:
Duyệt dữ liệu cột B: mặt hàng nào có bán thì điền tổng số lượng bán

PHP:
Sub DictExercise()
Dim MaxRw As Long, DataRw As Long, i As Long
Dim DataStore(), ColumnArr, sKey As String
Dim Dict, SArr(), RArr()
Set Dict = CreateObject("Scripting.Dictionary")
ColumnArr = Array(6, 10, 14, 18, 22, 26)
With Sheet3
    For col = 0 To 5
        DataRw = .Cells(1000, ColumnArr(col)).End(xlUp).Row
        DataStore = .Range(.Cells(10, ColumnArr(col)), _
        .Cells(DataRw, ColumnArr(col))).Resize(, 3).Value
        For i = 1 To UBound(DataStore, 1)
            sKey = DataStore(i, 1)
            If Not Dict.exists(sKey) Then
                Dict.Add sKey, DataStore(i, 3)
            Else
                Dict.Item(sKey) = Dict.Item(sKey) + DataStore(i, 3)
            End If
        Next
    Next
    SArr = .Range(.Cells(10, 2), .Cells(1000, 2).End(xlUp)).Value
    ReDim RArr(1 To UBound(SArr, 1), 1 To 1)
    For i = 1 To UBound(SArr, 1)
        If Dict.exists(SArr(i, 1)) Then
            RArr(i, 1) = Dict.Item(SArr(i, 1))
        Else
            RArr(i, 1) = 0
        End If
    Next
    .Range("D10:D1000").ClearContents
    .Range("D10").Resize(UBound(SArr, 1), 1) = RArr
End With
End Sub

1615437249774.png
 

File đính kèm

  • DictExercise.xlsm
    22.9 KB · Đọc: 10
Lần chỉnh sửa cuối:
Upvote 0
Nhiều người, và cả bạn, có thói quen rất xấu là chỉ dùng ảnh và nước bọt nên người khác muốn giúp nhưng không hiểu ý. .................
Do bạn không có code nên tôi đoán mò là vấn đề ở chỗ là bạn chưa hiểu rõ đối tượng RANGE....................

Dim i As Long, a As Long, hichic As Range
Set hichic = Union(Sheet3.Range("AD10:AF15"), Sheet3.Range("B10:D19"))
For a = 1 To hichic.Areas.Count
With hichic.Areas(a)
Debug.Print .Address
For i = 1 To .Rows.Count
Debug.Print .Cells(i, 2)
Next i
End With
Next a
Code cách 3, bài 17: Dùng 1 Sub và không phát sinh cột phụ giải bằng Dictionary, dựa theo hướng dẫn của bác @batman1 ở bài #24
PHP:
Sub dict_thayday_dientenmonhoc_c3_bac_batman1()
Dim Dict, SData As Range
Dim sKey As String, DataRows As Long
Dim Rng1 As Range, Rng2 As Range, Rng3 As Range, Rng4 As Range, _
Rng5 As Range, Rng6 As Range, Sample As Range
Set Rng1 = Sheet3.Range("F10:H12")
Set Rng2 = Sheet3.Range("j10:l14")
Set Rng3 = Sheet3.Range("n10:p13")
Set Rng4 = Sheet3.Range("r10:t14")
Set Rng5 = Sheet3.Range("v10:x16")
Set Rng6 = Sheet3.Range("z10:ab14")
Set Sample = Union(Rng1, Rng2, Rng3, Rng3, Rng4, Rng5, Rng5, Rng6)
Set Dict = CreateObject("Scripting.Dictionary")
'=====================================================
For a = 1 To Sample.Areas.Count
    With Sample.Areas(a)
        For i = 1 To Sample.Areas(a).Rows.Count
            sKey = Sample.Areas(a).Cells(i, 2).Value
            Dict.Add sKey, Array(Sample.Areas(a).Cells(i, 3))
        Next i
    End With
Next a
'Để ra được đoạn này thật không dễ chút nào. Tưởng ít nhưng đọc thấy mồ
'======================================================
Set SData = Sheet1.Range("b10:d38")
DataRows = SData.Rows.Count
ReDim RArr(1 To DataRows, 1 To 1)
For i = 1 To DataRows
    sKey = SData.Cells(i, 2).Value
    If Dict.exists(sKey) Then
        RArr(i, 1) = Dict.Item(sKey)(0)
    End If
Next
Sheet1.Range("d10").Resize(UBound(RArr, 1), 1).Value = RArr
End Sub
Sáng sớm nhận được 2 bài #23 và bài #24 của chú Mỹ và bác @batman1. Kế từ lúc "thả tim" đến giờ mới làm cho code nó chạy được nên mới có bài để trả. Cũng là cách cảm ơn sự chỉ dạy và mong cầu sự chỉ dạy của các chú các bác.
Bài #26 của chú Mỹ, chú đã mất công sức nhiều quá. Cháu cảm ơn chú đã hết lòng như vậy! Phần Array kiến thức thì cao cấp, còn Dictionary những gì thấy vướng cháu đã cơ bản. Giờ có bài mới cháu sẽ học sang Array và nghiền lại bài #26 vào một buổi khác.
Cảm ơn Chú Mỹ, Bác @batman1, cảm ơn tất cả thật nhiều!
 
Lần chỉnh sửa cuối:
Upvote 0
Code cách 3, bài 17: Dùng 1 Sub và không phát sinh cột phụ giải bằng Dictionary, dựa theo hướng dẫn của bác @batman1 ở bài #24
PHP:
            Dict.Add sKey, Array(Sample.Areas(a).Cells(i, 3)) '(1)'
Sao vẫn cứ sử dụng Array cho mỗi 1 phần tử vậy?
Và dữ liệu không trùng thì đâu có cần dùng Dict? Nếu dùng Dict thì phải điều kiện Exist như bài mắng 23 chứ
Thử lấy code này chạy cho file ở bài 26 xem
 
Upvote 0
Sao vẫn cứ sử dụng Array cho mỗi 1 phần tử vậy?
Và dữ liệu không trùng thì đâu có cần dùng Dict? Nếu dùng Dict thì phải điều kiện Exist như bài mắng 23 chứ
Thử lấy code này chạy cho file ở bài 26 xem
Bài #17 cháu cố tình lập dữ liệu để sử dụng Dictionary và tất cả vướng mắc bài #17 đã được xử lý được với bài # 24 của bác @batman1
Bài #26 vẫn là Dict nhưng cơ bản muốn làm được lại là Array. Nên tất cả giờ phải là Array(nhìn Array cháu thấy nó cứ cao cấp thế này í), cháu lại hành chú mất thôi.
 
Upvote 0
Set Sample = Union(Rng1, Rng2, Rng3, Rng3, Rng4, Rng5, Rng5, Rng6)
Ôm một mớ vào nên càng rắc rối, khó hiểu, khó làm.

Thay vì tiếp cận theo cách đó thì mình đi học lý thuyết đã.
1/ Tầm vực biến
2/ Cách tạo và dùng Sub-Function con, ByVal/ ByRef...

Rồi bài trên viết một Sub/Function con áp dụng cho 1 Range ngon lành. Sau đó chỉ cần gọi nó cho danh sách Range(s) là được.
 
Upvote 0
Code cách 3, bài 17: Dùng 1 Sub và không phát sinh cột phụ giải bằng Dictionary, dựa theo hướng dẫn của bác @batman1 ở bài #24
PHP:
Set Rng1 = Sheet3.Range("F10:H12")
Set Rng2 = Sheet3.Range("j10:l14")
Set Rng3 = Sheet3.Range("n10:p13")
Set Rng4 = Sheet3.Range("r10:t14")
Set Rng5 = Sheet3.Range("v10:x16")
Set Rng6 = Sheet3.Range("z10:ab14")
Set Sample = Union(Rng1, Rng2, Rng3, Rng3, Rng4, Rng5, Rng5, Rng6)
Nếu các vùng là hằng số như vầy thì người ta không viết như vậy. Mà chỉ cần viết 1 dòng
Mã:
Set Sample = Sheet3.Range("F10:H12,j10:l14,n10:p13,r10:t14,v10:x16,z10:ab14")
Nếu không nắm vững những kiến thức cơ bản có thể bạn sẽ phải viết hàng chục dòng code để xử lý vấn đề mà lẽ ra chỉ viết 2, 3 dòng là xong.
 
Upvote 0
Nếu các vùng là hằng số như vầy thì người ta không viết như vậy. Mà chỉ cần viết 1 dòng
Mã:
Set Sample = Sheet3.Range("F10:H12,j10:l14,n10:p13,r10:t14,v10:x16,z10:ab14")
Nếu không nắm vững những kiến thức cơ bản có thể bạn sẽ phải viết hàng chục dòng code để xử lý vấn đề mà lẽ ra chỉ viết 2, 3 dòng là xong.
ôi vậy ạ. hay quá! Cảm ơn bác đã chỉ cho ạ!
hoặc các biểu thức:
n = n1 + n2
m = m1 + m2
thì thành:
n = n1 + n2: m = m1 + m2
Cùng 1 dòng phải không ạ
Bài đã được tự động gộp:

Ôm một mớ vào nên càng rắc rối, khó hiểu, khó làm.
Thay vì tiếp cận theo cách đó thì mình đi học lý thuyết đã.
1/ Tầm vực biến
2/ Cách tạo và dùng Sub-Function con, ByVal/ ByRef...
Rồi bài trên viết một Sub/Function con áp dụng cho 1 Range ngon lành. Sau đó chỉ cần gọi nó cho danh sách Range(s) là được.
Do nóng vội muốn giải quyết xong chỗ còn vướng của Dictionary cháu gặp phải. Nên còn thiếu nhiều lắm ạ!
Cháu thây dễ nhớ và thấm hơn.Nếu học bài cụ thể. Sau đó vướng đến đâu bù lý thuyết đến đấy. Hơi trái khoái vây, nhưng lượm được nhiều lắm bác ạ. Đọc đến đâu nhớ luôn đến đấy!
Cụ thể như bài #24 của bác @batman1 thì rất dễ học và ứng dụng được luôn phải không ạ!
Mong bác giúp cho cháu ít vốn trong quá trình học VBA ạ. Cảm ơn bác nhiều ạ!
 
Lần chỉnh sửa cuối:
Upvote 0
Code cách 3, bài 17: Dùng 1 Sub và không phát sinh cột phụ giải bằng Dictionary, dựa theo hướng dẫn của bác @batman1 ở bài #24
Tôi không bàn về thuật toán, vì mỗi vấn đề có thể giải quyết theo nhiều cách khác nhau. Tôi chỉ bàn về cú pháp.

Bạn có
Mã:
For a = 1 To Sample.Areas.Count
    With Sample.Areas(a)
        For i = 1 To Sample.Areas(a).Rows.Count
            sKey = Sample.Areas(a).Cells(i, 2).Value
            Dict.Add sKey, Array(Sample.Areas(a).Cells(i, 3))
        Next i
    End With
Next a

Hoặc là bạn dùng WITH
Mã:
For a = 1 To Sample.Areas.Count
    With Sample.Areas(a)
        For i = 1 To .Rows.Count
            sKey = .Cells(i, 2).Value
            Dict.Add sKey, .Cells(i, 3).Value
        Next i
    End With
Next a

hoặc không dùng WITH
Mã:
For a = 1 To Sample.Areas.Count
        For i = 1 To Sample.Areas(a).Rows.Count
            sKey = Sample.Areas(a).Cells(i, 2).Value
            Dict.Add sKey, Sample.Areas(a).Cells(i, 3).Value
        Next i
Next a

chứ không ai viết như bạn.

Ngoài ra bạn nên thêm vào từ điển 1 GIÁ TRỊ với tư cách ITEM chứ sao lại thêm 1 MẢNG với chỉ 1 GIÁ TRỊ với tư cách ITEM? Tại sao lại làm phức tạp vấn đề vậy?
 
Upvote 0
Tôi không bàn về thuật toán, vì mỗi vấn đề có thể giải quyết theo nhiều cách khác nhau. Tôi chỉ bàn về cú pháp.

Bạn có
Mã:
For a = 1 To Sample.Areas.Count
    With Sample.Areas(a)
        For i = 1 To Sample.Areas(a).Rows.Count
            sKey = Sample.Areas(a).Cells(i, 2).Value
            Dict.Add sKey, Array(Sample.Areas(a).Cells(i, 3))
        Next i
    End With
Next a

Hoặc là bạn dùng WITH
Mã:
For a = 1 To Sample.Areas.Count
    With Sample.Areas(a)
        For i = 1 To .Rows.Count
            sKey = .Cells(i, 2).Value
            Dict.Add sKey, .Cells(i, 3).Value
        Next i
    End With
Next a

hoặc không dùng WITH
Mã:
For a = 1 To Sample.Areas.Count
        For i = 1 To Sample.Areas(a).Rows.Count
            sKey = Sample.Areas(a).Cells(i, 2).Value
            Dict.Add sKey, Sample.Areas(a).Cells(i, 3).Value
        Next i
Next a

chứ không ai viết như bạn.

Ngoài ra bạn nên thêm vào từ điển 1 GIÁ TRỊ với tư cách ITEM chứ sao lại thêm 1 MẢNG với chỉ 1 GIÁ TRỊ với tư cách ITEM? Tại sao lại làm phức tạp vấn đề vậy?
- With và End With là "xét bởi", xét bởi cái cái gì đó thì trong cái đang xét thì viết tắt đc, cháu hiểu nôm na là vậy.
- gán item là mảng 1 giá trị. Do trên cháu dùng code cũ đang xét 1 bảng để sửa lại cho nhanh.Thấy bỏ mảng lại lỗi. Để mảng lại chạy được. Hoặc có đến 2 lỗi lúc đó nên bỏ Array đi thấy lỗi lại hiểu nó là lỗi do không để giá trị là Array.
Đọc và thử đi thử lại nên đầu óc lu bu quá. Làm theo hướng dẫn bài #24 của bác mong cho code nó chạy được là đc.
Sau cháu chỉnh chu hơn ạ. Cháu cảm ơn bác!
 
Lần chỉnh sửa cuối:
Upvote 0
- Do bài #17 cháu cố tình tạo ra dữ liệu để dùng Dictionary,
- Bài #26 dùng Dictonary để giải nhưng muốn giải được lại là Array.
Cháu nghiền lại bài #26 ạ!
- Cố tình tạo thì phải có trùng, thì Dict mới thấy tác dụng loại trùng chứ?
- Ai bảo muốn giải lại là Array? Muốn các khối dữ liệu là Range vẫn được chứ? Chỉ có Array(6, 10, 14, 18, 22, 26) là mảng thôi.
PHP:
    For col = 0 To 5
        DataRw = .Cells(1000, ColumnArr(col)).End(xlUp).Row
        Set DataStore = .Range(.Cells(10, ColumnArr(col)), _
        .Cells(DataRw, ColumnArr(col))).Resize(, 3)
        For i = 1 To DataStore.Rows.Count
            sKey = DataStore(i, 1)
            If Not Dict.exists(sKey) Then
                Dict.Add sKey, DataStore(i, 3)
            Else
                Dict.Item(sKey) = Dict.Item(sKey) + DataStore(i, 3)
            End If
        Next
    Next
Nghiền lại bài 26 thì tải lại file, lúc trưa mảng ColumnArr sai 2 số cuối
 
Upvote 0
- With và End With là "xét bởi", xét bởi cái cái gì đó thì trong cái đang xét thì viết tắt đc, cháu hiểu nôm na là vậy.
- gán item là mảng 1 giá trị. Do trên cháu dùng code cũ đang xét 1 bảng để sửa lại cho nhanh.Thấy bỏ mảng lại lỗi. Để mảng lại chạy được. Hoặc có đến 2 lỗi lúc đó nên bỏ Array đi thấy lỗi lại hiểu nó là lỗi do không để giá trị là Array.
Đọc và thử đi thử lại nên đầu óc lu bu quá. Làm theo hướng dẫn bài #24 của bác mong cho code nó chạy được là đc.
Sau cháu chỉnh chu hơn ạ. Cháu cảm ơn bác!
Nếu là mình thấy lỗi mình sẽ tìm hiểu đó là lỗi gì học vậy mới mau tiến bộ. Chứ hỏi cú pháp thì học căn bản, lý luận, thuật toán là do bạn đụng nhiêu, làm nhiều thì có nhiều kinh nghiệm thôi.
Theo mình nghĩ là vậy, còn đối với mình vba mình chẳng biết ất giáp gì đâu nha kkmm
 
Upvote 0
Nghiền lại bài 26 thì tải lại file, lúc trưa mảng ColumnArr sai 2 số cuối
Dạ. Array và Dictionary thấy như hình với bóng ấy chú ạ. Trc giờ toàn bắt chiếc chứ thực ra "tròn mắt" là chính hihi. Dồn cho anh Arr này nữa mới khá lên được ạ.
Nếu là mình thấy lỗi mình sẽ tìm hiểu đó là lỗi gì học vậy mới mau tiến bộ. Chứ hỏi cú pháp thì học căn bản, lý luận, thuật toán là do bạn đụng nhiêu, làm nhiều thì có nhiều kinh nghiệm thôi.
Theo mình nghĩ là vậy, còn đối với mình vba mình chẳng biết ất giáp gì đâu nha kkmm
Vâng. Nhưng em toàn chết cái cú pháp lỗi từ đó. Khó diễn tả thành lời, nôm na là như là bài #24 của bác @batman1 ấy, nghĩ mà không nói phát ra tiếng đc ấy. Chỉ nhiêu đó mà mất mờ chân chậm. Em hay chết kiểu như thế. Những cái như vậy không thể tìm cơ bản mà có được.
Chắc anh làm vùng ở GPE lâu rồi.
 
Lần chỉnh sửa cuối:
Upvote 0
Dạ.

Vâng. Nhưng em toàn chết cái cú pháp lỗi từ đó. Khó diễn tả thành lời, nôm na là như là bài #24 của bác @batman1 ấy, nghĩ mà không nói phát ra tiếng đc ấy. Chỉ nhiêu đó mà mất mờ chân chậm. Em hay chết kiểu như thế. Những cái như vậy không thể tìm cơ bản mà có được.
Chắc anh làm vùng ở GPE lâu rồi. Nick mới thôi phải không ạ?
Nếu vậy theo tôi nghĩ bạn chưa nắm những cái cơ bản. Tôi thì mới tham gia DĐ cũng chẳng biết nhiều vba nhưng đọc bài cũng lờ mờ hiểu chúc ít. Trong đây tôi thấy nhiều ngưởi giỏi quá nên bạn theo từ từ thôi, tôi cũng đang học đây
 
Upvote 0
Trong đây tôi thấy nhiều ngưởi giỏi quá nên bạn theo từ từ thôi, tôi cũng đang học đây
Hiện em chưa có cách nào học cơ bản để dễ nhớ cả, quy ra bài tập dạng như kiểu gặp núi xẻ núi, gặp sông thì ngăn sông mà gặp rừng thì... hihi. Vậy ở đây chỗ nào mà "không nói nên lời" thì post vào đây cho nó vui. Bác đúng là người làm cho người khác bớt say, ở đây post bài với em nhé.
 
Lần chỉnh sửa cuối:
Upvote 0
Hiện em chưa có cách nào học cơ bản để nhớ cả, quy ra bài tập dạng như kiểu gặp núi xẻ núi mà gặp rừng thì... hihi. Vậy ở đây chỗ nào mà "không nói nên lời" thì post vào đây cho nó vui. Bác đúng là người làm cho người khác bớt say, ở đây post bài với em nhé.
Kkk tôi cũng muốn cày ít điểm nhưng dạo quanh diễn đàng thấy nhiều thứ mới mẻ quá, cám ơn bạn tôi vẫn theo dõi top của bạn để học đây
 
Upvote 0
Web KT

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

Back
Top Bottom