Các câu hỏi về mảng trong VBA (Array)

  • Thread starter Thread starter viehoai
  • Ngày gửi Ngày gửi
Liên hệ QC

viehoai

Thành viên gắn bó
Tham gia
22/5/09
Bài viết
2,599
Được thích
2,908
Xin các anh chị giúp đỡ Code Gán các giá trị của một Range là các phần tử của Mãng
Ví dụ: Tôi có các giá trị của Range("A1:A10"). Tôi muốn viết code để gán giá trị của các cells từ A1:A10 là các phần tử của Mãng Arr chẳn hạn.
Xin cảm ơn các anh chị
 
Đây bạn xem.Có đúng không nhé.
Mã:
Sub doiulieu()
Dim arr, arr1, dic As Object, i As Long, lr As Long, j As Long, dk As String, dks As String, b As Long, c As Long, d As Long
Set dic = CreateObject("scripting.dictionary")
With Sheet1
     arr = .Range("D5:n9").Value
     For j = 1 To UBound(arr, 2)
         For i = 3 To UBound(arr, 1)
             dk = CLng(arr(1, j)) & "#" & arr(i, j)
             If Not dic.exists(dk) Then
                dic.Item(dk) = Array(i - 4, j)
             End If
         Next i
     Next j
     lr = .Range("D" & Rows.Count).End(xlUp).Row
     If lr < 11 Then Exit Sub
     arr = .Range("a11:N" & lr).Value
     For i = 1 To UBound(arr, 1)
         If Len(arr(i, 1)) > 0 Then
            If Not dic.exists(arr(i, 1)) Then
               dic.Add arr(i, 1), i
            End If
         End If
     Next i
     dk = CLng(.Range("T14").Value) & "#" & .Range("V14").Value
     dks = .Range("W14").Value
     If dic.exists(dk) Then
           b = dic.Item(dk)(0)
           c = dic.Item(dk)(1)
         If dic.exists(dks) Then
            d = dic.Item(dks)
            arr(b + d, c + 3) = .Range("u14").value
           End If
      End If
      .Range("a11:N" & lr).Value = arr
End With
End Sub
Dic thường dùng lưu dữ liệu và truy xuất nhiều lần, bài nầy chỉ tìm 1 lần, dùng Dic khá lãng phí, thử bỏ Dic code sẽ gọn và nhanh hơn
Trong code nên thêm phần thông báo không đổi được do trong ngày, nhóm đó không có ca tương ứng ;)
 
Upvote 0
Dic thường dùng lưu dữ liệu và truy xuất nhiều lần, bài nầy chỉ tìm 1 lần, dùng Dic khá lãng phí, thử bỏ Dic code sẽ gọn và nhanh hơn
Trong code nên thêm phần thông báo không đổi được do trong ngày, nhóm đó không có ca tương ứng ;)
Em có thử code không sử dụng Dic! Nhưng thấy nó nặng nề quá!

Mã:
Sub CA()

Dim Ngay As Variant, GT As Variant, CHUAN As Variant
Dim ARR3 As Variant
Dim i
Dim j
Dim k
Dim range1 As Range
Dim Arr8 As Variant
Ngay = Range("D5:N5").Value
CHUAN = Range("D7:N9").Value
GT = Range("D11:N13").Value
BT = Range("D15:N17").Value
MGT = Range("D19:N21").Value
MBT = Range("D23:N25").Value
QT = Range("D27:N29").Value
KT = Range("D31:N33").Value
arr = Range("W14").Value
For i = 1 To 11
    For j = 1 To 3
        For k = 1 To 4
            If Ngay(1, i) = Range("T14").Value Then
             
                For Each range1 In Range("A8:A32")
                        If range1.Value = Range("W14").Value Then                            ' xac dinh Group
                            row1 = range1.Row
                            col1 = range1.Column
                            Arr8 = Range(Cells(row1 - 1, 4), Cells(row1 + 1, 14)).Value  ' Xac dinh mang Group
                                If CHUAN(j, i) = Range("V14").Value Then                         'xác dinh Ca
                                    Arr8(j, i) = Range("U14").Value                                      ' add Name
                                    Range(Cells(row1 - 1, 4), Cells(row1 + 1, 14)).Value = Arr8

                                End If
                        End If
                Next range1
            End If


        Next k
    Next j

