Câu hỏi liên quan đến dictionary

Liên hệ QC

nguyenvanlinhab

Thành viên mới
Tham gia
27/2/22
Bài viết
40
Được thích
0
Em có file như đính kèm. Sau khi tự học hỏi trên GPE mà vẫn không giải quyết dược bài này. Mọi người có thể chỉ giúp xem sai ở đâu không ạ
 

File đính kèm

  • hocvba.xlsm
    24.3 KB · Đọc: 32
Muốn người ta giúp thì hãy nói cho người ta hiểu. Tung tập tin lên rồi muốn người ta đoán ý? Thế nào, khi nào thì "không lấy", khi nào thì "cộng dồn" thì phải mô tả. Đã không biết nói, không biết giải thích thì sau đó phải lấy thêm ví dụ cụ thể, và giải thích tại sao chỗ này này "không lấy", chỗ này này "cộng dồn". Tóm lại nói về cách thức làm BẰNG TAY. Người khác chỉ đưa cách thức đó vào máy cho tay khỏi mỏi, công việc chạy nhanh hơn mà thôi. Ý mình thì cứ giữ lại mà bắt người khác phải đoán mò? Chủ đề "bên kia" chưa đủ dài hay sao mà lập thêm chủ đề này? Không mô tả kỹ mà chỉ kiểu: "Em muốn hỏi là key chính của em là mã sản phẩm,em muốn add thêm key nữa là vị trí .nếu key mã sản phẩm đã tồn tại thì không lấy. key vị trí đã tồn tại thì cộng dồn ra số lượng ạ" thì là bắt người khác phải nhọc công hơn không cần thiết rồi.

Nếu vấn đề không quá dễ thì bắt buộc phải có 3 phần: tập tin, mô tả, và điền bằng tay kết quả mong đợi.

Không thể chấp nhận kiểu tung tập tin hay ảnh lên rồi mất 10 bài để nói cho người khác hiểu ý.

Bạn mới học code nên tôi đề xuất code dưới đây. Nếu bạn muốn dùng chỉ 1 "đít thon dễ thương", code ngắn nhất, ít dòng ít chữ nhất thì đợi người khác nhé.
Mã:
Sub hoc_vba()
Dim lastRow As Long, r As Long, count As Long, k As Long, maSP As Object, VT As Object, kq(), dulieu()
    With ThisWorkbook.Worksheets("Sheet1")
        .Range("L2:N1000").ClearContents    ' xoa ket qua cu
        lastRow = .Cells(Rows.count, "F").End(xlUp).Row
        If lastRow < 2 Then Exit Sub    ' khong co du lieu thi don do choi
        dulieu = .Range("D2:F" & lastRow).Value ' lay cot D:F vao mang dulieu
    End With
    ReDim kq(1 To UBound(dulieu, 1), 1 To 3)
    Set maSP = CreateObject("Scripting.Dictionary")
    Set VT = CreateObject("Scripting.Dictionary")
    For r = 1 To UBound(dulieu, 1)
        If maSP.exists(dulieu(r, 3)) Then   ' da co ma SP
            If VT.exists(dulieu(r, 1)) Then
                k = VT.item(dulieu(r, 1))   ' doc chi so dong cua vi tri hien hanh, duoc ghi nho o (*) hoac (**)
                kq(k, 3) = kq(k, 3) + 1 ' tang so luong o dong k them 1
            Else
                count = count + 1   ' vi tri moi nen tang count them 1
                kq(count, 2) = dulieu(r, 1) ' vi tri
                VT.Add dulieu(r, 1), count  ' vi tri hien hanh se o dong count cua mang ket qua kq (**)
                kq(count, 3) = kq(count, 3) + 1 ' tang so luong o dong count them 1
            End If
        Else    ' la ma SP moi
            VT.RemoveAll    ' xoa cac vi tri cu
            maSP.Add dulieu(r, 3), ""   ' them ma SP moi vao tu dien voi tu cach KEY
            count = count + 1   ' vi tri moi nen tang count them 1
            kq(count, 1) = dulieu(r, 3) ' ma SP
            kq(count, 2) = dulieu(r, 1) ' vi tri
            VT.Add dulieu(r, 1), count  ' vi tri hien hanh se o dong count cua mang ket qua kq (*)
            kq(count, 3) = kq(count, 3) + 1 ' tang so luong o dong count them 1
        End If
    Next r
    ThisWorkbook.Worksheets("Sheet1").Range("L2").Resize(count, 3).Value = kq
