How to split excel columns into multiple rows - excel

I get exports from an event registration form, where each order(row) contains order date, purchase price, and info for between 1-4 registrants. Each registrant has columns for first name, last name, and date of birth. What I need is to split up these rows such that each individual person is on their own row, with first, last, and DOB on the row, ideally along with the other order information duplicated too.
This may be confusing so I have mockup date for the form I get exports in, and the form I'd like to convert them to.
What I get:
https://drive.google.com/file/d/1xt64Re2CTlbQnHuRy1dQaFeNV5OmETfW/view?usp=sharing
What I want:
https://drive.google.com/file/d/156WmiQ4Tx4JGB5FYLTqHBuVmJqi20pRZ/view?usp=sharing
I found this tutorial which seem very close to what I want using Excel Power Query, but it is describing a method for when the multiple items are in one column separated by comma. My situation is a bit different and I can't make it work.
Any ideas?

Below PowerQuery works on sample data set you had, when loaded into range Table1
Written dynamically for any number of First/Last/DOB sets of columns; You had 4 this would handle any number of them
Paste into Home ... Advanced Editor...
a bit long winded to separate the steps and make it visible
let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Order Date", type date}}),
// Get names of all First, Last and DOB fields
ColumnsToCombine1 = List.Select(Table.ColumnNames(#"Changed Type"), each Text.Contains(_, "(First)")),
ColumnsToCombine2 = List.Select(Table.ColumnNames(#"Changed Type"), each Text.Contains(_, "(Last)")),
ColumnsToCombine3 = List.Select(Table.ColumnNames(#"Changed Type"), each Text.Contains(_, "DOB")),
//Convert to Text, so we can merge columns; for date fields, convert to date first
#"Changed Type1" = Table.TransformColumnTypes(#"Changed Type", (List.Transform(ColumnsToCombine3 ,each {_,type date}))),
#"Changed Type2" = Table.TransformColumnTypes (#"Changed Type1",List.Transform(Table.ColumnNames(#"Changed Type1"), each {_, type text})),
// convert all First, Last and DOB fields into three comma separated columns
#"Combined1" = Table.AddColumn(#"Changed Type2" , "First", each Text.Combine(Record.FieldValues(Record.SelectFields(_,ColumnsToCombine1)),", ")),
#"Combined2" = Table.AddColumn(#"Combined1", "Last", each Text.Combine(Record.FieldValues(Record.SelectFields(_,ColumnsToCombine2)),", ")),
#"Combined3" = Table.AddColumn(#"Combined2", "DOB", each Text.Combine(Record.FieldValues(Record.SelectFields(_,ColumnsToCombine3)),", ")),
#"Removed Other Columns" = Table.SelectColumns(Combined3,{"ID", "Order Date", "Quantity", "Payment", "First", "Donate", "Last", "DOB"}),
//expand all comma separated columns into their own rows
TableTransform = Table.Combine(List.Transform(List.Transform(Table.ToRecords(#"Removed Other Columns" ), (x) => List.Transform(Record.ToList(x), each Text.Split(_,","))), each Table.FromColumns(_, Table.ColumnNames(#"Removed Other Columns" )))),
#"Reordered Columns" = Table.ReorderColumns(TableTransform,{"ID", "Order Date", "Quantity", "First", "Last", "DOB", "Payment", "Donate"}),
#"Filled Down" = Table.FillDown(#"Reordered Columns",{"ID", "Order Date", "Quantity", "Payment", "Donate"}),
#"Changed Type3" = Table.TransformColumnTypes(#"Filled Down",{{"DOB", type date}, {"Order Date", type date}, {"Payment", type number}, {"Donate", type number}, {"Quantity", type number}, {"First", type text}, {"Last", type text}})
in #"Changed Type3"
Alternate version, hard coded to 4 tables, based on Ron's
let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
colNames = Table.ColumnNames(Source),
Table1 = Table.Skip(Table.DemoteHeaders(Table.SelectColumns(Source,List.RemoveMatchingItems(colNames , List.Select(colNames, each Text.Contains(_, "-2") or Text.Contains(_, "-3") or Text.Contains(_, "-4"))))),1),
Table2 = Table.Skip(Table.DemoteHeaders(Table.SelectColumns(Source,List.RemoveMatchingItems(colNames , List.Select(colNames, each Text.Contains(_, "-1") or Text.Contains(_, "-3") or Text.Contains(_, "-4"))))),1),
Table3 = Table.Skip(Table.DemoteHeaders(Table.SelectColumns(Source,List.RemoveMatchingItems(colNames , List.Select(colNames, each Text.Contains(_, "-1") or Text.Contains(_, "-2") or Text.Contains(_, "-4"))))),1),
Table4 = Table.Skip(Table.DemoteHeaders(Table.SelectColumns(Source,List.RemoveMatchingItems(colNames , List.Select(colNames, each Text.Contains(_, "-1") or Text.Contains(_, "-2") or Text.Contains(_, "-3"))))),1),
combined = Table1 & Table2 & Table3 & Table4,
#"Filtered Rows" = Table.SelectRows(combined, each ([Column4] <> null)),
#"Sorted Rows" = Table.Sort(#"Filtered Rows",{{"Column1", Order.Ascending}}),
#"Renamed Columns" = Table.RenameColumns(#"Sorted Rows",{{"Column2", "Order Date"}, {"Column3", "Quantity"}, {"Column4", "First"}, {"Column5", "Last"}, {"Column6", "DOB"}, {"Column7", "Payment"}, {"Column8", "Donate"}, {"Column1", "ID"}}),
#"Changed Type" = Table.TransformColumnTypes(#"Renamed Columns",{{"ID", type number}, {"Quantity", type number}, {"Payment", type number}, {"Donate", type number}, {"Order Date", type date}, {"DOB", type date}, {"First", type text}, {"Last", type text}})
in #"Changed Type"

Here is another PQ method to accomplish this.
I post it as a PQ beginner, and I have no idea whether this method or the first method posted is more efficient and/or scalable
It is still a work in progress, as I have fixed column names in some of the steps, and I want to make that more generalized eventually. But this problem of repeating groups of columns comes up from time to time.
Source Data
This method:
Reorder the columns to put the "common columns" together, which, in this case, would be the first three and the last two.
Demote the header row and transpose the table
Process the first column so as to create a proper list of what will be eventual column headers.
Split this table into multiple tables where
the first table represents the common columns
the other tables represent each repeating group of columns
Combine the first table with each of the other tables
Combine the resulting tables
Transpose back to the original column/row orientation, and promote the first row to headers.
Clean up by removing nulls and sorting
Reorder the columns to put the first three and last two back where they were initially.
Note: You'll need to change Table1 in the code to the actual table name, if it is different
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
colNames = Table.ColumnNames(Source),
commonTableColumnCount = 5,
colOrder = List.Combine({List.FirstN(colNames,3),List.LastN(colNames,2),List.Range(colNames,3,List.Count(colNames)-commonTableColumnCount)}),
#"Reordered Columns" = Table.ReorderColumns(Source,colOrder),
//Demote Headers and transpose
transpose1 = Table.Transpose(Table.DemoteHeaders(#"Reordered Columns")),
//Split up Column 1 to create multiple matched names
split = Table.SplitColumn(transpose1, "Column1", Splitter.SplitTextByDelimiter("-", QuoteStyle.Csv), {"Column1", "Column1.1"}),
#"Split Column by Delimiter" = Table.SplitColumn(split, "Column1.1", Splitter.SplitTextByEachDelimiter({" "}, QuoteStyle.Csv, true), {"Column1.1.1", "Column1.1.2"}),
#"Removed Columns" = Table.RemoveColumns(#"Split Column by Delimiter",{"Column1.1.1"}),
#"Merged Columns" = Table.CombineColumns(#"Removed Columns",{"Column1", "Column1.1.2"},Combiner.CombineTextByDelimiter(" ", QuoteStyle.None),"Column1"),
commonTable = Table.Split(#"Merged Columns",commonTableColumnCount){0},
record = Table.ToRecords(commonTable),
//repeated tables
//rem CommonTables Rows and split
data = Table.Split(Table.RemoveRows(#"Merged Columns",0,commonTableColumnCount),3),
//insert common rows into each table
data1 = Table.InsertRows(data{0},0,record),
//get final order of column names
colNames2 = Table.Column(data1,"Column1"),
finalOrder = List.Combine({List.FirstN(colNames2,3),List.LastN(colNames2,List.Count(colNames2)-commonTableColumnCount), List.Range(colNames2,3,2)}),
custom1 = List.Transform(data, each Table.InsertRows(_,0,record)),
//Transpose and combine each Table
custom2 = List.Transform(custom1, each(Table.PromoteHeaders(Table.Transpose(_),[PromoteAllScalars=true]))),
#"Converted to Table" = Table.FromList(custom2, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Expanded Column1" = Table.ExpandTableColumn(#"Converted to Table","Column1",colNames2),
//need to do this manually
#"Changed Type" = Table.TransformColumnTypes(#"Expanded Column1",{{"ID ", Int64.Type}, {"Order Date ", type date}, {"Quantity ", Int64.Type}, {"Payment ", Currency.Type}, {"Donate ", Currency.Type}, {"Name (First)", type text}, {"Name (Last)", type text}, {"DOB ", type date}}),
#"Filtered Rows" = Table.SelectRows(#"Changed Type", each ([#"Name (Last)"] <> null)),
#"Sorted Rows" = Table.Sort(#"Filtered Rows",{"ID ", Order.Ascending}),
#"Reordered Columns1" = Table.ReorderColumns(#"Sorted Rows", finalOrder)
in
#"Reordered Columns1"
Reordered Table

Related

Excel: arrange prescription journey based on dates and IDs

I am trying to arrange patient's journey based on first regimen then second regimen and so on.
However, after sorting data based on date:
I tried using IF formula as follow but it does not work correctly ( it worked for ID with three rows without having A5 in the formula):
=IF(AND(A2=A3,A3=A4,A4=A5,(C5-C4<=30),(C4-C3<=30),D3>(C4+30),D2>(C3+30)),B2&", "&B3&", "&B4&", "&B5,
IF(AND(A2=A3,A3=A4,A4=A5,(C4-C3<=30),D2>(C3+30)),B2&", "&B3&", "&B4,
IF(AND(A2=A3,A3=A4,A4=A5,(C4-C3<=30),D2<(C3+30)),B3&", "&B4,
IF(AND(A2=A3,A3=A4,A4=A5,(C4-C3>30),D2<(C3+30)), B3, "N")
I need to have similar results as follow:
Is there any way to have a formula helping to do so, or any other way to have similar results.
I had been working on Power Query code so I will present that first.
You can adapt the same algorithm to use in VBA, if you prefer. I would probably be using nested dictionaries and/or a class module to accomplish it effectively
To use Power Query
Select some cell in your Data Table
Data => Get&Transform => from Table/Range or from within sheet
When the PQ Editor opens: Home => Advanced Editor
Make note of the Table Name in Line 2
Paste the M Code below in place of what you see
Change the Table name in line 2 back to what was generated originally.
Read the comments and explore the Applied Steps to understand the algorithm
M Code
let
//Change next line to reflect your data source
Source = Excel.CurrentWorkbook(){[Name="Drugs"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"ID", Int64.Type}, {"CATEGORY", type text},
{"F.DATE", type date}, {"L.DATE", type date}}),
//Group by ID, then run fnJourney custom function on each subtable to return results
#"Grouped Rows" = Table.Group(#"Changed Type", {"ID"}, {
{"Count", each fnJourney(_)}}),
//Expand results
#"Expanded Count" = Table.ExpandListColumn(#"Grouped Rows", "Count"),
#"Expanded Count1" = Table.ExpandRecordColumn(#"Expanded Count", "Count", {"Year", "Reg"}),
//Pivot on Year column with no aggregation
#"Year Headers" = List.Sort(List.Distinct(Table.TransformColumnTypes(#"Expanded Count1", {{"Year", type text}}, "en-US")[Year])),
#"Pivoted Column" = Table.Pivot(Table.TransformColumnTypes(#"Expanded Count1", {{"Year", type text}}, "en-US"),
#"Year Headers", "Year", "Reg"),
#"Changed Type1" = Table.TransformColumnTypes(#"Pivoted Column", List.Transform(#"Year Headers", each {_, type text})),
//Join with original table
join = Table.NestedJoin(#"Changed Type", "ID", #"Changed Type1","ID", "Joined", JoinKind.LeftOuter),
//add shifted ID column to decide if the joined table should be retained or deleted
#"Shifted ID" = Table.FromColumns(Table.ToColumns(join) & {{null} & List.RemoveLastN(join[ID])},
type table[ID=Int64.Type, CATEGORY=text, F.DATE=date, L.DATE=date, joined=table, shiftedID=Int64.Type]),
#"Added Custom" = Table.AddColumn(#"Shifted ID", "Custom", each if [shiftedID] <> [ID] then [joined] else null, type nullable table),
//Remove shifted and Joined columns
//Then expand the tables in the Custom Column
#"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"joined", "shiftedID"}),
#"Expanded Custom" = Table.ExpandTableColumn(#"Removed Columns", "Custom", #"Year Headers"),
#"Changed Type2" = Table.TransformColumnTypes(#"Expanded Custom", List.Transform(#"Year Headers", each {_, type text}))
in
#"Changed Type2"
Custom Function CodeCreate new Blank query and paste code below
//Rename this query fnJourney
(tbl as table) =>
let
//Source = Drugs,
Source = tbl,
Years = {List.Min(List.Transform(Source[F.DATE], each Date.Year(_)))..
List.Max(List.Transform(Source[L.DATE], each Date.Year(_)))},
inJourney = List.Generate(
()=>[yr=Years{0},
reg=Text.Combine(Table.SelectRows(Source,
each Years{0} >= Date.Year([F.DATE])
and Years{0} <= Date.Year([L.DATE]))[CATEGORY],", "),
idx=0],
each [idx] < List.Count(Years),
each [yr=Years{[idx]+1},
reg=Text.Combine(Table.SelectRows(Source,
(r)=>Years{[idx]+1} >= Date.Year(r[F.DATE])
and Years{[idx]+1} <= Date.Year(r[L.DATE]))[CATEGORY],", "),
idx=[idx]+1],
each Record.FromList({[yr], [reg]},{"Year","Reg"})
)
in
inJourney
Before
After

Excel Power Query; Expand table into columns

I have two tables that I'd like to merge, but I can't quite get the merge to work the way I'd like it to. The first is a list of days and some data, the second is a ranking of items sold that day along with the number sold, etc. I'd like to get the top 'x' items added as columns to my daily data. I got the merge to work, and so now I have a column that says 'table.' However if I expand the table, each item turns into its own row. Instead I'd like table item 2 to repeat all of its columns with a postfix.
date
total_sales
items
1/1/21
$50000
table
1/2/21
$40000
table
date
total_sales
items_1
units_1
items_2
units_2
1/1/21
$50000
pens
15
pencils
10
1/2/21
$40000
erasers
35
pens
5
etc.
I can do this with visual basic but I don't think that's the best way to go about it. Thanks for your help! Also, is there a specific term for this operation that I could have searched for?
Let's suppose your second table looks like this:
First, let's group by date where for each group we sort and index the subtable. (This is the hardest step.)
Once we have the index for each group, expand that column back so we're back to the start except with the new index column.
From here, you can filter the index to get only the top N and then unpivot the [items] and [units] columns.
Merge the [index] and [Attribute]
and then pivot on [Merged]
Ta da! Now your data is shaped so that you can easily merge it with the first table.
Here's the full code for this example. (You can paste this into the Advanced Editor and look through Applied Steps.)
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WMtQ31DcyMDJU0lEqSM0rBlKGpkqxOugSyZk5YDkDqJwRTC61KLE4tQgkZ2yKLgc1EMM8hB5sWqBWGSnFxgIA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [date = _t, items = _t, units = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"date", type date}, {"items", type text}, {"units", Int64.Type}}),
#"Grouped Rows" = Table.Group(#"Changed Type", {"date"}, {{"indexed", each Table.AddIndexColumn(Table.Buffer(Table.Sort(_, {{"units", Order.Descending}})), "Index", 1, 1, Int64.Type), type table}}),
#"Expanded indexed" = Table.ExpandTableColumn(#"Grouped Rows", "indexed", {"items", "units", "Index"}, {"items", "units", "Index"}),
#"Filtered Rows" = Table.SelectRows(#"Expanded indexed", each [Index] < 3),
#"Unpivoted Columns1" = Table.UnpivotOtherColumns(#"Filtered Rows", {"date", "Index"}, "Attribute", "Value"),
#"Merged Columns" = Table.CombineColumns(Table.TransformColumnTypes(#"Unpivoted Columns1", {{"Index", type text}}, "en-US"),{"Attribute", "Index"},Combiner.CombineTextByDelimiter("_", QuoteStyle.None),"Merged"),
#"Pivoted Column1" = Table.Pivot(#"Merged Columns", List.Distinct(#"Merged Columns"[Merged]), "Merged", "Value"),
#"Changed Type1" = Table.TransformColumnTypes(#"Pivoted Column1",{{"items_1", type text}, {"units_1", Int64.Type}, {"items_2", type text}, {"units_2", Int64.Type}})
in
#"Changed Type1"
The only place I'm doing special M language magic (not just clicking stuff in the GUI) is this step which I created by applying a couple of steps to one of the sub-tables and pasting the GUI-generated code back into the group by step (plus Table.Buffer wrapper to make sure the sorting "sticks").
#"Grouped Rows" =
Table.Group(
#"Changed Type",
{"date"},
{
{"indexed", each
Table.AddIndexColumn(
Table.Buffer(
Table.Sort(_, {{"units", Order.Descending}})
),
"Index", 1, 1, Int64.Type
), type table
}
}
),

Compare columns return maximum power query

I have data from multiple suppliers which I wish to compare. The data shown in the image below has been previously transformed via a series of steps using power query. The final step was to pivot the Supplier column (in this example consisting of X,Y,Z) so that these new columns can be compared and the maximum value is returned.
How can I compare the values in columns X, Y and Z to do this? Importantly, X Y and Z arent necessarily the only suppliers. If I Add Say A as a new supplier to the original data, a new column A will be generated and I wish to include this in the comparison so that at column at the end outputs the highest value found for each row. So reading from the top down it would read in this example: 3,3,1,1,5,0.04,10 etc.
Thanks
Link to file https://onedrive.live.com/?authkey=%21AE_6NgN3hnS6MpA&id=8BA0D02D4869CBCA%21763&cid=8BA0D02D4869CBCA
M Code:
let
Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Material", type text}, {"Residual Solvents", type text}, {"RMQ", type text}, {"COA", type text}, {"Technical Data Sheet", type text}}),
//Replace Time and null with blank
#"Replaced Value" = Table.ReplaceValue(#"Changed Type","00:00:00","",Replacer.ReplaceText,{"Material", "RMQ", "Residual Solvents", "Technical Data Sheet", "COA"}),
#"Replaced Value1" = Table.ReplaceValue(#"Replaced Value",null,"",Replacer.ReplaceValue,{"Material", "RMQ", "Residual Solvents", "Technical Data Sheet", "COA"}),
//Trims all whitespace from user
#"Power Trim" = Table.TransformColumns(#"Replaced Value1",{{"Material", #"PowerTrim", type text}, {"Residual Solvents", #"PowerTrim", type text}, {"RMQ", #"PowerTrim", type text}, {"COA", #"PowerTrim", type text}, {"Technical Data Sheet",#"PowerTrim", type text}}),
//Unpivot to develop a single column of solvent/metals/date data
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Power Trim", {"Material", "Supplier"}, "Attribute", "Value"),
//split into rows by line feed
#"Split Column by Delimiter" = Table.ExpandListColumn(Table.TransformColumns(#"Unpivoted Other Columns",
{{"Value", Splitter.SplitTextByDelimiter("#(lf)", QuoteStyle.Csv), let itemType = (type nullable text) meta [Serialized.Text = true] in type {itemType}}}), "Value"),
#"Trimmed Text" = Table.TransformColumns(#"Split Column by Delimiter",{{"Value", Text.Trim, type text}}),
//filter out the blank rows
#"Filtered Rows" = Table.SelectRows(#"Trimmed Text", each ([Value] <> "" and [Value] <> "Not Provided")),
//Add custom column for separating the tables
#"Added Custom" = Table.AddColumn(#"Filtered Rows", "Custom", each try Date.FromText([Value]) otherwise
if [Value] = "Heavy Metals" or [Value] = "Residual Solvents" or [Value] = "Other" then [Value] else null),
#"Changed Type1" = Table.TransformColumnTypes(#"Added Custom",{{"Custom", type text}}),
#"Filled Down" = Table.FillDown(#"Changed Type1",{"Custom"}),
//Filter the value and custom columns to remove contaminant type from Value column and remove dates from Custom column
#"Filtered Rows1" = Table.SelectRows(#"Filled Down", each ([Custom] = "Heavy Metals" or [Custom] = "Residual Solvents") and ([Value] <> "Heavy Metals" and [Value] <> "Residual Solvents")),
//split substance from amount
#"Split Column by Delimiter1" = Table.SplitColumn(#"Filtered Rows1", "Value",
Splitter.SplitTextByEachDelimiter({" "}, QuoteStyle.Csv, true), {"Substance", "Amount"}),
//Filter for Solvents Table
#"Filtered Rows2" = Table.SelectRows(#"Split Column by Delimiter1", each ([Custom] = "Heavy Metals")),
#"Changed Type2" = Table.TransformColumnTypes(#"Filtered Rows2",{{"Amount", type number}}),
//Group by Material and Substance, then extract the Max contaminant and Source
#"Grouped Rows" = Table.Group(#"Changed Type2", {"Substance","Material", "Supplier"}, {
{"Amount", each List.Max([Amount]), type number},
{"Source", (t) => t[Attribute]{List.PositionOf(t[Amount],List.Max(t[Amount]))}, type text}
}),
#"Sorted Rows" = Table.Sort(#"Grouped Rows",{{"Substance", Order.Ascending}}),
//PIVOT to compare suppliers
#"Pivoted Column" = Table.Pivot(#"Sorted Rows", List.Distinct(#"Sorted Rows"[Supplier]), "Supplier", "Amount", List.Sum)
in
#"Pivoted Column"
Add an Index Column starting with zero (0).
Add a Custom Column:
=List.Max(
Record.ToList(
Table.SelectColumns(#"Added Index",
List.RemoveFirstN(
Table.ColumnNames(#"Pivoted Column"),3)){[Index]}))
Then remove the Index column
Algorithm
Generate a list of the relevant column names to sum.
We exclude the first three column names from this list
Note that we refer to the step PRIOR to adding the Index column for the list of column names. If we referred to the actual previous step where we added the Index column, we'd also have to remove the Last column name
Select the relevant columns
{[Index]} will return a record corresponding to the Index number.
Convert the record to a list and use List.Max

How do I filter for the concentrate of all set filters in PowerBI?

I have data in this form:
In PowerBI, I added another column where I keep only code combinations that consist of one single code. I did this with something like IF(LEN(Code > 1), "", Code). Result:
This enables me to create a slicer that contains only single codes. I also added a table that shows Codes.
Now, when I select codes in the slicer, I want the table to show these codes, plus the exact combination of it.
For example, when I select A and B, the table should show me A and B and A, B. I don't want it to show A, B, C although it contains A and B.
If I filter for A and B and C, however, I want it to show A and B and C and A, B, C - but not A, B.
How can I achieve that?
All entries in Codes are saved as strings.
You need a disconnected (not connected to the base table) table for your slicer. Now, if I consider your base table name is - your_table_name, you can create the new slicer table with this below code-
slicer =
SELECTCOLUMNS(
FILTER(
your_table_name_8,
LEN(your_table_name_8[codes]) = 1
),
"code",your_table_name_8[codes]
)
After creating the new slicer table, check in the model is there any auto relation detected between 2 tables or not. If you find any relation, just Remove the relation.
Now, create your slicer from the newly created table and create this below measure in your base table your_table_name-
show_or_hide =
VAR current_code = MIN(your_table_name_8[codes])
VAR comma_separated_list =
CALCULATE (
CONCATENATEX (
VALUES(slicer[code]),
slicer[code],
","
)
)
RETURN
IF(
current_code = comma_separated_list || (LEN(current_code) = 1 && CONTAINSSTRING(comma_separated_list,current_code)),
1,
0
)
lets see the outcome-
Finally, you can apply a visual level filter using the new measure show_or_hide and apply a filter so that value with True only shown in the visual.
Reorder Combination
Let we have this following table-
Now this following code from Advanced Query Editor will give the the expected output-
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WctRx0nFWitUBsZx1nJRiYwE=", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Column1 = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", type text}}),
#"Added Index" = Table.AddIndexColumn(#"Changed Type", "Index", 1, 1, Int64.Type),
#"Reordered Columns" = Table.ReorderColumns(#"Added Index",{"Index", "Column1"}),
#"Split Column by Delimiter" = Table.SplitColumn(#"Reordered Columns", "Column1", Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv), {"Column1.1", "Column1.2", "Column1.3"}),
#"Changed Type1" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Column1.1", type text}, {"Column1.2", type text}, {"Column1.3", type text}}),
#"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type1", {"Index"}, "Attribute", "Value"),
#"Added Custom" = Table.AddColumn(#"Unpivoted Other Columns", "column_name", each "Column-" & [Value]),
#"Changed Type2" = Table.TransformColumnTypes(#"Added Custom",{{"column_name", type text}}),
#"Removed Columns" = Table.RemoveColumns(#"Changed Type2",{"Attribute"}),
#"Reordered Columns1" = Table.ReorderColumns(#"Removed Columns",{"Index", "column_name", "Value"}),
#"Sorted Rows" = Table.Sort(#"Reordered Columns1",{{"Index", Order.Ascending}, {"column_name", Order.Ascending}}),
#"Pivoted Column" = Table.Pivot(#"Sorted Rows", List.Distinct(#"Sorted Rows"[column_name]), "column_name", "Value", List.Min),
#"Merged Columns" = Table.CombineColumns(#"Pivoted Column",{"Column-A", "Column-B", "Column-C"},Combiner.CombineTextByDelimiter(",", QuoteStyle.None),"Merged")
in
#"Merged Columns"
Please check what applied in steps one by one for better understanding. Here is the output with ascending order in the combination-
Index column added for keep tracking the row from start to end. If you have already a similar column, you can use that column as well.

How to get the column names in excel

I am currently working on converting an excel table with >100 calculated columns into a DAX table with similar calculated columns.
Excel formula refers to the columns by their column coordinates, e.g. sum = A2+B2
whereas DAX refers the column name in the formula, e.g. sum = Principal +Interest
Now, when I am trying to convert excel version of sum=A2+B2, is there any clever way for me to find out A=Principal and B= Interest in the spreadsheet.
I am talking about a table which has >50 non calculated columns and >100 calculated columns to be converted to comparable DAX model. Every time I look into a formula for the calculated columns in excel,
e.g.
Interest = =IF(AND(AR7="Pending",OR(V7="Completed",V7="Approved", LEFT(V7,4)="OPEN")),IF(U7*1>0,U7*1,N7)/VLOOKUP(F7,Tax!A:B,2,0),0)
I need to go back and forth in the table to find out what are the corresponding column for each coordinate in this.
Is there any clever way for me to find out what column names correspond to which column coordinate in the above formula, for example AR=Status, V=Application, U=Amount.....
Thank you in advance.
Thanks everyone. I think I managed to solve it using Power query. The following generates a table for an excel table with columns from A-ZZ and their corresponding coordinates.
Table Name - Query1
let
Source = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"},
#"Converted to Table" = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Added Custom" = Table.AddColumn(#"Converted to Table", "Custom", each {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"}),
#"Expanded Custom" = Table.ExpandListColumn(#"Added Custom", "Custom"),
#"Inserted Merged Column" = Table.AddColumn(#"Expanded Custom", "Merged", each Text.Combine({[Column1], [Custom]}, ""), type text),
#"Removed Columns" = Table.RemoveColumns(#"Inserted Merged Column",{"Column1", "Custom"}),
#"Renamed Columns" = Table.RenameColumns(#"Removed Columns",{{"Merged", "Column1"}}),
Custom1 = #"Converted to Table"&#"Renamed Columns",
#"Added Index" = Table.AddIndexColumn(Custom1, "Index", 1, 1) in
#"Added Index"
Now if I have a table like following, I run COLUMN syntax on my data source columns which produces the column number and I can use the previous PQWRY table to this to get the names
then
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WUtLBQLE60UoupcnZCkCOe35+cSqQds4vB3EDMtNT8/OADI/8ouJUqAiIcs7ITM5OzQPrNQTyjYDYGIhNgNgUiM2A2FwpNhYA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Column1 = _t, Column2 = _t, Column3 = _t, Column4 = _t, Column5 = _t, Column6 = _t, Column7 = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", type text}, {"Column2", type text}, {"Column3", type text}, {"Column4", type text}, {"Column5", type text}, {"Column6", type text}, {"Column7", type text}}),
#"Removed Top Rows" = Table.Skip(#"Changed Type",1),
#"Transposed Table" = Table.Transpose(#"Removed Top Rows"),
#"Changed Type1" = Table.TransformColumnTypes(#"Transposed Table",{{"Column2", Int64.Type}}),
#"Merged Queries" = Table.NestedJoin(#"Changed Type1", {"Column2"}, Query1, {"Index"}, "Query1", JoinKind.LeftOuter),
#"Expanded Query1" = Table.ExpandTableColumn(#"Merged Queries", "Query1", {"Column1"}, {"Column1.1"}),
#"Removed Columns" = Table.RemoveColumns(#"Expanded Query1",{"Column2"}),
#"Renamed Columns" = Table.RenameColumns(#"Removed Columns",{{"Column1.1", "Alphabetical_Coordinate"}}) in
#"Renamed Columns"
which gives me this
You can use VBA and the precedents member of the range object to get this. It will work for everything on the current sheet. I was not able to pick up the Tax!A:B and didn't have time to look further. Although, slightly incomplete, I at least wanted to provide this answer as a very good start
Sub formulaByField()
Dim formula As String
formula = Selection.formula
Debug.Print formula
Dim p As Range
For Each p In Selection.Precedents
'Debug.Print p.Address(False, False)
'Debug.Print Selection.Parent.Cells(1, p.Column).Value
formula = Replace(formula, p.Address(False, False), Selection.Parent.Cells(1, p.Column).Value)
Next
Debug.Print formula
End Sub
Code based on this setup:
Output
=IF(AND(A7="Pending",OR(B7="Completed",C7="Approved", LEFT(C7,4)="OPEN")),IF(D7*1>0,U7*1,E7)/VLOOKUP(F7,Tax!A:B,2,0),0)
=IF(AND(Duck="Pending",OR(Goose="Completed",Cow="Approved", LEFT(Cow,4)="OPEN")),IF(Pigeon*1>0,*1,Horse)/VLOOKUP(Pig,Tax!A:B,2,0),0)

Resources