Next i
MsgBox ("Done")
End Sub
 

File đính kèm

Upvote 0
Đây bạn xem.Có đúng không nhé.
Mã:
Sub doiulieu()
Dim arr, arr1, dic As Object, i As Long, lr As Long, j As Long, dk As String, dks As String, b As Long, c As Long, d As Long
Set dic = CreateObject("scripting.dictionary")
With Sheet1
     arr = .Range("D5:n9").Value
     For j = 1 To UBound(arr, 2)
         For i = 3 To UBound(arr, 1)
             dk = CLng(arr(1, j)) & "#" & arr(i, j)
             If Not dic.exists(dk) Then
                dic.Item(dk) = Array(i - 4, j)
             End If
         Next i
     Next j
     lr = .Range("D" & Rows.Count).End(xlUp).Row
     If lr < 11 Then Exit Sub
     arr = .Range("a11:N" & lr).Value
     For i = 1 To UBound(arr, 1)
         If Len(arr(i, 1)) > 0 Then
            If Not dic.exists(arr(i, 1)) Then
               dic.Add arr(i, 1), i
            End If
         End If
     Next i
     dk = CLng(.Range("T14").Value) & "#" & .Range("V14").Value
     dks = .Range("W14").Value
     If dic.exists(dk) Then
           b = dic.Item(dk)(0)
           c = dic.Item(dk)(1)
         If dic.exists(dks) Then
            d = dic.Item(dks)
            arr(b + d, c + 3) = .Range("u14").value
           End If
      End If
      .Range("a11:N" & lr).Value = arr
End With
End Sub

Em có chỗ muốn hỏi! Mong anh giúp!
1.> Em giải nghĩa đoan code dưới các anh xem giúp em thế có đúng không ạ!

Mã:
dk = CLng(arr(1, j)) & "#" & arr(i, j)

             If Not dic.exists(dk) Then                         ' 

                dic.Item(dk) = Array(i - 4, j)

             End If

Em hiểu đoạn code trên là:
- Xét xem có key "dk" chưa nếu chưa thì gán cho key "dk" một item mảng: Array(i-4,j)
-
Để xác định vị trí của key "dk "ta dùng :
b = dic.Item(dk)(0) '
b: là giá trị của chiều thứ 1
c = dic.Item(dk)(1) ' c: là giá trị của chiều thứ 2
- Đôi với key "dks" item là một biến i nên để xác định ta dùng:
d = dic.Item(dks)

2.> Sao ta không dùng dấu "&" mà lại dùng dấu "#" ở đây: dk = CLng(arr(1, j)) & "#" & arr(i, j)
Có sự khác biệt gì không ạ!

Em cảm ơn các anh nhiều!
 
Upvote 0
Dic thường dùng lưu dữ liệu và truy xuất nhiều lần, bài nầy chỉ tìm 1 lần, dùng Dic khá lãng phí, thử bỏ Dic code sẽ gọn và nhanh hơn
Trong code nên thêm phần thông báo không đổi được do trong ngày, nhóm đó không có ca tương ứng ;)
Vậy bảo bạn đó là dữ liệu có thể thay thế nhiều lần cùng 1 lúc.Hihi.Cảm ơn anh nhé.
Bài đã được tự động gộp:

Em có chỗ muốn hỏi! Mong anh giúp!
1.> Em giải nghĩa đoan code dưới các anh xem giúp em thế có đúng không ạ!

Mã:
dk = CLng(arr(1, j)) & "#" & arr(i, j)

             If Not dic.exists(dk) Then                         '

                dic.Item(dk) = Array(i - 4, j)

             End If

Em hiểu đoạn code trên là:
- Xét xem có key "dk" chưa nếu chưa thì gán cho key "dk" một item mảng: Array(i-4,j)
-
Để xác định vị trí của key "dk "ta dùng :
b = dic.Item(dk)(0) '
b: là giá trị của chiều thứ 1
c = dic.Item(dk)(1) ' c: là giá trị của chiều thứ 2
- Đôi với key "dks" item là một biến i nên để xác định ta dùng:
d = dic.Item(dks)