End Sub
 
Upvote 0
Đã chạy thử nó vẫn không như em nghĩ ạ.Cột mã sản phẩm nó vẫn không lọc trùngView attachment 272841
Khi tối hỏi thử code rồi nhưng thấy bạn trước code dữ quá nên thôi mình lui, thôi thì góp vui:
Mã:
Sub test()
    
    Dim dict As Object
    Dim data As Variant, res As Variant
    Dim dongcuoi As Long, i As Long, k As Long, r As Long
    Dim str As String, itemCode As String, rackNo As String
    Dim Quanity As Double
    Dim this_sheet As Worksheet
    
    Set this_sheet = ThisWorkbook.ActiveSheet
    
    With this_sheet
        dongcuoi = .Cells(.Rows.count, "F").End(xlUp).Row
        If dongcuoi < 2 Then Exit Sub
        data = .Range("D2:G" & dongcuoi).Value
        Set dict = CreateObject("scripting.dictionary")
        dict.CompareMode = vbTextCompare
        ReDim res(1 To UBound(data, 1), 1 To 3)
        For i = LBound(data, 1) To UBound(data, 1)
            rackNo = data(i, 1)
            itemCode = data(i, 3)
            Quanity = 1 'data(i, 4)
            str = rackNo & itemCode
            If Not dict.Exists(str) Then
                k = k + 1
                dict.Add str, k
                res(k, 2) = rackNo
                res(k, 3) = Quanity
                If Not dict.Exists(itemCode) Then
                    dict.Add itemCode, k
                    res(k, 1) = itemCode
                End If
            Else
                r = dict.Item(str)
                res(r, 2) = rackNo
                res(r, 3) = res(r, 3) + Quanity
            End If
        Next i
        .Range("L6").Resize(1000, 3).ClearContents
        .Range("L6").Resize(k, UBound(res, 2)).Value = res
    End With
End Sub
Bài đã được tự động gộp:

Muốn người ta giúp thì hãy nói cho người ta hiểu. Tung tập tin lên rồi muốn người ta đoán ý? Thế nào, khi nào thì "không lấy", khi nào thì "cộng dồn" thì phải mô tả. Đã không biết nói, không biết giải thích thì sau đó phải lấy thêm ví dụ cụ thể, và giải thích tại sao chỗ này này "không lấy", chỗ này này "cộng dồn". Tóm lại nói về cách thức làm BẰNG TAY. Người khác chỉ đưa cách thức đó vào máy cho tay khỏi mỏi, công việc chạy nhanh hơn mà thôi. Ý mình thì cứ giữ lại mà bắt người khác phải đoán mò? Chủ đề "bên kia" chưa đủ dài hay sao mà lập thêm chủ đề này? Không mô tả kỹ mà chỉ kiểu: "Em muốn hỏi là key chính của em là mã sản phẩm,em muốn add thêm key nữa là vị trí .nếu key mã sản phẩm đã tồn tại thì không lấy. key vị trí đã tồn tại thì cộng dồn ra số lượng ạ" thì là bắt người khác phải nhọc công hơn không cần thiết rồi.

Nếu vấn đề không quá dễ thì bắt buộc phải có 3 phần: tập tin, mô tả, và điền bằng tay kết quả mong đợi.

Không thể chấp nhận kiểu tung tập tin hay ảnh lên rồi mất 10 bài để nói cho người khác hiểu ý.

