The post “When a Power BI dataset refresh completes” trigger in Power Automate appeared first on The BIccountant.

]]>Just create a data driven alert in Power BI with a threshold that will be reached with every refresh of the dataset. You can do this by setting a dedicated “Trigger-Flow”-measure to 1 for example. Then configure the data driven alert to trigger every time the measure is above 0. Within the data driven alert, choose the option to “Use Microsoft Power Automate to trigger additional actions”. That will create a new flow that will trigger whenever the dataset refreshes.

As you can see in the screenshot above, this method will not work more than once in an hour. But for most workloads withing a pro workspace this will probably be sufficient.

Enjoy and stay queryious 😉

The post “When a Power BI dataset refresh completes” trigger in Power Automate appeared first on The BIccountant.

]]>The post Create Power BI Metrics/Goals Scorecards from Excel files using Power Automate appeared first on The BIccountant.

]]>The biggest challenge for this task I see are the goals hierarchies. Take a look at the sample data below:

The first 2 columns (id and parentid) determine the hierarchical structure of the goals. It would be great if we could use them in the flow to create the same connections in the Power BI goals. But unfortunately that is not possible: Once a goal is created through the connector, it is assigned a unique ID by the API and that ID must be used by the other goals to connect to it. This can be interpreted as a recursive task and in my previous blogpost I have described some techniques on how to solve that in Power Automate.

We can use an array-variable in the flow to store the “Old_ID”-“New_ID”-value pairs for all created goals. That allows for each newly created goal to lookup the correct parentid. Please refer to my previous blogpost to understand the general setup.

These are the flows’ steps:

The following pictures display the details. In the comments you will see the formulas from the formula editor:

If you want to play around with it, please check out the template enclosed: CreatePowerBIScorecardfromExceltable_20221008170230.zip (43 downloads)

I have created trigger parameters for the Excel-connection to make this work in different environments. But I find it generally easier to enter the connection details directly in the connector. So once you have imported the template into your environment feel free to delete these parameters and connect to your table directly in the Excel-connector.

Enjoy the flow and stay queryious 😉

The post Create Power BI Metrics/Goals Scorecards from Excel files using Power Automate appeared first on The BIccountant.

]]>The post Recursive Flows in Power Automate – Introduction appeared first on The BIccountant.

]]>Daniil Maslyuk contributed a great introduction into recursion on my blog here. Please check it out if the concept of recursion is new to you.

Here, I will take his basic example as a starting point to convert into a flow in Power Automate. The task is to multiply a number by 2 and then continue to multiply the result of the previous multiplication with 2 again until the result is greater than 10. In Power Query, you can solve this with the native recursion operator “@” like so:

In row 1, you feed in a number as an initial value for the calculation. Row 2 has the condition when the recursive repetition shall stop, row 3 defines the output in case the recursion has stopped (or the initial values is already greater than 10) and row 4 describes the operation that shall happen during recursion. “MyFunction” references the result of the previous iterative step.

Conceptually, we can solve this in PA like so:

So we are going to use a variable that allows us to push the values from our actions to. That variable can then be queried and checked if the condition for further calculations is met or if the final result should be returned.

Technically, this can be designed like below. The process step numbers match in both pictures.

Next, let’s try to do the “Hello World” of recursion: Creating a flow that calculates a Fibonacci series. This is a sequence of numbers where each number is the sum of the two preceding values, starting from 0 and 1.

So we need to create a series where the next value will be calculated by adding the last 2 values from the series so far. As we need the 2 last results, for each new calculation, our variable cannot hold a single scalar like in the first example. Instead, we have to use a variable of type array and append each result to it. Then, we have to repeat that calculation n times (where n is the number we are feeding in). Therefore we could use the “do-until”-action with an additional counter parameter or we can use a “apply to each”-loop if we create an array which is n elements long. Let’s go for the later:

These are the 2 basic architectures on how to do recursive flows in Power Automate:

- Use one (or more) variables to store the results of the calculations so far and make them available for the next calculation steps.
- Decide which loop you need (“Do-until” or “For-each”) and pick the matching actions.
- If your variable is a scalar (single value), then you replace the variable in the recursive step (“Set variable” action) and if it is an array, you use the “append to array”-action.

