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

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ị
 
Bài toán gốc của bài này không phải đơn giản

Theo tôi biết, tác giả đưa đầu bài không rõ ràng, dẫn đến lời giải chưa tính đến các ô màu đỏ trong đầu đề bài toán:

- Đối với vật liệu, nhân công, máy đều có hệ số (1; 3,36; 1,4) nên sau khi tổng cộng phải nhân với hệ số
- Đối với vật liệu khác: được tính bằng 1,5% các vật liệu chính;
- Bài toán gốc trên diễn đàn thì mỗi công việc đều có Chi phí trực tiếp khác xác định bằng 1,5%(VL+NC+MTC)

Kết quả đúng bài toán sẽ hình sau
Baitoangoc.jpg




Tôi làm thử nhưng viết Code để tính thành phần chí phí trực tiếp khác nhưng làm mãi không được, kính nhờ các bác giúp cho một tay.
 

File đính kèm

  • Bai toan goc.xls
    37 KB · Đọc: 27
Upvote 0
Theo tôi biết, tác giả đưa đầu bài không rõ ràng, dẫn đến lời giải chưa tính đến các ô màu đỏ trong đầu đề bài toán:
.

Cho mình hỏi không phải một chút bài này bắt đầu từ đâu nhỉ. mong mọi người chỉ giúp
Xin lỗi mọi người chắc mình quá vô duyên!:=\+
 
Lần chỉnh sửa cuối:
Upvote 0
Tức bài này điền dữ liệu vào cột I đối với từng công việc chị ah (hình trên là kết quả minh hoạ), số dòng cần điền rất nhiều, mong chị giúp cho.
 
Upvote 0
Mình cũng chưa hiểu rõ ý bạn lắm nhưng mình cũng làm tạm một file Excel theo công việc mà bạn nêu ra, bạn có thể thay đổi dữ liệu cho phù hợp với công việc của mình. Mình cũng chuyển tổng hợp sang Sheet "Du thau" các công việc. Bạn có thể kiểm tra thử
P\S: nhấn Ctrl + Q để chạy nhé chúc bạn thành công! --=0
 

File đính kèm

  • Bai toan goc.zip
    29.4 KB · Đọc: 45
Upvote 0
Tôi chưa hiểu về Sfomula = "=" & Right(str, Len(str) - 1), tại sao lại trừ 1? Mong chị Ngọc Lan và mọi người giải thích dùm
PHP:
Public Function Sfomula(ByVal MySheet As Worksheet, slower As Long, sUpper As Long) As String

    Dim i As Long, str As String

    str = ""

    For i = slower To sUpper

        Select Case MySheet.Cells(i, 4)
            Case UNC("VËt liÖu"), UNC("Nh©n c«ng"), UNC("M¸y thi c«ng"), UNC("Trùc tiÕp phÝ kh¸c")
                str = str + "+" + MySheet.Cells(i, 9).Address(0, 0)
        End Select

        If MySheet.Cells(i, 1) <> vbNullString Then Exit For

    Next

    Sfomula = "=" & Right(str, Len(str) - 1)

End Function
 
Upvote 0
Tôi chưa hiểu về Sfomula = "=" & Right(str, Len(str) - 1), tại sao lại trừ 1? Mong chị Ngọc Lan và mọi người giải thích dùm

Vì khi thực hiện lệnh trong vòng lặp str = str + "+" + MySheet.Cells(i, 9).Address(0, 0) biến str đã dư ra một dấu "+" đằng trước thôi mà
 
Upvote 0
Xin nhờ mọi người giải thích dùm đoạn Code:

PHP:
Function Dconcatenate(ParamArray cel() As Variant) As String
    For N = LBound(cel) To UBound(cel)
        For i = 1 To cel(N).Rows.Count
            For j = 1 To cel(N).Columns.Count
                Ketqua = Ketqua & "," & cel(N)(i, j)
            Next
        Next
        Ketquachung = Ketquachung & "," & Ketqua
    Next
    Ketquachung = Right(Ketquachung, Len(Ketquachung) - 2)
    Dconcatenate = Ketquachung