2.> Sao ta không dùng dấu "&" mà lại dùng dấu "#" ở đây: dk = CLng(arr(1, j)) & "#" & arr(i, j)
Có sự khác biệt gì không ạ!

Em cảm ơn các anh nhiều!
Dùng cái gì phân cách cũng được nhé bạn.Miễn là nó ko bị trùng.
 
Upvote 0
Dic thường dùng lưu dữ liệu và truy xuất nhiều lần, bài nầy chỉ tìm 1 lần, dùng Dic khá lãng phí, thử bỏ Dic code sẽ gọn và nhanh hơn
Trong code nên thêm phần thông báo không đổi được do trong ngày, nhóm đó không có ca tương ứng ;)
Anh xem có đúng không nhé.
Mã:
Sub doiulieu()
Dim arr, arr1, dic As Object, i As Long, lr As Long, j As Integer, dk As Long, dks As String, b As Long, c As Long, d As Long
With Sheet1
     arr = .Range("D5:n9").Value
     lr = .Range("D" & Rows.Count).End(xlUp).Row
     If lr < 11 Then Exit Sub
     arr1 = .Range("a11:N" & lr).Value
     For i = 1 To UBound(arr, 2)
         If CLng(arr(1, i)) = CLng(.Range("T14")) Then
            For j = 3 To UBound(arr, 1)
                If UCase(arr(j, i)) = UCase(.Range("V14").Value) Then
                   For k = 1 To UBound(arr1, 1)
                       If UCase(arr1(k, 1)) = UCase(.Range("W14").Value) Then
                                arr1(j - 4 + k, i + 3) = .Range("U14").Value
                                dk = 1
                                Exit For
                       End If
                   Next k
                   Exit For
                End If
           Next j
           Exit For
        End If
    Next i
    If dk = 1 Then
      .Range("a11:N" & lr).Value = arr1
      MsgBox "da sua du lieu"
    Else
      MsgBox "khong tim thay"
   End If
End With
End Sub
 
Upvote 0
Anh xem có đúng không nhé.
Mã:
Sub doiulieu()
Dim arr, arr1, dic As Object, i As Long, lr As Long, j As Integer, dk As Long, dks As String, b As Long, c As Long, d As Long
With Sheet1
     arr = .Range("D5:n9").Value
     lr = .Range("D" & Rows.Count).End(xlUp).Row
     If lr < 11 Then Exit Sub
     arr1 = .Range("a11:N" & lr).Value
     For i = 1 To UBound(arr, 2)
         If CLng(arr(1, i)) = CLng(.Range("T14")) Then
            For j = 3 To UBound(arr, 1)
                If UCase(arr(j, i)) = UCase(.Range("V14").Value) Then
                   For k = 1 To UBound(arr1, 1)
                       If UCase(arr1(k, 1)) = UCase(.Range("W14").Value) Then
                                arr1(j - 4 + k, i + 3) = .Range("U14").Value
                                dk = 1
                                Exit For
                       End If
                   Next k
                   Exit For
                End If
           Next j
           Exit For
        End If
    Next i
    If dk = 1 Then
      .Range("a11:N" & lr).Value = arr1
      MsgBox "da sua du lieu"
    Else
      MsgBox "khong tim thay"
   End If
End With
End Sub
Hay quá anh! Cảm ơn anh nhiều!
 
Upvote 0

File đính kèm

Upvote 0
Em có một vấn đề mong các anh giải đáp giúp em!
Em có một vùng dữ liệu: Range(“B1:C10”) và em có hai cách xử lý:
-Cách 1:
Mã:
2.>    Theo Range:
Sub Test()
Dim range1 as range
For each range1 in Range(“B1:C10”)
    If range1.value = “ CAM ON GPE” then
                   Row1 = range1.row
                   Col1 = range1.column
    End if
Next range1
End sub

- Cách 2:

Mã:
Sub Test()
Dim Arr as variant
Arr = Range(“B1:D10”).value
For i = 1 to 10
       For j = 1 to 3
             If Arr( i,j) = “ CAM ON GPE” then
                    ‘  Row1= ?
                    ‘ Col1 = ?
            End if
       Next j