If you want to play around with these flows, you can download them here:

Recursion1-Mult2_20220904183943.zip

Recursion2-Fibonacciseries_20220904183502.zip

Enjoy and stay queryious 😉

The post Recursive Flows in Power Automate – Introduction appeared first on The BIccountant.

]]>The post Forecasting with seasonality in Power BI appeared first on The BIccountant.

]]>Please note, that the monthly variation I am using in this example is taken from an existing table and not derived by statistical methods like the Excel FORECAST.ETS.SEASONALITY function. Here, we simply apply an existing distribution to expected future sales, but I will cover forecasts using those statistical methods in upcoming blogposts.

Todays starting point is a request to calculate how many sales to expect until the end of the year and then distribute the expected sales according to a list of monthly %, which are all different, because there is an expected seasonality in the sales:

The total amount of expected sales for the year should be based on the sales of the past:

- Take the amount of the sales for the months, which are already closed
- Lookup the sum of % for the closed months and add them up
- Apply the rule of three to determine the expected sales of the whole year
- Allocate the difference to the remaining months, based on their monthly %

The following picture gives an overview of the situation:

So we are in May and have some sales in already, but the last closed month is April (these months add up to 1,435 sales in total). Therefore the % from the Forecast table will be taken from January until April as well (they add up to 28%). Applying the rule of three forecast the amount of 5,125 for the whole year. We will distribute the share for the months May-Dec according to the % from the forecast table.

One additional requirement is that the solution should be dynamic: As soon as a new month is closed, the amount shall be automatically updated. So the base sum that determines the level includes one more month and the months with forecast values start one month later.

My tables are connected as follows:

This DAX-measure returns the desired allocation:

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

Learn more about bidirectional Unicode characters

SumForecast = | |

VAR _previousMonth = | |

CALCULATE ( | |

MAX ( 'Date'[Year Month Number] ), — Must be the column that is connected to the Forecast-table | |

REMOVEFILTERS ( 'Date' ), | |

'Date'[Date] = TODAY () | |

) – 1 | |

VAR _latestYTD = | |

CALCULATE ( | |

[YTD SumSales], | |

REMOVEFILTERS ( 'Date' ), | |

'Date'[Year Month Number] = _previousMonth | |

) | |

VAR _cumulPercentage = | |

CALCULATE ( | |

[YTD SumPercentage], | |

REMOVEFILTERS ( 'Date' ), | |

'Date'[Year Month Number] = _previousMonth | |

) | |

VAR _amountForTotalYear = | |

DIVIDE ( _latestYTD, _cumulPercentage ) | |

VAR _result = | |

SUMX ( | |

'Forecast', | |

VAR _isPlanningMonth = | |

( CALCULATE ( MAX ( 'Date'[Year Month Number] ) ) > _previousMonth ) | |

VAR _relevantYTD = | |

IF ( _isPlanningMonth, _amountForTotalYear * Forecast[ % Forecast], [SumSales] ) | |

RETURN | |

_relevantYTD | |

) | |

RETURN | |

_result |

