A complete working answer to the question have been found after some research (the most helpful in stackoverflow and contributors suggestions, thanks).
METHOD 1 (preferred)
The single cell CSE (array) formula below uses several variations of the following
=((ROW(INDIRECT("1:"& e1))>=lb1)*(ROW(INDIRECT("1:"& e1))<=ub1))
where e1
is the number of elements in the 1-column array and lb1
is the lower bound for which a 1 is required and ub1
is the upper bound, out of the bounds elements' value is 0.
OP data needs to be trivially converted to cumulative indices for proposed formula
P1 P2 P3 P1 P2 P3
i01 2 6 6 i01 20.0 20.6
i02 3 3 3 i02 10.0
i03 2 9 18 i03 30.0 30.4 30.2
i04 4 6 6 i04 15.0 15.1
i05 5 5 5 i05 10.0
The following is a CSE formula to be applied over a range with the same number of columns as existing columns (sample above: 3 consecutive columns) and, then after inserting the formula in the formula bar, use ctrl-shift-enter.
Formula
{=TRANSPOSE(MMULT(TRANSPOSE(((ROW(INDIRECT("1:"&e1))>=IF(COLUMN(set_of_pos)-COLUMN(INDEX(set_of_pos;1;0)=0;0;OFFSET(set_of_pos;0;-1))+1)*(ROW(INDIRECT("1:"&e1))<=set_of_pos))*((ROW(INDIRECT("1:"&e1))>=x2+1)*(ROW(INDIRECT("1:"&e1))<=x1)));--(ROW(INDIRECT("1:"&e1))>0)))}
where e1
is the number of elements in the 1-column array (it's also the value at last position), x1
and x2
are refs to cells containing a start index and an end index; set_of_pos
is the RANGE that tells the last position of each in each section (for example, for i03: 2,9,18)
PARTS
((ROW(INDIRECT("1:"&e1))>=x2+1)*(ROW(INDIRECT("1:"&e1))<=x1)))
creates an (in-formula) array of a consecutive number of 1s (from booleans) bounded by 0s representing the indices that need to be kept or registered. (Dimensions e1 × 1.)
((ROW(INDIRECT("1:"&e1))>=IF(set_of_pos=1;0;OFFSET(set_of_pos;0;-1))+1)*(ROW(INDIRECT("1:"&e1))<=set_of_pos))
creates an (in-formula) array of dimensions e1 × columns(set_of_pos) in which each section cell expands the value into a stack of 1s. [In this part, for each column, upper bound is the actual value, and lower bound is the value to the left plus 1 - because set_of_pos is a RANGE, this is done for each column in set_of_pos as long as CSE is used to enter formula; nb: if it is the the leftmost cell, 0 is used instead.]
Then both parts are operated with *, thus obtaining an (in-formula) array of dimensions e1 × columns(set_of_pos) with the positions satisfying being in the section stack AND in the set of indices to be kept (conveniently separated in columns).
We need to TRANSPOSE this result obtaining an (in-formula) array of dimensions columns(set_of_pos) × e1. MMULT (and all-1s e1 × 1 defined by --(ROW(INDIRECT("1:"&e1))>0
) enables us to count the number of 1s for each column in a compressed array with the quantity in a different column [columns(set_of_pos) × 1]. [NB, we need to include double negative "--" to convert booleans into numbers as MMULT requires number array or else it throws an error - booleans are not accepted in MMULT, as per function specs.]
An additional transpose is required to put the array horizontally [1 × columns(set_of_pos)].
Now, final result is obtained by =SUMPRODUCT(previous_result;set_of_val)
where previous_result is the result from above and set_of_val is the RANGE with the values.
Having a way to preserve which stacks are modified serves other purposes (spent stacks can be computed) and obtaining the final result is a trivial application of function SUMPRODUCT. The number of columns or sections is not hardcoded - it is set by choosing the set_of_pos inside the formula range AND selecting the appropriate number of consecutive columns when applying the (CSE) array formula.
METHOD 2
For the sake of completeness, a second method has been explored. If that is thought to be less resource intensive, I would certainly like to know. My hunch is that it is more resource intensive albeit with less typing, but I have not been able to test it.
Basically, a string with all the values is built into a cell (for example, using REPT and pipes |, for i03 we would have "30.0|30.0|30.4|30.4|30.4|30.4|30.4|30.4|30.4|30.2|30.2|30.2|30.2|30.2|30.2|30.2|30.2|30.2|")
A working solution (CSE is not required - SUMPRODUCT takes care of the three 1-column arrays built adequately)
=SUMPRODUCT(((ROW(INDIRECT("1:"& e1))<=x1)*(ROW(INDIRECT("1:"&e1))>=x2+1))*TRIM(MID(SUBSTITUTE(s1;"|";REPT(" ";LEN(s1)));(ROW(INDIRECT("1:"& e1))-1)*LEN(s1)+1;LEN(s1))))
where x1, x2 and e1 are refs to cells containing a start index and an end index and the number of total elements (as defined above) and s1 is the string with all values in order.
PARTS
(ROW(INDIRECT("1:"& e1))<=x1)*(ROW(INDIRECT("1:"&e1))>=x2+1))
is essentially present in METHOD 1: an (in-formula) array of a consecutive number of 1s (from booleans) bounded by 0s representing the indices that need to be kept. (Dimensions e1 × 1.)
TRIM(MID(SUBSTITUTE(s1;"|";REPT(" ";LEN(s1)));(ROW(INDIRECT("1:"& e1))-1)*LEN(s1)+1;LEN(s1)))
The formula takes the string (s1) and replaces each separator with number of spaces equal to the length of the string, then places different sections on each element of the array created by ROW(INDIRECT("1:"& e1))
[A more general solution would have been to obtain the number of elements by getting the difference between the string and the string with delimiters taken out, but the number of elements is required in my little project and defined under the label e1. The technique is explained elsewhere, succinctly, places sections of of the length of the original string starting at the sequence number given by ROW(INDIRECT("1:"& e1)) times the length of the original string and then removing all surrounding spaces with TRIM.]
Acknowledgements and references
Thanks to answers and comments, it has been possible to locate two stackoverflow questions which have relevant comments:
https://stackoverflow.com/questions/25316094/split-a-string-cell-in-excel-without-vba-e-g-for-array-formula/25316426[enter link description here][1]
and
Is there a way to concatenate two arrays in Excel without VBA?
Both are a good read. Method 1 has been developed partly from scratch but Method 2 have been greatly improved by careful read, in particular, for converting a string into an in-formula array. ROW(INDIRECT()) has been chosen over SEQUENCE() as compatibility with Excel 2010 was desired.