PowerBI table: how to add number to column name - powerbi

I have a table with the following column names:
A
B
C
D
E
F
G
I need to rename my columns so that from a certain column onwards they are numbered sequentially:
A
B
C
D (1)
E (2)
F (3)
G (4)
I know how to do it manually, but since I have 65 of such columns I was hoping to use something like TransformColumnNames to do it programmatically.
Many thanks!

Here's one way: It starts with a table named Table 1 as the source.
let
Source = Table1,
//Replace the "D" below with the name of your column that you want to start numbering at
#"Get Column Number to Start Adding Numbers At" = List.PositionOf(Table.ColumnNames(Source),"D"),
#"Setup Column Numbers" = List.Transform({1..List.Count(Table.ColumnNames(Source))}, each if _-#"Get Column Number to Start Adding Numbers At" > 0 then " (" & Text.From(_-#"Get Column Number to Start Adding Numbers At") & ")" else ""),
#"Create New Column Names" = List.Zip({Table.ColumnNames(Source), #"Setup Column Numbers"}),
#"Converted to Table" = Table.FromList(#"Create New Column Names", Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Extracted Values" = Table.TransformColumns(#"Converted to Table", {"Column1", each Text.Combine(List.Transform(_, Text.From)), type text}),
Result = Table.RenameColumns(Source, List.Zip({Table.ColumnNames(Source),#"Extracted Values"[Column1]}))
in
Result

Maybe if you pivot the columns that need to have the number, then add an index and create a new concatenated column with number included. remove the other columns and unpivot again?

Related

Change column values based on its position

I'm trying to adjust some columns with negative values in my table, I want to all negative values be changed to 0,
The only problem is that the columns keep changing their names, so I would like to be able to make such adjustment based on column position,
For example, the columns are located in 3 and 4 position,
I have created a conditional column to adjust the negatives volumes,
#"New Column" = Table.AddColumn(#Previous Step", "New Column", each if OldColumnName < 0 then 0 else NewColumn),
Is there a way to make this conditional column based on the OldColumn position, and not by its name?
add column, custom column with formula
= if Record.Field(_,Table.ColumnNames(Source){2})<0 then 0 else Record.Field(_,Table.ColumnNames(Source){2})
or
= if Record.Field(_,Table.ColumnNames(Source){2})<0 then 0 else [some other column])
where {2} is the position in column names
Sample to transform in place to remove negatives
Stepname = Table.TransformColumns(#"PriorStepNameHere",{{Table.ColumnNames(#"PriorStepNameHere"){2}, each if _<0 then 0 else _, Int64.Type}})
for multiple column transformations
let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
ColumnsToTransform = {Table.ColumnNames(Source){2},Table.ColumnNames(Source){3}},
#"MultipleTransform" = Table.TransformColumns(Source, List.Transform(ColumnsToTransform,(x)=>{x, each if _<0 then 0 else _, type number}))
in #"MultipleTransform"

Power Query: recursive function to append elements in a table

I am trying to use a recursive function to append values from a list to a table, however the code below only show me the first and second results:
let
Source = {"second", "third", "forth", "fith", "seventh", "eighth"},
Count = List.Count(Source),
Table = Table.FromRecords({[sequence = "first"]}, type table[sequence = text]),
appendTbl = (x as list, n as number, tbl as table) =>
let
appTable = Table.InsertRows(Table, n, {[sequence = Source{n}]}),
Check = if n = (Count-1) then #appendTbl(x, n+1, appTable) else appTable
in
Check,
Result = appendTbl(Source, 0, Table)
in
Result
Can anyone please give me a help? Thanks !
Its kind of hard to tell if you are using the number to designate the spot in the table you want to insert, or the number of times you want to duplicate the array before inserting it into the table
That said, you can combine tables with Table.Combine() after converting the list to a table with Table.FromList(). If you need to append it multiple times then just use List.Repeat on the list. If you need to use the Count variable in your function, you have to send it there appendTbl = (x as list, n as number, tbl as table, count as number) =>
some sample codes that probably don't do exactly what you want
let Source = {"second", "third", "forth", "fith", "seventh", "eighth"},
AppendCount=2, //# times to append the list onto the table
#"Converted to Table" = Table.FromList(List.Repeat(Source,AppendCount), Splitter.SplitByNothing(), null),
#"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "sequence"}}),
Table = Table.FromRecords({[sequence = "first"]}, type table[sequence = text]),
combined= Table.Combine({Table, #"Renamed Columns"})
in combined
or
let Source = {"second", "third", "forth", "fith", "seventh", "eighth"},
Table = Table.FromRecords({[sequence = "first"]}, type table[sequence = text]),
appendTbl = (x as list, n as number, tbl as table) => // append list x to table tbl, n times on column sequence
let #"Converted to Table" = Table.FromList(List.Repeat(x,n), Splitter.SplitByNothing(), null),
#"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "sequence"}}),
combined= Table.Combine({tbl, #"Renamed Columns"})
in combined,
Result = appendTbl(Source, 2, Table) // append Source to Table, 2 times
in Result

generate a one-column table that contains hundreds of different categories using M or DAX

I need to split my products into a total of 120 predefined price clusters/buckets. These clusters can overlap and look somewhat like that:
As I dont want to write down all of these strings manually: Is there a convenient way to do this in M or DAX directly using a bit of code?
Thanks in advance!
Dave
With m-Query you can create a function. Open the query editor. Richt click and create empty query. Create function (ignore warning) and call it : RowGenerator.
Open advanced editor and past the following code:
let
Bron = (base as number, start as number, end as number) => let
Bron = Table.FromList(List.Generate(() => start, each _ <= end, each _ + 1), Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Aangepaste kolom toegevoegd" = Table.AddColumn(Bron, "Aangepast", each Number.ToText(base) & " - " & Number.ToText([Column1]))
in
#"Aangepaste kolom toegevoegd"
in
Bron
This function creates a table where base is your first number and start, end the range.
Add another empty query, open the advanged editor and paste:
let
Bron = List.Generate(() => 0, each _ < 5, each _ + 1),
#"Geconverteerd naar tabel" = Table.FromList(Bron, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
#"Aangeroepen aangepaste functie" = Table.AddColumn(#"Geconverteerd naar tabel", "test", each RowGenerator(_[Column1], _[Column1] + 1, 5)),
#"test uitgevouwen" = Table.ExpandTableColumn(#"Aangeroepen aangepaste functie", "test", {"Column1", "Aangepast"}, {"Column1.1", "Price Cluster"}),
#"Kolommen verwijderd" = Table.RemoveColumns(#"test uitgevouwen",{"Column1", "Column1.1"})
in
#"Kolommen verwijderd"
This creates first a list of 5 rows, then it calls the previous made function for each row and the last step is to expend the rows and remove the not needed columns.
Enjoy:
You can create this bucket by DAX (New Table):
Table = SELECTCOLUMNS(
GENERATE(SELECTCOLUMNS(GENERATESERIES(0,10,1),"FirstPart",[Value]), SELECTCOLUMNS(GENERATESERIES(0,10,1),"SecondPart",[Value]))
,"Bucket", [FirstPart] & " - " & [SecondPart]
)
Table = SELECTCOLUMNS(
GENERATE(SELECTCOLUMNS(GENERATESERIES(0,9,1),"FirstPart",[Value]), TOPN([FirstPart], SELECTCOLUMNS(GENERATESERIES(1,9,1),"SecondPart",[Value]), [SecondPart],ASC))
,"Bucket", [FirstPart] & " - " & [SecondPart]
)

Power Query conditional sumif

I need to add a column that Sums the value column of all columns that have a common id. However, any id = null is not summed, but equal to the value column.
The above example should result in:
TopPaymendId JournalLineNetAmount TopAmount
fcbcd407-ca26-4ea0-839a-c39767d05403 -3623.98 -7061.23
fcbcd407-ca26-4ea0-839a-c39767d05403 -3437.25 -7061.23
ce77faac-1638-40e9-ad62-be1813ce9031 -88.68 -88.68
531d9bde-3f52-47f3-a9cf-6f3566733af2 -152.23 -152.23
8266dfef-dd14-4654-a6d2-091729defde7 229.42 229.42
f8b97a47-15ef-427d-95e0-ce23cc8efb1f -777 -777
null -3.01 -3.01
null -2.94 -2.94
null 3312.5 3312.5
This code should work:
let
Source = Excel.CurrentWorkbook(){[Name="Data"]}[Content],
group = Table.Group(Source, {"TopPaymendId"}, {"TopAmount", each List.Sum([JournalLineNetAmount])}),
join = Table.Join(Source,{"TopPaymendId"},group,{"TopPaymendId"}),
replace = Table.ReplaceValue(join,each [TopAmount],each if [TopPaymendId] = null
then [JournalLineNetAmount] else [TopAmount],Replacer.ReplaceValue,{"TopAmount"})
in
replace

Converting non structured key value pairs data to a table

I have data in the following format, sample shown below:
ValA=101
ValB=2938
ValA=998
ValB=387
ValA=876
ValB=9832
I know that each set of ValA & ValB are a set of values that belong together, so output will be:
ValA ValB
101 2938
998 387
.......
.......
I need to get this into a tabular format so each valA ValB pair is one row.
Ive tried doing this in powerquery by splitting on the = sign and then pivoting on the Val name, but it doesnt work.
any idea on how this might be easily achieved in powerquery?
Thanks!
I ended up doing the exact same as Lukasz, here's the full code:
let
Source = "ValA=101
ValB=2938
ValA=998
ValB=387
ValA=876
ValB=9832",
Custom1 = Lines.FromText(Source),
#"Converted to Table" = Table.FromList(Custom1, Splitter.SplitTextByDelimiter("="), null, null, ExtraValues.Error),
ChangedType = Table.TransformColumnTypes(#"Converted to Table",{{"Column1", type text}, {"Column2", Int64.Type}}),
CustomA = Table.AddColumn(ChangedType, "ValA", each if [Column1] = "ValA" then [Column2] else null),
CustomB = Table.AddColumn(CustomA, "ValB", each if [Column1] = "ValB" then [Column2] else null),
FilledDown = Table.FillDown(CustomB,{"ValA"}),
FilteredRows = Table.SelectRows(FilledDown, each [ValB] <> null)
in
FilteredRows
Lukasz's second idea using pivot columns looks like this:
let
Source = "ValA=101
ValB=2938
ValA=998
ValB=387
ValA=876
ValB=9832",
Custom1 = Lines.FromText(Source),
#"Converted to Table" = Table.FromList(Custom1, Splitter.SplitTextByDelimiter("="), null, null, ExtraValues.Error),
ChangedType = Table.TransformColumnTypes(#"Converted to Table",{{"Column1", type text}, {"Column2", Int64.Type}}),
AddedIndex = Table.AddIndexColumn(ChangedType, "Index", 0, 1),
IntegerDividedColumn = Table.TransformColumns(AddedIndex, {{"Index", each Number.IntegerDivide(_, 2), Int64.Type}}),
PivotedColumn = Table.Pivot(IntegerDividedColumn, List.Distinct(IntegerDividedColumn[Column1]), "Column1", "Column2")
in
PivotedColumn
The trick I found was to add divided-by-two index column (that goes 0, 0, 1, 1, 2, 2...) so the pivot knows the first two rows should be related, and the next two, etc.
You can do the following:
1) create two new calculated columns with logic like if column1 contains ValA then Column1 else null. same logic for ValB in second column.
2) use the fill down feature on the left most column. This will produce rows with values for both ValA and ValB in distinct columns
3) use the filter feature to filter out rows that have nulls in your two new columns
That should give you what you want.
Edit: thinking about this more you might also try: split column1 on the equal sign. Then pivot the new column and it should produce two columns with the discrete values. HTH.