- The first variable “_previousMonth” determines the last closed month. For simplicity-reason, we assume that this will always be the last month before today. In a later blogpost I will show a solution where this can be individually selected. Please note, that the MAX-column that is picked from the Date-table needs to have the same granularity than the Forecast-table. Therefore, I’ve picked the column over which these 2 tables are connected.
- The next variable “_latestYTD” fetches the sum of sales that have been occurred up until the previous month. I’m referencing a YTD-measure here, which follows a fairly standard definition:
CALCULATE ( [SumSales], DATESYTD ( ‘Date'[Date] ) ).
- Variable “_cumulPercentage” adds up the %-values of the closed months. Again, referenced YTD-measure has same logic than for sales above.
- Now we have all the values for the rule of three to calculate the total amount of sales of the year (“_amountForTotalYear” in row 20).
- Then comes the final calculation where we apply the %-values on the annual amount (for the open months) and simply take the actual sales amounts for the closed months. As these amounts shall be aggregated correctly on non-month intervals like year or quarter, we have to iterate over the months.
- Therefore we take the whole Forecast-table (row 24), as we need the monthly granularity and also need to pick the %-value.
- VAR “_isPlanningMonth” determines if the currently iterated month is closed or not.
- VAR “_relevantYTD” then picks the fitting value for each month: Either the actual or forecasted (_amountTotalYear multiplied by the monthly %).

- All the months’ values will then be added up, because we are using the SUMX-function here (row 23).Wa

Doing forecasts with DAX has become a very viable solution for me since the availability of a standard connector for DAX queries against Power BI datasets recently. This allows me to export my DAX calculations back into ERP- or bookkeeping systems in an automated way. Check out my next blogpost where I describe how this could be done for the example above.

In upcoming posts I will also cover how to:

- integrate more attributes into the allocation like products or cost centres
- create the %-table automatically based on previous years figures
- give an option to increase or decrease the forecast amount by certain %
- use statistical methods to create a forecast with seasonality based on historical data in Power BI

The file is available for download here: Forecast-1.pbix

Do you see other use cases that I should cover? Please let me know in the comments below.

Enjoy and stay queryious 😉

The post Forecasting with seasonality in Power BI appeared first on The BIccountant.

]]>The post Create (empty) table string from schema in Power Query appeared first on The BIccountant.

]]>The function I’m sharing here creates a string with M-code that creates an empty table with the same column names and types than the original table automatically for you. All you have to do is reference the table without errors in the function parameter.

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

Learn more about bidirectional Unicode characters

let | |

fnFormatted = let | |

func = (myTable as table) => | |

let | |

#"Table1 Schema" = Table.Schema(myTable), | |

TypesList = Table.AddColumn( | |

#"Table1 Schema", | |

"TypeRecord", | |

each [Name] & "=" & [TypeName] | |

)[TypeRecord], | |

TypeRecordString = "[" & Text.Combine(TypesList, ", ") & "]", | |

TableString = "#table(type table " | |

& TypeRecordString | |

& ", {{" | |

& Text.Combine(List.Repeat({"null"}, List.Count(TypesList)), ", ") | |

& "}})" | |

in | |

TableString, | |

documentation = [ | |

Documentation.Name = " Text.CreateEmptyTableFromSchema ", | |

Documentation.Description | |

= " Creates the M-code for an empty table based on a table schema. ", | |

Documentation.LongDescription | |

= " Creates the M-code for an empty table based on a table schema (Table.Schema). ", | |

Documentation.Category = " Text.Transformations ", | |

Documentation.Source = " www.TheBIcountant.com https://wp.me/p6lgsG-2tJ . ", | |

Documentation.Version = " 1.0 ", | |

Documentation.Author = " Imke Feldmann ", | |

Documentation.Examples = { | |

[Description = " ", | |

Code = | |

" let | |

myTable = #table( type table [myText = Text.Type, myNumber = Int64.Type, myDate = Date.Type], | |

// myText| myNumber| myDate| | |

{//——-|———|——————| | |

{ ""A"", 10, #date(2022, 01, 01) } } ), | |

FunctionCall = fnText_CreateEmptyTableFromSchema( myTable ) | |

in | |

FunctionCall " | |

, | |

Result = " #table(type table [myText=Text.Type, myNumber=Int64.Type, myDate=Date.Type], {{null, null, null}}) " | |

]}] | |

in | |

Value.ReplaceType(func, Value.ReplaceMetadata(Value.Type(func), documentation)) | |

in | |

fnFormatted |

Copy the code above and paste it into the advanced editor in Power Query.

It will return a function that asks for 1 parameter: The table that shall be replicated. It will then return the M-code that you can use in the “otherwise” branch of your error handling.

It creates the table string from schema, using the Table.Schema M-function (row 5). It then adds a column that reads out column names and types from the schema table to create the string for the type record (row 6-10). Then it concatenates everything to create the M-code for an empty table like so:

`#table(type table [myText=Text.Type, myNumber=Int64.Type, myDate=Date.Type], {{null, null, null}})`

Enjoy & stay queryious 😉

The post Create (empty) table string from schema in Power Query appeared first on The BIccountant.

]]>The post Fill values to the right in Power Query and Power BI appeared first on The BIccountant.

]]>

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

Learn more about bidirectional Unicode characters

let func = | |

(SourceTable as table, FillColumns, optional FillLeft) => | |

let | |

Mode = if FillLeft = null then Table.FillDown else Table.FillUp, | |