Bạn mới học code nên tôi đề xuất code dưới đây. Nếu bạn muốn dùng chỉ 1 "đít thon dễ thương", code ngắn nhất, ít dòng ít chữ nhất thì đợi người khác nhé.
Mã:
Sub hoc_vba()
Dim lastRow As Long, r As Long, count As Long, k As Long, maSP As Object, VT As Object, kq(), dulieu()
    With ThisWorkbook.Worksheets("Sheet1")
        .Range("L2:N1000").ClearContents    ' xoa ket qua cu
        lastRow = .Cells(Rows.count, "F").End(xlUp).Row
        If lastRow < 2 Then Exit Sub    ' khong co du lieu thi don do choi
        dulieu = .Range("D2:F" & lastRow).Value ' lay cot D:F vao mang dulieu
    End With
    ReDim kq(1 To UBound(dulieu, 1), 1 To 3)
    Set maSP = CreateObject("Scripting.Dictionary")
    Set VT = CreateObject("Scripting.Dictionary")
    For r = 1 To UBound(dulieu, 1)
        If maSP.exists(dulieu(r, 3)) Then   ' da co ma SP
            If VT.exists(dulieu(r, 1)) Then
                k = VT.item(dulieu(r, 1))   ' doc chi so dong cua vi tri hien hanh, duoc ghi nho o (*) hoac (**)
                kq(k, 3) = kq(k, 3) + 1 ' tang so luong o dong k them 1
            Else
                count = count + 1   ' vi tri moi nen tang count them 1
                kq(count, 2) = dulieu(r, 1) ' vi tri
                VT.Add dulieu(r, 1), count  ' vi tri hien hanh se o dong count cua mang ket qua kq (**)
                kq(count, 3) = kq(count, 3) + 1 ' tang so luong o dong count them 1
            End If
        Else    ' la ma SP moi
            VT.RemoveAll    ' xoa cac vi tri cu
            maSP.Add dulieu(r, 3), ""   ' them ma SP moi vao tu dien voi tu cach KEY
            count = count + 1   ' vi tri moi nen tang count them 1
            kq(count, 1) = dulieu(r, 3) ' ma SP
            kq(count, 2) = dulieu(r, 1) ' vi tri
            VT.Add dulieu(r, 1), count  ' vi tri hien hanh se o dong count cua mang ket qua kq (*)
            kq(count, 3) = kq(count, 3) + 1 ' tang so luong o dong count them 1
        End If
    Next r
    ThisWorkbook.Worksheets("Sheet1").Range("L2").Resize(count, 3).Value = kq
End Sub
Cháu vừa đăng bài thì thấy bài của chú.
 
Upvote 0
Khi tối hỏi thử code rồi nhưng thấy bạn trước code dữ quá nên thôi mình lui, thôi thì góp vui:
Mã:
Sub test()
   
    Dim dict As Object
    Dim data As Variant, res As Variant
    Dim dongcuoi As Long, i As Long, k As Long, r As Long
    Dim str As String, itemCode As String, rackNo As String
    Dim Quanity As Double
    Dim this_sheet As Worksheet
   
    Set this_sheet = ThisWorkbook.ActiveSheet
   
    With this_sheet
        dongcuoi = .Cells(.Rows.count, "F").End(xlUp).Row
        If dongcuoi < 2 Then Exit Sub
        data = .Range("D2:G" & dongcuoi).Value
        Set dict = CreateObject("scripting.dictionary")
        dict.CompareMode = vbTextCompare
        ReDim res(1 To UBound(data, 1), 1 To 3)
        For i = LBound(data, 1) To UBound(data, 1)
            rackNo = data(i, 1)
            itemCode = data(i, 3)
            Quanity = 1 'data(i, 4)
            str = rackNo & itemCode
            If Not dict.Exists(str) Then
                k = k + 1
                dict.Add str, k
                res(k, 2) = rackNo
                res(k, 3) = Quanity
                If Not dict.Exists(itemCode) Then
                    dict.Add itemCode, k
                    res(k, 1) = itemCode
                End If
            Else
                r = dict.Item(str)
                res(r, 2) = rackNo
                res(r, 3) = res(r, 3) + Quanity
            End If
        Next i
        .Range("L6").Resize(1000, 3).ClearContents
        .Range("L6").Resize(k, UBound(res, 2)).Value = res
    End With
End Sub
Bài đã được tự động gộp:


Cháu vừa đăng bài thì thấy bài của chú.
Bài của bạn tốt mà.
 
Upvote 0
Bài của bạn tốt mà.
Cháu cảm ơn chú đã động viên, code của cháu còn tệ lắm.
Cháu thường xuyên đọc các bài viết của những người nhiều kinh nghiệm như chú mà kiến thức chưa khá hơn được.
Nhưng ít nhất cũng thấy được sự tâm huyết của chú và cố gắng học hỏi để phát huy.
 
Upvote 0
Đã bảo không ăn xổi được mà.
Cả hai bên kẹt nhau.
1. Bên thớt muốn học chạy trước khi học đi. Bài này là Đít-sần dạng nâng cao. Mới học thì cứ lo copy/páte code thôi. Chuyện hiểu thì nên quên đi.
2. Bên viết code thì viết theo kiểu truyền thống GPE, chỉ chú tâm về tốc độ chứ không coi trọng sự dễ hiểu (*1).

