Stumped 2

E

efreedland

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.
 
S

Sandy Mann

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


--
HTH

Sandy
In Perth, the ancient capital of Scotland
and the crowning place of kings

(e-mail address removed)
Replace @mailinator.com with @tiscali.co.uk
 
P

Pete_UK

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
 
B

Bernd P

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
 
E

efreedland

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
 
S

Sandy Mann

You're welcome Edward?

I did say that there may be better ways........

--
Regards,

Sandy
In Perth, the ancient capital of Scotland
and the crowning place of kings

(e-mail address removed)
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
 
H

Harlan Grove

Bernd P said:
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)
 
B

Bernd P

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
 
H

Harlan Grove

Bernd P said:
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.
 
B

Bernd P

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
 
H

Harlan Grove

Bernd P said:
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.
 
B

Bernd P

Hello Harlan,

Did you read the word "would" in my two recent news articles? It
appeared 3 times ...

Regards,
Bernd
 
H

Harlan Grove

Bernd P said:
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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top