Next i
End sub
Vấn đề em muốn hỏi:
- Ở cách 1 khi xác định được range1 em có thể xác định được: Row1/Col1
- Em có thể tìm được Row1/Col1 bằng cách 2 không ạ? Mảng có cho ta tìm row/col như range không ạ?, ( không tính việc tìm bằng thủ công ạ)

Em cảm ơn!
 
Lần chỉnh sửa cuối:
Upvote 0
Anh xem có đúng không nhé.
Mã:
Sub doiulieu()
Dim arr, arr1, dic As Object, i As Long, lr As Long, j As Integer, dk As Long, dks As String, b As Long, c As Long, d As Long
With Sheet1
     arr = .Range("D5:n9").Value
     lr = .Range("D" & Rows.Count).End(xlUp).Row
     If lr < 11 Then Exit Sub
     arr1 = .Range("a11:N" & lr).Value
     For i = 1 To UBound(arr, 2)
         If CLng(arr(1, i)) = CLng(.Range("T14")) Then
            For j = 3 To UBound(arr, 1)
                If UCase(arr(j, i)) = UCase(.Range("V14").Value) Then
                   For k = 1 To UBound(arr1, 1)
                       If UCase(arr1(k, 1)) = UCase(.Range("W14").Value) Then
                                arr1(j - 4 + k, i + 3) = .Range("U14").Value
                                dk = 1
                                Exit For
                       End If
                   Next k
                   Exit For
                End If
           Next j
           Exit For
        End If
    Next i
    If dk = 1 Then
      .Range("a11:N" & lr).Value = arr1
      MsgBox "da sua du lieu"
    Else
      MsgBox "khong tim thay"
   End If
End With
End Sub
Hay lắm, code rất tường minh /-*+/
Dùng 3 Exit For hơi "sang trọng", thay bằng 1 Exit Sub sẽ gọn hơn nhiều :)
Bài đã được tự động gộp:

Em có một vấn đề mong các anh giải đáp giúp em!
Em có một vùng dữ liệu: Range(“B1:C10”) và em có hai cách xử lý:
-Cách 1:
Mã:
2.>    Theo Range:
Sub Test()
Dim range1 as range
For each range1 in Range(“B1:C10”)
    If range1.value = “ CAM ON GPE” then
                   Row1 = range1.row
                   Col1 = range1.column
    End if
Next range1
End sub

- Cách 2:

Mã:
Sub Test()
Dim Arr as variant
Arr = Range(“B1:D10”).value
For i = 1 to 10
       For j = 1 to 3
             If Arr( i,j) = “ CAM ON GPE” then
                    ‘  Row1= ?
                    ‘ Col1 = ?
            End if
       Next j
Next i
End sub
Vấn đề em muốn hỏi:
- Ở cách 1 khi xác định được range1 em có thể xác định được: Row1/Col1
- Em có thể tìm được Row1/Col1 bằng cách 2 không ạ? Mảng có cho ta tìm row/col như range không ạ?, ( không tính việc tìm bằng thủ công ạ)

Em cảm ơn!
Mã:
Sub Test()
Dim Arr as variant
Arr = Range(“B1:D10”).value
fRow = Range(“B1:D10”).Row
fCol = Range(“B1:D10”).Column
For i = 1 to 10
       For j = 1 to 3
             If Arr( i,j) = “ CAM ON GPE” then
                    Row1= i + fRow - 1
                    Col1 = j + fCol - 1
            End if
       Next j
Next i
End sub
 
Lần chỉnh sửa cuối:
Upvote 0
Hay lắm, code rất tường minh /-*+/
Dùng 3 Exit For hơi "sang trọng", thay bằng 1 Exit Sub sẽ gọn hơn nhiều :)
Bài đã được tự động gộp:


Mã:
Sub Test()
Dim Arr as variant
Arr = Range(“B1:D10”).value
fRow = Range(“B1:D10”).Row
fCol = Range(“B1:D10”).Column
For i = 1 to 10
       For j = 1 to 3
             If Arr( i,j) = “ CAM ON GPE” then
                    Row1= i + fRow - 1
                    Col1 = j + fCol - 1
            End if
       Next j