End Function

Tại sao dòng Right(Ketquachung, Len(Ketquachung) - 2) lại trừ đi 2 nhỉ?
 
Upvote 0
Xin nhờ mọi người giải thích dùm đoạn Code:

PHP:
Function Dconcatenate(ParamArray cel() As Variant) As String
    For N = LBound(cel) To UBound(cel)
        For i = 1 To cel(N).Rows.Count
            For j = 1 To cel(N).Columns.Count
                Ketqua = Ketqua & "," & cel(N)(i, j)
            Next
        Next
        Ketquachung = Ketquachung & "," & Ketqua
    Next
    Ketquachung = Right(Ketquachung, Len(Ketquachung) - 2)
    Dconcatenate = Ketquachung
End Function

Tại sao dòng Right(Ketquachung, Len(Ketquachung) - 2) lại trừ đi 2 nhỉ?

Bạn để ý 2 dòng này

PHP:
...
Ketqua = Ketqua & "," & cel(N)(i, j)
...
Ketquachung = Ketquachung & "," & Ketqua
Bạn sẽ thấy ban đầu, biến Ketqua không có gì hết nên nó sẽ có dạng là ",abcxyz"
Sau đó nạp vào biến Ketquachung mà Ketquachung ban đầu không có gì, thành ra nó sẽ là ",,abcxyz"
Do đó để kết quả đúng thì phải lấy từ bên phải qua mà Len(ketquachung)-2 đi tức là chỉ còn "abcxyz".
 
Upvote 0
Dictionary của em sai ở đâu mà không được nhỉ

