How can I sum numbers in the same line in power query? - excel

Good Morning,
I have some doubt in PowerQuery, i have a column with some numbers in the same line that I need to sum, how can I do it?
Example input
field 1 | field 2 | field 3
Planeacion 2,3,1 2,2,2
field 1 | field 2 | field 3
Planeacion 6 6
output
Thanks in advance

In powerquery you can do this
Click-select the columns with the commas
Right click, Replace values, and replace the comma with a plus ( , to +)
Click-select the same columns
Right click, Transform ... lowercase...
edit the resulting formula so that each time you see
Text.Lower, type text
you replace it with
each Expression.Evaluate(_), type number
Sample version for the two columns
let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Replaced Value" = Table.ReplaceValue(Source,",","+",Replacer.ReplaceText,{"field 2", "field 3"}),
#"Transform1" = Table.TransformColumns(#"Replaced Value",{{"field 2", each Expression.Evaluate(_), type number}, {"field 3", each Expression.Evaluate(_), type number}})
in #"Transform1"

If you create a function like this:
CREATE FUNCTION [dbo].[csv2list]
(
#p1 varchar(max)
)
RETURNS TABLE
AS
RETURN
(
WITH List as (
SELECT CAST (value AS varchar(max)) value
FROM STRING_SPLIT(SUBSTRING(#p1, 1, LEN(#p1)), ',')
)
SELECT value
FROM List
)
GO
Then you can do:
SELECT * FROM csv2list('2,3,1');
which will produce:
2
3
1
or to sum them, use:
select sum(cast(value as integer)) from csv2list('2,3,1');

Related

PowerQuery/M: How can I combine text from multiple rows into one row

I have a table in PowerQuery like this:
#
KeyA
KeyB
Comment
Value
1.
A1
B1
Comment 1
1
2.
A1
B1
Comment 2
3
3.
A2
B2
Comment 3
6
How can I combine it so that rows with the same entries in columns KeyA and KeyB (e.g. #1 & #2 in the example) concat the text in column Comment and sum the value in column Value, i.e. resulting in this:
A
B
Comments
Sum
A1
B1
Comment 1, Comment 2
4
A2
B2
Comment 3
6
Table.Group is doing exactly what is required!
Here's the solution to the problem:
let
Source = Table.FromRecords({
[KeyA="A1", KeyB="B1", Comment="Comment 1", Value=1],
[KeyA="A1", KeyB="B1", Comment="Comment 2", Value=2],
[KeyA="A2", KeyB="B2", Comment="...", Value=3]
}),
Grouped = Table.Group(
Source,
{"KeyA", "KeyB"},
{
{"Comments", (t) => Text.Combine(t[Comment], ", ")}, // <- Magic happens here!
{"Sum", (t) => List.Sum(t[Value])},
{"RecordCount", each Table.RowCount(_), Int64.Type}
}
)
in
Grouped
Explanation:
The function requires 3 parameters:
the source data
a list of columns that should be used for grouping
a list of function that produce the new aggregated column(s)
The last parameter is the key and where the functions power comes in: internally PowerQuery calls each of these function provided with a table as parameter that contains all the rows for one group. What you do with it, is completely up to you, i.e. you can aggregate it using List.Sum, Avg, ... - but you can also do any other modification of the table.
The entry {"Comments", (t) => Text.Combine(t[Comment], ", ")} creates a new column Comments. (t) => ... is the function defition. This function get called for each group - with a table containing all rows of this group. t[Comment] extracts the Comment column from the table as a list - which can then be used with the List.Combine function to concatenate.
How to get started from the PowerQuery editor
If you have the Source table in the PowerQuery editor, select column KeyA and KeyB and click Group By in the Transform ribbon. This will scaffold the Table.Group query with a record count. USe the Advanced Editor for further modifications.

How to update values in more than one column based on another column with M in PowerQuery [duplicate]

I want to do something similar to Power Query Transform a Column based on Another Column, but I'm getting stuck on how to modify the syntax for my particular goal.
Similar to the linked question, assume that I have the following table:
Table 1:
Column A | Column B | Column C
------------------------------
1 | 4 | 7
2 | 5 | 8
3 | 6 | 9
Instead of changing the value of the Column A conditional on Column B, I want to multiply the values in multiple columns (Column B and Column C) by those in Column A and replace the values in the initial columns so that I can get the following:
Table 1:
Column A | Column B | Column C
------------------------------
1 | 4 | 7
2 | 10 | 16
3 | 18 | 27
Is this possible to do without using multiple sequences of Table.AddColumn followed by Table.RemoveColumns?
I have also tried Table.TransformColumns based on this, but not been able to get the syntax right to achieve this.
Table.TransformColumns won't give you Column A unless you can index back into the table, which will only be possible if your columns only have unique data.
Table.TransformRows will let you build new rows with whatever logic you want:
let
Source = Csv.Document("Column A,Column B,Column C
1,4,7
2,5,8
3,6,9"),
PromotedHeaders = Table.PromoteHeaders(Source),
ChangedType = Table.TransformColumnTypes(PromotedHeaders,{{"Column A", type number}, {"Column B", type number}, {"Column C", type number}}),
MultipliedRows = Table.FromRecords(Table.TransformRows(ChangedType,
each [
Column A = [Column A],
Column B = [Column A] * [Column B],
Column C = [Column A] * [Column C]
]))
in
MultipliedRows
This works well for columns B and C, but if you need B through Z you might want fancier logic to avoid repeating yourself.
EDIT: A more general solution for many columns is to use Record.TransformFields on a list of transforms for all column names except "Column A".
let
Source = Csv.Document("Column A,Column B,Column C,D,E,F
1,4,7,1,2,3
2,5,8,4,5,6
3,6,9,7,8,9"),
PromotedHeaders = Table.PromoteHeaders(Source),
ChangedType = Table.TransformColumnTypes(PromotedHeaders,{{"Column A", type number}, {"Column B", type number}, {"Column C", type number}, {"D", type number}, {"E", type number}, {"F", type number}}),
MultipliedRows = Table.FromRecords(Table.TransformRows(ChangedType, (row) =>
let
ColumnA = row[Column A],
OtherColumns = List.RemoveItems(Record.FieldNames(row), {"Column A"}),
Transforms = List.Transform(OtherColumns, (name) => { name, (cell) => cell * ColumnA })
in
Record.TransformFields(row, Transforms)))
in
MultipliedRows
I think the Table.AddColumn followed by Table.RemoveColumns is the usual and clearest way for this transformation. I'm also not happy with the fact that this results in so many steps in PowerQuery.
But due to internal backfolding methods of PowerQuery this will usualy not result in better performance. (PowerQuery trys to give the main Work back to the queried Database if avaiable)
Assuming this doesn't need to be VBA and/or programmatic, you can just copy values in the first column, then highlight the values in the second column, and "Paste Special..." > Multiply.
That will produce the results in the same place you paste the multiplier.

DAX LOOKUPVALUE on text/string

I would like to create some kind of LOOKUPVALUE on text in DAX that will match a sentence with a particular keyword. For instance in the example below the second and third row have a hit because “Apple” and "Chicken" is in the string. The problem is that the text is in a string and not a standalone value.
Table 1
Table 2
Output
EDIT, improved answer: this new version also works when there are multiple keys in one string.
I think PowerQuery is the natural place to perform an operation like this.
The Output table would look like this:
A description of the applied steps:
Source: a reference to Table1
Added Column Key lists: adds a custom column with lists of the Table2[Key] value(s) that are in the [String] value. This is the logic for this Custom column:
For each row the function selects the values from the Table2[Key] column that it finds in the [String] value. It then returns a list that holds only the selected values.
Expanded Key list: expands the lists in the [Key] column
Join with Table2 on Key: Joins with Table2 on the Key Value
Expanded Table2: Expands the table values in the [ItemTables] column and keeps the [Item] column
Group and concate keys/items: Groups the Output table on String, concatenating the Keys and the Items. If you don't want to see the [Key] column, delete {"Key", each Text.Combine([Key], " | "), type text}, from this step
The script in the Advanced Editor looks like this:
let
Source = #"Table1",
#"Added Column Key lists" = Table.AddColumn(Source, "Key", (r) => List.Select(Table.Column(Table2,"Key"),each Text.Contains(r[String],_,Comparer.OrdinalIgnoreCase)),type text),
#"Expanded Key lists" = Table.ExpandListColumn(#"Added Column Key lists", "Key"),
#"Join with Table2 on Key" = Table.NestedJoin(#"Expanded Key lists", {"Key"}, Table2, {"Key"}, "ItemTables", JoinKind.LeftOuter),
#"Expanded ItemTables" = Table.ExpandTableColumn(#"Join with Table2 on Key", "ItemTables", {"Item"}, {"Item"}),
#"Group and concate keys / items" = Table.Group(#"Expanded ItemTables", {"String"},{{"Key", each Text.Combine([Key], " | "), type text},{"Item", each Text.Combine([Item], " | "), type text}})
in
#"Group and concate keys / items"
Here is a link to my .pbix file
I created the following dummy data sets.
My interpretation of what your after is to Identify if a sentence contains a key word.
This can be done via a calculated column with the following formula -
Lookup = LOOKUPVALUE(Table2[Result],Table2[LookUp], IF(SEARCH("Apple",Table1[Sentence],,0)> 0, "Apple",""))
You can combine the If and Search Functions with the Lookupvalue function.
The formula is searching for the word "Apple" and then returning its position within the text and if no result is found, displays 0.
The IF statement then takes any result greater then 0, as anything greater then 0 means a result has been found and that is its position within the string, and states "Apple". This then becomes your lookup value.
This then displays as bellow
You can then replace the Blank ("") that is currently the result if false, with another if statement to look for another key word such as "Orange" and then add add that to your lookup table to pull through the result your after.
Hope this makes sense and helps!
Try this formula (see the picture which cell is where in my assumptions):
=IFERROR(INDEX($B$7:$B$9,MATCH(1,--NOT(ISERROR(FIND($A$7:$A$9,$A12))),0)),"-")

Adding unique index in Excel Power Query

I have a table which looks like
Date
9/4/2016
9/11/2016
9/18/2016
9/25/2016
10/2/2016
10/9/2016
10/16/2016
10/23/2016
10/30/2016
11/6/2016
11/13/2016
11/20/2016
11/20/2016
I'm trying to assign unique index values to 'Date column' but couldn't do it using the 'Add custom index value' in power query which doesn't check duplication. Also I tried "Date.WeekOfYear" which gives number based on year, but I want to assign unique numbers from 1 to .... for dates like
Date Custom_weeknumber
9/4/2016 1
9/11/2016 2
9/18/2016 3
9/25/2016 4
10/2/2016 5
10/9/2016 6
10/16/2016 7
10/23/2016 8
10/30/2016 9
11/6/2016 10
11/13/2016 11
11/20/2016 12
11/20/2016 12
Any help would be helpful, thanks!
Assuming:
Your dates are sorted.
The row after duplicates will get the Custom_weeknumber from the duplicates + 1.
Then you can group by dates (with New column name e.g. "DateGroups" and Oparation "All Rows"), add an index column, expand the "DateGroups" field and remove the "DateGroups" field.
Code example created in Power Query in Excel:
let
Source = Excel.CurrentWorkbook(){[Name="Dates"]}[Content],
Typed = Table.TransformColumnTypes(Source,{{"Date", type date}}),
Grouped = Table.Group(Typed, {"Date"}, {{"DateGroups", each _, type table}}),
Numbered = Table.AddIndexColumn(Grouped, "Custom_weeknumber", 1, 1),
Expanded = Table.ExpandTableColumn(Numbered, "DateGroups", {"Date"}, {"DateGroups"}),
Removed = Table.RemoveColumns(Expanded,{"DateGroups"})
in
Removed
I'd do it this way (which seem to me a bit simplier, I don't like nested tables unless absolutely needed):
Group By Date column
Optional: Sort
Add index
Join source table
Code:
let
//Source = Excel.CurrentWorkbook(){[Name="YourTableName"]}[Content],
Source = #table(type table [Date = date], {{#date(2016, 10, 12)}, {#date(2016, 10, 13)}, {#date(2016,10,14)}, {#date(2016, 10, 14)}}),
GroupBy = Table.RemoveColumns(Table.Group(Source, "Date", {"tmp", each null, type any}), {"tmp"}),
//Optional: sort to ensure values are ordered
Sort = Table.Sort(GroupBy,{{"Date", Order.Ascending}}),
Index = Table.AddIndexColumn(Sort, "Custom_weeknumber", 1, 1),
JoinTables = Table.Join(Source, {"Date"}, Index, {"Date"}, JoinKind.Inner)
in
JoinTables

Power Query: transform a column by multiplying by another column

I want to do something similar to Power Query Transform a Column based on Another Column, but I'm getting stuck on how to modify the syntax for my particular goal.
Similar to the linked question, assume that I have the following table:
Table 1:
Column A | Column B | Column C
------------------------------
1 | 4 | 7
2 | 5 | 8
3 | 6 | 9
Instead of changing the value of the Column A conditional on Column B, I want to multiply the values in multiple columns (Column B and Column C) by those in Column A and replace the values in the initial columns so that I can get the following:
Table 1:
Column A | Column B | Column C
------------------------------
1 | 4 | 7
2 | 10 | 16
3 | 18 | 27
Is this possible to do without using multiple sequences of Table.AddColumn followed by Table.RemoveColumns?
I have also tried Table.TransformColumns based on this, but not been able to get the syntax right to achieve this.
Table.TransformColumns won't give you Column A unless you can index back into the table, which will only be possible if your columns only have unique data.
Table.TransformRows will let you build new rows with whatever logic you want:
let
Source = Csv.Document("Column A,Column B,Column C
1,4,7
2,5,8
3,6,9"),
PromotedHeaders = Table.PromoteHeaders(Source),
ChangedType = Table.TransformColumnTypes(PromotedHeaders,{{"Column A", type number}, {"Column B", type number}, {"Column C", type number}}),
MultipliedRows = Table.FromRecords(Table.TransformRows(ChangedType,
each [
Column A = [Column A],
Column B = [Column A] * [Column B],
Column C = [Column A] * [Column C]
]))
in
MultipliedRows
This works well for columns B and C, but if you need B through Z you might want fancier logic to avoid repeating yourself.
EDIT: A more general solution for many columns is to use Record.TransformFields on a list of transforms for all column names except "Column A".
let
Source = Csv.Document("Column A,Column B,Column C,D,E,F
1,4,7,1,2,3
2,5,8,4,5,6
3,6,9,7,8,9"),
PromotedHeaders = Table.PromoteHeaders(Source),
ChangedType = Table.TransformColumnTypes(PromotedHeaders,{{"Column A", type number}, {"Column B", type number}, {"Column C", type number}, {"D", type number}, {"E", type number}, {"F", type number}}),
MultipliedRows = Table.FromRecords(Table.TransformRows(ChangedType, (row) =>
let
ColumnA = row[Column A],
OtherColumns = List.RemoveItems(Record.FieldNames(row), {"Column A"}),
Transforms = List.Transform(OtherColumns, (name) => { name, (cell) => cell * ColumnA })
in
Record.TransformFields(row, Transforms)))
in
MultipliedRows
I think the Table.AddColumn followed by Table.RemoveColumns is the usual and clearest way for this transformation. I'm also not happy with the fact that this results in so many steps in PowerQuery.
But due to internal backfolding methods of PowerQuery this will usualy not result in better performance. (PowerQuery trys to give the main Work back to the queried Database if avaiable)
Assuming this doesn't need to be VBA and/or programmatic, you can just copy values in the first column, then highlight the values in the second column, and "Paste Special..." > Multiply.
That will produce the results in the same place you paste the multiplier.

Resources