Next i
End sub
Đây là thắc mắc em đã tìm rất lâu mà chưa tìm ra! haha!
Giờ em mới biết có công thức cho tìm Row/col đầu tiên của Range().
Cảm ơn anh @HieuCD rất nhiều! ^_^!
 
Upvote 0
Dear Anh/ Chin trong topic.
Mọi người giúp em làm sao để kiểm tra một giá trị trong mảng.?
Giống dạng hàm in_array trong php của bên này https://cuongquach.com/kiem-tra-mot-gia-tri-mang-arrray-in_array-php.html
Liệu trong VBA có cách nào được như thế không ạ?
Cám ơn !
Cái này bạn phải viết 1 Function để kiểm tra nó có tồn tại hay không? VB không như Php không có những hàm đó
 
Upvote 0
Upvote 0
tìm hiểu ArrayList trong VBA là được, search trên GPE cũng có bài nói về đối tượng này
Theo e nghĩ vốn dĩ mình đã tạo một Array rồi, vì chỉ cần kiểm tra một giá trị trong array đó mà lại phải tạo thêm một ArrayList nữa thì có hơi bất cập quá không ?
Bthuong e dùng For duyệt qua các giá trị của Array vẫn đạt được kết quả, tuy nhiên với giá trị của Array nhiều nên muốn tham khảo một phương pháp dạng giống như Find hay Exist chẳng hạn để giảm bớt thủ tục.
Anh góp ý thêm ạ !
 
Upvote 0
Theo e nghĩ vốn dĩ mình đã tạo một Array rồi, vì chỉ cần kiểm tra một giá trị trong array đó mà lại phải tạo thêm một ArrayList nữa thì có hơi bất cập quá không ?
Bthuong e dùng For duyệt qua các giá trị của Array vẫn đạt được kết quả, tuy nhiên với giá trị của Array nhiều nên muốn tham khảo một phương pháp dạng giống như Find hay Exist chẳng hạn để giảm bớt thủ tục.
Anh góp ý thêm ạ !
Uhm, nếu muốn tìm hiểu thuật toán thì có thể tự viết - tìm hiểu các thuật toán tìm kiếm nhanh (duyệt cũng là 1 cách cơ bản và chậm, duyệt dạng nhị phân -thuật toán chia đôi, ...vv)
Muốn dùng công cụ nhanh gọn thì tìm hiểu ARRAYLIST - nó cũng là array, hay DICTIONARY, tùy bạn thôi, Lập trình là do ta chọn con đường
Find hay Exist - thì gốc người ta cũng phải viết code tìm kiếm thôi
 
Lần chỉnh sửa cuối:
Upvote 0
Dear Anh/ Chin trong topic.
Mọi người giúp em làm sao để kiểm tra một giá trị trong mảng.?
Giống dạng hàm in_array trong php của bên này https://cuongquach.com/kiem-tra-mot-gia-tri-mang-arrray-in_array-php.html
Liệu trong VBA có cách nào được như thế không ạ?
Cám ơn !
Chỉ xét mảng Arr 1 dòng hoặc 1 cột
Mảng 1 chiều
InStr(1, "#" & Join(Arr, "#") & "#", "#" & BienX & "#") > 0
Mảng 2 chiều
InStr(1, "#" & Join(Application.Transpose(Arr), "#") & "#", "#" & BienX & "#") > 0
 
Upvote 0
Em thấy hoang mang quá Anh
Nếu bạn học lập trình thì trong quá trình học, có môn cấu trúc dữ liệu, cái môn này nó chỉ cho bạn các kỹ thuật sắp xếp và tìm kiếm, bạn có thể vận dụng nó mà làm, bạn có thể chọn bất cứ thuật toán nào thuận tiện cho bạn cũng được, hiện tại máy tính mạnh và bạn không ứng dụng số liệu lớn nên có thể tìm thuật toán nào đó đơn giản để áp dụng vào, không có gì hoang mang đâu bạn
 
Upvote 0
Web KT

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

Back
Top Bottom