(*1) tôi dùng "dễ hiểu" trên nguyên tắc tương đối.
GPE lâu ngày đã tự lập cho mình một "tiêu chuẩn" viết code. Những người chưa quen với truyền thống này đương nhiên đọc code rất khó hiểu.
Điển hình:
Input/Output:
- copy dữ liệu đầu vào từ sheet vào mảng và duyệt mảng
- kết quả đầu ra đợc ghi vào mảng trung gian. Làm việc xong mới chép xuống sheet.
Cách dùng khối With:
- rất hay dùng With cho đối tượng sheet. Ngay cả khi có đối tượng khác hữu lý hơn với With, như Dictionary.
Dùng With cho sheet rất nguy hiểm. Chỉ cần quên dấu chấm trước Range là nó mặc định trở về sheet hiện hành. Đồng thời, code bên trong With khó đem ra copy/paste.
Dùng cho các đối tượng khác ít nguy hiểm hơn. Thường thì quên dấu chấm trước hàm hay thuộc tính sẽ bị VBA đẩy ra.
Cách đặt tên và sử dụng biến:
- lúc khai báo biến, không bao giờ chú thích nhiệm vụ của biến. Chỉ cần vài từ giải thích nhiệm vụ, người đọc code sẽ đỡ tốn rất nhiều công sức đoán mò.
- k được dùng để đếm số dòng của mảng đầu ra. Thường thì lập trình giành tên biến k cho chuyện khác.
- hầu hết các code chỉ sử dụng 1 hay 2 mảng. Trường hợp này thì đặt tên a hay sArr cũng như nhau.

Chú cho người cần giải thích code cho thớt:
Code như bài #22 không phải là đơn giản Đít sần: Key-Item, tức là dùng Key để tham chiếu Item.
Đây là kỹ thuật tham chiếu gián tiếp. Chi tiết Item thực ra được chứa trong một mảng. Khi tham chiếu thì Key sẽ cho biết chỉ số của chi tiết này trong mảng. Từ chỉ số, truy cập mảng sẽ ra chi tiết.
Code bài #22 cũng hơi lười biếng, dùng 1 đít sần cho hai loại tra khác nhau. Đáng lẽ nếu mỗi loại dùng một đít sần riêng thì code dễ hiểu, dễ chỉnh sửa hơn.
 
Upvote 0
Cả hai bên kẹt nhau.
1. Bên thớt muốn học chạy trước khi học đi. Bài này là Đít-sần dạng nâng cao. Mới học thì cứ lo copy/páte code thôi. Chuyện hiểu thì nên quên đi.
2. Bên viết code thì viết theo kiểu truyền thống GPE, chỉ chú tâm về tốc độ chứ không coi trọng sự dễ hiểu (*1).

(*1) tôi dùng "dễ hiểu" trên nguyên tắc tương đối.
GPE lâu ngày đã tự lập cho mình một "tiêu chuẩn" viết code. Những người chưa quen với truyền thống này đương nhiên đọc code rất khó hiểu.
Điển hình:
Input/Output:
- copy dữ liệu đầu vào từ sheet vào mảng và duyệt mảng
- kết quả đầu ra đợc ghi vào mảng trung gian. Làm việc xong mới chép xuống sheet.
Cách dùng khối With:
- rất hay dùng With cho đối tượng sheet. Ngay cả khi có đối tượng khác hữu lý hơn với With, như Dictionary.
Dùng With cho sheet rất nguy hiểm. Chỉ cần quên dấu chấm trước Range là nó mặc định trở về sheet hiện hành. Đồng thời, code bên trong With khó đem ra copy/paste.
Dùng cho các đối tượng khác ít nguy hiểm hơn. Thường thì quên dấu chấm trước hàm hay thuộc tính sẽ bị VBA đẩy ra.
Cách đặt tên và sử dụng biến:
- lúc khai báo biến, không bao giờ chú thích nhiệm vụ của biến. Chỉ cần vài từ giải thích nhiệm vụ, người đọc code sẽ đỡ tốn rất nhiều công sức đoán mò.
- k được dùng để đếm số dòng của mảng đầu ra. Thường thì lập trình giành tên biến k cho chuyện khác.
- hầu hết các code chỉ sử dụng 1 hay 2 mảng. Trường hợp này thì đặt tên a hay sArr cũng như nhau.

