2013-08-11 7 views
12

Otrzymuję grupę komórek i wykonuję dla nich obliczenia w funkcji poniżej.vba przekazuje grupę komórek jako zakres do funkcji

Działa, jeśli przekazałem zakres (z : znakiem) jako pierwszy parametr, ale nie powiedzie się, jeśli wybiorę niektóre komórki jako ich zakres (A1, A3, B6, B9). Po prostu jako pierwszą wartość pobiera pierwszą komórkę przed przecinkiem. Ale chcę całe komórki.

Co mogę zrobić? (Z wyjątkiem korzystania ciągi dla przechodzących zakresów)

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

Jedno więcej: Czy to możliwe, aby przejść do grupy zakresów jako parametr? w jaki sposób?

+0

Jako alternatywę dla ParamArray może można przypisać zdefiniowaną nazwę do swojego zbioru komórek rozłącznych i podać nazwę. –

Odpowiedz

19

Jak napisano, twoja funkcja przyjmuje tylko dwa zakresy jako argumenty.

Aby umożliwić stosowanie w funkcji zmiennej liczby zakresów, należy zadeklarować tablicę wariantów ParamArray na liście argumentów. Następnie możesz przetworzyć każdy z zakresów w tablicy po kolei.

Na przykład

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 

Funkcja ta może być następnie wykorzystane w arkuszu, aby dodać wiele zakresów.

myAdd usage

Na swojej funkcji, pojawia się pytanie, który z zakresów (lub komórek), które mogą przekazanych do funkcji są „Sesje”, a które „Klienci”.

Najprostszym rozwiązaniem będzie, jeśli zdecydujesz, że pierwszy zakres to Sesje, a kolejne kolejne to Klienci.

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 

Jeśli chcesz zawierać dowolną liczbę zakresów Sesje i dowolną liczbę Klientów wahać, a potem trzeba będzie to argument, który powie funkcję tak, że można go oddzielić sesji waha się od wahają klientów.

Ten argument może zostać ustawiony jako pierwszy, numeryczny, argument funkcji, która określałaby, ile z następujących argumentów to zakresy Sesji, a pozostałe argumenty niejawnie są zakresami klientów. podpis danej funkcji będzie wówczas:

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

Albo może to być „straż” Argument, że oddziela sesji waha się od zakresów klientów. Następnie twój kod będzie musiał przetestować każdy argument, aby sprawdzić, czy to był strażnik. Funkcja będzie wyglądać następująco:

Function calculateIt(ParamArray Args() As Variant) 

Może o czymś połączeń takich jak:

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

Logika program może następnie być wzdłuż linii:

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

Dzięki, ale dla mnie to trochę niejasne. Czy możesz podać przykład użycia? Jeśli chcę dopasować funkcję 'myAdd' do mojej funkcji' calculateIt', 'Arg1' będzie miała postać' Sesji', a 'Arg2' będzie' Klientami'? – mrdaliri

+0

Wow! Wspaniale! używanie argumentu strażnika jest odpowiedzią. Dzięki jeszcze raz! – mrdaliri

+0

@ Chuff, nie dostaję żadnego wyniku. Wpisałem nawet kod 'Stop', ale żaden z argumentów nie jest widoczny w * Immediate Window *. Funkcja zwraca także 0. Każdy pomysł, co jest tutaj nie tak? –

5

Jest jeszcze inny sposób przekazać wiele zakresów do funkcji, co moim zdaniem wydaje się dużo czystsze dla użytkownika.Kiedy wywołujesz swoją funkcję w arkuszu kalkulacyjnym, zawijasz każdy zestaw zakresów w nawiasach, na przykład: calculateIt((A1,A3), (B6,B9))

Powyższe wezwanie zakłada, że ​​twoje dwie sesje znajdują się w A1 i A3, a Twoi klienci są w B6 i B9.

Aby to zadziałało, funkcja musi przechodzić przez każdy z Areas w zakresie wejściowym. Na przykład:

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 

Zaletą jest, jeśli mają zarówno swoje wejść jako ciągły zakres, można wywołać tę funkcję tak samo jak normalny jeden, na przykład calculateIt(A1:A3, B6:B9).

nadzieję, że pomoże :)

+0

Podczas gdy 'ParamArray' to dobry sposób na przejście, ta opcja zapewnia bardzo czysty sposób dla argumentów wielokomórkowych. Powinien zdobyć o wiele więcej głosów ... –