Jun 18 2021 05:49 PM
I am wondering if there is away to Split the Spill that comes from the Following ARRAY.
=SORT(FILTER(FILTER(TableHLP,TableHLP[District]=$A$7),{1,1,0,0,0,0,0,0}),1)
It produces a list of names and services that looks like something like this.
Name Services
John ABC
John DEF
John GHI
greg DEF
greg GHI
cindy ABC
Cindy GHI
There is about 100 Records. I would like to be able to split this Data 30 records on sheet1, 30 on sheet2 and 30 on sheet3. Is there a way to split the spill by providing a minimum and maximum range? Second question is there away to add a Space after each person. and remove duplicate names?
Example:
Name Services
John ABC
DEF
GHI
greg DEF
GHI
cindy ABC
GHI
I have tried a bunch of different things and have hit a wall. Any help would be greatly appreciated.
I am open to VBA or macros if the solution needs to go there.
Thanks,
Jun 19 2021 02:19 AM
SolutionOn each sheet you may use formulas like
=LET(k, SEQUENCE(ROWS(array)),
r, IF( (k >= minN)*(k <= maxN),
INDEX(array,k),
"remove"),
FILTER(r, r <> "remove"))
Jun 19 2021 09:20 PM
Jun 20 2021 10:33 AM
Formula could be like
=LET(
array, SORT(FILTER(FILTER(TableHLP,TableHLP[District]=$A$7),{1,1,0,1,1,1,1,1}),1),
k, SEQUENCE(ROWS(array)),
m, SEQUENCE(,COLUMNS(array)),
r, IF(k<5,INDEX(array,k,m),"remove"),
FILTER(r, INDEX(r, 0, 1) <> "remove")
)
Creating an array we already filtered columns. After that we check each element of it one by one returning it's value or "remove" depends on each row we check.
In general if return some columns using INDEX that will be like
=INDEX(Table1,SEQUENCE(ROWS(Table1)),{1,3,4})
Please check sample attached.
Jun 20 2021 04:06 PM
This is the Formula I ended up with trying to produce the end product I need. I will also attach and example file that shows what i have and what Im trying to obtain. Thanks again for your help.
=LET(
mtbl,TableHLP,mtbd,TableHLP[District],dis,B1,
array,SORT(FILTER(mtbl,mtbd=dis),1),
sf,FILTER(array,{0,0,0,0,1,0,0,0}),af,FILTER(array,{0,0,0,0,0,1,0,0}),rf,FILTER(array,{0,0,0,1,0,0,0,0}),tf,FILTER(array,{0,0,0,0,0,0,1,0}),
min,1,max,35,
k,SEQUENCE(ROWS(array)),ksf,SEQUENCE(ROWS(sf)),kaf,SEQUENCE(ROWS(af)),krf,SEQUENCE(ROWS(rf)),ktf,SEQUENCE(ROWS(tf)),
r,IF((k>=min)*(k<=max),INDEX(array,k),""),rsf,IF((ksf>=min)*(ksf<=max),INDEX(sf,ksf),""),raf,IF((kaf>=min)*(kaf<=max),INDEX(af,kaf),""),
rrf,IF((krf>=min)*(krf<=max),INDEX(rf,krf),""),rtf,IF((ktf>=min)*(ktf<=max),INDEX(tf,ktf),""),
report,FILTER(r,r<>""),reportser,FILTER(rsf,rsf<>""),reportatt,FILTER(raf,raf<>""),reportrat,FILTER(rrf,rrf<>""),reporttot,FILTER(rtf,rtf<>""),
stcnt,SORT(UNIQUE(report)),snct,COUNTA(stcnt),
rep,CHOOSE({1,2,3,4,5,6,7},report,reportser,reportatt,"",reportrat,"",reporttot),rep)
Jun 21 2021 01:07 AM
From my point of view that's bit overcomplicated, same result gives
=LET(
array, FILTER(TableHLP,TableHLP[District]=$B$1),
k, SEQUENCE(ROWS(array)),
minK, 1, maxK, 30,
col, {1,5,6,0,4,0,7,8},
res, IF( (k>=minK)*(k<=maxK),
IF(col=0, "", INDEX(array,k,col)),
"remove"),
FILTER(res, INDEX(res, 0, 1) <> "remove"))
please check in attached file.
Not sure right now how to empty repeated names, will play with it some later.
Jun 21 2021 02:48 AM
If skip repeated names
=LET(
array, SORT(FILTER(TableHLP,TableHLP[District]=$B$1)),
col, {1,5,6,0,4,0,7,8},
headers, IF(col=0, "", INDEX(TableHLP[#Headers], 1, col)),
n, ROWS(array),
k, SEQUENCE(n+1,,0,1),
minK, 1, maxK, 35,
res, IF(k=0, headers,
IF( (k>=minK)*(k<=maxK),
IF(col=0, "",
IF( (INDEX(array,k-1,col)=INDEX(array,k,col))*
((col=1)+(col=8))*
(k<>minK),
"", INDEX(array,k,col) ) ),
"remove")),
FILTER(res, (INDEX(res, 0, 1) <> "remove")+(INDEX(res, 0, 1) = "Name"))
)
which gives
Jun 21 2021 11:09 AM
Wow that formula is way cleaner than mine. Question is there away to drop the name total down to the end line of each Name? Also can we put a blank row in after each name? Thanks again for all your help. I really appreciate it.
Jun 21 2021 01:11 PM
Name Total to down could be
=LET(
array, SORT(FILTER(TableHLP,TableHLP[District]=$B$1)),
col, {1,5,6,0,4,0,7,8},
headers, IF(col=0, "", INDEX(TableHLP[#Headers], 1, col)),
n, ROWS(array),
k, SEQUENCE(n+2,,0,1),
minK, 1, maxK, MIN(35, n),
v, INDEX(array,k,col),
vPrev, INDEX(array,k-1,col),
vNext, INDEX(array,k+1,col),
res, IF(k=0, headers,
IF( (k>=minK)*(k<=maxK),
IF(col=0, "",
IF( (vPrev=v)*(col=1)* (k<>minK),
"",
IF( k<maxK,
IF( (vNext=v)*(col=8), "", v ),
v )
) ),
"remove")),
FILTER(res, (INDEX(res, 0, 1) <> "remove")+(INDEX(res, 0, 1) = "Name"))
)
result is
With empty row is more complex, we need to calculate number of names in given block and correctly work with bounds. Maybe next time.
As workaround you may apply conditional formatting to separate blocks with names, as variant
Jun 21 2021 06:52 PM
Thanks for your assistance again. I updated the code to count names to provide the min and max that way is doesn't cut off services. The only thing left is to add the row spacing. trying to use the same count function to do this. this is the code Im trying to use.
afu,UNIQUE(af),
cc,IF((af>=mins)*(af<=maxs),INDEX(afu,af),"remove"),ccr,FILTER(cc,(INDEX(cc,0,1)<>"remove")),
Im trying to take afu and add those to ccr to get the extra spacing.
The following is the updated code with the counting.
=LET(
array, SORT(FILTER(TableHLP,TableHLP[District]=$A$7)),array1,SORT(FILTER(FILTER(TableHLP,TableHLP[District]=$A$7),{1,0,0,0,0,0,0,0})),
col, {1,5,6,0,4,0,7,8},
mins,1,maxs,8,
suc, UNIQUE(array1),
af,MATCH(array1,suc,0),
cn,IF((af>=mins)*(af<=maxs),INDEX(suc,af),"remove"),cnt,FILTER(cn,(INDEX(cn,0,1)<>"remove")),
c, ROWS(cnt),
afu,UNIQUE(af),
cc,IF((af>=mins)*(af<=maxs),INDEX(afu,af),"remove"),ccr,FILTER(cc,(INDEX(cc,0,1)<>"remove")),
n, ROWS(array),
k, SEQUENCE(n+2,,0,1),
minK, 1, maxK, MIN(c, n),
v, INDEX(array,k,col),
vPrev, INDEX(array,k-1,col),
vNext, INDEX(array,k+1,col),
res, IF( (k>=minK)*(k<=maxK),
IF(col=0, "",
IF( (vPrev=v)*(col=1)* (k<>minK),
"",
IF( k<maxK,
IF( (vNext=v)*(col=8), "", v ),
v )
) ),
"remove"),
Final,FILTER(res, (INDEX(res, 0, 1) <> "remove")+(INDEX(res, 0, 1) = "Name")),
Final
)
I also attached the example with the updated code.
Thanks again.
Jun 22 2021 06:56 AM
I did that on mockup with the table (one block)
formula is
=LET(
array, Table1,
columnsToShow, {1,2,4},
columnNameTotal, 4,
arrayRows, ROWS(array),
names, INDEX(array, SEQUENCE(arrayRows),1),
distinct, UNIQUE(names),
distinctRows, ROWS(distinct),
startPos, INDEX( XMATCH(distinct, names),
SEQUENCE(,distinctRows-1,2)) +
SEQUENCE(,distinctRows-1,0),
enumPos, SEQUENCE( COLUMNS(startPos),,1,0),
k, SEQUENCE(arrayRows+distinctRows-1),
i, k - MMULT(--(k>startPos), enumPos ),
emptyPos, MMULT(--(k=startPos), enumPos ),
v, INDEX(array, i, columnsToShow),
vPrev, INDEX(array, i-1, columnsToShow),
vNext, INDEX(array, i+1, columnsToShow),
result, IF(
emptyPos, "",
IF( (vPrev=v)*(columnsToShow=1)*(i<>1), "",
IF( i < arrayRows,
IF( (vNext=v)*(columnsToShow=columnNameTotal), "", v), v)
) ),
result )
Jun 22 2021 10:49 AM
Thank you very much for all your help. I took what you had there and added the ability to control how many names appear on 1 sheet. I'm sure there is a more eloquent way of doing this. take a look and let me know what you think. Again thank you.
=LET(
array, SORT(FILTER(TableHLP,TableHLP[District]=$A$7)),array1,SORT(FILTER(FILTER(TableHLP,TableHLP[District]=$A$7),{1,0,0,0,0,0,0,0})),
columnsToShow, {1,5,6,0,4,0,7,8},
columnNameTotal, 4,
lmaxs,1,
mins,1,maxs,8,
suc, UNIQUE(array1),
af,MATCH(array1,suc,0),
cn,IF((af>=mins)*(af<=maxs),INDEX(suc,af),"remove"),cnt,FILTER(cn,(INDEX(cn,0,1)<>"remove")),
c, ROWS(cnt),
cnm,IF((af>=mins)*(af<=lmaxs),INDEX(suc,af),"remove"),cntm,FILTER(cnm,(INDEX(cnm,0,1)<>"remove")),
cm, ROWS(cntm),
arrayR, ROWS(array),
cntseq, SEQUENCE(arrayR,,0,1),
minK,IF(lmaxs=1,mins,cm+1), maxK, MIN(c, arrayR),
removeArray,IF((cntseq>=minK)*(cntseq<=maxK),INDEX(array,cntseq,{1,2,3,4,5,6,7,8}),"remove"),
trunkArray,FILTER(removeArray,(INDEX(removeArray,0,1)<>"remove")+(INDEX(removeArray,0,1)= "Name")),
arrayRows, ROWS(trunkArray),
names, INDEX(trunkArray, SEQUENCE(arrayRows),1),
distinct, UNIQUE(names),
distinctRows, ROWS(distinct),
startPos, INDEX( XMATCH(distinct, names),
SEQUENCE(,distinctRows-1,2)) +
SEQUENCE(,distinctRows-1,0),
enumPos, SEQUENCE( COLUMNS(startPos),,1,0),
k, SEQUENCE(arrayRows+distinctRows-1),
i, k - MMULT(--(k>startPos), enumPos ),
emptyPos, MMULT(--(k=startPos), enumPos ),
v, INDEX(trunkArray, i, columnsToShow),
vPrev, INDEX(trunkArray, i-1, columnsToShow),
vNext, INDEX(trunkArray, i+1, columnsToShow),
res, IF(
emptyPos, "",
IF( (vPrev=v)*(columnsToShow=1)*(i<>1), "",
IF( i < arrayRows,
IF( (vNext=v)*(columnsToShow=columnNameTotal), "", v), v)
) ),
res)
Jun 22 2021 11:39 AM
I did find an error in my code.
columnsToShow, {1,5,6,0,4,0,7,8},
I the 0 will return the name. Im trying to figure out how to prevent that.
Jun 22 2021 12:16 PM
I Think I got it. Check out the Formula and let me know what you think.
=LET(
array, SORT(FILTER(TableHLP,TableHLP[District]=$A$7)),array1,SORT(FILTER(FILTER(TableHLP,TableHLP[District]=$A$7),{1,0,0,0,0,0,0,0})),
columnsToShow, {1,5,6,0,4,0,7,8},
columnNameTotal, 8,
lmaxs,1,
mins,1,maxs,8,
suc, UNIQUE(array1),
af,MATCH(array1,suc,0),
cn,IF((af>=mins)*(af<=maxs),INDEX(suc,af),"remove"),cnt,FILTER(cn,(INDEX(cn,0,1)<>"remove")),
c, ROWS(cnt),
cnm,IF((af>=mins)*(af<=lmaxs),INDEX(suc,af),"remove"),cntm,FILTER(cnm,(INDEX(cnm,0,1)<>"remove")),
cm, ROWS(cntm),
arrayR, ROWS(array),
cntseq, SEQUENCE(arrayR,,0,1),
minK,IF(lmaxs=1,mins,cm+1), maxK, MIN(c, arrayR),
removeArray,IF((cntseq>=minK)*(cntseq<=maxK),INDEX(array,cntseq,{1,2,3,4,5,6,7,8}),"remove"),
trunkArray,FILTER(removeArray,(INDEX(removeArray,0,1)<>"remove")+(INDEX(removeArray,0,1)= "Name")),
arrayRows, ROWS(trunkArray),
names, INDEX(trunkArray, SEQUENCE(arrayRows),1),
distinct, UNIQUE(names),
distinctRows, ROWS(distinct),
startPos, INDEX( XMATCH(distinct, names),
SEQUENCE(,distinctRows-1,2)) +
SEQUENCE(,distinctRows-1,0),
enumPos, SEQUENCE( COLUMNS(startPos),,1,0),
k, SEQUENCE(arrayRows+distinctRows-1),
i, k - MMULT(--(k>startPos), enumPos ),
emptyPos, MMULT(--(k=startPos), enumPos ),
v, IF(columnsToShow=0,"",INDEX(trunkArray, i, columnsToShow)),
vPrev, INDEX(trunkArray, i-1, columnsToShow),
vNext, INDEX(trunkArray, i+1, columnsToShow),
res, IF(
emptyPos, "",
IF( (vPrev=v)*(columnsToShow=1)*(i<>1), "",
IF( i < arrayRows,
IF( (vNext=v)*(columnsToShow=columnNameTotal), "", v), v)
) ),
res)
Jun 22 2021 12:27 PM
Well I think it is finished. Thank you for all your help. I learned a lot. Let me know what you think. I know its not as elegant as your code and could probably be cleaned up. Let me know if there is anything that could be done simpler. Thanks again.
=LET(
array, SORT(FILTER(TableHLP,TableHLP[District]=$B$1)),array1,SORT(FILTER(FILTER(TableHLP,TableHLP[District]=$B$1),{1,0,0,0,0,0,0,0})),
columnsToShow, {1,5,6,0,4,0,7,8},
columnNameTotal, 8,
lmaxs,1,
mins,1,maxs,3,
suc, UNIQUE(array1),
af,MATCH(array1,suc,0),
cn,IF((af>=mins)*(af<=maxs),INDEX(suc,af),"remove"),cnt,FILTER(cn,(INDEX(cn,0,1)<>"remove")),
c, ROWS(cnt),
cnm,IF((af>=mins)*(af<=lmaxs),INDEX(suc,af),"remove"),cntm,FILTER(cnm,(INDEX(cnm,0,1)<>"remove")),
cm, ROWS(cntm),
arrayR, ROWS(array),
cntseq, SEQUENCE(arrayR,,0,1),
minK,IF(lmaxs=1,mins,cm+1), maxK, MIN(c, arrayR),
removeArray,IF((cntseq>=minK)*(cntseq<=maxK),INDEX(array,cntseq,{1,2,3,4,5,6,7,8}),"remove"),
trunkArray,FILTER(removeArray,(INDEX(removeArray,0,1)<>"remove")+(INDEX(removeArray,0,1)= "Name")),
arrayRows, ROWS(trunkArray),
names, INDEX(trunkArray, SEQUENCE(arrayRows),1),
distinct, UNIQUE(names),
distinctRows, ROWS(distinct),
startPos, INDEX( XMATCH(distinct, names),
SEQUENCE(,distinctRows-1,2)) +
SEQUENCE(,distinctRows-1,0),
enumPos, SEQUENCE( COLUMNS(startPos),,1,0),
k, SEQUENCE(arrayRows+distinctRows-1),
i, k - MMULT(--(k>startPos), enumPos ),
emptyPos, MMULT(--(k=startPos), enumPos ),
v, IF(columnsToShow=0,"",INDEX(trunkArray, i, columnsToShow)),
vPrev, INDEX(trunkArray, i-1, columnsToShow),
vNext, INDEX(trunkArray, i+1, columnsToShow),
res, IF(
emptyPos, "",
IF( (vPrev=v)*(columnsToShow=1)*(i<>1), "",
IF( i < arrayRows,
IF( (vNext=v)*(columnsToShow=columnNameTotal), "", v), v)
) ),
res)
Jun 22 2021 12:33 PM
Looks great. Perhaps the code could be bit optimized, but that's on another iterations. What I'd do now - apply at least minimum of formatting to make function easier to read, and use more descriptive name. Perhaps except indexes. Otherwise in few month you forget what is what and it takes more time to analyze the code.
Comments here if can be used when indirectly. I'm not fun of comments, if use very few of them is enough and they shall answer on question why we do that, not what we do here. Descriptive names is enough for that.
Quite small cosmetic changes are in attached file, spill at very bottom.
Jun 22 2021 12:41 PM
Jun 22 2021 12:46 PM
@dshawSLDC , you are welcome, that was interesting task
Jun 22 2021 03:02 PM
Hey I found an error. If you only have 1 name in a district you get a #CALC! error " empty arrays are not supported". any thoughts on how to fix this?
Jun 22 2021 03:28 PM
Perhaps to wrap by IFERROR(), but don't know what exactly. If you don't solve will try to play tomorrow.