递归创建 Power Query 列

问题描述 投票:0回答:1

EMI计算:

Number.Round((rate/12*pv)/(1-Number.Power(1+rate/12,-nper)),0)

其中 PV 是初始贷款金额 利率是开始时的初始利率 和

nper is 180 = Tenure in months

这里

EMI = 107485

保持 EMI 不变,现在我需要计算每月的利息和本金

利息计算公式为 以前的余额 * 利率/12 * 没有。上个月的天数/天数 因此,如果没有利率变化,利率将是 prev bal * 利率 /12,否则将适用新利率的天数。

Principal = EMI-Interest paid
New Balance = Previous Balance - Principal
Amount

我无法实现的是:

每次计算利息时,我都想参考以前的余额,这是没有的。

我尝试创建递归函数来计算利息、本金和余额列:

以下函数计算开始时的 EMI 值

PMT

    (pv,rate,nper)=>
    let
    payment = Number.Round((rate/12*pv)/(1-Number.Power(1+rate/12,-nper)),0)
    in
    payment

以下函数计算利息金额(索引值是行号/付款编号)

Get_InterestValue

    (indexValue,table,rate,no_of_days,no_of_days_in_Month)=>
    let
    prev_idx=indexValue-1,
    previousbal = get_previous_balance(indexValue,table),
    interest=previousbal*rate/12/no_of_days_in_Month*no_of_days
    in
    interest

以下函数计算支付的本金金额

GetPrincipalPaid
    (indexvalue,table,EMI_amount,Interest_amount)=>
    let
    principal_amount= EMI_amount-Interest_amount
    in
    principal_amount

下面的函数计算以前的余额

get_previous_balance

    (index_value,table)=>
    let
    prev_idx=index_value-1,
    prev_bal=if prev_idx=0 then fParameter("ParameterTable","Initial_Loan_Amount") else Table.SelectRows(table, each ([Index] = prev_idx)){0}[Bal]
    in 
    prev_bal

f参数函数读取初值表

列给出错误

excel powerquery recursive-query
1个回答
0
投票

我找到了如下代码所示的解决方案:

现在我面临性能问题。以下解决方案适用于 10 个月或更短的时间。一旦你获得更高的 Tenure,计算就会非常缓慢并且长时间不会产生任何输出或者可能在计算完成之前崩溃, 有什么办法可以加快查询处理速度吗?

PMT
功能:

(pv,rate,nper)=>
let
    payment = Number.Round((rate/12*pv)/(1-Number.Power(1+rate/12,-nper)),0)
in
    payment

fParameter
功能:

let Parameter=(TableName,ParameterLabel) =>
let
    Source=Excel.CurrentWorkbook(){[Name=TableName]}[Content],
    value=Source{[Parameter=ParameterLabel]}[Value]
in
    value
in Parameter

Payment Schedule
查询:

