Fill in the alphabets from Names column in Name1……Name8 columns where X is marked. If number of alphabets gets exhausted, then alphabets repeat. If some alphabets are remaining to be used, then those would appear in Remaining column.
📌 Challenge Details and Links
ExcelBI Power Query Challenge Number: 110
Challenge Difficulty: ⭐️⭐️⭐️
📥Download Sample File
📥Link to the solutions on LinkedIn
Solving the challenge of Fill Alphabets in Pattern Columns with Power Query
Power Query solution 1 for Fill Alphabets in Pattern Columns, proposed by Bo Rydobon 🇹🇭:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
Ans = Table.FromRows(
Table.TransformRows(
Source,
each
let
l = Record.ToList(_),
t = Text.Split(l{0}, ", ")
in
List.Transform(
{0 .. List.Count(l)},
(n) =>
try
if n = 0 then
l{0}
else if l{n} = "X" then
t{Number.Mod(List.NonNullCount(List.FirstN(l, n)) - 1, List.Count(t))}
else
null
otherwise
Text.Combine(List.Skip(t, List.NonNullCount(l) - 1), ", ")
)
),
Table.ColumnNames(Source) & {"Remaining"}
)
in
Ans
Power Query solution 2 for Fill Alphabets in Pattern Columns, proposed by Zoran Milokanović:
let
Source = Excel.CurrentWorkbook(){[Name = "Input"]}[Content],
S = Table.FromRows(
List.Transform(
Table.ToRows(Source),
each
let
n = Text.Split(_{0}, ", "),
s = List.Skip(_),
p = List.Transform(
List.Positions(s),
each
if s{_} = null then
s{_}
else
n{Number.Mod(List.NonNullCount(List.FirstN(s, _ + 1)) - 1, List.Count(n))}
)
in
{_{0}} & p & {Text.Combine(List.Difference(n, p), ", ")}
),
Table.ColumnNames(Source) & {"Remaining"}
)
in
S
Power Query solution 3 for Fill Alphabets in Pattern Columns, proposed by Kris Jaganah:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
Rep = Table.ReplaceValue(Source, null, "Y", Replacer.ReplaceValue, Table.ColumnNames(Source)),
Unpiv = Table.UnpivotOtherColumns(Rep, {"Names"}, "A", "V"),
Filter = Table.SelectRows(Unpiv, each ([V] = "X")),
Group = Table.Group(
Filter,
{"Names"},
{
"All",
each Table.AddColumn(
Table.AddIndexColumn(_, "I", 1, 1),
"Col",
each Text.Split([Names], ", "){Number.Mod([I] - 1, List.Count(Text.Split([Names], ", ")))}
)
}
),
Xpand = Table.ExpandTableColumn(Group, "All", {"A", "Col"}, {"A", "V"}),
FilY = Xpand & Table.SelectRows(Unpiv, each ([V] = "Y")),
RepValue = Table.ReplaceValue(FilY, "Y", null, Replacer.ReplaceValue, {"V"}),
Pivot = Table.Pivot(RepValue, List.Sort(List.Distinct(RepValue[A])), "A", "V"),
Sort = Table.Sort(Pivot, {each List.PositionOf(Source[Names], [Names]), 0}),
Rem = Table.AddColumn(
Sort,
"Remaining",
each Text.Combine(
List.Difference(
Text.Split([Names], ", "),
List.RemoveNulls(List.Distinct(List.Skip(Record.ToList(_))))
),
", "
)
)
in
Rem
Power Query solution 4 for Fill Alphabets in Pattern Columns, proposed by Rick de Groot:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
Unpv = Table.UnpivotOtherColumns(Source, {"Names"}, "Attribute", "Value"),
Group = Table.Group(
Unpv,
{"Names"},
{
{"Count", each List.Count(_)},
{"Details", each Table.AddIndexColumn(_, "i", 1, 1), type table}
}
),
Exp = Table.ExpandTableColumn(Group, "Details", {"Attribute", "Value", "i"}),
Repl = Table.ReplaceValue(
Exp,
each [Value],
each [
z = List.Count(Text.Split([Names], ", ")),
a = Number.Mod([i] - 1, z),
b = Text.Split([Names], ", "){a}
][b],
Replacer.ReplaceValue,
{"Value"}
),
Rem = Table.RemoveColumns(Repl, {"i"}),
Table1 = Table.Pivot(Rem, List.Distinct(Rem[Attribute]), "Attribute", "Value"),
Table2 = Table.SelectRows(Source, each List.NonNullCount(List.Skip(Record.FieldValues(_))) = 0),
Comb = Table.Combine({Table2, Table1}),
Remain = Table.AddColumn(
Comb,
"Remaining",
each [
NameItems = Text.Split([Names], ", "),
CNameItems = List.Count(Text.Split([Names], ", ")),
XRecord = [Count] ?? 0,
c = CNameItems - XRecord,
d = if CNameItems > XRecord then Text.Combine(List.LastN(NameItems, c), ", ") else ""
][d]
),
Remove = Table.RemoveColumns(Remain, {"Count"})
in
Remove
Power Query solution 5 for Fill Alphabets in Pattern Columns, proposed by Alejandro Simón 🇵🇦 🇪🇸:
let
Source = Excel.CurrentWorkbook(){[Name = "Table1"]}[Content],
Group = Table.Group(
Source,
{"Names"},
{
{
"All",
each
let
a = Table.ColumnNames(_),
b = Table.RemoveColumns(
Table.UnpivotOtherColumns(_, {"Names"}, "Name", "Att"),
{"Names", "Att"}
),
c = List.Transform([Names], each Text.Split(_, ", ")){0},
d = List.FirstN(
List.Repeat(c, Number.RoundUp(Table.RowCount(b) / List.Count(c))),
Table.RowCount(b)
),
e = Table.ToColumns(b){0} & List.Difference(List.Skip(a), Table.ToColumns(b){0}),
g = List.FirstN(d & List.Repeat({null}, List.Count(e)), Table.ColumnCount(Source) - 1),
f = Table.Sort(Table.FromColumns({e} & {d}, {"Names", "A"}), {"Names"})
in
f
}
}
),
Expand = Table.ExpandTableColumn(Group, "All", {"Names", "A"}, {"Names.1", "A"}),
Pivot = Table.Sort(
Table.Pivot(Expand, List.Distinct(Expand[Names.1]), "Names.1", "A"),
each List.PositionOf(Source[Names], [Names])
),
Names = List.Transform(Pivot[Names], each Text.Split(_, ", ")),
Sol = Table.AddColumn(
Pivot,
"Remaining",
each Text.Combine(
List.Difference(
Text.Split([Names], ", "),
List.Distinct(List.RemoveNulls(List.Skip(Record.ToList(_))))
),
", "
)
)
in
Sol
Power Query solution 6 for Fill Alphabets in Pattern Columns, proposed by Luan Rodrigues:
let
Fonte = Tabela1,
ad = Table.AddColumn(
Fonte,
"Personalizar",
each [
a = List.Count(List.RemoveNulls(List.RemoveFirstN(Record.FieldValues(_), 1))),
b =
if List.Count(Text.Split([Names], ", ")) < a then
List.Select(
List.Transform(Text.ToList(Text.Repeat([Names], a)), each Text.Select(_, {"a" .. "z"})),
each _ <> ""
)
else
Text.Split([Names], ", ")
][b]
),
gp = Table.Group(
ad,
{"Names"},
{
{
"Contagem",
each [
a = Table.AddIndexColumn(
Table.UnpivotOtherColumns(_, {"Names", "Personalizar"}, "Atributo", "Valor"),
"Ind",
0,
1
),
b = Table.AddColumn(a, "ext", each [Personalizar]{[Ind]})
][b]
}
}
),
ex = Table.ExpandTableColumn(gp, "Contagem", {"Atributo", "ext"}),
pb = Table.FillDown(ex, {"Atributo"}),
pv = Table.Pivot(pb, List.Distinct(pb[Atributo]), "Atributo", "ext"),
ac = Table.AddColumn(
pv,
"Remaining",
each Text.Combine(
List.Difference(
Text.Split([Names], ", "),
List.Distinct(List.RemoveNulls(List.RemoveFirstN(Record.FieldValues(_), 1)))
),
", "
)
),
cs = Table.Sort(ac, each List.PositionOf(ad[Names], [Names])),
re = Table.ReorderColumns(
cs,
List.RemoveFirstN(Table.ColumnNames(Fonte), 1) & {"Remaining"},
MissingField.UseNull
)
in
re
Power Query solution 7 for Fill Alphabets in Pattern Columns, proposed by Eric Laforce:
let
Source = Excel.CurrentWorkbook(){[Name = "tData110"]}[Content],
CN = Table.ColumnNames(Source),
Transform = List.Transform(
Table.ToRows(Source),
each
let
_NV = Text.Split(_{0}, ", "),
_Nb = List.Count(_NV),
_NbCheck = List.Count(List.Select(_, each _ = "X")),
_RemainV = Text.Combine(
List.LastN(_NV, if (_NbCheck < _Nb) then _Nb - _NbCheck else 0),
", "
),
_CNV = List.Select(List.Zip({List.Skip(CN), List.Skip(_)}), each _{1} = "X"),
_RDetails = List.Accumulate(
_CNV,
[],
(s, c) =>
s
& Record.FromList(
{if (c{1} = "X") then _NV{Number.Mod(Record.FieldCount(s), _Nb)} else ""},
{c{0}}
)
)
in
[Names = _{0}] & _RDetails & [Remaining = _RemainV]
),
Result = Table.FromRecords(Transform, CN & {"Remaining"}, MissingField.UseNull)
in
Result
Power Query solution 8 for Fill Alphabets in Pattern Columns, proposed by Matthias Friedmann:
let
Source = Excel.CurrentWorkbook(){[Name = "DistributeNames"]}[Content],
Custom = Table.FromRows(
Table.TransformRows(
Source,
each [
names = Text.Split([Names], ", "),
nameCount = List.Count(names),
row = Record.ToList(_),
xCount = List.NonNullCount(row) - 1,
remaining =
let
r = nameCount - xCount
in
if r > 0 then Text.Combine(List.LastN(names, r), ", ") else null,
transform = List.Transform(
{0 .. List.Count(row) - 1},
each
if row{_} = "X" then
names{Number.Mod(List.NonNullCount(List.FirstN(row, _)) - 1, nameCount)}
else
row{_}
)
& {remaining}
][transform]
),
Table.ColumnNames(Source) & {"Remaining"}
)
in
Custom
Power Query solution 9 for Fill Alphabets in Pattern Columns, proposed by Rafael González B.:
let
Source = Excel.CurrentWorkbook(){0}[Content],
New = Table.AddColumn(
Source,
"NewTable",
each
let
a = Text.Split([Names], ", "),
b = Record.RemoveFields(_, {"Names"}),
c = Record.FieldCount(b),
d = List.Repeat(a, c),
e = List.Transform(
List.PositionOf(Record.ToList(b), "X", 2),
each "Name" & Text.From(_ + 1)
),
f = Table.SelectRows(Table.FromColumns({e, d}), each [Column1] <> null),
g = Table.PromoteHeaders(Table.Transpose(f)),
h = Table.FromRecords({_}),
i = Table.LastN(Table.FillDown(h & g, {"Names"}), 1),
j = Text.Combine(List.Difference(a, f[Column2]), ", "),
k = Table.AddColumn(i, "Remaining", each j)
in
k
)[NewTable]
in
Table.Combine(New)
Solving the challenge of Fill Alphabets in Pattern Columns with Excel
Excel solution 1 for Fill Alphabets in Pattern Columns, proposed by Bo Rydobon 🇹🇭:
=LET(z,A2:I5,REDUCE(HSTACK(A1:I1,"Remaining"),SEQUENCE(ROWS(z)),LAMBDA(a,r,LET(n,INDEX(z,r,),
s,TEXTSPLIT(@+n,,", "),r,ROWS(s),t,SCAN(0,n,LAMBDA(b,v,SWITCH(v,"X",INDEX(s,MOD(COUNTA(INDEX(n,2):v)-1,r)+1),0,"",v))),
VSTACK(a,HSTACK(t,IFERROR(TEXTJOIN(", ",,DROP(s,SUM(N(t>""))-1)),"")))))))
Excel solution 2 for Fill Alphabets in Pattern Columns, proposed by John V.:
=LET(n,A2:A5,z,B2:I5,VSTACK(HSTACK(A1:I1,"Remaining"),HSTACK(n,REPT(MID(n,1+3*MOD(MAP(z,LAMBDA(x,IF(x>0,SUM(N(TAKE(B2:x,-1)>0)))))-1,(2+LEN(n))/3),1),z>0),MID(n,1+3*BYROW(z,LAMBDA(r,SUM(N(r>0)))),99))))
Excel solution 3 for Fill Alphabets in Pattern Columns, proposed by محمد حلمي:
=REDUCE(A1:I1,A2:A5,LAMBDA(c,d,LET(
b,OFFSET(d,,1,,8)>0,
x,TEXTSPLIT(d,", "),
r,IF(b,INDEX(x,
SCAN(,b,LAMBDA(a,d,IF(a+d>COUNTA(x),1,a+d)))),""),
IFNA(VSTACK(c,HSTACK(d,r,
ARRAYTOTEXT(IFERROR(DROP(x,,SUM(--b)),"")))),
"Remaining"))))
Excel solution 4 for Fill Alphabets in Pattern Columns, proposed by Hussein SATOUR:
=TEXTSPLIT(LET(u,IF(B2:I2="", NA(), $B$1:$I$1), v,TEXTSPLIT(A2,", "), w,TOCOL(u,2), x,TAKE(TOCOL(IFNA(v,SEQUENCE(COUNTA(w)))), COUNTA(w)), y,IFERROR(XLOOKUP(u,w,x), ""), z, TEXTJOIN(", ",,IF(ISNA(XMATCH(v,y)), v, "")), TEXTJOIN("/",0, y,z)), "/")
Excel solution 5 for Fill Alphabets in Pattern Columns, proposed by Oscar Mendez Roca Farell:
=LET(_d,A2:I5, REDUCE(HSTACK(A1:I1, "Remaining"), SEQUENCE(ROWS(_d)), LAMBDA(j, y, LET(_a,INDEX(TAKE(_d, ,1), y),_w, TEXTSPLIT(_a, ,","),_r,IFERROR(INDEX(_w, SCAN(0, INDEX(DROP(_d, ,1), y, ), LAMBDA(i, x, IF(x="", "", MOD(COUNTIF(INDEX(DROP(_d,´,1), y, 1):x, "X")-1, ROWS(_w))+1)))), ""),_u, TEXTJOIN(", ", 1, REPT(_w,ISERROR(XMATCH(_w, UNIQUE(_r))))), VSTACK(j, HSTACK(_a,_r,_u))))))
Excel solution 6 for Fill Alphabets in Pattern Columns, proposed by LEONARD OCHEA 🇷🇴:
=LET(t,A1:I5,x,--(DROP(t,1,1)="X"),n,DROP(INDEX(t,,1),1),l,SUBSTITUTE(n,", ",""),y,LEN(l),p,DROP(REDUCE("",SEQUENCE(ROWS(x)),LAMBDA(a,b,VSTACK(a,SCAN(0,INDEX(x,b,),LAMBDA(c,d,c+d))))),1)*x,z,BYROW(p,LAMBDA(a,MAX(a))),VSTACK(HSTACK(INDEX(t,1,),"Remaining"),HSTACK(n,IFERROR(MID(l,IF(p,MOD(p-1,y)+1,""),1),""),IF(y>z,RIGHT(n,3*(y-z)-2),""))))
Excel solution 7 for Fill Alphabets in Pattern Columns, proposed by Ziad A.:
=MAP(A2:A5,LAMBDA(a,LET(s,SPLIT(a,", ",),r,INDEX(B1:I5,ROW(a)),v,MAP(r,LAMBDA(_,IF(_<>"X",,INDEX(s,,MOD(COUNTIF(INDEX(r,,1):_,"X")-1,COUNTA(s))+1)))),{v,IFNA(JOIN(", ",FILTER(s,COUNTIF(v,s)=0)))})))
Excel solution 8 for Fill Alphabets in Pattern Columns, proposed by Daniel Garzia:
=LET(f,LAMBDA(r,LET(f,TAKE(r,,1),n,TEXTSPLIT(f,,", "),c,ROWS(n),d,DROP(r,,1),t,d>0,HSTACK(f,IF(t,INDEX(n,1+MOD(SCAN(0,d,LAMBDA(a,b,a+1*(b>0)))-1,c)),""),IFERROR(RIGHT(f,1+(c-SUM(1*t))*2),"")))),REDUCE(A1:I1,ROW(1:4),LAMBDA(a,b,VSTACK(IFNA(a,"Remaining"),f(INDEX(A2:I5,b,))))))
Excel solution 9 for Fill Alphabets in Pattern Columns, proposed by samir tobeil:
=LET(r,HSTACK(A2:A5,MAP(B2:I5,LAMBDA(k,LET(h,INDIRECT("a"&ROW(k)),s,SUBSTITUTE(CONCAT(REPT(h,10)),", ",""),
IF(k="x",MID(s,COUNTA(OFFSET(h,,1,1,COLUMN(k)-1)),1),""))))),
p,BYROW(r,LAMBDA(t,SUBSTITUTE(TAKE(t,,1),TEXTJOIN(", ",,UNIQUE(TOCOL(DROP(t,,1)))),""))),HSTACK(r,p))
Excel solution 10 for Fill Alphabets in Pattern Columns, proposed by Md Ismail Hosen:
=LET(Data, A1:I5, fxOne, LAMBDA(RowIndex, LET(RowData, CHOOSEROWS(Data, RowIndex), Names, TEXTSPLIT(INDEX(RowData, 1, 1), ", "), NameCount, COLUMNS(Names), ColIndex, SCAN(0, DROP(RowData, , 1), LAMBDA(a,v, IF(v = "X", IF(a + 1 > NameCount, a + 1 - NameCount, a + 1), a))), Seq, SEQUENCE(, COLUMNS(RowData) - 1), XPlaceFilled, IF(INDEX(DROP(RowData, , 1), 1, Seq) = "X", INDEX(Names, 1, INDEX(ColIndex, 1, Seq)), ""), Remaining, IFERROR(TEXTJOIN(", ", FALSE, DROP(&Names, , MAX(ColIndex))), ""), Result, HSTACK(INDEX(RowData, 1, 1), XPlaceFilled, Remaining), Result)), Result, REDUCE(HSTACK(CHOOSEROWS(Data, 1), "Remaining"), SEQUENCE(ROWS(Data) - 1), LAMBDA(a,v, VSTACK(a, fxOne(v + 1)))), Result)
Solving the challenge of Fill Alphabets in Pattern Columns with Python in Excel
Python in Excel solution 1 for Fill Alphabets in Pattern Columns, proposed by Bo Rydobon 🇹🇭:
https://1drv.ms/x/s!Ak8Fla2fCeo6g6kw7u789aFM5Tctlw?e=GO2Yau
def row(x):
n = 0
r =[]
t = x[0].split(", ")
for a in x:
if a =='X':
n +=1
r.append(t[n% len(t)])
else:
r.append('' if a is None else a)
r.append('') if n >= len(t) else r.append(', '.join(t[n:]))
return r
[row(a) for a in list(xl("A2:I5").values)]
Python in Excel solution 2 for Fill Alphabets in Pattern Columns, proposed by Diarmuid Early:
Python solution...
def rowCalc(rw):
ltrs = rw[0]
ltrList = ltrs.split(", ")
nmList = rw[1:len(rw)]
ltrList = [ltrList[np.count_nonzero(nmList[0:clNum] == "X") % len(ltrList)] if nm == "X" else "" for clNum, nm in enumerate(nmList)]
return np.hstack([ltrs, ltrList, ltrs[3 * np.count_nonzero(nmList == "X"):]])
df = xl("A3:I7").values
np.vstack([np.hstack([df[0],"Remaining"]),[rowCalc(testRw) for n, testRw in enumerate(df[1:])]])
https://1drv.ms/f/s!Aryypvyx4xIO3BDB5UetNvBOsC3a?e=kRX2o6
&&
