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:
- Phân tích cấu trúc cột làm key, chia đôi ra đc 2 ký tự text và 1 số có 2 chữ số. Nếu ông nào không phải cấu trúc này thì không lấy làm key. Không lấy làm key thì không cần phân tích cấu trúc của Item. Phân tích cấu truc Key, bỏ qua Item
Nếu bảng danh mục có MH01 đến MH 30, cửa hàng 7 bán MH35 thì MH35 cùng cấu trúc? Cho nên vấn đề không phải cấu trúc mã, mà là mã chưa có trong danh mục. Vấn đề thứ 2 lại không phải có dòng trống (hình có dòng trống đâu?) vấn đề là CHỈ CÓ 1 DÒNG 1 CỘT, tức là chỉ có 1 ô, gắn vào mảng bị lỗi, gắn vào biến đơn thì không truy xuất kiểu mảng được.
 
Upvote 0
- Thôi thì cháu cứ ra dạng bài tập số 8 áp dụng Dictionary (đặt tên theo quy định)
- Trân quý những kiến thức những gì được dạy thì có thức thứ 8 "Dictionary Bí Truyền" (cái này em(cháu) đặt tên = Long Đằng Ngũ Nhạc)
- Cách gọi thức thứ 8 trong bí kíp Dictionary bí truyền là cách nói vui, rằng có 1 dạng bài tập áp dụng được Dictionary, các bảng văng ra các Sheet, rồi các cột trong bảng giãn cách và đổi thứ tự cho nhau, sau đó các cột trong hàng lại so le nhau, sau đó lại có kiểu data không thuộc cấu trúc để làm Key làm Item được.

Cách giải rất giản dị: Ông nào muốn làm Key thì đầu tiên ông không được trống ông IsEmpty(...) = False, khi ông không trống thì ông phải có Len = 4, tách ra 2 ký tự đầu phải = MH, hai ký tự sau phải là số. Ngang với ông Key thì bà nào làm Item phải không trống IsEmpty(...) = False và khi không trống bà phải là số cho tui.
Và có code như sau:
hocthatkhongvet.jpg
PHP:
[/COLOR][/SIZE]
Sub Dict_Episode_8()
Dim DataRw As Long, i As Long
Dim ColumnArr, sKey As String, RowArr, ShArr
Dim Dict, SArr(), RArr(), txt As String, txt2 As String
Set Dict = CreateObject("Scripting.Dictionary")
ShArr = Array(2, 3, 4, 5, 6, 7, 8)
ColumnArrCode = Array(2, 4, 7, 3, 12, 12, 2)
RowArrCode = Array(7, 19, 10, 12, 11, 8, 6)
ColumnArrQty = Array(8, 14, 20, 7, 4, 6, 7)
RowArrQty = Array(9, 7, 15, 4, 17, 13, 13)
For Seq = 0 To 6
    With Sheets(ShArr(Seq))
        DataRwCode = .Cells(1000000, ColumnArrCode(Seq)).End(xlUp).Row
        DataRwQty = .Cells(1000000, ColumnArrQty(Seq)).End(xlUp).Row
        StoreCode = .Range(.Cells(RowArrCode(Seq), ColumnArrCode(Seq)), _
        .Cells(DataRwCode, ColumnArrCode(Seq))).Value2
        StoreQty = .Range(.Cells(RowArrQty(Seq), ColumnArrQty(Seq)), _
        .Cells(DataRwQty, ColumnArrQty(Seq))).Value2
        For i = 1 To UBound(StoreCode, 1)
            mc = StoreCode(i, 1): mq = StoreQty(i, 1): txt = Mid(mc, 1, 2): txt2 = Mid(mc, 3, 2)
            If (IsEmpty(mc) = False And Len(mc) = 4 And txt = "MH" And IsNumeric(txt2) = True _
            And IsEmpty(mq) = False And IsNumeric(mq) = True) Then
                sKey = StoreCode(i, 1)
                If Not Dict.exists(sKey) Then
                    Dict.Add sKey, StoreQty(i, 1)
                Else
                    Dict.Item(sKey) = Dict.Item(sKey) + StoreQty(i, 1)
                End If
            End If
        Next
    End With