let
    Custom1 = List.Generate(()=>Date.Month(fParameter("ParameterTable","StartDate")),each _<=fParameter("ParameterTable","Tenure_in_Months")*1.5+Date.Month(fParameter("ParameterTable","StartDate"))-1,each _+1),
    #"Converted to Table" = Table.FromList(Custom1, Splitter.SplitByNothing(), null, null, ExtraValues.Error),
    #"Added Custom" = Table.AddColumn(#"Converted to Table", "Month", each if Number.Mod([Column1],12)=0 then 12 else Number.Mod([Column1],12)),
    #"Added Custom1" = Table.AddColumn(#"Added Custom", "Year1", each Date.Year(fParameter("ParameterTable","StartDate"))+Number.RoundDown([Column1]/12)),
    #"Added Custom2" = Table.AddColumn(#"Added Custom1", "Year", each if [Month]=12 then [Year1]-1 else [Year1]),
    #"Renamed Columns1" = Table.RenameColumns(#"Added Custom2",{{"Column1", "PaymentMonth"}}),
    #"Added Custom3" = Table.AddColumn(#"Renamed Columns1", "Payment Date", each #date([Year],[Month],Date.Day(fParameter("ParameterTable","StartDate")))),
    #"Removed Other Columns" = Table.SelectColumns(#"Added Custom3",{"Payment Date"}),
    #"Changed Type" = Table.TransformColumnTypes(#"Removed Other Columns",{{"Payment Date", type date}}),
    #"Added Custom4" = Table.AddColumn(#"Changed Type", "EMI", each EMIValue),
    #"Merged Queries" = Table.NestedJoin(#"Added Custom4",{"Payment Date"},Loan_Rates,{"Date"},"Loan_Rates",JoinKind.FullOuter),
    #"Expanded Loan_Rates" = Table.ExpandTableColumn(#"Merged Queries", "Loan_Rates", {"Date", "Loan Rate"}, {"Date", "Loan Rate"}),
    #"Added Custom5" = Table.AddColumn(#"Expanded Loan_Rates", "New_Date", each if [Date] = null then [Payment Date] else [Date]),
    #"Sorted Rows" = Table.Sort(#"Added Custom5",{{"New_Date", Order.Ascending}}),
    #"Filled Down" = Table.FillDown(#"Sorted Rows",{"Loan Rate"}),
    #"Removed Columns" = Table.RemoveColumns(#"Filled Down",{"Payment Date", "Date"}),
    #"Renamed Columns" = Table.RenameColumns(#"Removed Columns",{{"New_Date", "Payment Date"}}),
    #"Reordered Columns" = Table.ReorderColumns(#"Renamed Columns",{"Payment Date", "EMI", "Loan Rate"}),
    #"Added Index" = Table.AddIndexColumn(#"Reordered Columns", "Index", 0, 1),
    #"Added Index1" = Table.AddIndexColumn(#"Added Index", "Index.1", 1, 1),
    #"Merged Queries1" = Table.NestedJoin(#"Added Index1",{"Index"},#"Added Index1",{"Index.1"},"Added Index1",JoinKind.LeftOuter),
    #"Expanded Added Index1" = Table.ExpandTableColumn(#"Merged Queries1", "Added Index1", {"Payment Date"}, {"Payment Date.1"}),
    #"Added Custom7" = Table.AddColumn(#"Expanded Added Index1", "Payment.Date.2", each if [Index.1]=1 then fParameter("ParameterTable","Disbursement Date") else [Payment Date.1]),
    #"Changed Type1" = Table.TransformColumnTypes(#"Added Custom7",{{"Payment.Date.2", type date}}),
    #"Removed Columns2" = Table.RemoveColumns(#"Changed Type1",{"Payment Date.1"}),
    #"Renamed Columns2" = Table.RenameColumns(#"Removed Columns2",{{"Payment.Date.2", "Payment Date.1"}}),
    #"Added Custom6" = Table.AddColumn(#"Renamed Columns2", "Days", each [Payment Date]-[Payment Date.1]),
    #"Extracted Days" = Table.TransformColumns(#"Added Custom6",{{"Days", Duration.Days, Int64.Type}}),
    #"Added Custom8" = Table.AddColumn(#"Extracted Days", "No Of Days in Month", each Date.EndOfMonth([Payment Date.1])-Date.StartOfMonth([Payment Date.1])+#duration(1,0,0,0)),
    #"Removed Columns1" = Table.RemoveColumns(#"Added Custom8",{"Index",  "Payment Date.1"}),
    #"Extracted Days1" = Table.TransformColumns(#"Removed Columns1",{{"No Of Days in Month", Duration.Days, Int64.Type}}),
    #"Reordered Columns1" = Table.ReorderColumns(#"Extracted Days1",{"Payment Date", "Days", "EMI", "Loan Rate"}),
    #"Renamed Columns3" = Table.RenameColumns(#"Reordered Columns1",{{"Index.1", "Index"}}),
    #"Reordered Columns2" = Table.ReorderColumns(#"Renamed Columns3",{"Index", "Payment Date", "EMI", "No Of Days in Month", "Days", "Loan Rate"}),
    #"Replaced Value" = Table.ReplaceValue(#"Reordered Columns2",null,0,Replacer.ReplaceValue,{"EMI"}),
    #"Invoked Custom Function" = Table.AddColumn(#"Replaced Value", "Interest", each Get_InterestValue([Index], Table.Buffer(#"Replaced Value"))),
    #"Added Custom9" = Table.AddColumn(#"Invoked Custom Function", "Principal", each [EMI]-[Interest]),
    #"Added Custom11" = Table.AddColumn(#"Added Custom9", "Balance", each fParameter("ParameterTable","Initial_Loan_Amount")-List.Sum(List.FirstN(#"Added Custom9"[Principal],[Index]))),
    #"Filtered Rows" = Table.SelectRows(#"Added Custom11", each [Interest] > 0)
    
in
    #"Filtered Rows"

Loan_Rates
表查询 == 这读取了一段时间内贷款利率的变化:

let
    Source = Excel.CurrentWorkbook(){[Name="Loan_Rates"]}[Content],
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Date", type date}, {"Loan Rate", Percentage.Type}})
in
    #"Changed Type"

Get_InterestValue
功能

(indexValue,table)=>
let
    prev_idx=indexValue-1,
    rate=Table.SelectRows(table, each ([Index] = indexValue)){0}[Loan Rate],
    no_of_days_in_Month=Table.SelectRows(table, each ([Index] = indexValue)){0}[No Of Days in Month],
    no_of_days=Table.SelectRows(table, each ([Index] = indexValue)){0}[Days],
    previousbal = get_previous_balance(indexValue,table),
    interest=previousbal*rate/12/no_of_days_in_Month*no_of_days
in
    interest

GetPrincipalPaid
功能:

(indexValue,table)=>
let
    EMI_Amount=Table.SelectRows(table, each ([Index] = indexValue)){0}[EMI],
    principal_amount= EMI_Amount-Get_InterestValue(indexValue,table)
in
    principal_amount

GetBalance
功能:

(indexValue,table)=>
let
    bal = get_previous_balance(indexValue,table)-GetPrincipalPaid(indexValue,table) 
in
    bal

get_previous_balance
功能:

(indexValue,table)=>
let
prev_idx=indexValue-1,
prev_bal=if prev_idx=0 then fParameter("ParameterTable","Initial_Loan_Amount") else  GetBalance(prev_idx,table)
in 
prev_bal

EMIValue
功能: 让

    Source = PMT(fParameter("ParameterTable","Initial_Loan_Amount"), fParameter("ParameterTable","Rate_int_PA"), fParameter("ParameterTable","Tenure_in_Months")),
    #"Converted to Table" = #table(1, {{Source}}),
    #"Renamed Columns" = Table.RenameColumns(#"Converted to Table",{{"Column1", "EMI"}}){0}[EMI]
in
    #"Renamed Columns"
© www.soinside.com 2019 - 2024. All rights reserved.