Chú cho người cần giải thích code cho thớt:
Code như bài #22 không phải là đơn giản Đít sần: Key-Item, tức là dùng Key để tham chiếu Item.
Đây là kỹ thuật tham chiếu gián tiếp. Chi tiết Item thực ra được chứa trong một mảng. Khi tham chiếu thì Key sẽ cho biết chỉ số của chi tiết này trong mảng. Từ chỉ số, truy cập mảng sẽ ra chi tiết.
Code bài #22 cũng hơi lười biếng, dùng 1 đít sần cho hai loại tra khác nhau. Đáng lẽ nếu mỗi loại dùng một đít sần riêng thì code dễ hiểu, dễ chỉnh sửa hơn.
Đúng kiểu như anh nói, chưa biết đi nhưng cứ đòi chạy.
 
Upvote 0
Dữ liệu đã được xếp thứ thứ tự theo 2 cột sản phẩm và vị trí, dùng búa tạ dic quá lãng phí lại chạy chậm :)
Mã:
Sub ABC()
  Dim sh As Worksheet, rng As Range, res(), sp$, vt$
  Dim sRow&, i&, k&

  Set sh = Sheets("sheet1")
  Set rng = sh.Range("D2", sh.Range("D" & Rows.count).End(xlUp)) 'Vung du lieu
  sRow = rng.Rows.count  'So dong vung du lieu
  ReDim res(1 To sRow, 1 To 3) 'Mang ket qua
  For i = 1 To sRow
    If vt <> rng(i, 1) Or sp <> rng(i, 3) Then 'Khac Vi tri hoac san pham
      k = k + 1 'Them 1 dong ket qua
      vt = rng(i, 1) 'vi tri
      res(k, 2) = vt 'Ghi nhan vi tri
      res(k, 3) = 1 'Dem so luong
      If sp <> rng(i, 3) Then 'Khac san pham
        sp = rng(i, 3) 'Ma san pham
        res(k, 1) = sp 'Ghi nhan Ma san pham
      End If
    Else
      res(k, 3) = res(k, 3) + 1 'Dem so luong
    End If
    sh.Range("L2").Resize(1000, 3).ClearContents ' xoa ket qua
    sh.Range("L2").Resize(k, 3).Value = res 'Gan ket qua
  Next i
End Sub
Nếu dữ liệu không xếp thứ tự, code nầy và code bài 21# bài 22# đều tèo, cần viết lại với dic phức tạp hơn
 
Upvote 0
lúc khai báo biến, không bao giờ chú thích nhiệm vụ của biến
Cũng bài #22: Tên biến vừa đặt tiếng Việt, vừa đặt tiếng Anh, tôi đọc thấy hụt hẫng. Tiếng Anh lại sai chính tả (quanity).
Code bài #22 cũng hơi lười biếng, dùng 1 đít sần cho hai loại tra khác nhau. Đáng lẽ nếu mỗi loại dùng một đít sần riêng thì code dễ hiểu, dễ chỉnh sửa hơn.
Ở đâu đó tôi cũng từng nói việc này. 1 Dict dùng chung khi cần sẽ không đếm được, cũng không khai thác được hiệu quả. Nếu 2 Dict trở lên thì tên Dict cũng nên đặt cho có hình tượng. Tên mảng cũng thế. Nói chung tên biến đặt có hình tượng thì chưa cần chú thích cho tên biến.
 
Upvote 0
Cũng bài #22: Tên biến vừa đặt tiếng Việt, vừa đặt tiếng Anh, tôi đọc thấy hụt hẫng. Tiếng Anh lại sai chính tả (quanity).

Ở đâu đó tôi cũng từng nói việc này. 1 Dict dùng chung khi cần sẽ không đếm được, cũng không khai thác được hiệu quả. Nếu 2 Dict trở lên thì tên Dict cũng nên đặt cho có hình tượng. Tên mảng cũng thế. Nói chung tên biến đặt có hình tượng thì chưa cần chú thích cho tên biến.
à tiếng anh là tiêu đề trong file của thớt cháu chỉ copy vào là cột nào thôi chứ tiếng anh cháu không rành, còn ban đầu thì cháu định khai báo tiếng việt để người học dễ hiểu.
 