Next Seq
With Sheets("Data")
SArr = .Range(.Cells(3, 2), .Cells(1000000, 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("D3:D1000").ClearContents
.Range("D3").Resize(UBound(SArr, 1), 1) = RArr
End With
End Sub[code]
 

File đính kèm

  • Dict_Exercise_8.xlsm
    1.4 MB · Đọc: 5
Lần chỉnh sửa cuối:
Upvote 0
Sau cảnh báo ở bài 121 thì code bài 122 vô giá trị. Đó là chưa kể 1 số biến chưa khai báo mặc dù đã được nhắc.
 
Upvote 0
Sau cảnh báo ở bài 121 thì code bài 122 vô giá trị. Đó là chưa kể 1 số biến chưa khai báo mặc dù đã được nhắc.
Dạ Dạ.
- Nếu biến nào không khai báo, là số thì tự nó ép là kiểu interge, nếu không thì nó là variant, cháu thấy không cần khai vẫn chạy được. Tối cháu sửa ạ. Liệu bài 8 này đã trùm hết khả năng chưa ạ?
- Còn danh mục nếu lấy là cập nhật mới nhất thì cháu gán nó xuống sheet là Dict.Item(sKey) ạ(ở bài 122 coi là danh sách tách rời. Không coi là cũ mới gì ạ)
 
Lần chỉnh sửa cuối:
Upvote 0
Thế cái này là cái gì đây:

1615885462906.png
 
Upvote 0
Có phải cách duy nhất là chuyển sang Range không ạ?
Chết dở. If đủ các trường hợp rầu mà. Để cháu chỉnh tiếp ạxuly.jpg
Giờ cháu mới hiểu cảnh báo! Nếu bảng có 1 dòng giá trị sẽ bị lỗi như cảnh báo bài 121. Hiện chưa biết cách khắc phục nào triệt để. Vì nếu bảng có từ 2 dòng trở lên thì code xử lý chính xác.
Dùng On Error Resume Next cháu thật sự chưa ưng ý.
Dùng cái này có được không ạ.Sách bị ... chỗ đó lên lấy câu lệnh On Error Resume Next xử lý được không ạ?
 
Lần chỉnh sửa cuối:
Upvote 0
chắc phụ thân nhà cô nương đau đầu vì cô nương lắm
cô nương vào link dưới này học bài bản dùm
rồi thích luyện code thì dạo các post cần hỗ trợ trên GPE để luyện như tôi này

p/s: "xử lý" không phải "sử lý"
 
Upvote 0
chắc phụ thân nhà cô nương đau đầu vì cô nương lắm
cô nương vào link dưới này học bài bản dùm
rồi thích luyện code thì dạo các post cần hỗ trợ trên GPE để luyện như tôi này

p/s: "xử lý" không phải "sử lý"
Muội đọc nhanh lắm, nhưng phải có từ khóa để tra ngược và phải áp vào bài mới nhớ ạ!
Huynh thử bài #126 xem. Nếu không dùng câu lệnh On Error Resume Next thì huynh sẽ xử lý sao?
Code bài #126, nếu bảng dữ liệu có từ 2 dòng trở lên thì chạy luôn đúng, còn nếu chỉ có 1 dòng dữ liệu thì lỗi (cảnh báo bài #121).
 
Lần chỉnh sửa cuối:
Upvote 0
Muội đọc nhanh lắm, nhưng phải có từ khóa để tra ngược và phải áp vào bài mới nhớ ạ!
về mặt lý luận, cô nương lên nhìn một cách phổ quát hơn.
cô nương cho người dùng được phép "buông thả", nhưng lại không cho phép dữ liệu được "buông thả".
người dùng trình bày báo cáo ở cột nào, ô nào cũng được. 100 người cô nương phải chiều theo ý của 100 người, sửa lại đống (ColumnArrCode, RowArrCode, ColumnArrQty, RowArrQty) theo ý họ.
còn dữ liệu chỉ cho đến 99 mã, nếu hơn 100 mã hàng thì sao? dữ liệu trống, dữ liệu không khớp,... thì sao?
 
Upvote 0
Có phải cách duy nhất là chuyển sang Range không ạ?
lấy câu lệnh On Error Resume Next xử lý được không ạ?
Chuyển sang range cho mà chết
Resume next là bỏ qua dữ liệu không lấy lên báo cáo à? Báo cáo kiểu gì vậy?
Chia ra 3 trường hợp:
- Không có dòng nào (có quyền bỏ qua)
- Có 1 dòng: DataArr là giá trị đơn, xét trực tiếp không cần vòng lặp (bao gồm StoreCode và SoreQty)
- Nhiều hơn 1 dòng: DataArr là mảng, truy xuất kiểu mảng DataArr(i, 1)
Trường hợp mã chưa có trong danh mục (không cần đúng cấu trúc, #$%^ kệ nó), nếu có SL bán là PHẢI BÁO CÁO, thêm 1 dòng vào danh mục.
 
Upvote 0
Nổ não, sẵn tiện đây cho mình hỏi không dùng index co thể đưa union rang vào array không và cách tối ưu nhất
 
Upvote 0
Chuyển sang range cho mà chết
Resume next là bỏ qua dữ liệu không lấy lên báo cáo à? Báo cáo kiểu gì vậy?
Chia ra 3 trường hợp:
- Không có dòng nào (có quyền bỏ qua)
- Có 1 dòng: DataArr là giá trị đơn, xét trực tiếp không cần vòng lặp (bao gồm StoreCode và SoreQty)
- Nhiều hơn 1 dòng: DataArr là mảng, truy xuất kiểu mảng DataArr(i, 1)
Trường hợp mã chưa có trong danh mục (không cần đúng cấu trúc, #$%^ kệ nó), nếu có SL bán là PHẢI BÁO CÁO, thêm 1 dòng vào danh mục.
Xuống núi vội quá gặp đúng chỗ chữ "nhòe" lại lần lên núi tìm thầy! Hi hi xong rồi. Chú sửa cháu với để cháu biên tập lại hết các bài ạ!
PHP:
Sub Dict_Episode_8_fix()
Dim DataRw As Long, i As Long, sKey As String
Dim Dict, SArr(), RArr(), txt As String, txt2 As String
Dim ShArr, ColumnArrCode, RowArrCode, ColumnArrQty, RowArrQty, StoreCode, StoreQty
Set Dict = CreateObject("Scripting.Dictionary")
ShArr = Array(2, 3, 4, 5, 6, 7, 8)
ColumnArrCode = Array(2, 4, 7, 3, 12, 12, 2)
RowArrCode = Array(7, 19, 10, 12, 11, 8, 6)
ColumnArrQty = Array(8, 14, 20, 7, 4, 6, 7)
RowArrQty = Array(9, 7, 15, 4, 17, 13, 13)
For Seq = 0 To 6
    With Sheets(ShArr(Seq))
            DataRwCode = .Cells(1000000, ColumnArrCode(Seq)).End(xlUp).Row
            DataRwQty = .Cells(1000000, ColumnArrQty(Seq)).End(xlUp).Row
            StoreCode = .Range(.Cells(RowArrCode(Seq), ColumnArrCode(Seq)), _
            .Cells(DataRwCode, ColumnArrCode(Seq))).Value
            StoreQty = .Range(.Cells(RowArrQty(Seq), ColumnArrQty(Seq)), _
            .Cells(DataRwQty, ColumnArrQty(Seq))).Value
            a = DataRwCode - RowArrCode(Seq)
            If (a = 1) Then
            mc = StoreCode(1, 1): mq = StoreQty(1, 1): txt = Mid(mc, 1, 2): txt2 = Mid(mc, 3, 2)
                If (IsEmpty(mc) = False And Len(mc) = 4 And txt = "MH" And IsNumeric(txt2) = True _
                And IsEmpty(mq) = False And IsNumeric(mq) = True) Then
                    sKey = StoreCode(1, 1)
                    If Not Dict.exists(sKey) Then
                        Dict.Add sKey, StoreQty(1, 1)
                    Else
                        Dict.Item(sKey) = Dict.Item(sKey) + StoreQty(1, 1)
                    End If
                End If
            End If
            If (a > 1) Then
            For i = 1 To UBound(StoreCode, 1)
                mc = StoreCode(i, 1): mq = StoreQty(i, 1): txt = Mid(mc, 1, 2): txt2 = Mid(mc, 3, 2)
                If (IsEmpty(mc) = False And Len(mc) = 4 And txt = "MH" And IsNumeric(txt2) = True _
                And IsEmpty(mq) = False And IsNumeric(mq) = True) Then
                    sKey = StoreCode(i, 1)
                    If Not Dict.exists(sKey) Then
                        Dict.Add sKey, StoreQty(i, 1)
                    Else
                        Dict.Item(sKey) = Dict.Item(sKey) + StoreQty(i, 1)
                    End If
                End If
            Next
            End If
        End With
Next Seq
With Sheets("Data")
SArr = .Range(.Cells(3, 2), .Cells(1000000, 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("D3").Resize(UBound(SArr, 1), 1) = RArr
End With
End Sub
 
Upvote 0
Upvote 0
Vẫn tiếp tục vô giá trị. 3 điều ở 130 không được điều nào.
Vì số dòng tượng trưng cho phần tử của Arr, và lấy số chênh nhau của chỉ số dòng ô trên vào chỉ ô dưới trong cột. Để lọc ra các trường hợp để không bị lỗi.
1. Chênh = 0 thì không xét
2. Chênh = 1 thì xét
3. Chênh lớn hơn 1 thì xét
Do đã không lỗi, và đã bao trùm tất cả các trường hợp nên ở bài này cháu thấy khó sửa vì không tìm ra lỗi nữa. Xin chú chỉ cho ạ? Đúng là không thấy lỗi thành ra không biết sửa sao ạ!
 
Upvote 0
Thử 2 trường hợp sau, nhớ kiểm tra kết quả (số 1 triệu thì không thể nào không thấy)
1615904642847.png
Mục số 2:
Đã nói là không đưa về range

Mục số 3:
Mặt hàng không có trong danh mục thì dù có bán được tỷ đồng cũng không tính

1615904884390.png

Sửa: bỏ mục số 2
_____________
Đính chính:
Mục số 2:
Nếu làm đúng mục 1, thì vẫn chưa hiểu gì về "giá trị đơn" và giá trị mảng"
 
Lần chỉnh sửa cuối:
Upvote 0
Thử 2 trường hợp sau, nhớ kiểm tra kết quả (số 1 triệu thì không thể nào không thấy)
View attachment 255546
Mục số 2:
Đã nói là không đưa về range
Mục số 3:
Mặt hàng không có trong danh mục thì dù có bán được tỷ đồng cũng không tính

View attachment 255548
Khu vực cháu đang bị mất điện khổ ghê. Kiểu này "bổ củi" lâu lâu đây.
Nếu như thấy
TH1: thấy MH01 = 1 triệu + các bảng khác nếu có là xong ảnh 1
TH2: thấy MH01 = 1 triệu + 1 triệu + các bảng khác nếu có là xong bức ảnh xong ảnh 2
TH3: lờ đi vì ko có trong danh mục. Kiểm tra vậy là xong phải ko ạ?
- Hoàn cảnh giờ rất oái oăm. Là không biết có lỗi hay không mà sửa. Ở các bài trc thì thấy lỗi và sửa lỗi. Ở bài này thì công nhận là chưa lĩnh hội được.
Giá thầy thị phạm cho vài đường thì tuyệt quá (chỗ code lập luận 3 trường hợp ấy ạ)
- Cụ thể chỗ biến đơn không truy xuất được kiểu dữ liệu mảng. Cháu đúng không hiểu chỗ này. Nên mới nghĩ ra a = sự chênh nhau giữa ô chỉ số trên và ô chỉ số dưới trong cùng 1 dòng. sao a trong trường hợp này lại không được dùng
 
Lần chỉnh sửa cuối:
Upvote 0
Hình 1: Từ dòng 6 đến dòng 6 là mấy dòng dữ liệu? (a= 6 - 6 = 0)
Hình 2: Từ dòng 6 đến dòng 7 là mấy dòng dữ liệu? ( a = 7 - 6 = 1).
Quan sát cho kỹ vào, đừng trả lời bừa.
1 tỷ đồng của người ta mà "lờ" đi là sao?
 
Upvote 0
Hình 1: Từ dòng 6 đến dòng 6 là mấy dòng dữ liệu? (a= 6 - 6 = 0)
Hình 2: Từ dòng 6 đến dòng 7 là mấy dòng dữ liệu? ( a = 7 - 6 = 1).
Quan sát cho kỹ vào, đừng trả lời bừa.
1 tỷ đồng của người ta mà "lờ" đi là sao?
a = DataRwCode - RowArrCode(Seq) không dùng được ạ. Tầng này khó vào thật chú ạ
Chú cho cháu vài dòng code đi. Ăn không 1 tỷ. Muốn giả lại không được ạ hic hic
 
Upvote 0
a = DataRwCode - RowArrCode(Seq) không dùng được ạ. Tầng này khó vào thật chú ạ
Chú cho cháu vài dòng code đi. Ăn không 1 tỷ. Muốn giả lại không được ạ hic hic
Quay về bài toán trồng cây lớp 4: Có 4 mét hàng rào, cách 1 mét trồng 1 cây thì mấy khoảng và mấy cây?
Tính số dòng cũng vậy: Số dòng (a) = cuối trừ đầu +1.
Quy luật rành rành trước mắt: từ 6 đến 6 là 1 dòng, từ 6 đến 7 là 2 dòng, thì quy luật là 6-6+1 và 7-6 +1 chứ là gì. Quen copy riết rồi đầu óc trở thành đậu hũ
 
Upvote 0
Quay về bài toán trồng cây lớp 4: Có 4 mét hàng rào, cách 1 mét trồng 1 cây thì mấy khoảng và mấy cây?
Tính số dòng cũng vậy: Số dòng (a) = cuối trừ đầu +1.
Quy luật rành rành trước mắt: từ 6 đến 6 là 1 dòng, từ 6 đến 7 là 2 dòng, thì quy luật là 6-6+1 và 7-6 +1 chứ là gì. Quen copy riết rồi đầu óc trở thành đậu hũ
Vâng.Untitled.jpg
a = 0 nghĩa là bàng dữ liệu có 1 dòng
a > 0 đang có 2 dòng trở lên.
Bệnh là do: Có 1 dòng: DataArr là giá trị đơn, xét trực tiếp không cần vòng lặp (bao gồm StoreCode và SoreQty) là câu này ạ!
Nhưng vẫn chưa hiểu sao nó không thấy 1 tỷ đâu ạ :wallbash:
 
Lần chỉnh sửa cuối:
Upvote 0
Web KT
Back
Top Bottom