Oct 01 2024 02:51 AM
Hopefully I will be able to explain my problem correctly.
I have a table with two columns in it. Column A has students in it, column B has the subject that each student is taking. Both column A and column B have repeating values, but together they are unique. For example
Name | Subject |
Jimmy | Maths |
Jimmy | Biology |
Jimmy | Chemistry |
Maxime | Maths |
Maxime | Computer Science |
Maxime | History |
What I need to do is turn this into a matrix (is that the correct term?) which looks like this
Name | Subject A | Subject B | Subject C |
Jimmy | Maths | Biology | Chemistry |
Maxime | Maths | Computer Science | History |
Can this be done?
Oct 01 2024 05:10 AM
@RMF40 If you have Excel for Microsoft 365, you could try something along these lines (using the new PIVOTBY function):
=LET(
a, FILTER(A2:B1000,A2:A1000<>""),
r, CHOOSECOLS(a,1),
v, CHOOSECOLS(a,2),
n, ROWS(r),
c, "Subject "&CHAR(MMULT((SEQUENCE(n)>=SEQUENCE(,n))*(r=TOROW(r)),EXPAND(1,n,,1))+64),
PIVOTBY(r,c,v,CONCAT,0,0,,0)
)
See attached...
Oct 01 2024 05:33 AM
As variant that could be Power Query
let
Source = Excel.CurrentWorkbook(){[Name="Students"]}[Content],
GroupNames = Table.Group(
Source, {"Name"},
{
{"Subject", each List.Sort( [Subject] )}
}),
SubjectNames = List.Transform(
{1..List.Max( Table.TransformColumns(
GroupNames,
{"Subject", (q) => List.Count(q)} )[Subject] )},
(e) => "Subject " & Character.FromNumber(e+64)
),
ExtractSubjects = Table.TransformColumns(
GroupNames,
{"Subject", each Text.Combine(List.Transform(_, Text.From), ","), type text}
),
SplitSubjects = Table.SplitColumn(
ExtractSubjects,
"Subject",
Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), SubjectNames)
in
SplitSubjects
Please check attached.
Oct 03 2024 06:59 AM
@nduhiye2018 that was my initial thought, but the pivot table keeps putting totals into the cells rather than the subject choices.
Oct 03 2024 08:53 AM
A Power Query variant attached:
let
Source = TableSource,
GroupedName = Table.Group(Source, {"Name"},
{
{"DATA", each
Table.Transpose(
Table.SelectColumns(_, {"Subject"})
),
type table
},
{"Count", Table.RowCount, Int64.Type}
}
),
RemovedCount = Table.RemoveColumns(GroupedName, {"Count"}),
SortedName = Table.Sort(RemovedCount, {{"Name", Order.Ascending}}),
ListMaxCount = { 1..List.Max( GroupedName[Count] ) },
ExpandedSubject = Table.ExpandTableColumn(SortedName, "DATA",
List.Transform( ListMaxCount, each "Column" & Text.From(_) ),
List.Transform( ListMaxCount, each "Subject " & Character.FromNumber(_ +64) )
)
in
ExpandedSubject
Oct 03 2024 01:39 PM
Oct 04 2024 02:14 AM
All you are trying to do is generated a list of subjects for each student. Unfortunately the current implementation of Excel will simply return an error message "Nested arrays are not supported". Not very helpful when the whole purpose of the calculation is to return a nested array"! A possible solution is to use
=LET(
student, UNIQUE(Name),
SubjectListλ, LAMBDA(n, TOROW(FILTER(Subject, Name = n))),
subjectList, MAPλ(student, SubjectListλ),
SORT(HSTACK(student, subjectList))
)
The first line creates a list of distinct student names. The second line defines a function that will return a list of subjects for any given student. The third line uses MAP to return the subject list for each student in turn. This is where the Excel in-built functionality fails. What I have done instead is use a function MAPλ that I wrote to overcome the problem. The final line sorts the data alphabetically by student name, to give
It is complicated but the user need never look at it!