Upvote 0
@tác giả bài #22:
Code trong bài này sử dụng key kép, tức là nhiều keys nhỏ gộp lại.
Theo kinh nghiệm thì cách gộp bằng phép concat (&) đơn giản khá nguy hiểm
Alpha: key1 = "abc"; key2 = "def"
Beta: key1 = "abcd"; key2 = "ef"
Sau khi gộp, hai keys Alpha và Beta ra in hệt nhau.
Người code kinh nghiệm luôn luôn có cách gộp chuỗi phân biệt. Cách thường dùng nhấy là chèn một ký tự đặc biệt giữa các giá trị. Ký tự này gọi là delimeter, trong lập trình thường gọi tắt là delim.

Chỉnh code:
Const DELIM = "|"
...
str = rackNo & DELIM & itemCode
...

Chú thêm:
Hôm nọ, có người bạn (không liên quan đến GPE) mách cho tôi một cách gộp chuỗi khá thú vị
str = Join(Array(rackNo, itemCode), DELIM)
Đương nhiên, gọi thêm hai hàm Join và Array thì hơi tốn năng lượng (chắc cỡ vài chục phần triệu giây). Nhưng bù lại, đọc code quen sẽ thấy nó khá dễ hiểu, ít bị sai sót. Ở ví dụ này chỉ có hai chuỗi cho nên chưa thấy gì. Khi phải gộp 5 chuỗi trở lên thì sẽ thấy cái lợi.
 
Upvote 0
@tác giả bài #22:
Code trong bài này sử dụng key kép, tức là nhiều keys nhỏ gộp lại.
Theo kinh nghiệm thì cách gộp bằng phép concat (&) đơn giản khá nguy hiểm
Alpha: key1 = "abc"; key2 = "def"
Beta: key1 = "abcd"; key2 = "ef"
Sau khi gộp, hai keys Alpha và Beta ra in hệt nhau.
Người code kinh nghiệm luôn luôn có cách gộp chuỗi phân biệt. Cách thường dùng nhấy là chèn một ký tự đặc biệt giữa các giá trị. Ký tự này gọi là delimeter, trong lập trình thường gọi tắt là delim.

Chỉnh code:
Const DELIM = "|"
...
str = rackNo & DELIM & itemCode
...

Chú thêm:
Hôm nọ, có người bạn (không liên quan đến GPE) mách cho tôi một cách gộp chuỗi khá thú vị
str = Join(Array(rackNo, itemCode), DELIM)
Đương nhiên, gọi thêm hai hàm Join và Array thì hơi tốn năng lượng (chắc cỡ vài chục phần triệu giây). Nhưng bù lại, đọc code quen sẽ thấy nó khá dễ hiểu, ít bị sai sót. Ở ví dụ này chỉ có hai chuỗi cho nên chưa thấy gì. Khi phải gộp 5 chuỗi trở lên thì sẽ thấy cái lợi.
Vầng,cháu cảm ơn chú đã góp ý.
 
Upvote 0
Code của bạn rất khá, thử viết lại code với dữ liệu không được xếp thứ tự
Cháu cảm ơn chú đã nhận xét và đưa thêm yêu cầu tổng quát hơn.
Với dữ liệu và yêu cầu của bạn chủ thớt ban đầu có lẽ tất cả cũng đã đủ, nhưng với yêu cầu thêm như dữ liệu chưa được sắp xếp thì cháu sẽ làm như sau:
Khai báo thêm một mảng đặt là: dulieugoc
B1: Gán dữ liệu chưa sắp xếp vào mảng dulieugoc
B2: Sắp xếp dữ liệu trên bảng tính (điều kiện sort itemCode)
B3: Vẫn là code cũ (gán dữ liệu đã sắp xếp vào mảng data rồi làm như bài 22)
B4: gán dữ liệu trong mảng dulieugoc chèn lên bảng dữ liệu đã được sắp xếp trở lại vị trí gốc.

Nếu viết thì cháu sẽ viết như vậy,nói gì thì nói dữ liệu phải sắp xếp trước thì cháu mới làm được còn không cháu chịu thua.
Ở đây có nhiều Sao lớn quá,cháu xin phép ngồi ngoài học hỏi thôi, không dám phát biểu gì nữa.
 