#"Added Custom" = Table.AddColumn( | |

SourceTable, | |

"Custom", | |

each Table.FromRows( | |

{ | |

Function.Invoke( | |

Mode, | |

{ | |

Table.FromColumns( | |

{Record.FieldValues(Record.SelectFields(_, FillColumns))} | |

), | |

{"Column1"} | |

} | |

)[Column1] | |

}, | |

FillColumns | |

) | |

), | |

#"Removed Columns" = Table.RemoveColumns(#"Added Custom", FillColumns), | |

#"Expanded Custom" = Table.ExpandTableColumn(#"Removed Columns", "Custom", FillColumns), | |

#"Reordered Columns" = Table.ReorderColumns( | |

#"Expanded Custom", | |

Table.ColumnNames(SourceTable) | |

) | |

in | |

#"Reordered Columns" , | |

documentation = [ | |

Documentation.Name = " Table.FillRight.pq ", | |

Documentation.Description = " Returns a table from the <code>SourceTable</code> specified where the value of a previous cell is propagated to the null-valued cells right from the <code>FillColumns</code> specified. ", | |

Documentation.LongDescription = " Returns a table from the <code>SourceTable</code> specified where the value of a previous cell is propagated to the null-valued cells right from the <code>FillColumns</code> specified. Optional <code>third parameter</code> fills to the left instead. ", | |

Documentation.Category = " Table ", | |

Documentation.Source = " www.TheBIcountant.com – hhttps://wp.me/p6lgsG-2t1 ", | |

Documentation.Version = " 1.0 ", | |

Documentation.Author = " Imke Feldmann ", | |

Documentation.Examples = {[Description = " ", | |

Code = " let | |

SourceTable = #table( type table [Column1 = Text.Type, H1 = Text.Type, H2 = Text.Type, H3 = Text.Type], | |

// Column1| H1| H2| H3| | |

{//—————|———|—————–|——————| | |

{ ""BalanceSheet"", ""Assets"", null, null }, | |

{ ""BalanceSheet"", null, ""Current Assets"", null }, | |

{ ""BalanceSheet"", null, null, ""Current Asset 1"" } } ) , | |

FillColumns = {""H1"", ""H2"", ""H3""}, | |

FunctionCall = fnSampleFunction(SourceTable, FillColumns) | |

in | |

FunctionCall ", | |

Result = " #table( type table [Column1 = Text.Type, H1 = Any.Type, H2 = Any.Type, H3 = Any.Type], | |

// Column1| H1| H2| H3| | |

{//—————|———|—————–|——————| | |

{ ""BalanceSheet"", ""Assets"", ""Assets"", ""Assets"" }, | |

{ ""BalanceSheet"", null, ""Current Assets"", ""Current Assets"" }, | |

{ ""BalanceSheet"", null, null, ""Current Asset 1"" } } ) | |

"]}] | |

in | |

Value.ReplaceType(func, Value.ReplaceMetadata(Value.Type(func), documentation)) | |

The first function argument takes the table you want to apply the function on. The second argument is the list of column names that shall be filled up into empty values to the right. In the example in the function documentation, this is: {“H1”, “H2”, “H3”}. The curly brackets define a list object in Power Query and its list elements must be put in quotes if they shall represent strings. So here the columns H1, H2 and H3 are included.

An optional 3rd argument can be used to fill to the left instead. You can fill in any value there, so once it is used, the fill will work to the left instead.

First the function will add a custom column to the existing table where it selects the values of the selected fill-columns from the current record/row (see row 14 in the function above):

`Record.SelectFields(_, FillColumns)`

Then it will fetch the values from these selected column with the Record.FieldValues-function that has been wrapped around the selection (still row 14):

`{Record.FieldValues(Record.SelectFields(_, FillColumns))}`

This will return a list of values. Now the target is to bring this into a shape where I can use the existing function Table.FillDown or Table.FillUp to fill in empty values. Therefore I transform this list into a table. This happens in row 13 with the Table.FromColumns-function.

This returns a table with one column named “Column1”. On it, we can now do the fill-operations. The direction on which to fill is determined by the 3rd function argument. In there you can change the default right-fill to fill down instead. The logic for this is handled in row 4. There the variable “Mode” will return the selected function. Then in row 10 the function Function.Invoke can conditionally execute the Mode-function. Rows 11 – 17 provide the arguments for it. As a result, I get a one-column table with all values filled in.

Now I only have to tip this by 90° to bring the rows into columns and restore the original column names. Therefore I use the Table.FromRows function in row 8. It allows me to determine the column names in one go (row 20).

Then I remove the original columns (row 23), expand my newly created columns (row 24) and reorder the columns to its original shape (row 25).

Enjoy and stay queryious 😉

The post Fill values to the right in Power Query and Power BI appeared first on The BIccountant.

]]>The post Why are Power Platform Dataflows adding steps automatically at the end? appeared first on The BIccountant.

]]>It will be a step that replaces errors on certain columns followed by a step that transforms these columns into text.

