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:
bài của mình nó không có nằm 3 cột liền nhau như vậy đâu, có sheet có mã - họ - tên - số lượng bán, có sheet có mã - họ - tên đệm - tên - đơn vị tính - số lượng bán, có sheet có số lượng bán họ - tên - mã - đệm - tên
nếu theo như vi dụ đó thì chắc làm AdvanFileter ra sheet tmp cũng được khỏi cần dic
 
Upvote 0
bài của mình nó không có nằm 3 cột liền nhau như vậy đâu, có sheet có mã - họ - tên - số lượng bán, có sheet có mã - họ - tên đệm - tên - đơn vị tính - số lượng bán, có sheet có số lượng bán họ - tên - mã - đệm - tên
nếu theo như vi dụ đó thì chắc làm AdvanFileter ra sheet tmp cũng được khỏi cần dic
Code bài 26 chế lại chạy được hết
 
Upvote 0
Không phải mất mà là bị cố tình xoá. Tự viết code mới gọi là bài tập, ở đâu có sẵn mãi?
Cháu làm theo dạng: các bảng khác Sheets không trùng chỉ số dòng và cột của ô bắt đầu, dòng bắt đầu dữ liệu của bảng.Loay hoay từ chiều đến giờ không chạy được code chú ạ!
- Thêm 1 mảng RowArr = Array(4, 9, 17, 21, 4, 18)
- Thêm 2 vòng For để duyệt sheet và duyệt chỉ số ô bắt đầu dữ liệu của bảng
Khả năng duyệt sai cú pháp phải không chú?
PHP:
Sub DictExercise5()
Dim MaxRw As Long, DataRw As Long, i As Long
Dim ColumnArr, sKey As String, RowArr
Dim Dict, SArr(), RArr()
Set Dict = CreateObject("Scripting.Dictionary")
ColumnArr = Array(2, 3, 1, 4, 18, 2)
RowArr = Array(4, 9, 17, 21, 4, 18)
For b = 2 To ThisWorkbook.Worksheets.Count
    For col = 0 To 5
        For dong = 0 To 5
            DataRw = ThisWorkbook.Worksheets(b).Cells(1000, ColumnArr(col)).End(xlUp).Row
            DataStore = ThisWorkbook.Worksheets(b).Range(ThisWorkbook.Worksheets(b).Cells(RowArr(dong), ColumnArr(col)), _
            ThisWorkbook.Worksheets(b).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
                    [COLOR=rgb(209, 72, 65)]Dict.Item(sKey) = Dict.Item(sKey) + DataStore(i, 3) 'dòng này báo lỗi: Type mismatch[/COLOR]
                End If
            Next i
        Next dong
    Next col
Next b
    SArr = Sheets("Episode5").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
    Sheets("Episode5").Range("D10:D1000").ClearContents
    Sheets("Episode5").Range("D10").Resize(UBound(SArr, 1), 1) = RArr
End Sub
 

File đính kèm

  • DictExercise5.xlsm
    31.5 KB · Đọc: 6
Lần chỉnh sửa cuối:
Upvote 0
Cháu làm theo dạng: các bảng khác Sheets không trùng chỉ số dòng và cột của ô bắt đầu, dòng bắt đầu dữ liệu của bảng.Loay hoay từ chiều đến giờ không chạy được code chú ạ!
- Thêm 1 mảng RowArr = Array(4, 9, 17, 21, 4, 18)
- Thêm 2 vòng For để duyệt sheet và duyệt chỉ số ô bắt đầu dữ liệu của bảng
Khả năng duyệt sai cú pháp phải không chú?
PHP:
Sub DictExercise5()
Dim MaxRw As Long, DataRw As Long, i As Long
Dim ColumnArr, sKey As String, RowArr
Dim Dict, SArr(), RArr()
Set Dict = CreateObject("Scripting.Dictionary")
ColumnArr = Array(2, 3, 1, 4, 18, 2)
RowArr = Array(4, 9, 17, 21, 4, 18)
For b = 2 To ThisWorkbook.Worksheets.Count
    For col = 0 To 5
        For dong = 0 To 5
            DataRw = ThisWorkbook.Worksheets(b).Cells(1000, ColumnArr(col)).End(xlUp).Row
            DataStore = ThisWorkbook.Worksheets(b).Range(ThisWorkbook.Worksheets(b).Cells(RowArr(dong), ColumnArr(col)), _
            ThisWorkbook.Worksheets(b).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) 'dòng này báo lỗi: Type mismatch
                End If
            Next i
        Next dong
    Next col
Next b
    SArr = Sheets("Episode5").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
    Sheets("Episode5").Range("D10:D1000").ClearContents
    Sheets("Episode5").Range("D10").Resize(UBound(SArr, 1), 1) = RArr
End Sub
Bạn đọc lại cú pháp câu lệnh, Đọc căn bản cho hiểu rồi vọc mấy cái đó, làm vậy hiểu được chỗ này mất hết chỗ kia đó.
 
Upvote 0
Cháu làm theo dạng: các bảng khác Sheets không trùng chỉ số dòng và cột của ô bắt đầu, dòng bắt đầu dữ liệu của bảng.Loay hoay từ chiều đến giờ không chạy được code chú ạ!
- Thêm 1 mảng RowArr = Array(4, 9, 17, 21, 4, 18)

Mã:
For b = 2 To ThisWorkbook.Worksheets.Count
    For col = 0 To 5
        For dong = 0 To 5
Thêm 1 mảng SheetArr = Array("CH1", "CH2", ...)
Chỉ cần 1 vòng lặp
Mã:
for Sequence = 0 to 5
   with Sheets(SheetArr(Sequence))
      .DataRw = ...
      DataStore = ...
      For i = 1 To UBound(DataStore, 1)
            ...
 
Upvote 0
bài của mình nó không có nằm 3 cột liền nhau như vậy đâu, có sheet có mã - họ - tên - số lượng bán, có sheet có mã - họ - tên đệm - tên - đơn vị tính - số lượng bán, có sheet có số lượng bán họ - tên - mã - đệm - tên
nếu theo như vi dụ đó thì chắc làm AdvanFileter ra sheet tmp cũng được khỏi cần dic
Bạn đọc lại cú pháp câu lệnh, Đọc căn bản cho hiểu rồi vọc mấy cái đó, làm vậy hiểu được chỗ này mất hết chỗ kia đó.
Do vẫn cần Dict giải quyết bài có các bảng ở các Sheets khác nhau. Có lễ đây là trường hợp cuối cùng Dict cần xử lý.
Chứ làm cho ra kết quả tốn nhiều Sub và làm nặng thêm file vẫn sử lý được phải không bạn?
Bài đã được tự động gộp:

Thêm 1 mảng SheetArr = Array("CH1", "CH2", ...)
Chỉ cần 1 vòng lặp
Mã:
for Sequence = 0 to 5
   with Sheets(SheetArr(Sequence))
      .DataRw = ...
      DataStore = ...
      For i = 1 To UBound(DataStore, 1)
            ...
Trường hợp file cháu đính kèm bài #63 là có dòng và cột quang lung tung, vậy thì phải có vòng duyệt chỉ số dòng có ô bắt đầu dữ liệu nữa phải không ạ?
 
Upvote 0
Do vẫn cần Dict giải quyết bài có các bảng ở các Sheets khác nhau. Có lễ đây là trường hợp cuối cùng Dict cần xử lý.
Chứ làm cho ra kết quả tốn nhiều Sub và làm nặng thêm file vẫn sử lý được phải không bạn?
Bài đã được tự động gộp:


Trường hợp file cháu đính kèm bài #63 là có dòng và cột quang lung tung, vậy thì phải có vòng duyệt chỉ số dòng có ô bắt đầu dữ liệu nữa phải không ạ?
Mình đưa ra lời góp ý chân thành vậy thôi. Mong bạn hiểu. Cứ căn bản mà học, Học tốt rồi lên cao đâu có muộn bạn à.
Đôi lúc cần cái đơn giản có thể giải quyết vấn đề rồi. Giống như Thầy @ptm0412 góp ý cho bạn.
 
Upvote 0
Trường hợp file cháu đính kèm bài #63 là có dòng và cột quang lung tung, vậy thì phải có vòng duyệt chỉ số dòng có ô bắt đầu dữ liệu nữa phải không ạ?
Đọc kỹ nhé, tôi nói là "thêm SheetArr" tức là đã có 2, thêm 1 là 3, chứ không phải "chỉ thêm 1 thành 2"
 
Lần chỉnh sửa cuối:
Upvote 0
Đọc kỹ nhé, tôi nói là "thêm SheetArr" tức là đã có 2, thêm 1 là 3, chứ không phải "chỉ thêm 1 thành 2"
Vâng. Sợ nhiều việc quá chú quên í, nên hỏi lại cho chắc ăn ạ! Ngoài thêm mảng RowArr thêm 1 mảng SheetArr nữa.
Bài đã được tự động gộp:

Mình đưa ra lời góp ý chân thành vậy thôi. Mong bạn hiểu. Cứ căn bản mà học, Học tốt rồi lên cao đâu có muộn bạn à.
Đôi lúc cần cái đơn giản có thể giải quyết vấn đề rồi. Giống như Thầy @ptm0412 góp ý cho bạn.
Cảm ơn bạn. Mình hiểu chỗ kẹt này là do thiếu kiến thức cơ bản. Ham đánh cả cụm quá nên phải chày cối, chịu bao búa rìu. Cố nốt bài này thôi rồi làm hàm con Sub/Function ByRef, ByVal
 
Upvote 0
PHP:
    For col = 0 To 5
        For dong = 0 To 5
              ...
                   Dict.Item(sKey) = Dict.Item(sKey) + DataStore(i, 3) 'dòng này báo lỗi: Type mismatch
Mỗi 1 sheet chỉ có 1 ô "đầu tiên chứa dữ liệu", Chạy 2 vòng for lồng nhau té ra mỗi sheet có 5 x 5 là 25 bộ dữ liệu à. 24 bộ thừa kia trùng hợp có chứa dữ liệu text cộng dồn vào item nên bị Type Mismatch
 
Upvote 0
Mỗi 1 sheet chỉ có 1 ô "đầu tiên chứa dữ liệu", Chạy 2 vòng for lồng nhau té ra mỗi sheet có 5 x 5 là 25 bộ dữ liệu à. 24 bộ thừa kia trùng hợp có chứa dữ liệu text cộng dồn vào item nên bị Type Mismatch
Vâng ạ! do chưa tạo ra và chọn đúng vùng để tạo Key nên bị lỗi ạ. Nhưng cháu vẫn chưa nghĩ ra được nếu không có thêm 1 vòng để gán chỉ số dòng ô đầu tiên bắt đầu dữ liệu bảng(bảng văng lung tung) thì sao mà xác đinh được đoạn thẳng đứng (cột dữ liệu đầu tiên của bảng), nếu không có đoạn thằng đứng này thì không resize ra hình chữ nhật được. Và như vậy chưa duyệt trúng vị trí của bảng dữ liệu( nguyên nhân tạo Key lỗi). Mong chú chỉ cho cháu đoạn này với!
 
Lần chỉnh sửa cuối:
Upvote 0
Vâng ạ! do chưa tạo ra và chọn đúng vùng để tạo Key nên bị lỗi ạ. Nhưng cháu vẫn chưa nghĩ ra được nếu không có thêm 1 vòng để gán chỉ số dòng ô đầu tiên bắt đầu dữ liệu bảng thì sao mà xác đinh được đoạn thẳng đứng (cột dữ liệu đầu tiên của bảng), nếu không có đoạn thằng đứng này thì không resize ra hình chữ nhật được. Và như vậy chưa duyệt trúng vị trí của bảng dữ liệu( nguyên nhân tạo Key lỗi). Mong chú chỉ cho cháu đoạn này với!
Chỉ cần 1 vòng lặp:
1 sheet, 1 cột, 1 dòng là ra ô đầu, cột đó xác định dòng cuối, rồi cột đó resize chứ sao.
Ví dụ Sequence = 0:
Sheets(SheetArr(0)) = sheets("shop1")
RowArr(0) = 4
ColumnArr(0) = 2
Thế là có ô đầu Cells(4, 2)
DataRw = Cells(1000,2).End ...
Ô cuối là Cells(DataRw,2),
Resize 3
__________
Seq = 1
Sheets(SheetArr(1)) = sheets("shop2")
RowArr(1) = 9
ColumnArr(1) = 3
 
Upvote 0
Chỉ cần 1 vòng lặp:
1 sheet, 1 cột, 1 dòng là ra ô đầu, cột đó xác định dòng cuối, rồi cột đó resize chứ sao.
Cháu hoàn thành rồi chú ạ. Cách dùng "For Sequence" nó phải thuộc dự án vba lớn thì mới có. Chứ mò sách nào mà có được ạ! Cảm ơn chú nhiều lắm!
Bài Dict có Bảng văng lung tung.
Chỉ 1 dấu chấm trong code thôi mà chết ngắc đến giờ ạ! Bài học quá quý giá!
PHP:
Dim MaxRw As Long, DataRw As Long, i As Long
Dim ColumnArr, sKey As String, RowArr, SheetArr
Dim Dict, SArr(), RArr()
Set Dict = CreateObject("Scripting.Dictionary")
SheetArr = Array(2, 3, 4, 5, 6, 7)
ColumnArr = Array(2, 3, 1, 4, 18, 2)
RowArr = Array(4, 9, 17, 21, 4, 18)
For Sequence = 0 To 5
   With Sheets(SheetArr(Sequence))
        DataRw = .Cells(1000, ColumnArr(Sequence)).End(xlUp).Row
        ' .Range(.Cells.... the định nghĩa trước chữ Cell không có dấu chấm. mỗi dấu chấm đó mất cả buổi sợ thật
        ' Theo định nghĩa Range(Cells(a,b), Cells(c,d)) mà trong bài lại có cái dấu chấm trước chữ .Cells khổ cái dấu chấm này quá(khóc)
        DataStore = .Range(.Cells(RowArr(Sequence), ColumnArr(Sequence)), _
        .Cells(DataRw, ColumnArr(Sequence))).Resize(, 3).Value  '<--------- chỉ vì dấu chấm trước chữ Cells (.Cells) theo định nghĩa mà không biết lỗi từ đâu.
        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 i
    End With
Next Sequence
SArr = Sheets("Episode5").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
Sheets("Episode5").Range("D10:D1000").ClearContents
Sheets("Episode5").Range("D10").Resize(UBound(SArr, 1), 1) = RArr
End Sub
 

File đính kèm

  • DictExercise5.xlsm
    32.2 KB · Đọc: 9
Lần chỉnh sửa cuối:
Upvote 0
Upvote 0
Khiếp, tỷ năm mới thấy tự làm, tự sai, tự sửa 1 lần. Thưởng cho 1 tim
Tuy làm được đến đây rồi, nhưng vẫn chưa hoàn hồn, cháu vẫn còn 2 câu hỏi nữa:
- Dấu chấm trước chữ Cells trong đoạn code:
PHP:
DataStore = .Range(.Cells(RowArr(Sequence), ColumnArr(Sequence)), _
        .Cells(DataRw, ColumnArr(Sequence))).Resize(, 3).Value
Mà theo định nghĩa lại không có?
- Với lại data các bảng có Key là màu sắc(interior.Color) thì có phải xử lý gì không? Hay chỉ cần gọi nó là Key chuỗi là được ạ?
 
Lần chỉnh sửa cuối:
Upvote 0
Tuy làm được đến đây rồi, nhưng vẫn chưa hoàn hồn, cháu vẫn còn 2 câu hỏi nữa:
- Dấu chấm trước chữ Cells trong đoạn code:

- Với lại data các bảng có Key là màu sắc(interior.Coler) thì có phải xử lý gì không? Hay chỉ cần gọi nó là Key chuỗi là được ạ?
- Định nghĩa không có chấm mút mắm tôm chanh gì cả, và mặc định là sheet hiện hành. Nếu không phải sheet hiện hành thì phải ghi rõ sheets(...).Range(sheets(...).Cels(...), sheets(...).Cells(...))
Nhưng sheets(...) đã viết tắt bằng With - End With nên không cần nhắc lại tỷ lần mà chỉ chấm chấm thôi
- Các bảng key là màu sắc thì không dùng mảng được mà phải dùng range
Set DataStore = Range(......) rồi sKey = nối chuỗi
 
Upvote 0
- Định nghĩa không có chấm mút mắm tôm chanh gì cả, và mặc định là sheet hiện hành. Nếu không phải sheet hiện hành thì phải ghi rõ sheets(...).Range(sheets(...).Cels(...), sheets(...).Cells(...))
Nhưng sheets(...) đã viết tắt bằng With - End With nên không cần nhắc lại tỷ lần mà chỉ chấm chấm thôi
- Các bảng key là màu sắc thì không dùng mảng được mà phải dùng range
Set DataStore = Range(......) rồi sKey = nối chuỗi
Quá bổ ích "For Sequence = 0 To 5", thay thử Sequence = biến, thì lỗi. Vậy Sequence là hàm điền số theo thứ tự à chú (vì nếu để điền số thì theo định nghĩa là khác cơ?)
 
Upvote 0
Quá bổ ích "For Sequence = 0 To 5", thay thử Sequence = biến, thì lỗi. Vậy Sequence là hàm điền số theo thứ tự à chú (vì nếu để điền số thì theo định nghĩa là khác cơ?
Sequence là tên biến được đặt theo ý nghĩa số thứ tự trong các Array từ 0 đến 5, không liên quan đến hàm hiếc gì. Đặt tên khác chả sao, nhưng nên đặt mang ý nghĩa cần diễn tả
 
Upvote 0
Sequence là tên biến được đặt theo ý nghĩa số thứ tự trong các Array từ 0 đến 5, không liên quan đến hàm hiếc gì. Đặt tên khác chả sao, nhưng nên đặt mang ý nghĩa cần diễn tả
Vậy khả năng lúc cháu đổi nó là biến khác vẫn còn lỗi nên hiểu lầm.
Kiểm tra lại vẫn sai: Mã hàng 6 = 0 thì đúng, mà mã hàng 29 = 0 thì sai. Chắc mai mới có thời gian kiểm tra, giờ muộn lắm rồi. Chú đi nghỉ sớm nhé, muộn lắm rồi ạ! --=--
 
Upvote 0

File đính kèm

  • DictExercise_3.xlsm
    1.4 MB · Đọc: 9
Upvote 0
Web KT

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

Back
Top Bottom