Tập làm Dictionary, em làm thử lại ví dụ của thày Ndu nhưng không hiểu sao chạy không nổi vậy, xin được góp ý thêm để hoàn thiện Code (khi chạy nó báo #NAME?):

PHP:
Function UniqueList(SrcArray)
    Dim Item
    Set Dic = CreateObject("Scripting.Dictionary")
    Tmp = SrcArray.Value      'co tac dung chuyen Range thanh Variant
    For Each Item In Tmp
        If Not Dic.Exists(Item) And Item <> "" Then
            Dic.Add Item, ""
        End If
    Next
    UniqueList = .Keys
End Function
 
Lần chỉnh sửa cuối:
Upvote 0
Tập làm Dictionary, em làm thử lại ví dụ của thày Ndu nhưng không hiểu sao chạy không nổi vậy, xin được góp ý thêm để hoàn thiện Code (khi chạy nó báo #NAME?):
1. Function phải để trong module mới xài trên sheet được

2. Câu lệnh
UniqueList = .Keys
chắc chắn sẽ báo lỗi vì không có With - End With

3. Biến Tmp và biến Dic chưa khai báo

4. Do function sử dụng trên sheet (lấy value từ ScrArray), nên tốt hơn là nên khai báo
Function UniqueList(SrcArray As Range)

5. Nếu lấy Dic.Keys để gán xuống sheet, sẽ được kết quả nằm ngang. Tô dọc rồi gõ hàm sẽ chỉ ra kết quả đầu tiên.
 
Lần chỉnh sửa cuối:
Upvote 0
Tập làm Dictionary, em làm thử lại ví dụ của thày Ndu nhưng không hiểu sao chạy không nổi vậy, xin được góp ý thêm để hoàn thiện Code (khi chạy nó báo #NAME?):

PHP:
Function UniqueList(SrcArray)
    Dim Item
    Set Dic = CreateObject("Scripting.Dictionary")
    Tmp = SrcArray.Value      'co tac dung chuyen Range thanh Variant
    For Each Item In Tmp
        If Not Dic.Exists(Item) And Item <> "" Then
            Dic.Add Item, ""
        End If
    Next
    UniqueList = .Keys
End Function
UniqueList = .Keys là cái gì? Phải là UniqueList = Dic.Keys chứ
Ngoài ra nên sửa Tmp = SrcArray.Value thành Tmp = SrcArray (lỡ SrcArray không phải là Range thì câu lệnh ấy sẽ báo lỗi)
 
Upvote 0
PHP:
Function UniqueList(SrcArray)
    Dim Item
    Set Dic = CreateObject("Scripting.Dictionary")
    Tmp = SrcArray
    For Each Item In Tmp
        If Not Dic.Exists(Item) And Item <> "" Then
            Dic.Add Item, ""
        End If
    Next
    UniqueList = Dic.Keys
End Function

Lỗi Code thì thày Ndu đã nói ở trên rồi, nhưng bạn nhớ UniqueList = Dic.Keys nó là 1 mảng chứ không phải là 1 giá trị đơn đâu nhé.

Ví dụ: không dùng được UniqueList(A1:A3) trực tiếp đâu, mà cách dùng phải cho nó đi kèm với hàm nào đó ví dụ Counta(UniqueList(A1:A3)) hoặc là phải gán chuyển thành Range (thông qua thủ tục Sub).

Chú ý: Keys khác với key
 
Lần chỉnh sửa cuối:
Upvote 0
Lỗi Code thì thày Ndu đã nói ở trên rồi, nhưng bạn nhớ UniqueList = Dic.Keys nó là 1 mảng chứ không phải là 1 giá trị đơn đâu nhé.

Ví dụ: không dùng được UniqueList(A1:A3) trực tiếp đâu, mà cách dùng phải cho nó đi kèm với hàm nào đó ví dụ Counta(UniqueList(A1:A3)) hoặc là phải gán chuyển thành Range (thông qua thủ tục Sub).

Hàm mảng thì xài kiểu mảng chứ ai nói không được:

Có thể tô 10 ô hàng ngang và gõ = UniqueList(A1:A10), nhấn Ctrl Shift Enter
 
Upvote 0
Em thử làm truyền tham số bằng Sub, Code này của em chạy không hiểu sao ô cuối bằng #N/A
PHP:
Function UniqueList(SrcArray)
    Dim Item
    Set Dic = CreateObject("Scripting.Dictionary")
    tmp = SrcArray
    For Each Item In tmp
        If Not Dic.Exists(Item) And Item <> "" Then
            Dic.Add Item, ""
        End If
    Next
    UniqueList = Dic.Keys
End Function

PHP:
Sub Loc()
  Dim Arr, tmp, i As Long
  tmp = UniqueList(Sheet1.Range("A2:B50"))
  If IsArray(tmp) Then
    ReDim Arr(1 To UBound(tmp), 1 To 1)
    For i = 1 To UBound(tmp)
          Arr(i, 1) = tmp(i)
    Next
    Sheet2.Range("A1").Resize(i).Value = Arr
  End If
End Sub

-----------------
Em cứ có cảm giác có gì đó không ổn lắm, việc lặp lại 2 dòng này có vẻ như mâu thuẫn nhau thì phải
PHP:
tmp = SrcArray
xuống dưới lại có

PHP:
tmp = UniqueList(Sheet1.Range("A2:B50"))
 
Lần chỉnh sửa cuối:
Upvote 0
Em thử làm truyền tham số bằng Sub, Code này của em chạy không hiểu sao ô cuối bằng #N/A
PHP:
Function UniqueList(SrcArray)
    Dim Item
    Set Dic = CreateObject("Scripting.Dictionary")
    tmp = SrcArray
    For Each Item In tmp
        If Not Dic.Exists(Item) And Item <> "" Then
            Dic.Add Item, ""
        End If
    Next
    UniqueList = Dic.Keys
End Function

PHP:
Sub Loc()
  Dim Arr, tmp, i As Long
  tmp = UniqueList(Sheet1.Range("A2:B50"))
  If IsArray(tmp) Then
    ReDim Arr(1 To UBound(tmp), 1 To 1)
    For i = 1 To UBound(tmp)
          Arr(i, 1) = tmp(i)
    Next
    Sheet2.Range("A1").Resize(i).Value = Arr
  End If
End Sub

-----------------
Em cứ có cảm giác có gì đó không ổn lắm, việc lặp lại 2 dòng này có vẻ như mâu thuẫn nhau thì phải
PHP:
tmp = SrcArray
xuống dưới lại có

PHP:
tmp = UniqueList(Sheet1.Range("A2:B50"))
1. Bạn đưa file của bạn để mọi người test cho tiện. Khi code thực hiện
Sheet2.Range("A1").Resize(i).Value = Arr
thì i=Ubound(Tmp)+1 (mặt dù Fori=1 To UBound(tmp))
2. bạn sửa
Arr(i, 1) = tmp(i-1) vì Tmp() luôn bắt đầu bằng 0 chứ không phải là 1
 
Lần chỉnh sửa cuối:
Upvote 0
Theo tôi, bạn sửa thử thành thế này

PHP:
Function UniqueList(SrcArray)
    Dim Item
    Set Dic = CreateObject("Scripting.Dictionary")
    SubArr = SrcArray
    For Each Item In SubArr
        If Not Dic.Exists(Item) And Item <> "" Then
            Dic.Add Item, ""
        End If
    Next
    UniqueList = Dic.Keys
End Function

PHP:
Sub Loc()

    Dim Arr, tmp, i As Long
    tmp = UniqueList(Sheet1.Range("A2:B50"))
    ReDim Arr(1 To UBound(tmp) + 1, 1 To 1)
    For i = 0 To UBound(tmp)
        Arr(i + 1, 1) = tmp(i)
    Next
    Sheet2.Range("A1").Resize(i).Value = Arr
End Sub
 

File đính kèm

  • Loc duy nhat.xlsx
    8.5 KB · Đọc: 37
Upvote 0
Em chưa hiểu đoạn này, xin bác nói rõ giúp em hiểu với ah, đặc biệt là chỗ bôi đậm

1. Bạn đưa file của bạn để mọi người test cho tiện. Khi code thực hiện
Sheet2.Range("A1").Resize(i).Value = Arr
thì i=Ubound(Tmp)+1 (mặt dù Fori=1 To UBound(tmp))
 
Upvote 0
Em chưa hiểu đoạn này, xin bác nói rõ giúp em hiểu với ah, đặc biệt là chỗ bôi đậm
i sẽ tăng lên 1, sau đó mới kiểm tra nó thỏa mãn cận cuối không, nếu chưa đạt thì code chạy tiếp, ngược lại nó sẽ thoát vòng lập. Nghĩa là khi i=Ubound(Tmp) thì vẫn thỏa mãn nên code vẫn chạy, sau đó i tăng lên 1 là Ubound(Tmp)+1 vượt cận cuối nên thoát vòng For. lệnh cuối cùng liên quan đến i sẽ là Ubound(Tmp)+1 (ví dụ: For i=1 to 5, sau khi kết thúc vòng lập thì i=6 )
Tóm lại i tăng trước và kiểm tra điều kiện sau
 
Lần chỉnh sửa cuối:
Upvote 0
Phần mảng em vẫn còn lơ mơ, em Test thử thế này
PHP:
Sub thunghiem()
Set Vung = Range("A1:A100")
DL = Vung.Value
MsgBox UBound(DL, 1)
End Sub

Sao kết quả ra 100 nhỉ?

em cứ tưởng ra 99 vì phần tử đầu tiên nó là phần tử 0 chứ (vì mảng phần tử bắt đầu bao giờ cũng là 0 mà)?
 
Upvote 0
Phần mảng em vẫn còn lơ mơ, em Test thử thế này
PHP:
Sub thunghiem()
Set Vung = Range("A1:A100")
DL = Vung.Value
MsgBox UBound(DL, 1)
End Sub

Sao kết quả ra 100 nhỉ?

em cứ tưởng ra 99 vì phần tử đầu tiên nó là phần tử 0 chứ (vì mảng phần tử bắt đầu bao giờ cũng là 0 mà)?
Bạn chú ý Ubound() là phần tử cuối cùng chứ không phải là số phần tử, số phần tử = Ubound()-Lbound()+1, trường hợp trên 100 là đúng rồi, phần tử đầu tiên là 1, phần tử cuối là 100
 
Upvote 0
Web KT

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

Back
Top Bottom