Lần chỉnh sửa cuối:
Upvote 0
...
Ở đây có nhiều Sao lớn quá,cháu xin phép ngồi ngoài học hỏi thôi, không dám phát biểu gì nữa.
Cách cho sao, huân chương của diễn đàn này nó sến như cải lương.

Vả lại, sao lớn và sáng quá thì càng đáng lo ngại. Có thể đó là ngôi sao đã đến lúc hết đời và đang nổ tung. Nếu bạn không hiểu tôi nói gì thì nên tìm tài liệu về supernova (siêu tân tinh)
 
Upvote 0
Cháu cảm ơn chú đã nhận xét và đưa thêm yêu cầu tổng quát hơn.
Với dữ liệu và yêu cầu của bạn chủ thớt ban đầu có lẽ tất cả cũng đã đủ, nhưng với yêu cầu thêm như dữ liệu chưa được sắp xếp thì cháu sẽ làm như sau:
Khai báo thêm một mảng đặt là: dulieugoc
B1: Gán dữ liệu chưa sắp xếp vào mảng dulieugoc
B2: Sắp xếp dữ liệu trên bảng tính (điều kiện sort itemCode)
B3: Vẫn là code cũ (gán dữ liệu đã sắp xếp vào mảng data rồi làm như bài 22)
B4: gán dữ liệu trong mảng dulieugoc chèn lên bảng dữ liệu đã được sắp xếp trở lại vị trí gốc.
Đó cũng là cách hiệu quả, chỉ cần ra kết quả đúng và mình hiểu được cách làm là tốt rồi
Tuy nhiên đã xếp thứ tự thì không nên dùng dic mà sử dụng thuần mảng như bạn @VetMini từng hướng dẫn, ý mình là không cần bước xếp thứ tự và dùng dic để xử lý, tuy khó 1 chút nhưng kỷ năng dùng dic sẽ thuần thục hơn
Trước đây mình hầu như không biết các lệnh VBA, chỉ dùng bộ thu macro rồi chỉnh sửa tí xíu chạy theo ý mình, từ từ bắt chước code của các bạn trên diễn đàn, được mọi người gợi ý các tình huống xử lý dần dần mới quen các lệnh. Từ lúc có các loạt bài viết https://www.giaiphapexcel.com/diendan/threads/index-các-bài-viết-về-vba.129388/ của bạn @befaint mình mới biết được phần nào các lệnh VBA
 
Upvote 0
Đó cũng là cách hiệu quả, chỉ cần ra kết quả đúng và mình hiểu được cách làm là tốt rồi
Tuy nhiên đã xếp thứ tự thì không nên dùng dic mà sử dụng thuần mảng như bạn @VetMini từng hướng dẫn, ý mình là không cần bước xếp thứ tự và dùng dic để xử lý, tuy khó 1 chút nhưng kỷ năng dùng dic sẽ thuần thục hơn
Trước đây mình hầu như không biết các lệnh VBA, chỉ dùng bộ thu macro rồi chỉnh sửa tí xíu chạy theo ý mình, từ từ bắt chước code của các bạn trên diễn đàn, được mọi người gợi ý các tình huống xử lý dần dần mới quen các lệnh. Từ lúc có các loạt bài viết https://www.giaiphapexcel.com/diendan/threads/index-các-bài-viết-về-vba.129388/ của bạn @befaint mình mới biết được phần nào các lệnh VBA
Tuy bác Hiếu nói là mới học VBA, nhưng em cực kỳ nể phục tư duy của bác. Code chỉ là công cụ để viết ra tư duy của mình. Trong số các bác, các thầy trên GPE này, thì bác là một trong số những người em cực kỳ ngưỡng mộ!
 
Upvote 0
Tuy bác Hiếu nói là mới học VBA, nhưng em cực kỳ nể phục tư duy của bác. Code chỉ là công cụ để viết ra tư duy của mình. Trong số các bác, các thầy trên GPE này, thì bác là một trong số những người em cực kỳ ngưỡng mộ!
Cha nội này có tư duy toán ứng dụng khá cao (*1)
Bạn để ý sẽ thấy va chỉ nắm một mớ căn bản về lập trình. Chỗ còn lại là do tư duy thuật toán. Nhưng cái quan trọng nhất là tất cả những người lập trình giỏi đều có chí kiên trì: cái gì không biết thì thử; thử đi thử lại cỡ chục lượt thì biết. Và tôi nói "tất cả", không phải "hầu hết".

