You’re close. What’s holding it up is the UD1 check in the If, and that one is easy to miss because it compiles and runs without an error. In a stored calc only the data unit dimensions (entity, scenario, time, consolidation) have context. Account, Flow, IC and the UDs don’t, so api.Pov.UD1 can’t be used to filter, and the Calculate never gets reached.
The year loop and the NoData check work. I’d make four changes:
- Remove UD1 from the If.
U1#IFRS is already in the member scripts, so the IFRS filter still applies. - Use a base Origin member on the left side of the Calculate. A destination can only contain writable base members, so
O#Top won’t write. Any base Origin member works; I use O#Forms for calculated results. - Fully qualify the GetDataCell script. Any dimension the script doesn’t name comes from the POV, and a stored calc has no POV for IC or UD2 to UD8. I set them to Top. If Net Income sits on specific members there then I’d use those instead.
- Add the
D suffix to 10825556.05. Without it VB treats the literal as a Double, and the suffix keeps the math in Decimal.
' 1. Explicitly filter for Entity MyEntity and Scenario Actual.
' UD1 is not part of the data unit, so it cannot be tested in a stored calc;
' U1#IFRS is applied in the member scripts below instead.
If api.Pov.Entity.Name.XFEqualsIgnoreCase("MyEntity") And
api.Pov.Scenario.Name.XFEqualsIgnoreCase("Actual") Then
' 3. Determine the prior year boundaries based on the current POV
Dim currentYear As Integer = api.Time.GetYearFromId(api.Pov.Time.MemberId)
Dim priorYear As Integer = currentYear - 1
Dim startYear As Integer = 2023
' 4. Calculate the sum of prior years using GetDataCell variables.
' IC and UD2 to UD8 are named because unspecified dimensions come from the POV,
' and a stored calc has no POV for them.
Dim priorYearsSum As Decimal = 0
For y As Integer = startYear To priorYear
' Pull M12 YTD Net Income cell value for each historical year
Dim cell As DataCell = api.Data.GetDataCell("S#Actual:A#NetIncome:T#" & y & "M12:V#YTD:F#Endbal_Input:O#Top:I#Top:U1#IFRS:U2#Top:U3#Top:U4#Top:U5#Top:U6#Top:U7#Top:U8#Top")
If Not cell Is Nothing AndAlso Not cell.CellStatus.IsNoData Then
priorYearsSum += cell.CellAmount
End If
Next
' 5. Combine the historical actuals and the 10825556.05 baseline constant
Dim totalTargetValue As Decimal = priorYearsSum + 10825556.05D
' The destination can only hold writable base members, so Origin is Forms rather than Top.
api.Data.Calculate("A#MyAccount:F#Endbal_Input:O#Forms:U1#IFRS = (Current:F#None:O#Top:U1#None * 0) + " & totalTargetValue.ToString(System.Globalization.CultureInfo.InvariantCulture))
End If
One thing to check on your side is what Current:F#None:O#Top:U1#None returns. Calculate math runs per cell, so the result has one cell for each cell in that buffer:
- If it’s empty then nothing is written, since a constant added to an empty buffer gives nothing.
- If it has more than one cell then the constant lands on each of them.
- It gives you exactly one value when it holds exactly one cell.
Writing the constant straight to the destination throws the data explosion error. If you only ever want one value in one cell then api.Data.SetDataCell writes it directly, with every dimension named:
vb
api.Data.SetDataCell("A#MyAccount:F#Endbal_Input:O#Forms:I#None:U1#IFRS:U2#None:U3#None:U4#None:U5#None:U6#None:U7#None:U8#None", totalTargetValue, False)
A few settings on MyAccount can also stop it from showing data:
- Formula Type needs to be FormulaPass1 to FormulaPass16 for the formula to run in the DUCS.
- Is Consolidated defaults to Conditional, and with a formula on the account that means it doesn’t consolidate. I’d set it to True if the balance needs to roll up.
- Force Calculate while testing. A regular Consolidate checks calc status first and can skip the data unit; Force ignores it.
Once it’s running, I’d look at three more things:
- Translation. If MyEntity’s currency differs from its parent’s then I’d think about translation before adding a consolidation filter. A retained earnings calc can run on base entities without filtering to Local, so it carries forward the prior year’s translated amount instead of re-translating at the current rate.
- Roll-forward. You can pull the prior year once, in the first period (
api.Time.IsFirstPeriodInYear), and copy from the prior period after that. Reading a prior year costs more because it hits a different data table, so this keeps it to one cross-year read per year. - Opening balance. I’d move the 10825556.05 into a stat account instead of hard coding it here