This will happen for every untyped column of the table that’s going to be loaded. So unlike Power BI datasets, who accept untyped columns, dataflows don’t.

As text is the format that most other simple types can also be stored in without loosing their content, this is the format in which untyped columns will be stored in. But before that, all errors will automatically be removed, because these wouldn’t be translated into text.

So be sure to apply the types to your columns as you want them to be. Otherwise you will risk an automatic error-removal in your queries, that could cause trouble at the end.

Enjoy & stay queryious 😉

The post Why are Power Platform Dataflows adding steps automatically at the end? appeared first on The BIccountant.

]]>The post TRIMMEAN function for Power Query and Power BI appeared first on The BIccountant.

]]>

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

Learn more about bidirectional Unicode characters

let func = | |

// fnTRIMMEAN | |

(array, percent) => | |

let | |

percentage = | |

if percent > 1 or percent < 0 | |

then error Error.Record("Percentage must be between 0 and 1 (100%)") | |

else percent, | |

Source = List.Buffer( List.Sort(array, Order.Ascending) ), | |

CountOfTotalRows = List.Count( Source ), | |

CutOffAtEachSide = Number.RoundDown((percentage * CountOfTotalRows) / 2), | |

RelevantRange = List.Range( Source, CutOffAtEachSide, CountOfTotalRows – CutOffAtEachSide * 2), | |

Result = List.Average( RelevantRange) | |

in | |

Result , | |

documentation = [ | |

Documentation.Name = " Xls.TRIMMEAN.pq ", | |

Documentation.Description = " Returns the mean of the interior of a data set. TRIMMEAN calculates the mean taken by excluding a percentage of data points from the top and bottom tails of a data set. ", | |

Documentation.LongDescription = " Returns the mean of the interior of a data set. TRIMMEAN calculates the mean taken by excluding a percentage of data points from the top and bottom tails of a data set. https://support.microsoft.com/en-us/office/trimmean-function-d90c9878-a119-4746-88fa-63d988f511d3?ui=en-us&rs=en-us&ad=us ", | |

Documentation.Category = " Xls.Statistical ", | |

Documentation.Source = " www.TheBIccountant.com ", | |

Documentation.Version = " 1.0 ", | |

Documentation.Author = " Imke Feldmann ", | |

Documentation.Examples = {[Description = " ", | |

Code = " ", | |

Result = " "]}] | |

in | |

Value.ReplaceType(func, Value.ReplaceMetadata(Value.Type(func), documentation)) |

It has the same function parameters than the Excel-function:

TRIMMEAN(array, percent)

The TRIMMEAN function syntax has the following arguments:

**Array**Required. The array or range of values to trim and average.-
**Percent**Required. The fractional number of data points to exclude from the calculation. For example, if percent = 0.2, 4 points are trimmed from a data set of 20 points (20 x 0.2): 2 from the top and 2 from the bottom of the set.

If you are interested in more Power Query functions that replicate Excel functions who haven’t made it into the M-language (yet?) please check out this collection.

Enjoy and stay queryious 😉

The post TRIMMEAN function for Power Query and Power BI appeared first on The BIccountant.

]]>The post Excel WEEKNUM function for Power Query appeared first on The BIccountant.

]]>As this is also a function that has many regional options, I was lucky to find an algorithm that I could use for its main part here: M functions to convert between ISO 8601 Week & Year ⇄ dates (e.g., `2014-12-29`

⇄ `"2015-W01-1"`

) (github.com)

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

