MS Office Forum / Excel / New Users / August 2007
Stumped 2
|
|
Thread rating:  |
efreedland@gmail.com - 31 Jul 2007 21:20 GMT Is there a way to extend solution(s) in thread "Stumped" to accomodate a situation that follows:
A B C Key Input Desired Solution
X1 10 10 X2 -2 0 X3 5 5 X1 3 13 X1 -15 0 X2 3 3 X2 -5 0 X3 -7 0 X1 10 10 X1 -7 3 X1 8 11 X3 -2 0 X3 5 5 X2 -4 0 X1 -6 5 X1 -7 0 X1 4 4 X1 4 8
Thanks.
Sandy Mann - 31 Jul 2007 22:28 GMT There may be better way but:
with the data in A2:B19 enter in C2: =MAX(B2,0)
then in C3 aray enter, (Ctrl + Shift + Enter):
=IF(MAX(($A$2:A2=A3)*(ROW($A$2:A2))),MAX(INDIRECT("D"&MAX(($A$2:A2=A3)*(ROW($A$2:A2))))+B3,0),MAX(B3,0)) and copy down using the fill handle. If entered correctly XL will but curly braces {=Formula} around the formula
 Signature HTH
Sandy In Perth, the ancient capital of Scotland and the crowning place of kings
sandymann2@mailinator.com Replace @mailinator.com with @tiscali.co.uk
> Is there a way to extend solution(s) in thread "Stumped" to accomodate > a situation that follows: [quoted text clipped - 22 lines] > > Thanks. Bernd P - 01 Aug 2007 06:06 GMT Hello,
Put into C3:
=IF(ISERROR(MATCH(A3,A$2:A2,)),MAX(B3,0),MAX(INDEX(C:C,LOOKUP(2,1/(A3=A $2:A2),ROW(A$2:A2)))+B3,0))
No array formula and twice as fast.
Regards, Bernd
efreedland@gmail.com - 01 Aug 2007 14:46 GMT It works. Very efficient. Thank you.
> Hello, > [quoted text clipped - 7 lines] > Regards, > Bernd Harlan Grove - 03 Aug 2007 08:26 GMT "Bernd P" <bplumhoff@gmail.com> wrote...
>Put into C3: > >=IF(ISERROR(MATCH(A3,A$2:A2,)),MAX(B3,0),MAX(INDEX(C:C, >LOOKUP(2,1/(A3=A$2:A2),ROW(A$2:A2)))+B3,0)) ...
Could be shortened. With C2 containing
=MAX(B2,0)
make C3
=MAX(IF(COUNT(MATCH(A3,A$2:A2,0)),LOOKUP(2,1/(A$2:A2=A3),C$2:C2),0)+B3,0)
Bernd P - 26 Aug 2007 16:02 GMT Hi Harlan,
That's a good one.
It would be nice if we could trick our search values to the beginning of the arrays, but this would involve a UDF, as it seems:
=MAX($B3+LOOKUP(2,1/($A3=myarray($A3,$A$2:$A2)),myarray(0,C$2:C2)),0)
Function myarray(ParamArray v() As Variant) As Variant Dim v1 As Variant, v2 As Variant Dim i As Long, idim As Long idim = 100 ReDim vR(idim) As Variant On Error GoTo newdim i = 0 For Each v1 In v If IsArray(v1) Then For Each v2 In v1 vR(i) = v2 i = i + 1 Next v2 Else vR(i) = v1 i = i + 1 End If Next v1 myarray = vR Exit Function newdim: idim = 10 * idim ReDim Preserve vR(idim) As Variant vR(i) = v2 'repeat statement which went wrong Resume Next End Function
Regards, Bernd
Harlan Grove - 27 Aug 2007 06:45 GMT Bernd P <bplumh...@gmail.com> wrote... ...
>It would be nice if we could trick our search values to the >beginning of the arrays, but this would involve a UDF, as it >seems: > >=MAX($B3+LOOKUP(2,1/($A3=myarray($A3,$A$2:$A2)), >myarray(0,C$2:C2)),0) ...
Why? Certainly not for recalc speed. UDFs are slow due to the Excel/ VBA interface.
Bernd P - 27 Aug 2007 09:44 GMT To save one "IF" in our formula. Excel seems to lack an ARRAY worksheet function. With such an internal function this would be another approach...
Regards, Bernd
Harlan Grove - 27 Aug 2007 19:17 GMT Bernd P <bplumh...@gmail.com> wrote...
>To save one "IF" in our formula. Excel seems to lack an ARRAY >worksheet function. With such an internal function this would be >another approach... To save one IF call at what cost?
My formula, reformatted: =MAX( IF( COUNT( MATCH(A3,A$2:A2,0) ), LOOKUP(2,1/(A$2:A2=A3),C$2:C2), 0 )+B3, 0 )
5 function calls, 3 levels of nested function calls.
Your formula, reformatted: =MAX( $B3+ LOOKUP( 2, 1/($A3=myarray($A3,$A$2:$A2)), myarray(0,C$2:C2) ), 0 )
4 function calls, 2 levels of nested function calls.
One fewer function call, but 2 of the remaining function calls are udf calls. Guaranteed to be slower.
I could drop a function call from my formula, make it slower, but still avoid udfs.
C2 formula remains =MAX(B2,0), but C3 formula becomes (reformatted)
=MAX( IF( COUNTIF(A$2:A2,A3), LOOKUP(2,1/(A$2:A2=A3),C$2:C2), 0 )+B3, 0 )
4 function calls, 2 levels of nested function calls. The COUNTIF call is usually going to be slower than COUNT(MATCH(..)) because the former will always iterate through the entire A$2:A# range while the MATCH call in the latter will only do so on the first instance of each new Key, but will exit as soon as it finds the key thereafter.
If you like elegant formulas and lethargic recalculation, fine for you, but others should be warned that udfs are ALWAYS slow and only make sense when either absolutely necessary (providing functionality that can't actually be provided by built-in functions) or when one udf would do the work of at least 6 (yes, SIX) built-in functions. Otherwise, the udf performance trade-off just isn't worth it.
Bernd P - 27 Aug 2007 20:26 GMT Hello Harlan,
Did you read the word "would" in my two recent news articles? It appeared 3 times ...
Regards, Bernd
Harlan Grove - 27 Aug 2007 21:04 GMT Bernd P <bplumh...@gmail.com> wrote...
>Did you read the word "would" in my two recent news articles? It >appeared 3 times ... I did. I disagree that it *WOULD* be a better idea to use your formula if there WERE a built-in function like your myarray udf because
IF(condition,simple_lookup,0)
would still be more efficient than
lookup_involving_augmented_arrays
What *WOULD* be nicer is 'reverse' searching and lookup functions that would search from right to left or bottom to top, e.g., VLOOKUPREV that *WOULD* search from bottom to top of the 1st column of its 2nd argument. That *COULD* be used as
C3: =MAX(IFERROR(VLOOKUPREV(A3,A$2:C2,3,0),0)+B3,0)
also making use of Excel 12's IFERROR function.
Bernd P - 28 Aug 2007 07:28 GMT Hello Harlan,
That's a fair point. But it's a different one.
Regards, Bernd
efreedland@gmail.com - 01 Aug 2007 14:56 GMT Sandy.
Your solution works, but use of arrays makes it very slow... on a set of 3000+ records, prohibitively so.
Just the same, thank you for your help.
Eduard
> There may be better way but: > [quoted text clipped - 49 lines] > > - Show quoted text - Sandy Mann - 01 Aug 2007 16:10 GMT You're welcome Edward?
I did say that there may be better ways........
 Signature Regards,
Sandy In Perth, the ancient capital of Scotland and the crowning place of kings
sandymann2@mailinator.com Replace @mailinator.com with @tiscali.co.uk
Sandy.
Your solution works, but use of arrays makes it very slow... on a set of 3000+ records, prohibitively so.
Just the same, thank you for your help.
Eduard
Pete_UK - 31 Jul 2007 22:46 GMT Does the key here represent 3 different sequences? It looks like you have:
X1 --> 10,13, 0, 10, 3, 11, 5, 0, 4, 8 X2 --> 0, 3, 0, 0 X3 --> 5, 0, 0, 5
where each sequence gets reset to 0 if the cumulative sum goes negative, as before. However, it could also be concluded that there are two sequences - one for X1 and a combined one for X2 and X3, such that if the key is X2 or X3 and B is negative then the (composite) sequence gets set to 0, otherwise it is set to the value in B. Maybe there are not enough examples of X2 and X3 in your sample.
Please advise.
Pete
On Jul 31, 9:20 pm, efreedl...@gmail.com wrote:
> Is there a way to extend solution(s) in thread "Stumped" to accomodate > a situation that follows: [quoted text clipped - 22 lines] > > Thanks. efreedland@gmail.com - 31 Jul 2007 22:56 GMT Each distinct Key represents a distinct sequence.
> Does the key here represent 3 different sequences? It looks like you > have: [quoted text clipped - 44 lines] > > - Show quoted text -
|
|
|