Workflows

Workflow Substitution Variables

OneStream provides substitution variables that resolve to the current workflow context at runtime. These variables let you write generic Business Rules, Transformation Rules, and Dashboard expressions that automatically adapt based on which Workflow Profile, Scenario, and Time period the user (or batch process) is operating in. Instead of hard-coding dimension member names into your rules, you reference the workflow variable and let the engine fill in the correct value.

Variable Reference

VariableResolves ToExample Value
WFWorkflow Scenario/Time for POV expressions (e.g. T#WF) — not an Entity(used as T#WF)
WFProfileName of the current Workflow ProfileRevenue_Import
WFProfileIndexIndex of the current profile in the hierarchy3
WFScenarioName of the current Scenario memberActual
WFTimeName of the current Time member2024M6
WFCubeName of the current CubeMainCube
These are substitution tokens resolved by the OneStream substitution engine wherever it runs — parameter values, POV expressions (T#WF), Transformation Rule expressions, Cube View and Dashboard/XFBR string expressions, and Data Management step parameters. There is no GetWorkflowSubstitutionVariable BRApi that returns them by name; you either use the token inside a string the engine resolves, or read the workflow context directly from the workflow APIs (shown below).

Using Variables in Business Rules

Inside a Business Rule you don't fetch a substitution token by name — you read the current workflow context from the workflow APIs, then branch on it. BRApi.Workflow.General.GetWorkflowUnitPk(si) returns the workflow POV (profile, scenario, time, and workflow keys); resolve the member keys to names with BRApi.Finance.Members.GetMemberName.
1' Get the current workflow POV
2Dim wfPk As WorkflowUnitPk = BRApi.Workflow.General.GetWorkflowUnitPk(si)
3Dim wfScenario As String = BRApi.Finance.Members.GetMemberName(si, DimType.Scenario.Id, wfPk.ScenarioKey)
4Dim wfTime As String = BRApi.Finance.Members.GetMemberName(si, DimType.Time.Id, wfPk.TimeKey)
5
6' Use workflow context to branch logic
7If wfScenario = "Actual" Then
8  ' Run actuals-specific calculation
9  BRApi.ErrorLog.LogMessage(si, $"Processing actuals for {wfTime}")
10Else
11  ' Run forecast/budget calculation
12  BRApi.ErrorLog.LogMessage(si, $"Processing {wfScenario} for {wfTime}")
13End If

Using Variables in Transformation Rules

Transformation Rules run during the IVL (Import, Validate, Load) pipeline and have full access to workflow substitution variables. A common pattern is routing data to different accounts based on the Scenario — for example, mapping a source "Revenue" line to A#GLRevenue for Actual but to A#PlanRevenue for Budget.
The variables are resolved before the transformation expression is evaluated, so you can use them directly in conditional mapping expressions. If a Transformation Rule needs to apply different account mappings depending on whether the load is for Actual or Forecast, it reads WFScenario and branches accordingly — one rule handles every scenario.
💡Tip
Keep Transformation Rules scenario-agnostic where possible. Only branch on WFScenario when the source-to-target mapping genuinely differs between scenarios. Over-branching makes rules harder to maintain.

Using Variables in Dashboard Expressions

Dashboard parameters and XFBR string functions can reference workflow variables to build context-aware displays. Two common patterns:
  • Dynamic labels — Display the active context in report headers (e.g., "Revenue Report — Actual 2024M6") by reading WFScenario and WFTime and concatenating them into a label string.
  • Data Adapter filtering — Pass WFScenario or WFTime into a Data Adapter expression so the grid or chart automatically filters to the user's current workflow context without requiring manual parameter selection.
ℹ️Info
Workflow substitution tokens only resolve within a workflow context. If they are resolved outside one (e.g. a standalone Data Management sequence not tied to a workflow), they may resolve to empty strings.

Conditional Logic Based on WFScenario

A practical pattern is using WFScenario in a Select Case / switch block to apply entirely different calculation models per scenario. This keeps all logic in a single Business Rule while still allowing each scenario to have its own formula.
ℹ️Info
WFScenario returns the Scenario member name (e.g., "Actual", "Budget_2024"). In simple configurations the scenario name aligns with the scenario type, but in complex setups multiple scenarios can share one type — branch on the scenario name, not the type.
1' Adjust calculation logic based on workflow scenario
2Dim wfPk As WorkflowUnitPk = BRApi.Workflow.General.GetWorkflowUnitPk(si)
3Dim wfScenario As String = BRApi.Finance.Members.GetMemberName(si, DimType.Scenario.Id, wfPk.ScenarioKey)
4
5Select Case wfScenario
6  Case "Actual"
7      ' Actuals: load from GL, no driver calculations
8      api.Data.Calculate("A#Revenue = A#GLRevenue")
9  Case "Budget", "Forecast"
10      ' Budget/Forecast: apply driver models
11      api.Data.Calculate("A#Revenue = A#Units * A#PricePerUnit")
12  Case "Plan"
13      ' Long-range plan: apply growth rates
14      api.Data.Calculate("A#Revenue = A#PriorRevenue * (1 + A#GrowthRate)")
15End Select
⚠️Warning
Always include a default or fallback branch. If a new Scenario is added to the application and your rule does not handle it, the calculation will silently skip — which is much harder to debug than an explicit error message.