Learn more about bidirectional Unicode characters

let func = | |

(Date as date, optional Return_type as number) => | |

let | |

// For a detailled description about the options of the Return_types see the official documentation: | |

// https://support.microsoft.com/en-us/office/weeknum-function-e5c43a03-b4ab-426c-b411-b18c13c75340 | |

// PQ native Date.WeekFromYear starts to count from 0(Sunday) to 6(Saturday) as opposed to Excel from 1(Sunday) to 7(Saturday) | |

ConvertedNumber = | |

if Return_type = null then | |

0 | |

else | |

Record.Field( | |

[1 = 0, 2 = 1, 11 = 1, 12 = 2, 13 = 3, 14 = 4, 15 = 5, 16 = 6, 17 = 0, 21 = 21], | |

Text.From(Return_type) | |

), | |

IsoWeek = // this function comes from r-k-b on Github: https://gist.github.com/r-k-b/18d898e5eed786c9240e3804b167a5ca | |

let | |

getDayOfWeek = (d as date) => | |

let | |

result = 1 + Date.DayOfWeek(d, Day.Monday) | |

in | |

result, | |

getNaiveWeek = (inDate as date) => | |

let | |

// monday = 1, sunday = 7 | |

weekday = getDayOfWeek(inDate), | |

weekdayOfJan4th = getDayOfWeek(#date(Date.Year(inDate), 1, 4)), | |

ordinal = Date.DayOfYear(inDate), | |

naiveWeek = Number.RoundDown((ordinal – weekday + 10) / 7) | |

in | |

naiveWeek, | |

thisYear = Date.Year(Date), | |

priorYear = thisYear – 1, | |

nwn = getNaiveWeek(Date), | |

lastWeekOfPriorYear = getNaiveWeek(#date(priorYear, 12, 28)), | |

// http://stackoverflow.com/a/34092382/2014893 | |

lastWeekOfThisYear = getNaiveWeek(#date(thisYear, 12, 28)), | |

weekYear = | |

if nwn < 1 then | |

priorYear | |

else if nwn > lastWeekOfThisYear then | |

thisYear + 1 | |

else | |

thisYear, | |

weekNumber = | |

if nwn < 1 then | |

lastWeekOfPriorYear | |

else if nwn > lastWeekOfThisYear then | |

1 | |

else | |

nwn | |

in | |

Number.RoundDown(weekNumber), | |

Default = Date.WeekOfYear(Date, ConvertedNumber), | |

Result = if Return_type = 21 then IsoWeek else Default | |

in | |

Result , | |

documentation = [ | |

Documentation.Name = " Xls.WEEKNUM.pq ", | |

Documentation.Description = " Returns the week number of a specific date. For example, the week containing January 1 is the first week of the year, and is numbered week 1. Equivalent of the YEARFRAC-Function in Excel. ", | |

Documentation.LongDescription = " Returns the week number of a specific date. For example, the week containing January 1 is the first week of the year, and is numbered week 1. There are two systems used for this function: | |

System 1 The week containing January 1 is the first week of the year, and is numbered week 1. | |

System 2 The week containing the first Thursday of the year is the first week of the year, and is numbered as week 1. This system is the methodology specified in ISO 8601, which is commonly known as the European week numbering system. | |

Equivalent of the YEARFRAC-Function in Excel. ", | |

Documentation.Category = " Xls.Date ", | |

Documentation.Source = " www.TheBIcountant.com – https://wp.me/p6lgsG-2ta . ", | |

Documentation.Version = " 1.0 ", | |

Documentation.Author = " Imke Feldmann ", | |

Documentation.Examples = {[Description = " ", | |

Code = " let | |

Serial_number = #date(2012, 3, 9) , | |

Return_type = 2, | |

FunctionCall = Xls_WEEKNUM(Serial_number, Return_type) | |

in | |

FunctionCall ", | |

Result = " 11 | |

"]}] | |

in | |

Value.ReplaceType(func, Value.ReplaceMetadata(Value.Type(func), documentation)) |

The function takes the same parameters as its Excel equivalent. So this is just a copy for your convenient reference:

WEEKNUM(serial_number,[return_type])

The WEEKNUM function syntax has the following arguments:

**Serial_number**Required. A date within the week. Dates should be entered by using the DATE function, or as results of other formulas or functions. For example, use DATE(2008,5,23) for the 23rd day of May, 2008. Problems can occur if dates are entered as text.**Return_type**Optional. A number that determines on which day the week begins. The default is 1.

Return_type |
Week begins on |
System |
---|---|---|

1 or omitted | Sunday | 1 |

2 | Monday | 1 |

11 | Monday | 1 |

12 | Tuesday | 1 |

13 | Wednesday | 1 |

14 | Thursday | 1 |

15 | Friday | 1 |

16 | Saturday | 1 |

17 | Sunday | 1 |

21 | Monday | 2 |

If you are interested in more Power Query functions that replicate Excel functions who haven’t made it into the M-language (yet?) please check out this collection.

Enjoy and stay queryious 😉

The post Excel WEEKNUM function for Power Query appeared first on The BIccountant.

]]>The post Excel YEARFRAC function for Power Query appeared first on The BIccountant.

]]>

This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.

Learn more about bidirectional Unicode characters

let func = | |

let | |

//Algo source: https://lists.oasis-open.org/archives/office-formula/200806/msg00039.html | |

FIsLeapYear = (Year) => | |

if Number.Mod(Year, 4) > 0 then | |

false | |

else if Number.Mod(Year, 100) > 0 then | |

true | |

else if Number.Mod(Year, 400) = 0 then | |

true | |

else | |

false, | |

FIsEndOfMonth = (Day, Month, Year) => | |

if List.Contains({1, 3, 5, 7, 8, 10, 12}, Day) then | |

31 | |

else if List.Contains({4, 6, 9, 11}, Day) then | |

30 | |

else if FIsLeapYear(Year) then | |

29 | |

else | |

28, | |

Days360 = (StartYear, EndYear, StartMonth, EndMonth, StartDay, EndDay) => | |

((EndYear – StartYear) * 360) + ((EndMonth – StartMonth) * 30) + (EndDay – StartDay), | |

TmpDays360Nasd = (StartDate, EndDate, Method, UseEom) => | |

let | |

StartDay = Date.Day(StartDate), | |

StartMonth = Date.Month(StartDate), | |

StartYear = Date.Year(StartDate), | |

EndDay = Date.Day(EndDate), | |

EndMonth = Date.Month(EndDate), | |

EndYear = Date.Year(EndDate), | |

Select = [ | |

EndDay = | |

if (EndMonth = 2 and FIsEndOfMonth(EndDay, EndMonth, EndYear)) | |

and ( | |

(StartMonth = 2 and FIsEndOfMonth(StartDay, StartMonth, StartYear)) | |

or Method | |

= 3 | |

) | |

then | |

30 | |

else if EndDay = 31 and (StartDay >= 30 or Method = 3) then | |

30 | |

else | |

EndDay, | |

StartDay = | |

if StartDay = 31 then | |

30 | |

else if ( | |

UseEom | |

= 2 and StartMonth | |

= 2 and FIsEndOfMonth(StartDay, StartMonth, StartYear) | |

) | |

then | |

30 | |

else | |

StartDay | |

], | |

TmpDays360Nasd = Days360(StartYear, EndYear, StartMonth, EndMonth, StartDay, EndDay) | |

in | |

#"TmpDays360Nasd", | |

TmpDays360Euro = (StartDate, EndDate) => | |

let | |

StartDay = Date.Day(StartDate), | |

StartMonth = Date.Month(StartDate), | |

StartYear = Date.Year(StartDate), | |

EndDay = Date.Day(EndDate), | |

EndMonth = Date.Month(EndDate), | |

EndYear = Date.Year(EndDate), | |

StartDay_ = if (StartDay = 31) then 30 else StartDay, | |

EndDay_ = if (EndDay = 31) then 30 else EndDay, | |

TmpDays360Euro = Days360(StartYear, EndYear, StartMonth, EndMonth, StartDay_, EndDay_) | |

in | |

TmpDays360Euro, | |

TmpDiffDates = (StartDate, EndDate, Basis) => | |

if Basis = 0 then | |

TmpDays360Nasd(StartDate, EndDate, 0, true) | |

else if List.Contains({1, 2, 3}, Basis) then | |

Duration.Days(EndDate – StartDate) | |

else | |

TmpDays360Euro(StartDate, EndDate), | |

TmpCalcAnnualBasis = (StartDate, EndDate, Basis) => | |

if List.Contains({0, 2, 4}, Basis) then | |

360 | |

else if Basis = 3 then | |

365 | |

else | |

let | |

StartDay = Date.Day(StartDate), | |

StartMonth = Date.Month(StartDate), | |

StartYear = Date.Year(StartDate), | |

EndDay = Date.Day(EndDate), | |

EndMonth = Date.Month(EndDate), | |

EndYear = Date.Year(EndDate), | |

TmpCalcAnnualBasis_ = | |

if (StartYear = EndYear) then | |

if FIsLeapYear(StartYear) then 366 else 365 | |

else if ((EndYear – 1) = StartYear) | |

and ( | |

(StartMonth > EndMonth) | |

or ((StartMonth = EndMonth) and StartDay >= EndDay) | |

) | |

then | |

if FIsLeapYear(StartYear) then | |

if StartMonth < 2 or (StartMonth = 2 and StartDay <= 29) then | |

366 | |

else | |

365 | |

else if FIsLeapYear(EndYear) then | |

if EndMonth > 2 or (EndMonth = 2 and EndDay = 29) then 366 else 365 | |

else | |

365 | |

else | |

List.Accumulate( | |

{StartYear .. EndYear}, | |

0, | |

(state, current) => | |

if FIsLeapYear(current) then state + 366 else state + 365 | |

), | |

TmpCalcAnnualBasis__ = TmpCalcAnnualBasis_ / (EndYear – StartYear + 1) | |

in | |

TmpCalcAnnualBasis__, | |

Result = (StartDate, EndDate, Basis_) => | |

let | |

Basis = if Basis_ = null then 0 else Basis_, | |

nNumerator = TmpDiffDates(StartDate, EndDate, Basis), | |

nDenom = TmpCalcAnnualBasis(StartDate, EndDate, Basis), | |

TmpYearFrac = nNumerator / nDenom | |

in | |

TmpYearFrac | |

in | |

Result , | |

documentation = [ | |

Documentation.Name = " Xls.YEARFRAC.pq ", | |

Documentation.Description = " Calculates the fraction of the year represented by the number of whole days between two dates (the start_date and the end_date). Equivalent of the YEARFRAC-Function in Excel. ", | |

Documentation.LongDescription = " Calculates the fraction of the year represented by the number of whole days between two dates (the start_date and the end_date). For instance, you can use YEARFRAC to identify the proportion of a whole year's benefits, or obligations to assign to a specific term. Equivalent of the YEARFRAC-Function in Excel. ", | |

Documentation.Category = " Xls.Date ", | |

Documentation.Source = " www.TheBIcountant.com – https://wp.me/p6lgsG-2t4 . ", | |

Documentation.Version = " 1.0 ", | |

Documentation.Author = " Imke Feldmann ", | |

Documentation.Examples = {[Description = " ", | |

Code = " let | |

Start_date = #date(2012,1,1) , | |

End_date = #date(2012, 7, 30), | |

Basis = 3, | |

FunctionCall = Xls_YEARFRAC(Start_date, End_date, Basis) | |

in | |

FunctionCall ", | |

Result = " 0.578082191780821 | |

"]}] | |

in | |

Value.ReplaceType(func, Value.ReplaceMetadata(Value.Type(func), documentation)) |

The Excel YEARFRAC function for Power Query has the same parameters than its Excel equivalent:

YEARFRAC(start_date, end_date, [basis])

The YEARFRAC function syntax has the following arguments:

**Start_date**Required. A date that represents the start date.**End_date**Required. A date that represents the end date.**Basis**Optional. The type of day count basis to use.

Basis |
Day count basis |
---|---|

0 or omitted | US (NASD) 30/360 |

1 | Actual/actual |

2 | Actual/360 |

3 | Actual/365 |

4 |
European 30/360 |

If you are interested in more Power Query functions that replicate Excel functions who haven’t made it into the M-language (yet?) please check out this collection.

Enjoy and stay queryious 😉

The post Excel YEARFRAC function for Power Query appeared first on The BIccountant.

]]>