Nếu tôi là bạn hay tác giả bài #22, tức là người tự nhận mình "mới học VBA", thì tôi tìm tài liệu học những hàm căn bản của VBA. Viết một số code test chúng thâtk kỹ để hiểu rõ cách hoạt động của chúng.
Gợi ý: có một số hàm hoạt động không hoàn toàn như quý vị nghĩ. Hàm VBA và hàm bảng tính có thể tên gióng nhau nhưng hoạt động khác nhau.

(*1) tôi cũng chẳng hiểu sao có một thành viên hạng chiến trong GPE này đặt câu hỏi "ngày xưa hì hục học Toán cho thật cao rồi ra đời có thấy sử dụng vào đâu?".
Toán là một nghệ thuật tư duy lô gic. Học lên càng cao thì khả năng lô ngic càng phát triển cả bề sâu lẫn bề rộng.
Bạn nào không hiểu bề sâu và bề rộng là gì thì chịu khó học Toán lên cao :p
 
Upvote 0
Cháu cảm ơn chú đã nhận xét và đưa thêm yêu cầu tổng quát hơn.
Với dữ liệu và yêu cầu của bạn chủ thớt ban đầu có lẽ tất cả cũng đã đủ, nhưng với yêu cầu thêm như dữ liệu chưa được sắp xếp thì cháu sẽ làm như sau:
Khai báo thêm một mảng đặt là: dulieugoc
B1: Gán dữ liệu chưa sắp xếp vào mảng dulieugoc
B2: Sắp xếp dữ liệu trên bảng tính (điều kiện sort itemCode)
B3: Vẫn là code cũ (gán dữ liệu đã sắp xếp vào mảng data rồi làm như bài 22)
B4: gán dữ liệu trong mảng dulieugoc chèn lên bảng dữ liệu đã được sắp xếp trở lại vị trí gốc.

Nếu viết thì cháu sẽ viết như vậy,nói gì thì nói dữ liệu phải sắp xếp trước thì cháu mới làm được còn không cháu chịu thua.
Ở đây có nhiều Sao lớn quá,cháu xin phép ngồi ngoài học hỏi thôi, không dám phát biểu gì nữa.
Gởi bạn code dùng 2 dic cho trường hợp không xếp thứ tự bài #32
Mã:
Sub XYZ()
  Dim sh As Worksheet, dic As Object, dicSP As Object, sarr(), S, res()
  Dim sRow&, i&, k&, sp, sp_vt$
 
  Set dicSP = CreateObject("scripting.dictionary")
  Set dic = CreateObject("scripting.dictionary")
  Set sh = Sheets("Sheet1")
  sarr = sh.Range("D2", sh.Range("F" & Rows.count).End(xlUp)).Value
  sRow = UBound(sarr)
  ReDim res(1 To sRow, 1 To 3)
  For i = 1 To sRow
    sp = sarr(i, 3)
    sp_vt = sp & "|" & sarr(i, 1)
    If dic.exists(sp_vt) = False Then dicSP.Item(sp) = dicSP.Item(sp) & "^" & sp_vt
    dic.Item(sp_vt) = dic.Item(sp_vt) + 1
  Next i
  For Each sp In dicSP.keys
    res(k + 1, 1) = sp
    S = Split(dicSP.Item(sp), "^")
    For i = 1 To UBound(S)
      k = k + 1
      res(k, 2) = Split(S(i), "|")(1)
      res(k, 3) = dic.Item(S(i))
    Next i
  Next sp
  sh.Range("L6").Resize(1000, 3).ClearContents
  sh.Range("L6").Resize(k, 3).Value = res
End Sub
 
Upvote 0
Mã:
Sub XYZ()
...
    S = Split(dicSP.Item(sp), "^")
    For i = 1 To UBound(S)
      k = k + 1
      res(k, 2) = Split(S(i), "|")(1)
      res(k, 3) = dic.Item(S(i))
    Next i
...

For Each sp In Split(Mid(dicSP.Item(sp),2), "^")
k = k + 1
res(k, 2) = Split(sp, "|")(1)
res(k, 3) = dic.Item(sp)
Next sp
 
Upvote 0
Web KT

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

Back
Top Bottom