2013-08-11 41 views
12

Tôi nhận được một nhóm ô và thực hiện một số phép tính trên chúng theo hàm bên dưới.vba chuyển một nhóm ô làm phạm vi hoạt động

Nó hoạt động nếu tôi vượt qua một phạm vi (với : ký) làm tham số đầu tiên, nhưng không thành công nếu tôi chọn một số ô làm dải ô (A1, A3, B6, B9). Nó chỉ nhận được ô đầu tiên trước dấu phẩy là tham số đầu tiên. Nhưng tôi muốn toàn bộ tế bào.

Tôi có thể làm gì? (Ngoại trừ sử dụng dây cho các phạm vi đi qua)

Function calculateIt(Sessions As Range, Customers As Range) As Single 
    ' calculate them... 
End Function 

Một điều nữa: Có thể vượt qua một nhóm phạm vi như một tham số? làm sao?

+0

Là một thay thế cho ParamArray, có thể gán một tên được xác định cho tập hợp các ô tách rời và chuyển tên. –

Trả lời

19

Khi được viết, hàm của bạn chỉ chấp nhận hai phạm vi làm đối số.

Để cho phép một số phạm vi biến được sử dụng trong hàm, bạn cần khai báo một mảng biến thể ParamArray trong danh sách đối số của bạn. Sau đó, bạn có thể xử lý từng dãy trong dãy lần lượt.

Ví dụ,

Function myAdd(Arg1 As Range, ParamArray Args2() As Variant) As Double 
    Dim elem As Variant 
    Dim i As Long 
    For Each elem In Arg1 
     myAdd = myAdd + elem.Value 
    Next elem 
    For i = LBound(Args2) To UBound(Args2) 
     For Each elem In Args2(i) 
      myAdd = myAdd + elem.Value 
     Next elem 
    Next i 
End Function 

Chức năng này sau đó có thể được sử dụng trong bảng tính để thêm nhiều dãy.

myAdd usage

Đối với chức năng của bạn, đó là câu hỏi mà các phạm vi (hoặc các tế bào) có thể truyền cho hàm là 'phiên' và đó là 'Khách hàng'.

Trường hợp dễ nhất để giải quyết sẽ là nếu bạn quyết định phạm vi đầu tiên là Phiên và bất kỳ phạm vi tiếp theo nào là Khách hàng.

Function calculateIt(Sessions As Range, ParamArray Customers() As Variant) As Double 
    'This function accepts a single Sessions range and one or more Customers 
    'ranges 
    Dim i As Long 
    Dim sessElem As Variant 
    Dim custElem As Variant 
    For Each sessElem In Sessions 
     'do something with sessElem.Value, the value of each 
     'cell in the single range Sessions 
     Debug.Print "sessElem: " & sessElem.Value 
    Next sessElem 
    'loop through each of the one or more ranges in Customers() 
    For i = LBound(Customers) To UBound(Customers) 
     'loop through the cells in the range Customers(i) 
     For Each custElem In Customers(i) 
      'do something with custElem.Value, the value of 
      'each cell in the range Customers(i) 
      Debug.Print "custElem: " & custElem.Value 
     Next custElem 
    Next i 
End Function 

Nếu bạn muốn bao gồm bất kỳ số lượng phiên dao động và bất kỳ số lượng khách hàng dao động, sau đó bạn sẽ phải bao gồm một cuộc tranh cãi rằng sẽ cho các chức năng để nó có thể tách các phiên dao động từ khách hàng dao động.

Đối số này có thể được thiết lập làm đối số đầu tiên, số, đối số cho hàm sẽ xác định số lượng đối số sau là Phạm vi phiên, với các đối số còn lại là phạm vi Khách hàng. Chữ ký của hàm sẽ là:

Function calculateIt(numOfSessionRanges, ParamAray Args() As Variant) 

Hoặc có thể là đối số "bảo vệ" phân tách phạm vi phiên từ phạm vi Khách hàng. Sau đó, mã của bạn sẽ phải kiểm tra từng đối số để xem đó có phải là người bảo vệ không. Các chức năng sẽ trông như thế:

Function calculateIt(ParamArray Args() As Variant) 

Có lẽ với một cái gì đó gọi như:

calculateIt(sessRange1,sessRange2,...,"|",custRange1,custRange2,...) 

sau đó các chương trình logic có thể là dọc theo dòng:

Function calculateIt(ParamArray Args() As Variant) As Double 
    ... 
    'loop through Args 
    IsSessionArg = True 
    For i = lbound(Args) to UBound(Args) 
     'only need to check for the type of the argument 
     If TypeName(Args(i)) = "String" Then 
      IsSessionArg = False 
     ElseIf IsSessionArg Then 
      'process Args(i) as Session range 
     Else 
      'process Args(i) as Customer range 
     End if 
    Next i 
    calculateIt = <somevalue> 
End Function 
+0

Cảm ơn, nhưng có một chút không rõ ràng đối với tôi. Bạn có thể vui lòng cho tôi một ví dụ sử dụng? Nếu tôi muốn kết hợp hàm 'myAdd' với hàm' calculateIt', 'Arg1' sẽ là' Sessions' và 'Arg2' sẽ là' Customers'? – mrdaliri

+0

Chà! Tuyệt vời! sử dụng một đối số bảo vệ là câu trả lời. Cảm ơn, một lần nữa! – mrdaliri

+0

@chuff, tôi không nhận được bất kỳ kết quả nào. Tôi thậm chí đặt một 'Stop' trong mã, nhưng không ai trong số các đối số có thể được nhìn thấy trong * Cửa sổ ngay lập tức *. Chức năng cũng trả về 0. Bất kỳ ý tưởng gì sai ở đây? –

5

Có một cách khác để chuyển nhiều phạm vi cho một hàm, mà tôi cho rằng cảm thấy sạch hơn nhiều cho người dùng.Khi bạn gọi hàm của mình trong bảng tính, bạn quấn từng bộ phạm vi trong ngoặc vuông, ví dụ: calculateIt((A1,A3), (B6,B9))

Cuộc gọi trên giả định hai Phiên của bạn là A1 và A3 và hai Khách hàng của bạn ở B6 và B9.

Để thực hiện công việc này, chức năng của bạn cần lặp qua từng số Areas trong phạm vi nhập liệu. Ví dụ:

Function calculateIt(Sessions As Range, Customers As Range) As Single 

    ' check we passed the same number of areas 
    If (Sessions.Areas.Count <> Customers.Areas.Count) Then 
     calculateIt = CVErr(xlErrNA) 
     Exit Function 
    End If 

    Dim mySession, myCustomers As Range 

    ' run through each area and calculate 
    For a = 1 To Sessions.Areas.Count 

     Set mySession = Sessions.Areas(a) 
     Set myCustomers = Customers.Areas(a) 

     ' calculate them... 
    Next a 

End Function 

Điều thú vị là, nếu bạn có cả hai đầu vào của bạn là dải liền kề, bạn có thể gọi hàm này giống như bình thường, ví dụ: calculateIt(A1:A3, B6:B9).

Hy vọng rằng sẽ giúp :)

+0

Trong khi 'ParamArray' là một cách tốt để đi, tùy chọn này cung cấp một cách rất sạch sẽ cho các đối số nhiều ô. Đáng lẽ phải có nhiều phiếu bầu hơn ... –

Các vấn đề liên quan