Fabric is Generally Available. Browse Fabric Presentations. Work towards your Fabric certification with the Cloud Skills Challenge.
If you've been doing finance-related tasks, you've probably been asked to prepare aging of receivables or run a static report from an accounting system. In this blog post, I will explore how to replicate this report in Power BI (and showcase Power BI's capability to generate random data without using an external data source).
Let's start by creating our fact table. Head over to the query editor and select a blank query as the data source. In the advanced editor, delete the default contents and paste the following code:
let startdate = #date(2021,7,1), enddate = Date.From(DateTime.FixedLocalNow()), step = Number.From( enddate - startdate ) + 1, Source = List.Dates(startdate, step , #duration(1,0,0,0)), #"Converted to Table" = Table.FromList(Source, Splitter.SplitByNothing(), null, null, ExtraValues.Error), #"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "Transaction Date"}}), #"Changed Type" = Table.TransformColumnTypes(#"Renamed Columns",{{"Transaction Date", type date}}), #"Added Custom" = Table.AddColumn(#"Changed Type", "CustomerNumbers", each let start = Number.Round ( Number.RandomBetween ( 1, 10 ), 0), end = Number.Round ( Number.RandomBetween ( 20, 50 ), 0) in {start..end}, type list), #"Expanded CustomerNumbers" = Table.ExpandListColumn(#"Added Custom", "CustomerNumbers"), #"Changed Type1" = Table.TransformColumnTypes(#"Expanded CustomerNumbers",{{"CustomerNumbers", Int64.Type}}), #"Added Custom1" = Table.AddColumn(#"Changed Type1", "Sales on Credit", each let start = Number.RandomBetween ( 10, 20 ), end = Number.RandomBetween ( 100, 200 ), sign = Number.RandomBetween ( -2, 3 ) in Number.RandomBetween ( start, end ) * sign, type number), #"Added Custom2" = Table.AddColumn(#"Added Custom1", "Customer", each let x = Text.From([CustomerNumbers]), y = Text.PadStart(x, 2, "0" ) in "Customer " & y, type text), #"Reordered Columns" = Table.ReorderColumns(#"Added Custom2",{"Transaction Date", "Customer", "CustomerNumbers", "Sales on Credit"}), #"Removed Columns" = Table.RemoveColumns(#"Reordered Columns",{"CustomerNumbers"}), #"Added Index" = Table.AddIndexColumn(#"Removed Columns", "Index", 1, 1, Int64.Type), #"Added Custom3" = Table.AddColumn(#"Added Index", "Invoice Number", each "INV" & Text.PadStart( Text.From ( [Index] ), 10, "0" ), type text), #"Removed Columns1" = Table.RemoveColumns(#"Added Custom3",{"Index"}) in #"Removed Columns1"
Name this table FactSalesOnCredit before loading it.
Next Let's create our dates table in DAX and name it DimDates. Use the formula below:
DimDates =
VAR __BASE =
CALENDAR (
MIN ( FactSalesOnCredit[Transaction Date] ),
MAX ( FactSalesOnCredit[Transaction Date] )
)
RETURN
ADDCOLUMNS (
__BASE,
"Year", YEAR ( [Date] ),
"Month Short", FORMAT ( [Date], "mmm" ),
"Month Long", FORMAT ( [Date], "mmmm" ),
"Month Number", MONTH ( [Date] ),
"Month and Year", FORMAT ( [Date], "mmm-yy" ),
"YYYYMM", FORMAT ( [Date], "YYYYMM" )
)
Once DimDates is created, sort the following columns:
Create a one-to-many relationshiop between Date column in DimDates and Transaction Date in FactSalesOnCredit. You may choose to hide Transaction Date from report view to make it look cleaner. We'll be using Date going forward.
Let's create another table in DAX without a relationship to fact or dates table. Let's call it AgeTable. This will hold the age and their corresponding category or bucket.
AgeTable =
VAR __max =
TODAY () - MIN ( FactSalesOnCredit[Transaction Date] ) + 1
VAR __BASE =
SELECTCOLUMNS ( GENERATESERIES ( 0, __max, 1 ), "Age", [Value] )
RETURN
ADDCOLUMNS (
__BASE,
"Age Category",
SWITCH (
TRUE (),
[Age] <= 30, " 0-30 days",
[Age] <= 60, " 31 - 60 days",
[Age] <= 90, " 61 - 90 days",
[Age] <= 120, "91 - 120 days",
"over 120 days"
)
)
And one more table where we will keep our measures.
**MEASURES =
ROW ( "Ignore", BLANK() )
//serves as a container of measures
Let us start creating our measures.
Sum of Sales on Credit =
SUM ( FactSalesOnCredit[Sales on Credit] )
Running Sales on Credit =
//to calculate the cumulative amount of sales at a given date
//unless a specific date is selected, selecting a period (month, quarter, etc) will return the cumulative amount as at max date within that period.
CALCULATE (
[Sum of Sales on Credit],
FILTER ( ALL ( DimDates ), DimDates[Date] <= MAX ( DimDates[Date] ) )
)
Receivables by Age =
VAR __MAX_DATE =
MAX ( DimDates[Date] )
VAR __START =
__MAX_DATE - CALCULATE ( MAX ( AgeTable[Age] ), ALLEXCEPT ( AgeTable, AgeTable[Age Category] ) )
VAR __END =
__MAX_DATE - CALCULATE ( MIN ( AgeTable[Age] ), ALLEXCEPT ( AgeTable, AgeTable[Age Category] ) )
RETURN
CALCULATE (
[Running Sales on Credit],
DATESBETWEEN ( DimDates[Date], __START, __END )
)
Dissecting Receivables by Age Measure -
Assuming the selected month is October, the Year is 2021 and Age Category is 0-30 days
The measure then returns the Running Sales on Credit where DimDate[Date] is between __START and __END date variables.
After we're done with the measures we can then use them in visuals and start using and sharing the report.
Please see attached pbix for your reference.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.