Forum Discussion
How to Return Column Data Based on All Populated Cells in Row Range and Match to Other Worksheet
- Jun 29, 2018
Hi Anthony,
That could be done by Power Query. Here is the simple mockup to illustrate idea based on your initial pictures, for the real data queries will be bit more complex.
Here on the left are source tables and resulting one are on the right
First query generates list of roles for users, here it dynamically split on columns
let Source = Excel.CurrentWorkbook(){[Name="User"]}[Content], UnpivotJobs = Table.UnpivotOtherColumns(Source, {"User ID"}, "Attribute", "Value"), RemoveValues = Table.RemoveColumns(UnpivotJobs,{"Value"}), GroupRows = Table.Group(RemoveValues, {"User ID"}, {{"Role", each [Attribute]}}), MaxInList = Table.AddColumn(GroupRows, "ListMax", each List.Count([Role])), ElementNumber = List.Max(MaxInList[ListMax]), ListColumns = List.Transform({1..ElementNumber}, each "Role " & Number.ToText(_)), ExtractElements = Table.TransformColumns(GroupRows, {"Role", each Text.Combine(List.Transform(_, Text.From), ","), type text}), SplitElements = Table.SplitColumn(ExtractElements, "Role", Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), ListColumns) in SplitElements
For the second table we first create connection query which maps roles on lists of classes
let Source = Excel.CurrentWorkbook(){[Name="Job"]}[Content], UnpivotClasses = Table.UnpivotOtherColumns(Source, {"Job"}, "Attribute", "Value"), RemoveValue = Table.RemoveColumns(UnpivotClasses,{"Value"}), GroupRows = Table.Group(RemoveValue, {"Job"}, {{"Class", each [Attribute]}}) in GroupRows
and here we take users with roles and merge with that query
let Source = Excel.CurrentWorkbook(){[Name="User"]}[Content], UnpivotJobs = Table.UnpivotOtherColumns(Source, {"User ID"}, "Job", "Value"), RemoveValues = Table.RemoveColumns(UnpivotJobs,{"Value"}), MergeWithClasses = Table.NestedJoin(RemoveValues,{"Job"},ClassesForRoles,
{"Job"},"Classes",JoinKind.LeftOuter), ExpandClasses = Table.ExpandTableColumn(MergeWithClasses, "Classes", {"Class"}, {"Class"}), ExtractClasses = Table.TransformColumns(ExpandClasses, {"Class",
each Text.Combine(List.Transform(_, Text.From), ", "), type text}), SortUsers = Table.Sort(ExtractClasses,{{"User ID", Order.Descending},
{"Job", Order.Ascending}}) in SortUsersHere classes are as lists, could be split dynamically same way as roles in first query. Sample file is attached.
In your example I can see that there are two jobs for each participant as well. It appears that each job is only associated with two classes. Is this realistic? Or do you have a more precise data set that can display a better representation of your data.
For example:
1. How far does your data go column wise for jobs?
2. How far does your data go column wise for classes?
3. What is the max number of jobs?
4. What is the max number of classes for an individual job?
I've spent a fair amount of time on issues like this in the past only to find that the representation of data provided by the end user was not accurate which caused further questions. In order to potentially avoid this issue would it be possible for you to confirm that this is the case or provide a more data. There may be a formula that can give you what you need but it's more likely that the only way to have a simple solution would be to implement some kind of more complex logic using VBA code. I believe it may save some headaches for yourself as well as other people replying to your inquiry if you could please provide a little more information.
http://www.fiscal.ca.gov/training-academy/documents/SummaryRolesCourseMatrix20171220.xlsx
This is the document from which I'll be pulling courses depending on a user's roles. However, I will not be using all of these roles and courses. Not all of the user's have all of the jobs listed.